回复监听器容器
当使用3.4.0之前的Rabbit版本,每个回复都会使用一个新临时队列. 然而,可在模板上配置单个回复队列, 这将更加高效,同时也允许你在队列上设置参数.然而,在这种情况下,你必须提供子元素.
这个元素为回复队列提供了监听器容器, 以模板为监听器.
所有 Section 3.1.15, “Message Listener Container Configuration” 中的属性都可以配置在 元素中,除了connection-factory 和 message-converter(它们是模块配置中继承下来的).
重要
如果运行了多个应用程序实例或者使用了多个RabbitTemplate,那么你必须为每个都使用唯一的回复队列- RabbitMQ 没有在队列中选择消息的能力,如果它们都使用相同队列,每个实例都将竞争的答复,而不一定是收到他们自己的。
由于容器和模板可共享一个连接工厂,它们不会共享一个通道,因此请求和回复不是在同一个事务中执行的(如果是事务的).
重要
在1.5.0版本之前,reply-address属性不可用,回复总是通过默认交换器和reply-queue作路由键来进行的. 现在这依然是默认的,但现在你可以指定新的reply-address属性.reply-address可以包含/形式的地址,回复将会路由到设定的exchange和路由到routing key绑定的队列上.reply-address优先于reply-queue.必须配置为一个单独的组件, 当只使用reply-address时,无论是reply-address还是reply-queue(在中的queue属性) 必须指的是同一个队列.
在这个配置中,SimpleListenerContainer 用于接收回复; 而RabbitTemplate 将成为MessageListener. 当使用 命名空间元素定义模板时, 正如上面所展示的, 分析器会定义容器,并将模板作为监听器进行包装.
重要
当模板不使用固定replyQueue(或使用Direct reply-to - 参考the section called “RabbitMQ Direct reply-to”) ,则不需要监听器容器. 当在RabbitMQ3.4.0+使用时,Directreply-to是更好的机制.
如果你将 RabbitTemplate 定义为 , 或使用 @Configuration 类将其定义为@Bean,或者通过编程来创建模板,你需要自己定义和包装回复监听器容器.
如果这样做失败了,模板将不会收到回复,并最终会超时并返回null作为对sendAndReceive 方法调用者的回复.
从1.5版本开始, RabbitTemplate 会探测是否配置了MessageListener 来接收回复.如果没有,它会尝试发送并使用回复地地址来接收消息,如果失败了,则会抛出 IllegalStateException (因为不会收到回复).
此外,如果使用了简单的replyAddress (队列名称),回复监听器容器会验证与监听的队列是否是一样的名称.但如果这个地址是交换器和路由键,这种检查不会被执行,会输出调试日志信息.
重要
当在编写回复监听器和模板时,重要的一点是要保证模板的replyQueue与容器的queues(或queueNames) 属性指的是相同的队列. 模板会将回复队列插入到出站消息的replyTo属性中.
下面的例子展示了如何来包装这些beans.@Beanpublic RabbitTemplate amqpTemplate() {
RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory());
rabbitTemplate.setMessageConverter(msgConv());
rabbitTemplate.setReplyQueue(replyQueue());
rabbitTemplate.setReplyTimeout(60000);
return rabbitTemplate; }
@Beanpublic SimpleMessageListenerContainer replyListenerContainer() {
SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
container.setConnectionFactory(connectionFactory());
container.setQueues(replyQueue());
container.setMessageListener(amqpTemplate());
return container;
}
@Beanpublic Queue replyQueue() {
returnnew Queue("my.reply.queue");
}
完整的RabbitTemplate 包装固定回复队列,与远程监听器容器的请求回复处理展示在 this test case.
重要
当回复超时时(replyTimeout),sendAndReceive()方法会返回null.
在1.3.6版本之前, 消息超时回复只是简单地记录下来.现在,如果收到了迟到回复,将会拒绝(模板会抛出AmqpRejectAndDontRequeueException).
如果回复队列配置了将拒绝消息到死信交换器中, 可获取回复来作后面的分析. 只须将队列以队列名称作为路由键绑定到死信交换器中.
你也可以看示例中关于FixedReplyQueueDeadLetterTests 测试用例.
1万+

被折叠的 条评论
为什么被折叠?



