我的经验:在发布/订阅的情况下,如果订阅者收到一条消息,则立即将未打消的消息重新排队在队列的最前面,这将是订阅者收到的下一条消息。
有办法避免这种情况吗?是否可以以某种方式使一条消息不被接收,而下一条消息肯定不会成为刚刚被接收的消息?
我正在使用Node.js和amqp.node与RabbitMQ通信
答案 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来实现。实现此目的的一种方法是将邮件重新发布到需要的地方。
答案 2 :(得分:0)
作为一般规则,您可以认为,如果使用者正常运行,则无论处理该消息的结果如何(无论是错误还是成功),都应始终确认一条消息。
您可以使用requeue = false拒绝/拒绝格式错误的错误消息,以将其路由到死信交换并对其执行操作(绑定队列并消耗以进行事后分析),或选择确认并执行任何操作是必需的(例如,发送其他消息,例如BadRequest消息,...)。
(几乎)永无问题的最佳方法是将ack作为处理消息的最后动作,并准备处理重新交付(幂等可能会有所帮助)。您可以在交付后立即确认,但是如果消费者崩溃,则消息会丢失(并且您需要自己处理这种情况-有很多模式)。
希望这会有所帮助。