第一次后 RabbitMQ 消息没有发送到死信

RabbitMQ Messages not getting sent to dead letter after first time

我们已将 queue 配置为将死信消息(特别是 nack'ed 消息)发送到死信交换器,该交换器按其原始主题将它们路由到单个死信 queue秒。这一切都很好,当消息被拒绝时,它们会被发送到正确的死信 queue.

当我们将这些消息从 dlq 铲回到正常 queue 时,问题就来了,在那里它们再次被拒绝。出于某种原因,第二次通过它们就消失了,而不是被送回死信交换。

我假设正在进行某种“循环消息路由”检测,但找不到类似的东西。第二次检查消息给出了所有预期的 headers 所以我不确定这样的事情甚至可以基于什么。任何关于下一步去哪里或兔子是否有这样的东西的建议都将不胜感激!

如果有必要,我们的消费者在python中使用鼠兔库进行通信。

假设您有以下 queues/exchanges:

交流

  • global_exchange - 你的主要交易所
  • DLX - 另一个专门针对 dead-letters
  • 的交易所

队列

  • queue - global_exchange 内的主队列。包含 arguments=x-dead-letter-exchange: 'DLX'
  • queue.dlq - 您的 dead-letter 队列在 global_exchange

绑定

  • test_message routing_key 绑定到 queuequeue.dlq

最后,我假设您正在像这样使用 queue.dlq 管理页面上的 shovel 插件,将消息从 queue.dlq 移动到 queue:

以下是当您将 test_message 作为 routing_key 发送到 global_exchange 的消息时路由的工作方式:

  1. 消息从 test_message
  2. 上的绑定到达 queue
  3. 消费者 nack 的(nack 或 reject 无关紧要)消息,因此 dead-lettering it
  4. x-dead-letter-exchange参数用routing_key= test_message
  5. 发送到DLX
  6. 由于 queue.dlq 绑定,该队列接收消息

当您使用该特定管理面板将消息铲回 queue 时,它会使用 default exchange。这 更改了路由键 。所以第二次收到的消息有一个路由键,它等于你要铲入的队列的名称。

由于您没有配置 x-dead-letter-routing-key,消息被 dead-lettered 到 current routing key:

If this is not set, the message's own routing keys will be used.

所以在铲子的结果上,是这样路由的:

  1. 消息出现在 queuerouting_key = queue
  2. 由于没有配置 x-dead-letter-routing-key,它死信给 DLXrouting_key = queue
  3. 未绑定到 DLX 中的 queue,消息已丢弃

有 2 种可能的解决方法:

  1. queue.dlq 的另一个绑定添加到 routing_key = queue
  2. 手动配置 queue 上的 x-dead-letter-routing-key 始终发送到 dead-letter 上的相同路由键,无论最初发送给它的消息是什么,并确保有绑定到它在 DLX
  3. 之内