以下是我们的内容:
DLE
,旨在成为死信交换E
,即“主要”Exchange EQ1
,...,EQn
)绑定到E
(并使用x-dead-letter-exchange = DLE
初始化),每个队列都有自己的路由密钥。这些队列是从中消耗的队列。EQn
,有DLEQn
(使用x-dead-letter-exchange = E
和x-message-ttl = 5000
初始化),绑定到DLE
,路由密钥与{{1}相同}}。这些队列不正在从我想要的是以下内容:如果消费者无法处理来自EQn
的消息,则会将消息与EQn
无关,并且它会转到requeue: false
- 即Dead-Letter Exchange上的适当队列。现在,我希望此消息在DLEQn
上停留一段时间,然后再路由回原始队列DLEQn
以再次处理。
尽我所能,我无法将“重新传送到原始队列”工作。我看到消息位于EQn
,所有正确的标题和路由密钥完好无损,但在TTL过期后,它们就会消失得无影无踪。
我在这里做错了什么?
答案 0 :(得分:7)
是的,你可以这样做。我们目前在生产中这样做,效果很好。代码太长,不能包含在这里,但我将向您展示我创建的代表该过程的图表。基本思路是第一个DLX有一个TTL,一旦TTL到期,消息就会进入第二个队列重新发送回原始状态。
答案 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
那里得到了最后的启示。