6

这是我们在这里的:

  • 主题交换DLE,旨在成为死信交换
  • 主题交换E,这是“主要”交换
  • 几个队列 ( EQ1, ..., EQn) 绑定到E(并用 初始化x-dead-letter-exchange = DLE),每个队列都有自己的 Routing Key。这些队列是从中消费的。
  • 对于每个EQn,都有一个(用和DLEQn初始化),绑定到与 相同的路由键。这些队列没有被消耗x-dead-letter-exchange = Ex-message-ttl = 5000DLEEQn

我想要的是以下内容:如果消费者无法处理来自EQn的消息,它会使用 Nacks 消息requeue: false并到达DLEQn- 也就是说,到达死信交换上的适当队列。现在,我希望这条消息在队列中DLEQn停留一段时间,然后被路由回原始队列EQn以再次处理。

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

我在这里做错了什么?

4

3 回答 3

9

是的,你可以这样做。我们目前正在生产中这样做,效果很好。代码太长,无法在此处包含,但我将向您展示我创建的代表流程的图表。基本思想是第一个 DLX 有一个 TTL,一旦 TTL 过期,消息就会进入第二个队列,然后重新发送回原来的队列。

在此处输入图像描述

于 2015-02-20T17:35:56.203 回答
5

RabbitMQ 检测消息流循环(E -> DLE -> E -> DLE ...)并静默丢弃消息:

来自DLX 手册(路由死信消息部分)

有可能形成死信队列的循环。例如,当队列死信消息发送到默认交换时,可能会发生这种情况,而没有指定死信路由键。如果整个周期是由于消息到期而导致的,则此类周期中的消息(即两次到达同一队列的消息)将被丢弃。

于 2015-02-20T16:40:07.990 回答
3

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

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

因此,如果消费者对来自 TargetQueue 的消息进行 nacks,它会在 RetryQueue 中排队,并且由于 TTL,消息会再次被 nack 并在原始 TargetQueue 中重新排队。线索是,TargetQueue 可能没有定义 TTL,否则 RabbitMQ 日志中会出现这样的消息:

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

所以最终解决方案非常简单(并且只需要一个消费者)。我从https://medium.com/@igkuz/ruby-retry-scheduled-tasks-with-dead-letter-exchange-in-rabbitmq-9e38aa39089b获得了最后的灵感

于 2019-09-30T13:53:02.093 回答