好了,我让您走了……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 可能会重新投递消息或将其发送到死信队列,这使得它对于前面提到的“消息锁定”场景无效。
因此,我们选择实现最简单但有用的功能,即重新排队消息,并将其视为一条全新的消息。这意味着消费者可以再次接收到它之前拒绝过的消息。