如何在RabbitMQ中重新查询消息

如何在RabbitMQ中重新查询消息,rabbitmq,amqp,node-amqp,Rabbitmq,Amqp,Node Amqp,消费者收到消息后,消费者/工作者进行一些验证,然后调用web服务。在此阶段,如果发生任何错误或验证失败,我们希望将消息放回最初使用它的队列 我已经阅读了RabbitMQ文档。但我对拒绝、nack和取消方法之间的区别感到困惑。简短回答: 要重新获取特定消息,您可以选择basic.reject或basic.nack,并将multiple标志设置为false basic.consume如果您正在使用message acknowledge,并且消费者在特定时间有未确认的消息,并且消费者在未确认消息的情况

消费者收到消息后,消费者/工作者进行一些验证,然后调用web服务。在此阶段,如果发生任何错误或验证失败,我们希望将消息放回最初使用它的队列


我已经阅读了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)