Rabbitmq 如何配置";“端到端”;publisher与Spring AMQP确认
我想将publisher-confirms与RabbitMQ和Spring-AMQP一起使用,这样,如果侦听器在处理消息期间抛出异常,那么消息确认回调将获得一个NACK 下面,我讨论的是用红色标记的用例: 主要问题是:Rabbitmq 如何配置";“端到端”;publisher与Spring AMQP确认,rabbitmq,spring-amqp,Rabbitmq,Spring Amqp,我想将publisher-confirms与RabbitMQ和Spring-AMQP一起使用,这样,如果侦听器在处理消息期间抛出异常,那么消息确认回调将获得一个NACK 下面,我讨论的是用红色标记的用例: 主要问题是: 如何配置ConnectionFactory、RabbitTemplate和ListenerContainer以启用手动NACK 如果出现异常,我必须在侦听器中执行什么操作才能调用消息并使用success=false调用确认回调 这是我的豆子: @Bean 公共连接工厂连接工厂(
success=false
调用确认回调@Bean
公共连接工厂连接工厂(){
CachingConnectionFactory connectionFactory=新的CachingConnectionFactory(“localhost”);
connectionFactory.SetPublisherConfigrms(true);
返回连接工厂;
}
@豆子
公共ConfirmCallback ConfirmCallback(){
返回新的ConfirmCallbackTestImplementation();
}
@豆子
公共RabbitTemplate RabbitTemplate(ConnectionFactory ConnectionFactory,ConfirmCallback ConfirmCallback){
RabbitTemplate RabbitTemplate=新的RabbitTemplate(连接工厂);
setConfirmCallback(confirmCallback);
rabbitTemplate.setExchange(直接交换);
返回兔模板;
}
@豆子
公共故障消息侦听器故障侦听器(RabbitAdmin RabbitAdmin、DirectExchange exchange、ConnectionFactory ConnectionFactory){
队列=队列(rabbitAdmin,exchange,“faultyListener”);
FaultyMessageListener=新的FaultyMessageListener();
SimpleMessageListenerContainer容器=新的SimpleMessageListenerContainer(connectionFactory);
setMessageListener(监听器);
container.setQueues(队列);
container.setDefaultRequeueRejected(false);
container.setAcknowledgeMode(AcknowledgeMode.MANUAL);
container.start();
返回侦听器;
}
专用队列队列(RabbitAdmin RabbitAdmin、DirectExchange exchange、字符串路由密钥){
队列=新队列(routingKey,true,false,true);
rabbitAdmin.declareQueue(队列);
rabbitAdmin.declareBinding(BindingBuilder.bind(queue).to(exchange).with(routingKey));
返回队列;
}
以下是我的侦听器实现:
public类FaultyMessageListener实现ChannelAwareMessageListener{
private final List receivedMessages=new ArrayList();
专用最终倒计时闩锁=新倒计时闩锁(1);
@凌驾
public void onMessage(消息消息、通道)引发异常{
receivedMessages.add(消息);
channel.basicNack(message.getMessageProperties().getDeliveryTag(),false,false);
倒计时();
抛出新的AmqpException(“无法处理消息”);
}
}
这是我的确认回电:
公共静态类ConfirmCallbackTestImplementation实现ConfirmCallback{
private volatile Map confirmations=new HashMap();
私有易失性HashMap ExpectationLatchs=新HashMap();
@凌驾
public void confirm(CorrelationData CorrelationData,布尔成功,字符串s){
confirmations.put(correlationData.getId(),success);
expectationLatchs.get(correlationData.getId()).countDown();
}
公共倒计时闩锁预期(字符串相关ID){
CountDownLatch闩锁=新的CountDownLatch(1);
this.expectationLatchs.put(correlationId,latch);
回程闩锁;
}
}
然后,我使用以下测试来验证所需的行为:
@Autowired
私有rabbit模板;
@自动连线
私人过错信息披露人过错信息披露人;
@自动连线
私有ConfirmCallbackTestImplementation testConfirmCallback;
@试验
public void sendMessageToFaultyMessageListenerResultsInNack()引发InterruptedException{
字符串correlationId=“corr-data-test-2”;
CountDownLatch confirmationLatch=testConfirmCallback.expect(correlationId);
convertAndSend(“ConnectionsTests.PublisherConfig”、“faultyListener”、“FaultMessage”、新的CorrelationData(correlationId));
assertTrue(faultyListener.latch.await(1,TimeUnit.SECONDS));
确认锁存。等待(1,时间单位。秒);
断言(faultyListener.receivedMessages.size(),为(1));
断言(testConfirmCallback.confirmations.get(correlationId)为(false));
}
试验结果如下:
java.lang.AssertionError:
Expected: is <false>
but: was <true>
java.lang.AssertionError:
预期:是吗
但是:是吗
最后一句话。对于我来说,这就像总是用
success=true
调用confirm回调,而不是使用success=false
我在侦听器中期望的channel.basicNack(…)
调用。它不会那样工作;发布服务器端的ack/nack纯粹是代理是否接受了消息。事实上,nack很少返回,因为它意味着代理本身存在问题-请参阅
只有在负责队列的Erlang进程中发生内部错误时,才会传递basic.nack
类似地,消费者侧的ack/nack纯粹是关于消费者是否已接受对消息的责任,并且nack允许消息被重新排队、丢弃或路由到死信队列
消息发布后,消费者将无法与发布者进行通信。如果需要此类通信,则需要设置回复队列
如果希望发布者和使用者之间紧密耦合,则可以使用。如果使用者抛出异常,它将被传播回发布者-但是,该机制仅支持JavaSerializable
对象
尽管文档引用了XML,但您可以将代理和服务调用程序连接为@Bean
s