如何在RabbitMQ中重新查询消息
消费者收到消息后,消费者/工作者进行一些验证,然后调用web服务。在此阶段,如果发生任何错误或验证失败,我们希望将消息放回最初使用它的队列如何在RabbitMQ中重新查询消息,rabbitmq,amqp,node-amqp,Rabbitmq,Amqp,Node Amqp,消费者收到消息后,消费者/工作者进行一些验证,然后调用web服务。在此阶段,如果发生任何错误或验证失败,我们希望将消息放回最初使用它的队列 我已经阅读了RabbitMQ文档。但我对拒绝、nack和取消方法之间的区别感到困惑。简短回答: 要重新获取特定消息,您可以选择basic.reject或basic.nack,并将multiple标志设置为false basic.consume如果您正在使用message acknowledge,并且消费者在特定时间有未确认的消息,并且消费者在未确认消息的情况
我已经阅读了RabbitMQ文档。但我对拒绝、nack和取消方法之间的区别感到困惑。简短回答: 要重新获取特定消息,您可以选择
basic.reject
或basic.nack
,并将multiple
标志设置为false
basic.consume
如果您正在使用message acknowledge,并且消费者在特定时间有未确认的消息,并且消费者在未确认消息的情况下退出,则呼叫也可能导致消息重新传递
basic.recover
将重新传递特定频道上所有未确认的邮件
长答案:
并且两者都有相同的用途——特定消费者无法处理的丢弃或重新请求消息(在给定时刻、特定条件下或根本无法处理)。它们之间的主要区别在于basic.nack
支持批量消息处理,而basic.reject
不支持
官方RabbitMQ网站上的文章中描述了这种差异:
AMQP规范定义了basic.reject
方法,该方法允许客户端拒绝单个已传递的消息,指示代理放弃或重新获取这些消息。不幸的是,basic.reject
不支持批量负面确认消息
为了解决这个问题,RabbitMQ支持basic.nack
方法,该方法提供basic.reject
的所有功能,同时还允许批量处理消息
要批量拒绝消息,客户端将basic.nack
方法的multiple
标志设置为true
。然后,代理将拒绝所有未确认的已传递消息,包括basic.nack
方法的delivery_标记字段中指定的消息。在这方面,它补充了的批量确认语义
注意,basic.nack
方法是RabbitMQ特定的扩展,而basic.reject
方法是AMQP 0.9.1规范的一部分
至于方法,它用于通知服务器客户端停止消息消费。请注意,客户端可能会在basic.cancel
方法发送接收cancel-ok
回复之间接收任意数量的消息。如果客户端使用消息确认,并且它有任何未确认的消息,则这些消息将被移回最初使用它们的队列
RabbitMQ中有一些限制:它
-
-
除勘误表外,basic.recover
还提供部分支持(不支持使用requeue=false进行恢复)
注意:
如果启动时没有自动确认(no-ack=false
),并且存在一些未确认的未决消息,则当消费者被取消(死亡、致命错误、异常等)时,未决消息将被重新发送。从技术上讲,在消费者发布这些待处理消息(ack/nack/reject/recover)之前,不会处理这些消息(即使是死信)。只有在这之后,才会对其进行处理(例如,不记名)
例如,假设我们连续发布5条消息:
Queue(main) (tail) { [4] [3] [2] [1] [0] } (head)
然后消费其中3个,但不确认,然后取消消费。我们将遇到这种情况:
Queue(main) (tail) { [4] [3] [2*] [1*] [0*] } (head)
其中星号(*
)表示已重新交付
标志设置为真
假设我们有死信交换集和死信消息队列的情况
Exchange(e-main) Exchange(e-dead)
Queue(main){x-dead-letter-exchange: "e-dead"} Queue(dead)
假设我们发布了5条expire
属性设置为5000
(5秒)的消息:
然后我们使用main
队列中的3条消息并保持10秒:
Queue(main) (tail) { [2!] [1!] [0!] } (head)
Queue(dead) (tail) { [4*] [3*] } (head)
其中感叹号(!
)表示未确认的消息。此类消息无法传递给任何消费者,并且通常无法在管理面板中查看。但让我们取消消费者,记住,它仍然保存3条未确认的消息:
Queue(main) (tail) { } (head)
Queue(dead) (tail) { [2*] [1*] [0*] [4*] [3*] } (head)
因此,现在头部的3条消息被放回原始队列,但由于它们具有每个消息TTL集,它们被死信写到死信队列的尾部(当然,通过死信交换)
p.S.:
使用消息(即侦听新消息)与直接队列访问(在不关心其他消息的情况下获取一条或多条消息)有所不同。有关更多信息,请参阅方法说明。如果basic.nack与basic.reject完全相同,但支持批量消息处理,那么什么时候basic.reject优先于basic.nack?为什么不在所有情况下都使用basic.nack呢?是否为RabbitMQ特定扩展。通过“RabbitMQ特定扩展”,您的意思是不使用扩展之外的扩展?意思是如果我使用Spring AMQP与RabbitMQ集成,那么我就不能使用basic.nack?我的意思是basic.nack
不是AMQP标准的一部分,而是RabbitMQ特定的扩展(我添加了关于这个问题的注释,以使更多读者能够看到它)。如果您使用RabbitMQ作为AMQP代理,则可以使用basic.nack
代替basic.reject
@NeoWang是的,我的意思可能是如果basic.consume
开始时没有自动确认(no-ack=false
),并且当消费者被取消时,会出现一些未确认的未决消息(死亡、致命错误、异常等)待决消息将被重新发送。从技术上讲,待决消息在消费者发布(确认/确认/拒绝/恢复)之前不会被处理(甚至是死信)。只有在这之后才会被处理(例如,死信).但感谢您在原始答案中指出这种模糊性,我将添加此解释和示例。
Queue(main) (tail) { } (head)
Queue(dead) (tail) { [2*] [1*] [0*] [4*] [3*] } (head)