1

使用 Spring 和 RabbitMQ,我设置了两个主题交换xdlx两个队列qdlq. q绑定到x并且dlqdlxdlx被配置为死信交换q

当一条消息q被拒绝(取消队列)时,它会成功发送到dlx,然后发送到dlq

现在我使用 shovel-plugin 将死信消息dlq移回q. 只要这次成功处理了消息(ack),这就会成功。

但是,如果这些铲入的消息之一q再次被拒绝,它就会被静默丢弃。我希望它会再次发送到 DLX dlx。是我配置错误还是误解了 DLX 或铲子的概念?

4

2 回答 2

1

我怀疑你正在打这种味道......

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

...因为你在铲。请参阅死信交换

相反,使用 TTL 配置 DLQ,以及导致过期消息路由回原始队列的死信配置。这样,x-death标头会获得两个条目 - 1 个用于原始队列的拒绝,1 个用于 DLQ 的到期。

我猜想,铲子,经纪人认为有一个循环。

于 2018-04-30T13:23:13.127 回答
0

我不认为你的问题是周期。假设您使用 Rabbit 管理 GUI 中的 shovel 插件,这会更改消息的路由键,以显式使用“默认交换”上队列的路由键

https://www.rabbitmq.com/tutorials/amqp-concepts.html#exchange-default

默认交换是代理预先声明的没有名称(空字符串)的直接交换。它有一个特殊的属性,使它对简单的应用程序非常有用:创建的每个队列都会自动绑定到它,并使用与队列名称相同的路由键。

根据您上面的示例,我假设您具有以下设置:

  • q论据 -x-dead-letter-exchange = dlx
  • q捆绑:test_message
  • dlq捆绑:test_message

x因此,如果您使用路由键向 发送消息test_message,这就是它的路由方式:

  1. 出现在q
  2. 消费者在q获取消息,发送 nack,nackdlx使用路由键发送到test_message
  3. dlxdlq配置为绑定到test_message路由键,因此消息出现在dlq

现在,当您使用 shovel 插件dlq将所有消息移入时q,如下所示:

在此处输入图像描述

然后这会向exchange = ''和发送一条消息routing_key = 'q'。同样来自https://www.rabbitmq.com/dlx.html#using-optional-queue-arguments它指出:

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

所以现在发生了这样的事情:

  1. 消息出现qrouting_key = q
  2. 由于没有x-dead-letter-routing-key配置,就dlx用routing_key死信了q
  3. 没有绑定到 q in dlx,消息被丢弃

2个潜在的修复:

  1. 添加另一个绑定dlqrouting_key = q
  2. 手动将队列x-dead-letter-routing-key上的配置q为始终在死信时发送到相同的路由键
于 2020-08-03T22:28:00.897 回答