嗯,我让你走... RabbitMQ 中的 basic.reject
对 AMQP 的 basic.reject
的支持刚刚在默认情况下上线。之所以花费这么长时间,是因为我们无法就一套符合规范、真正有用且实现起来不太复杂的语义达成一致。
首先,RabbitMQ 的 basic.reject
将执行以下操作:如果提供 requeue=false
,它将丢弃消息(在启用死信功能之前,这是代替将其发送到死信队列的);如果提供 requeue=true
,它会将其重新发送回队列,以便再次投递。
第一个在错误处理方面很有用;如果您的应用程序无法处理特定消息,您可以将其删除。目前,它的语义与确认消息相同;但是,考虑到死信机制,它将意味着无法处理的消息可以在其他地方被提取以进行诊断。
第二个,使用 requeue=true
,例如在您的应用程序需要“消息锁定”语义时很有用。在这种情况下,可以将消息传递给消费者,然后消费者可以决定最终不处理该消息,并将其放回队列中。请注意,RabbitMQ *不会阻止同一个消费者再次获取消息*——请参见下文。
AMQP 0-9-1 规范在 basic.reject 上说了一些看似不兼容的内容。首先,它在方法描述中说
客户端一定不要使用此方法作为选择要处理的消息的方式。
以及在规范 XML 中(但不在生成的 PDF 中),
服务器一定不要在当前通道的上下文中将消息传递给同一个客户端。建议的策略是尝试将消息传递给其他消费者,如果无法做到这一点,则将消息移动到死信队列。服务器可以使用更复杂的跟踪来将消息保留在队列中,并在稍后阶段将其重新传递给同一个客户端。
这似乎表明服务器必须注意不要将消息两次传递给同一个消费者,但消费者不允许依赖此禁止。这意味着 basic.reject
可以重新传递消息或将其发送到死信队列,这使得它对于上面给出的“消息锁定”场景毫无用处。
因此,我们选择实现最简单且有用的方法,即重新入队消息并将其视为全新的消息。这意味着消费者可以再次收到它拒绝的消息。