RabbitMQ中的死字母死信

时间:2015-02-20 14:31:55

标签: rabbitmq dead-letter

以下是我们的内容:

  • 主题交换DLE,旨在成为死信交换
  • 主题交换E,即“主要”Exchange
  • 多个队列(EQ1,...,EQn)绑定到E(并使用x-dead-letter-exchange = DLE初始化),每个队列都有自己的路由密钥。这些队列是从中消耗的队列。
  • 对于每个EQn,有DLEQn(使用x-dead-letter-exchange = Ex-message-ttl = 5000初始化),绑定到DLE,路由密钥与{{1}相同}}。这些队列正在从
  • 中消耗

我想要的是以下内容:如果消费者无法处理来自EQn的消息,则会将消息与EQn无关,并且它会转到requeue: false - 即Dead-Letter Exchange上的适当队列。现在,我希望此消息在DLEQn上停留一段时间,然后再路由回原始队列DLEQn以再次处理。

尽我所能,我无法将“重新传送到原始队列”工作。我看到消息位于EQn,所有正确的标题和路由密钥完好无损,但在TTL过期后,它们就会消失得无影无踪。

我在这里做错了什么?

3 个答案:

答案 0 :(得分:7)

是的,你可以这样做。我们目前在生产中这样做,效果很好。代码太长,不能包含在这里,但我将向您展示我创建的代表该过程的图表。基本思路是第一个DLX有一个TTL,一旦TTL到期,消息就会进入第二个队列重新发送回原始状态。

enter image description here

答案 1 :(得分:4)

RabbitMQ检测到消息流循环(E - > DLE - > E - > DLE ...)并静默删除消息:

来自DLX manual (Routing Dead-Lettered Messages section)

  

可以形成死信队列的循环。例如,当队列在没有指定死信路由密钥的情况下将消息写入默认交换时,就会发生这种情况。如果整个周期是由于消息过期,那么这些周期中的消息(即两次到达同一队列的消息)将被删除

答案 2 :(得分:1)

那篇文章很老,但是花了我几天时间才找到类似问题的解决方案,所以我认为我应该在这里分享我的解决方案。

我们在TargetQueue中接收到消息,这些消息可能被使用者弄乱了(没有TTL !!!,绑定到TargetExchange)。 TargetQueue定义了一个DLX(RetryExchange),它又绑定了一个相应的队列(RetryQueue,TTL为60秒,TargetExchange定义为DLX)。

因此,如果使用者从TargetQueue收到一条消息,则该消息将在RetryQueue中排队,并且由于TTL,该消息将再次被否决并在原始TargetQueue中重新排队。提示是,TargetQueue可能未定义TTL,否则RabbitMQ日志中将显示以下消息:

  

检测到死信队列周期:[<<“ TargetQueue” >>,<<“ RetryQueue” >>,<<“ TargetQueue” >>]

因此最终,该解决方案非常简单(并且只需要一个消费者)。我从https://medium.com/@igkuz/ruby-retry-scheduled-tasks-with-dead-letter-exchange-in-rabbitmq-9e38aa39089b

那里得到了最后的启示。