Dead-lettering dead-lettered RabbitMQ 中的消息

Dead-lettering dead-lettered messages in RabbitMQ

我们这里有:

我想要的是以下内容:如果消费者无法处理来自 EQn 的消息,它会使用 requeue: false 拒绝消息并到达 DLEQn - 也就是说,到 Dead-Letter 交易所的适当 queue。现在,我希望此消息在 DLEQn 上停留一段时间,然后路由回原始 queue EQn 以再次处理。

尽我所能,我无法让 "redelivery to the original queue" 工作。我看到消息位于 DLEQn 中,所有正确的 headers 和路由密钥都完好无损,但在 TTL 到期后它们就消失得无影无踪。

我做错了什么?

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

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

It is possible to form a cycle of dead-letter queues. For instance, this can happen when a queue dead-letters messages to the default exchange without specifiying a dead-letter routing key. Messages in such cycles (i.e. messages that reach the same queue twice) will be dropped if the entire cycle is due to message expiry.

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

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

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

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

Dead-letter queues cycle detected: [<<"TargetQueue">>,<<"RetryQueue">>,<<"TargetQueue">>]

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