Spring AMQP 官方文档翻译

3.Reference

3.1 Using Spring AMQP

在本章中,我们将探索接口和类,它们是使用Spring AMQP开发应用程序的基本组件。

3.1.1 AMQP Abstractions(抽象)  

Introduction

Spring AMQP由几个模块组成,每个模块在发行版中由一个JAR表示。这些模块是:spring-amqp和spring-rabbit。spring-amqp模块包含org.springframework.amqp.core包。在该包中,您将找到表示核心AMQP“model”的类。我们的目的是提供不依赖于任何特定AMQP代理实现或客户端库的通用抽象。最终用户代码将更易于跨供应商实现移植,因为它只能针对抽象层开发。然后使用这些抽象由特定于broker的模块实现,比如spring-rabbit。目前只有一个RabbitMQ实现;然而,除了RabbitMQ之外,抽象还在. net中使用Apache Qpid进行了验证。由于AMQP原则上在协议级别上运行,因此RabbitMQ客户机可以与任何支持相同协议版本的代理一起使用,但是我们目前不测试任何其他代理。这里的概述假定您已经熟悉AMQP规范的基础知识。如果没有,请查看第5章“其他资源”中列出的资源。

Message

0-9-1 AMQP规范没有定义消息类或接口。相反,在执行basicPublish()等操作时,内容作为字节数组参数传递,其他属性作为单独的参数传递。Spring AMQP将消息类定义为更通用的AMQP域模型表示的一部分。Message类的目的是简单地将主体和属性封装在一个实例中,这样API就可以变得更简单。消息类定义非常简单。

public class Message {

    private final MessageProperties messageProperties;

    private final byte[] body;

    public Message(byte[] body, MessageProperties messageProperties) {
        this.body = body;
        this.messageProperties = messageProperties;
    }

    public byte[] getBody() {
        return this.body;
    }

    public MessageProperties getMessageProperties() {
        return this.messageProperties;
    }
}

MessageProperties接口定义了一些常见的属性,如messageId、时间戳、contentType等。通过调用setHeader(String key, Object value)方法,还可以用用户定义的头扩展这些属性。

重要:从版本1.5.7、1.6.11、1.7.4、2.0.0开始,如果消息体是一个序列化的可序列化java对象,那么在执行toString()操作(例如日志消息)时,它将不再反序列化(默认情况下)。这是为了防止不安全的反序列化。默认情况下,只有java.util和java.lang类是反序列化的。要恢复到前面的行为,可以通过调用Message.addWhiteListPatterns(…)添加允许的类/包模式。支持一个简单的*通配符,例如com.foo.*,*.MyClass。不能反序列化的主体将在日志消息中由byte[<size>]表示。

Exchange

Exchange接口表示AMQP交换,这是消息生成器发送到的对象。在代理的虚拟主机内的每个Exchange都有一个惟一的名称和一些其他属性:

public interface Exchange {

    String getName();

    String getExchangeType();

    boolean isDurable();

    boolean isAutoDelete();

    Map<String, Object> getArguments();

}

如您所见,Exchange还有一个类型,它由ExchangeTypes中定义的常量表示。基本类型有:Direct、Topic、Fanout和header。在核心包中,您将发现每种类型的Exchange接口的实现。就处理队列绑定的方式而言,这些交换类型之间的行为各不相同。例如,直接交换允许使用固定路由键(通常是队列的名称)绑定队列。主题交换支持具有路由模式的绑定,路由模式可能包含*和#通配符,分别用于1和0或多个通配符。Fanout exchange发布到绑定到它的所有队列,而不考虑任何路由键。有关这些和其他交换类型的更多信息,请参阅第5章“其他资源”。

注意:AMQP规范还要求任何代理提供没有名称的“缺省”直接交换。声明的所有队列都将绑定到该缺省交换器,并将其名称作为路由键。在第3.1.4节“AmqpTemplate”中,您将了解更多关于Spring AMQP中默认Exchange的用法。

Queue

Queue类表示消息使用者从其中接收消息的组件。与各种Exchange类一样,我们的实现也是这个核心AMQP类型的抽象表示。

public class Queue  {

    private final String name;

    private volatile boolean durable;

    private volatile boolean exclusive;

    private volatile boolean autoDelete;

    private volatile Map<String, Object> arguments;

    /**
     * The queue is durable, non-exclusive and non auto-delete.
     *
     * @param name the name of the queue.
     */
    public Queue(String name) {
        this(name, true, false, false);
    }

    // Getters and Setters omitted for brevity

}

注意,构造函数接受队列名称。根据实现的不同,管理模板可能提供生成惟一命名队列的方法。这种队列可以用作“答复”地址或其他临时情况。因此,自动生成队列的exclusive和autoDelete属性都将设置为true。

注意:

有关使用名称空间支持(包括队列参数)声明队列的信息,请参阅第3.1.10节“配置代理”中关于队列的部分。

Binding

假定生产者向交换器发送消息,消费者从队列接收消息,那么将队列连接到交换器的绑定对于通过消息传递将生产者和消费者连接起来是至关重要的。在Spring AMQP中,我们定义了一个绑定类来表示这些连接。让我们回顾一下将队列绑定到交换器的基本选项。

您可以使用固定路由键将队列绑定到DirectExchange。

new Binding(someQueue, someDirectExchange, "foo.bar")

您可以使用路由模式将队列绑定到TopicExchange。

new Binding(someQueue, someTopicExchange, "foo.*")

您可以将队列绑定到没有路由键的FanoutExchange。

new Binding(someQueue, someFanoutExchange)

我们还提供了一个BindingBuilder来促进“连贯API”风格。

Binding b = BindingBuilder.bind(someQueue).to(someTopicExchange).with("foo.*");

注意:为了清晰起见,上面显示了BindingBuilder类,但是当使用bind()方法的静态导入时,这种样式可以很好地工作。

绑定类的实例本身只是保存关于连接的数据。换句话说,它不是一个“活动”组件。但是,正如您稍后将在3.1.10节“配置代理”中看到的,AmqpAdmin类可以使用绑定实例来实际触发代理上的绑定操作。

同样,正如您将在同一节中看到的,绑定实例可以在@Configuration类中使用Spring的@ bean样式定义。还有一个方便的基类,它进一步简化了生成AMQP相关bean定义的方法,并识别队列、交换和绑定,以便在应用程序启动时在AMQP代理上声明它们。

AmqpTemplate也在核心包中定义。作为实际AMQP消息传递中涉及的主要组件之一,在其自己的部分(参见3.1.4节,“AmqpTemplate”)中对其进行了详细讨论。

3.1.2 Connection and Resource Management

Introduction

虽然我们在前一节中描述的AMQP模型是通用的,并且适用于所有实现,但是当我们进入资源管理时,详细信息是特定于代理实现的。因此,在本节中,我们将关注仅存在于“spring-rabbit”模块中的代码,因为此时,RabbitMQ是惟一受支持的实现。

管理到RabbitMQ代理的连接的中心组件是ConnectionFactory接口。ConnectionFactory实现的职责是提供org.springframework.amq.rabbit.connection.Connection 的实例,它是com.rabbitmq.client.Connection的包装器。我们提供的唯一具体实现是CachingConnectionFactory,默认情况下,它建立一个可以由应用程序共享的连接代理。共享连接是可能的,因为使用AMQP进行消息传递的“工作单元”实际上是一个“通道”(在某些方面,这类似于JMS中的连接和会话之间的关系)。可以想象,connection实例提供了一个createChannel方法。CachingConnectionFactory实现支持缓存这些通道,并根据它们是否是事务性的,为通道维护单独的缓存。在创建CachingConnectionFactory实例时,可以通过构造函数提供主机名。还应该提供用户名和密码属性。如果希望配置通道缓存的大小(默认为25),也可以在这里调用setChannelCacheSize()方法

从1.3版开始,CachingConnectionFactory可以配置为缓存连接和通道。在这种情况下,每次调用createConnection()都会创建一个新的连接(或从缓存中检索空闲连接)。关闭连接将返回到缓存(如果没有达到缓存大小)。在这样的连接上创建的通道也被缓存。在某些环境中,使用单独的连接可能是有用的,比如使用HA集群和负载平衡器连接到不同的集群成员。将cacheMode设置为 CacheMode.CONNECTION。

注意:这并不限制连接的数量,而是指定允许多少空闲打开的连接。

从1.5.5版本开始,提供了一个新的属性connectionLimit。当设置此选项时,它将限制允许的连接总数。设置时,如果达到限制,则使用channelCheckoutTimeLimit等待连接空闲。如果超时,则抛出AmqpTimeoutException。

重要:

当缓存模式为连接时,不支持队列的自动声明等(请参阅“交换、队列和绑定的自动声明”一节)。

另外,在编写本文时,rabbitmq-client库默认为每个连接(5个线程)创建一个固定的线程池。当使用大量连接时,应该考虑在CachingConnectionFactory上设置自定义执行器。然后,所有连接将使用同一个执行器,并且可以共享其线程。执行程序的线程池应该是无界的,或者为预期的利用率进行适当的设置(通常,每个连接至少有一个线程)。如果在每个连接上创建多个通道,那么池大小将影响并发性,因此最适合使用可变的(或简单缓存)线程池执行器。

重要的是要理解缓存大小(默认情况下)不是限制,而仅仅是可以缓存的通道数量。缓存大小为10时,实际上可以使用任意数量的通道。如果使用超过10个通道,并且它们都返回到缓存中,则10个通道将进入缓存;其余部分将在物理上关闭。

从1.6版开始,默认通道缓存大小从1增加到25。在大容量、多线程、环境中,小缓存意味着高速创建和关闭通道。增加默认缓存大小将避免这种开销。您应该通过RabbitMQ管理UI监视正在使用的通道,如果您看到正在创建和关闭许多通道,则应考虑进一步增加缓存大小。缓存只会按需增长(以适应应用程序的并发性需求),因此此更改不会影响现有的低容量应用程序。

从1.4.2版本开始,CachingConnectionFactory有一个属性channelCheckoutTimeout。当此属性大于零时,channelCacheSize将成为对可以在连接上创建的通道数量的限制。如果达到此限制,调用线程将阻塞,直到通道可用或达到此超时为止,在这种情况下,将抛出AmqpTimeoutException。

警告:框架中使用的通道(例如RabbitTemplate)将可靠地返回到缓存中。如果您在框架之外创建通道(例如,通过直接访问连接并调用createChannel()),您必须可靠地(通过关闭)返回它们(可能在finally块中),以避免通道耗尽。

CachingConnectionFactory connectionFactory = new CachingConnectionFactory("somehost");
connectionFactory.setUsername("guest");
connectionFactory.setPassword("guest");

Connection connection = connectionFactory.createConnection();

When using XML, the configuration might look like this:

<bean id="connectionFactory"
      class="org.springframework.amqp.rabbit.connection.CachingConnectionFactory">
    <constructor-arg value="somehost"/>
    <property name="username" value="guest"/>
    <property name="password" value="guest"/>
</bean>

注意:还有一个SingleConnectionFactory实现,它只在框架的单元测试代码中可用。它比CachingConnectionFactory更简单,因为它不缓存通道,但是由于它缺乏性能和弹性,所以不适合在简单测试之外的实际使用。如果由于某种原因需要实现自己的ConnectionFactory, AbstractConnectionFactory基类可能会提供一个很好的起点。

使用rabbit名称空间可以快速方便地创建ConnectionFactory:

<rabbit:connection-factory id="connectionFactory"/>

在大多数情况下,这将是可取的,因为框架可以为您选择最佳的默认值。创建的实例将是CachingConnectionFactory。请记住,通道的默认缓存大小是25。如果希望缓存更多的通道,可以通过channelCacheSize属性设置更大的值。在XML中是这样的:

<bean id="connectionFactory"
      class="org.springframework.amqp.rabbit.connection.CachingConnectionFactory">
    <constructor-arg value="somehost"/>
    <property name="username" value="guest"/>
    <property name="password" value="guest"/>
    <property name="channelCacheSize" value="50"/>
</bean>

使用名称空间,您可以添加通道缓存大小属性:

<rabbit:connection-factory
    id="connectionFactory" channel-cache-size="50"/>

默认缓存模式是CHANNEL,但您可以将其配置为缓存连接;在本例中,我们使用connection-cache-size:

<rabbit:connection-factory
    id="connectionFactory" cache-mode="CONNECTION" connection-cache-size="25"/>

可以使用名称空间提供主机和端口属性:

<rabbit:connection-factory
    id="connectionFactory" host="somehost" port="5672"/>

或者,如果在集群环境中运行,使用address属性。

<rabbit:connection-factory
    id="connectionFactory" addresses="host1:5672,host2:5672"/>

下面是一个自定义线程工厂的例子,它用rabbitmq-作为线程名的前缀。

<rabbit:connection-factory id="multiHost" virtual-host="/bar" addresses="host1:1234,host2,host3:4567"
    thread-factory="tf"
    channel-cache-size="10" username="user" password="password" />

<bean id="tf" class="org.springframework.scheduling.concurrent.CustomizableThreadFactory">
    <constructor-arg value="rabbitmq-" />
</bean>

从版本1.7开始,为注入AbstractionConnectionFactory提供了ConnectionNameStrategy。生成的名称用于目标RabbitMQ连接的特定于应用程序的标识。如果RabbitMQ服务器支持该连接名,则该连接名将显示在管理UI中。这个值不必是唯一的,也不能用作连接标识符,例如在HTTP API请求中。这个值应该是人类可读的,并且是connection_name键下ClientProperties的一部分。可以用作一个简单的Lambda:

connectionFactory.setConnectionNameStrategy(connectionFactory -> "MY_CONNECTION");

ConnectionFactory参数可以用一些逻辑来区分目标连接名。默认情况下,AbstractConnectionFactory的beanName和内部计数器用于生成connection_name。<rabbit:connection-factory>名称空间组件还提供了connection-name-strategy属性。

从1.7.7版本开始,提供了一个AmqpResourceNotAvailableException,当simpleconconnection . createchannel()无法创建通道时抛出该异常,例如,因为通道elmax限制已经达到,缓存中没有可用的通道。这个异常可以在RetryPolicy中使用,以在某些回退之后恢复操作。

Configuring the Underlying Client Connection Factory 配置基础客户端连接工厂

CachingConnectionFactory使用Rabbit客户机ConnectionFactory的实例;在CachingConnectionFactory上设置等效属性时,会传递许多配置属性(例如主机、端口、用户名、密码、requestedHeartBeat、connectionTimeout)。要设置其他属性(例如clientProperties),请定义rabbit factory的一个实例,并使用CachingConnectionFactory的适当构造函数提供对它的引用。

当使用上面描述的名称空间时,在connection-factory属性中提供对已配置工厂的引用。为了方便起见,提供了一个工厂bean来帮助在Spring应用程序上下文中配置连接工厂,下一节将对此进行讨论。

<rabbit:connection-factory
      id="connectionFactory" connection-factory="rabbitConnectionFactory"/>

注意:

The 4.0.x版本客户端默认支持自动恢复;虽然与此特性兼容,但Spring AMQP有自己的恢复机制,通常不需要客户机恢复特性。建议禁用amqm -client自动恢复,以避免在代理可用但连接尚未恢复时获得AutoRecoverConnectionNotCurrentlyOpenException s。您可能会注意到这个异常,例如,当在RabbitTemplate中配置了RetryTemplate时,甚至在集群中失败切换到另一个代理时也是如此。由于自动恢复连接在计时器上恢复,因此使用Spring AMQP的恢复机制可以更快地恢复连接。从1.7.1版本开始,Spring AMQP禁用它,除非您显式地创建自己的RabbitMQ连接工厂并将其提供给CachingConnectionFactory。由RabbitConnectionFactoryBean创建的RabbitMQ ConnectionFactory实例也将在缺省情况下禁用该选项。

RabbitConnectionFactoryBean and Configuring SSL

从1.4版开始,提供了一个方便的RabbitConnectionFactoryBean,使用依赖项注入在底层客户端连接工厂上启用方便的SSL属性配置。其他setter只委托给底层工厂。以前,您必须以编程方式配置SSL选项。

<rabbit:connection-factory id="rabbitConnectionFactory"
    connection-factory="clientConnectionFactory"
    host="${host}"
    port="${port}"
    virtual-host="${vhost}"
    username="${username}" password="${password}" />

<bean id="clientConnectionFactory"
        class="org.springframework.amqp.rabbit.connection.RabbitConnectionFactoryBean">
    <property name="useSSL" value="true" />
    <property name="sslPropertiesLocation" value="file:/secrets/rabbitSSL.properties"/>
</bean>

有关配置SSL的信息,请参阅RabbitMQ文档。省略密钥存储库和信任存储库配置,以便在没有证书验证的情况下通过SSL连接。密钥和信任存储库配置如下:

sslPropertiesLocation属性是指向包含以下键的属性文件的Spring资源:

keyStore=file:/secret/keycert.p12
trustStore=file:/secret/trustStore
keyStore.passPhrase=secret
trustStore.passPhrase=secret

keyStore和truststore是指向这些存储的Spring资源。通常,该属性文件将由具有读访问权限的操作系统保护。从Spring AMQP 1.5版本开始,可以直接在工厂bean上设置这些属性。如果同时提供离散属性和sslPropertiesLocation,则后者中的属性将覆盖离散值。

Routing Connection Factory

从1.3版本开始,已经介绍了AbstractRoutingConnectionFactory。这提供了一种机制来为几个ConnectionFactory配置映射,并在运行时通过某个lookupKey确定目标ConnectionFactory。通常,实现检查线程绑定上下文。为了方便起见,Spring AMQP提供了SimpleRoutingConnectionFactory,它从SimpleResourceHolder获取当前线程绑定的lookupKey:

<bean id="connectionFactory"
      class="org.springframework.amqp.rabbit.connection.SimpleRoutingConnectionFactory">
	<property name="targetConnectionFactories">
		<map>
			<entry key="#{connectionFactory1.virtualHost}" ref="connectionFactory1"/>
			<entry key="#{connectionFactory2.virtualHost}" ref="connectionFactory2"/>
		</map>
	</property>
</bean>
<rabbit:template id="template" connection-factory="connectionFactory" />
public class MyService {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    public void service(String vHost, String payload) {
        SimpleResourceHolder.bind(rabbitTemplate.getConnectionFactory(), vHost);
        rabbitTemplate.convertAndSend(payload);
        SimpleResourceHolder.unbind(rabbitTemplate.getConnectionFactory());
    }

}

重要的是在使用资源后解除绑定。有关更多信息,请参见AbstractRoutingConnectionFactory的JavaDocs。

从1.4版开始,RabbitTemplate支持SpEL sendConnectionFactorySelectorExpression和receiveConnectionFactorySelectorExpression属性,这些属性在每个AMQP协议交互操作(send、sendAndReceive、receive或receiveAndReply)上进行评估,并解析为提供的AbstractRoutingConnectionFactory的lookupKey值。可以在表达式中使用Bean引用,比如“@vHostResolver.getVHost(#root)”。对于发送操作,要发送的消息是根评估对象;对于接收操作,queueName是根计算对象。

路由算法是:如果选择器表达式为null,或者被计算为null,或者提供的ConnectionFactory不是AbstractRoutingConnectionFactory的实例,那么一切都像以前一样工作,依赖于提供的ConnectionFactory实现。如果计算结果不是null,则会发生相同的情况,但是该lookupKey没有目标ConnectionFactory, AbstractRoutingConnectionFactory配置lenientFallback = true。当然,在AbstractRoutingConnectionFactory的情况下,它会返回到基于行列式urrentlookupkey()的路由实现。但是,如果lenientFallback = false,则抛出一个IllegalStateException。

命名空间支持还在<rabbit:template>组件上提供了发送-连接-工厂-选择器-表达式和接收-连接-工厂-选择器-表达式属性。

同样,从1.4版本开始,您可以在侦听器容器中配置路由连接工厂。在这种情况下,队列名称列表用作查找键。例如,如果您使用setQueueNames(“foo”、“bar”)配置容器,那么查找键将是“[foo,bar]”(没有空格)。

从1.6.9版本开始,您可以使用侦听器容器上的setLookupKeyQualifier向查找键添加一个限定符。例如,这将启用侦听具有相同名称的队列,但是在不同的虚拟主机中(每个虚拟主机都有一个连接工厂)。

例如,使用查找键限定符foo和侦听队列栏的容器,您将注册目标连接工厂的查找键将是foo[bar]。

Queue Affinity and the LocalizedQueueConnectionFactory 队列关联和LocalizedQueueConnectionFactory

在集群中使用HA队列时,为了获得最佳性能,最好连接到主队列所在的物理代理。而CachingConnectionFactory可以配置多个代理地址;这是故障转移,客户端将尝试按顺序连接。LocalizedQueueConnectionFactory使用管理插件提供的REST API来确定控制了队列的哪个节点。然后,它创建(或从缓存中检索)一个CachingConnectionFactory,该工厂将仅连接到该节点。如果连接失败,则确定新的主节点并由使用者连接到它。LocalizedQueueConnectionFactory配置了一个默认连接工厂,以防无法确定队列的物理位置,在这种情况下,它将正常连接到集群。

LocalizedQueueConnectionFactory是一个RoutingConnectionFactory, SimpleMessageListenerContainer使用队列名称作为查找键,正如上面“路由连接工厂”一节中讨论的那样。

注意:由于这个原因(使用队列名称进行查找),LocalizedQueueConnectionFactory只能在容器被配置为侦听单个队列时使用。

注意:必须在每个节点上启用RabbitMQ管理插件。

谨慎:这个连接工厂适用于长生命周期的连接,比如SimpleMessageListenerContainer使用的连接。由于在建立连接之前调用REST API的开销,所以不打算使用短连接,比如使用RabbitTemplate。此外,对于发布操作,队列是未知的,而且消息无论如何都会发布给所有集群成员,因此查找节点的逻辑没有什么价值。

下面是一个配置示例,使用Spring Boot的RabbitProperties来配置工厂:

@Autowired
private RabbitProperties props;

private final String[] adminUris = { "http://host1:15672", "http://host2:15672" };

private final String[] nodes = { "rabbit@host1", "rabbit@host2" };

@Bean
public ConnectionFactory defaultConnectionFactory() {
    CachingConnectionFactory cf = new CachingConnectionFactory();
    cf.setAddresses(this.props.getAddresses());
    cf.setUsername(this.props.getUsername());
    cf.setPassword(this.props.getPassword());
    cf.setVirtualHost(this.props.getVirtualHost());
    return cf;
}

@Bean
public ConnectionFactory queueAffinityCF(
        @Qualifier("defaultConnectionFactory") ConnectionFactory defaultCF) {
    return new LocalizedQueueConnectionFactory(defaultCF,
            StringUtils.commaDelimitedListToStringArray(this.props.getAddresses()),
            this.adminUris, this.nodes,
            this.props.getVirtualHost(), this.props.getUsername(), this.props.getPassword(),
            false, null);
}

注意,前三个参数是地址、adminuri和节点的数组。当容器试图连接到队列时,它确定队列控制在哪个节点上,并连接到相同数组位置的地址。

Publisher Confirms and Returns

通过将CachingConnectionFactory的publisherconfirm和publisherReturns属性分别设置为“true”,可以支持已确认和返回的消息。

设置了这些选项后,工厂创建的通道s被包装在PublisherCallbackChannel中,用于方便回调。当获得这样一个通道时,客户机可以注册PPublisherCallbackChannel.Listener。PublisherCallbackChannel实现包含将确认/返回路由到适当侦听器的逻辑。下面几节将进一步解释这些特性。

提示:有关更多的背景信息,请参见RabbitMQ团队的博客文章《介绍Publisher》。

Logging Channel Close Events

在1.5版中引入了一种允许用户控制日志记录级别的机制。

CachingConnectionFactory使用默认策略记录通道关闭,如下所示:

  • 正常通道关闭(200 OK)没有被记录。
     
  • 如果通道由于被动队列声明失败而关闭,则会将其记录在调试级别。
     
  • If a channel is closed because the basic.consume is refused due to an exclusive consumer condition, it is logged at INFO level.
     
  • 所有其他日志记录在错误级别。

要修改此行为,请在CachingConnectionFactory的closeExceptionLogger属性中注入一个定制的ConditionalExceptionLogger。

Also see the section called “Consumer Events”.

Runtime Cache Properties

从1.6版开始,CachingConnectionFactory现在通过getCacheProperties()方法提供缓存统计信息。这些统计数据可用于在生产中优化缓存。例如,可以使用高水迹来确定是否应该增加缓存大小。如果它等于缓存大小,您可能需要考虑进一步增加。

Table 3.1. Cache properties for CacheMode.CHANNEL

Property Meaning
connectionName

 

ConnectionNameStrategy生成的连接的名称。

channelCacheSize

 

当前配置的允许空闲的最大通道。

localPort
连接的本地端口(如果可用)。这可以用来关联RabbitMQ管理UI上的连接/通道。
idleChannelsTx
当前空闲(缓存)的事务通道的数量。
idleChannelsNotTx
当前空闲(缓存)的非事务性通道的数量。
idleChannelsTxHighWater

 

并发空闲(缓存)的事务通道的最大数量。

idleChannelsNotTxHighWater

 

并发空闲(缓存)的非事务性通道的最大数量。

 

Table 3.2. Cache properties for CacheMode.CONNECTION

Property Meaning
connectionName:<localPort>

 

ConnectionNameStrategy生成的连接的名称。

openConnections

 

表示到代理的连接的连接对象的数量。

channelCacheSize

 

当前配置的允许空闲的最大通道。

connectionCacheSize

 

当前配置的允许空闲的最大连接。

idleConnections

 

当前空闲的连接数。

idleConnectionsHighWater

 

并发空闲的最大连接数。

idleChannelsTx:<localPort>

此连接当前空闲(缓存)的事务通道的数量。属性名的localPort部分可用于与RabbitMQ管理UI上的连接/通道关联。

idleChannelsNotTx:<localPort>

此连接当前空闲(缓存)的非事务性通道的数量。属性名的localPort部分可用于与RabbitMQ管理UI上的连接/通道关联。

idleChannelsTxHighWater:
<localPort>

并发空闲(缓存)的事务通道的最大数量。属性名的localPort部分可用于与RabbitMQ管理UI上的连接/通道关联。

idleChannelsNotTxHighWater:
<localPort>

并发空闲(缓存)的非事务性通道的最大数量。属性名的localPort部分可用于与RabbitMQ管理UI上的连接/通道关联。

cacheMode属性(还包括通道或连接)。

Figure 3.1. JVisualVM Example

cacheStats

RabbitMQ Automatic Connection/Topology recovery RabbitMQ自动连接/拓扑恢复

自Spring AMQP的第一个版本以来,该框架在代理失败时提供了自己的连接和通道恢复。

此外,正如3.1.10节“配置代理”中讨论的,当重新建立连接时,RabbitAdmin将重新声明任何基础设施bean(队列等)。因此,它不依赖于现在由amqp-client库提供的自动恢复。Spring AMQP现在使用4.0.x版本的amqp-client的,默认情况下启用了自动恢复功能。如果您愿意,Spring AMQP仍然可以使用它自己的恢复机制,在客户机中禁用它(通过将底层RabbitMQ connectionFactory上的automaticRecoveryEnabled属性设置为false)。然而,该框架完全兼容自动恢复功能。这意味着您在代码中创建的任何消费者(可能通过RabbitTemplate.execute())都可以自动恢复。

3.1.3 Adding Custom Client Connection Properties 添加自定义客户端连接属性

CachingConnectionFactory现在允许您访问底层连接工厂,例如,允许设置自定义客户端属性:

connectionFactory.getRabbitConnectionFactory().getClientProperties().put("foo", "bar");

在查看连接时,这些属性将出现在RabbitMQ管理UI中。

3.1.4 AmqpTemplate

Introduction

与Spring框架和相关项目提供的许多其他高级抽象一样,Spring AMQP提供了一个“模板”,它扮演着核心角色。定义主要操作的接口称为AmqpTemplate。这些操作涵盖了发送和接收消息的一般行为。换句话说,它们对于任何实现都不是惟一的,因此名称中有“AMQP”。另一方面,该接口的一些实现与AMQP协议的实现绑定在一起。与JMS本身是接口级API不同,AMQP是一个线级协议。该协议的实现提供了自己的客户机库,因此模板接口的每个实现都依赖于特定的客户机库。目前,只有一个实现:RabbitTemplate。在接下来的示例中,您将经常看到“AmqpTemplate”的用法,但是当您查看配置示例,或者调用模板实例化和/或setter的任何代码摘录时,您将看到实现类型(例如,“RabbitTemplate”)。

如上所述,AmqpTemplate接口定义了发送和接收消息的所有基本操作。我们将在下面的两部分中分别探讨消息发送和接收。

See also the section called “AsyncRabbitTemplate”.

Adding Retry Capabilities 添加重试功能

从1.3版开始,现在可以配置RabbitTemplate,使用RetryTemplate帮助处理代理连接问题。有关完整信息,请参阅spring-retry项目;下面只是使用指数回退策略和默认SimpleRetryPolicy的一个例子,默认SimpleRetryPolicy在将异常抛出给调用者之前会尝试三次。

Using the XML namespace:

<rabbit:template id="template" connection-factory="connectionFactory" retry-template="retryTemplate"/>

<bean id="retryTemplate" class="org.springframework.retry.support.RetryTemplate">
    <property name="backOffPolicy">
        <bean class="org.springframework.retry.backoff.ExponentialBackOffPolicy">
            <property name="initialInterval" value="500" />
            <property name="multiplier" value="10.0" />
            <property name="maxInterval" value="10000" />
        </bean>
    </property>
</bean>

Using @Configuration:

@Bean
public AmqpTemplate rabbitTemplate();
    RabbitTemplate template = new RabbitTemplate(connectionFactory());
    RetryTemplate retryTemplate = new RetryTemplate();
    ExponentialBackOffPolicy backOffPolicy = new ExponentialBackOffPolicy();
    backOffPolicy.setInitialInterval(500);
    backOffPolicy.setMultiplier(10.0);
    backOffPolicy.setMaxInterval(10000);
    retryTemplate.setBackOffPolicy(backOffPolicy);
    template.setRetryTemplate(retryTemplate);
    return template;
}

从版本1.4开始,除了retryTemplate属性之外,RabbitTemplate还支持recoveryCallback选项。它用作RetryTemplate的第二个参数。执行(RetryCallback<T, E> RetryCallback, RecoveryCallback<T> RecoveryCallback)。

注意:RecoveryCallback有一定的限制,因为retry上下文只包含lastThrowable字段。对于更复杂的用例,应该使用外部RetryTemplate,以便通过上下文的属性向RecoveryCallback传递额外的信息:

retryTemplate.execute(
    new RetryCallback<Object, Exception>() {

        @Override
        public Object doWithRetry(RetryContext context) throws Exception {
            context.setAttribute("message", message);
            return rabbitTemplate.convertAndSend(exchange, routingKey, message);
        }
    }, new RecoveryCallback<Object>() {

        @Override
        public Object recover(RetryContext context) throws Exception
  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值