好的,先到这里 ... 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
可以重新传递消息或将其死信化,这使其对于上面给出的“消息锁”场景毫无用处。
因此,我们选择实现最有用的最简单的事情,即将消息重新入队并将其视为完全新的消息。 这意味着消费者可以再次收到它拒绝的消息。