在消费者收到消息后,消费者/工作人员会进行一些验证,然后调用Web服务。在此阶段,如果发生任何错误或验证失败,我们希望将消息放回最初使用的队列。
我已阅读RabbitMQ文档。但我对reject,nack和cancel方法之间的区别感到困惑。
答案 0 :(得分:51)
简答:
要重新排列特定消息,您可以同时选择basic.reject
或basic.nack
并将multiple
标记设置为false。
basic.consume
调用也可能导致重新传递的消息,并且消费者在特定时间和消费者退出时都会收到未确认消息,而不会对其进行处理。
basic.recover
将在特定频道重新发送所有未启用的消息。
答案很长:
basic.reject
和basic.nack
都用于同一目的 - 删除或重新排列特定消费者无法处理的消息(在特定时刻,某些条件下或根本不会)。它们之间的主要区别在于basic.nack
支持批量邮件处理,而basic.reject
则不支持。
官方RabbitMQ网站上的Negative Acknowledgements文章中描述了这种差异:
AMQP规范定义了
basic.reject
方法,该方法允许客户拒绝单个传递的消息,指示代理丢弃它们或重新排队。不幸的是,basic.reject
不支持批量负面确认消息。要解决此问题,RabbitMQ支持
basic.nack
方法,该方法提供basic.reject
的所有功能,而也允许批量处理消息。要批量拒绝邮件,客户端会将
multiple
方法的basic.nack
标记设置为true
。然后,代理将拒绝所有未确认的,已发送的消息,包括delivery_tag
方法的basic.nack
字段中指定的消息。在这方面,basic.nack
补充了basic.ack
的批量确认语义。
注意,basic.nack
方法是RabbitMQ特定的扩展,而basic.reject
方法是AMQP 0.9.1规范的一部分。
对于basic.cancel
方法,它用于通知服务器客户端停止消息消费。请注意,客户端可能会在发送接收basic.cancel
回复的cancel-ok
方法之间收到任意消息编号。如果客户端使用了消息确认,并且它有任何未确认的消息,则它们将被移回到最初消耗的队列中。
basic.recover
在RabbitMQ中有一些限制:它
- basic.recover with requeue=false
- basic.recover synchronicity
除了勘误表,according to RabbitMQ specs basic.recover
有部分支持(不支持使用requeue = false恢复。)
关于basic.consume
的注意事项:
当basic.consume
在没有auto-ack(noack=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)
星号(*
)注意到redelivered
标志设置为true
。
假设我们有死信交换集的情况和死信函的队列
Exchange(e-main) Exchange(e-dead)
Queue(main){x-dead-letter-exchange: "e-dead"} Queue(dead)
并假设我们发布了5条消息,expire
属性设置为5000
(5秒):
Queue(main) (tail) { [4] [3] [2] [1] [0] } (head)
Queue(dead) (tail) { }(head)
然后我们从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.get
方法说明。