RabbitMQ NACK消息

时间:2019-01-28 16:39:13

标签: node.js rabbitmq amqp

我的经验:在发布/订阅的情况下,如果订阅者收到一条消息,则立即将未打消的消息重新排队在队列的最前面,这将是订阅者收到的下一条消息。

有办法避免这种情况吗?是否可以以某种方式使一条消息不被接收,而下一条消息肯定不会成为刚刚被接收的消息?

我正在使用Node.js和amqp.node与RabbitMQ通信

3 个答案:

答案 0 :(得分:1)

Nack是AMQP协议对RabbitMQ的特定增强。它允许消息的使用者在未成功处理消息 时通知服务器。我想你已经走了这么远。

这里有趣的是,AMQP最初并不认为Nack是必要的。为什么?因为当使用者无法处理消息时AMQP行为是让使用者关闭连接而无需ack-发送消息。在这种情况下,该邮件将按照其原始顺序自动重新排队,并通过设置redelivered标志将其传递给下一个可用的使用者。

为什么会这样?

因为Nack表示使用者有问题,而不是消息。如果消息本身是错误的,则AMQP假定使用者将足够聪明地识别ack消息,然后采取程序员设计用来处理错误消息的其他任何步骤。

RabbitMQ添加了Nack函数,该函数带有一个requeue参数。默认情况下,requeue为true-表示不满意时,代理将重新排队该消息。这与AMQP设计的初衷是一致的。但是,如果您将requeue传递为false,则代理将对消息进行死信。这是通常由智能应用程序架构师使用AMQP设计的行为的捷径,因此您可以认为这对程序员很方便。

两者之间的区别

在第一种情况下,Nack指示消息使用者的问题。消费者在解决问题时应使自己脱机。在第二种情况下,Nack表示消息有问题。第一种情况是暂时性问题,第二种情况是永久性故障。

如果我现在不能处理特定的消息 ,但是以后可能怎么办?

如果您的消息传递结构设计正确,那将永远是不对的。如果一条特定的消息与另一条消息相比需要不同的处理路径或资源,则该消息类型应具有自己的队列。当处理这些消息的依赖项脱机或不可用时,该队列的使用者可以停止使用。

答案 1 :(得分:0)

问题:我的经验:在发布/订阅的情况下,如果订户收到邮件,则立即将未确认的邮件重新排队在队列的最前面,这将是订户收到的下一封邮件。

  

是的,这是正确的。当邮件重新排队时   channel.basicNack,它将被放置在其原始位置   尽可能排队。如果不是(由于同时交货和   当多个消费者共享一个消费者时,来自其他消费者的确认   队列),邮件将重新排队到更靠近队列的位置   头。来源:https://www.rabbitmq.com/nack.html

问题:有没有办法避免这种情况?是否可以以某种方式使一条消息不被接收,而下一条消息肯定不会成为刚刚被接收的消息?

不可能用nack来实现。实现此目的的一种方法是将邮件重新发布到需要的地方。

  • 获取消息并立即将确认发送回去。
  • 处理消息,如果成功,则不执行任何操作。
  • 如果失败,请不要发送nack,而是将消息重新发布回 队列。

答案 2 :(得分:0)

作为一般规则,您可以认为,如果使用者正常运行,则无论处理该消息的结果如何(无论是错误还是成功),都应始终确认一条消息。

您可以使用requeue = false拒绝/拒绝格式错误的错误消息,以将其路由到死信交换并对其执行操作(绑定队列并消耗以进行事后分析),或选择确认并执行任何操作是必需的(例如,发送其他消息,例如BadRequest消息,...)。

(几乎)永无问题的最佳方法是将ack作为处理消息的最后动作,并准备处理重新交付(幂等可能会有所帮助)。您可以在交付后立即确认,但是如果消费者崩溃,则消息会丢失(并且您需要自己处理这种情况-有很多模式)。

希望这会有所帮助。