简体   繁体   English

当 RabbitMQ 无法路由消息时,发布者确认给出 ACK

[英]Publisher Confirms gives ACK when message can not be routed by RabbitMQ

I'm doing a small project to check how works Publisher Confirms for RabbitMQ with Spring Cloud Stream 3.0.1.我正在做一个小项目来检查发布者确认 RabbitMQ 与 Spring Cloud Stream 3.0.1 的工作原理。

I have a particular case when a message is send to the exchange of RabbitMQ, but this exchange can not route this message.我有一个特殊情况,当消息被发送到 RabbitMQ 的交换时,但是这个交换不能路由这个消息。 I expected that this message will be handled by the Publisher as an error but my surprise was that this is handled as an ACK.我预计此消息将由发布者作为错误处理,但令我惊讶的是,它被作为 ACK 处理。

This is the code of the Publisher:这是发布者的代码:

@Slf4j
@Timed
@Component
@RequiredArgsConstructor
public class TestPublisher {

    private final MessagingChannels messagingChannels;

    public boolean send(Message<Event<TestEvent>> message) {

        log.info("Message for Testing Publisher confirms sent: " + message);
        return messagingChannels.walletTest().send(message);
    }

    @ServiceActivator(inputChannel = TEST_ACK)
    public void acks(Message<?> ack) {
        log.info("Message ACK received for Test: " + ack);
    }

    @ServiceActivator(inputChannel = TEST_ERROR)
    public void errors(Message<?> error) {
        log.info("Message error for Test received: " + error);
    }
}

I can see this message printed in the log of org.springframework.integration.handler.LoggingHandler我可以在 org.springframework.integration.handler.LoggingHandler 的日志中看到这条消息

org.springframework.integration.amqp.support.ReturnedAmqpMessageException, failedMessage=GenericMessage [payload=byte[1009], headers={id=c9bc65bc-9256-1ce2-324f-167cc526a819, timestamp=1591962425292}] [amqpMessage=(Body:'{"payload":{"id":"f696668d-140e-4ba7-96c7-ea6decdfcccd","version":20000,"currency":"USD"},"eventName":"TEST_UPDATED",......contentType=application/json, contentLength=0, receivedDeliveryMode=PERSISTENT, priority=0, deliveryTag=0]), replyCode=312, replyText=NO_ROUTE, .....]

As you can see, it is reported as a failure message with replyCode=312 and replyText=NO_ROUTE.如您所见,它被报告为replyCode=312 和replyText=NO_ROUTE 的失败消息。

However, it is received as an ACK instead of NACK.但是,它是作为 ACK 而不是 NACK 接收的。 I have checked a bit in the documentation and I think this the expected behaviour with Publisher Confirms enabled, but I would like to confirm that.我在文档中检查了一下,我认为这是启用 Publisher Confirms 的预期行为,但我想确认一下。 And if it's the case, is there some way to detect in the context of the ACK that this message could not berouted?如果是这种情况,是否有某种方法可以在 ACK 的上下文中检测到该消息无法路由? Because inside this context, I don't have the replyCode and the replyText, I have only the proper message sent by the Publisher.因为在这个上下文中,我没有replyCode 和replyText,我只有Publisher 发送的正确消息。

Publisher confirms is activated properly with the next properties: Publisher 确认已使用以下属性正确激活:

spring:
  rabbitmq:
    publisher-confirm-type: correlated
    publisher-returns: true

ACK Channel and errors are correctly configured with errorChannelEnabled and confirmAckChannel properties.使用 errorChannelEnabled 和 confirmAckChannel 属性正确配置了 ACK 通道和错误。

That is how it works, the ack, not a nack, is sent after the returned message.这就是它的工作原理,在返回消息之后发送 ack,而不是 nack。

See the documentation .请参阅文档

For unroutable messages, the broker will issue a confirm once the exchange verifies a message won't route to any queue (returns an empty list of queues).对于不可路由的消息,一旦交换验证消息不会路由到任何队列(返回队列的空列表),代理将发出确认。 If the message is also published as mandatory, the basic.return is sent to the client before basic.ack.如果消息也是强制发布的,basic.return 会在 basic.ack 之前发送给客户端。

You cannot tell that is was returned in the context of the ack.你不能说它是在 ack 的上下文中返回的。

You can, if you use Spring AMQP directly rather than via Spring Cloud Stream because the ack callback gets CorrelationData which will containe the returned message.您可以,如果您直接使用 Spring AMQP 而不是通过 Spring Cloud Stream 使用,因为 ack 回调获取CorrelationData将包含返回的消息。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM