RabbitMQ 消息第一次发送后未发送至死信

Ken*_*all 3 rabbitmq pika rabbitmq-shovel rabbitmq-exchange

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

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

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

如果有必要,我们的消费者是用 python 编写的,使用 pika 库进行通信。

phi*_*rse 5

假设您有以下队列/交换器:

交流

  • global_exchange- 您的主要交易所
  • DLX- 另一种专门针对死信的交换

队列

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

绑定

  • test_messagerouting_key 绑定到queuequeue.dlq

最后,我假设您正在使用queue.dlq管理页面上的 shovel 插件,如下所示,将消息从 移动queue.dlqqueue

在此输入图像描述

test_message以下是当您使用作为routing_keyto the发送消息时路由的工作原理global_exchange

  1. queue消息从绑定进入test_message
  2. 消费者 nack(nack 或拒绝无关紧要)消息,从而将其置为死信
  3. 参数x-dead-letter-exchange将其发送到DLXwithrouting_key= test_message
  4. 由于queue.dlq绑定,该队列接收消息

当您使用特定的管理面板将消息铲回时queue,它会使用默认交换。这会更改路由键。因此,第二次收到的消息的路由键等于您要放入的队列的名称。

由于您没有配置,因此该消息对于当前路由键x-dead-letter-routing-key来说是死信的:

如果未设置,则将使用消息自己的路由密钥。

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

  1. 消息出现queuerouting_key = queue
  2. 由于没有配置 x-dead-letter-routing-key,因此它是DLX死信routing_key = queue
  3. 没有绑定到queuein DLX,消息被丢弃

有 2 个潜在的解决方法:

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