RabbitMQ - 在删除队列之前移动消息
RabbitMQ - Move messages before deleting a queue
使用 RabbitMQ 3.7.16
,使用 spring-amqp 2.2.3.RELEASE
。
多个客户端使用唯一的路由键将消息发布到我们 RabbitMQ 服务器中的 DataExchange
主题交换。在没有任何绑定的情况下,交换将通过 AE 将所有消息路由到 data.queue.generic
。
当某个客户端(图中的客户端 ID 1
和 2
)发布大量消息时,为了独立于其他客户端扩展其消息的消费,我们开始使用消费者并分配给他们只处理他们的客户 ID。为此,每个客户端消费者都定义了一个新队列,并使用路由键 events.<clientID>
.
将其绑定到主题交换
所以扩大规模已经涵盖并且效果很好。
现在,当此客户端的消息速率下降时,我们还想缩小其消费者的规模,直至删除所有消费者。目的是将所有这些消息路由到 GenericExchange
,那里有一群通用消费者负责处理它们。
问题是如果我删除data.queue.2
(为了删除它的绑定,这将导致新消息被路由到GenericExchange
)它所有待处理的消息都将丢失。
这是一个简化的架构视图:
让消息在客户端队列中以 TTL 过期是一个可接受的解决方案,然后将它们死信发送到通用交换,但我还需要停止路由主题交换 新 条消息到此 "dying" 队列。
那么,我有什么选择可以阻止主题交换将消息路由到现在没有消费者连接到它的客户端队列?
或者探索另一条路——如何在deleted/expired队列中处理死信消息?
如果正如您的解释所暗示的那样,客户端队列是唯一具有匹配绑定的队列,您可以只删除交换和队列之间的绑定。
从那时起,客户端的所有新消息都将通过备用交换器,您的 "generic exchange",由您的通用消费者处理。
对于客户端队列中剩余的消息,您可以使用铲子将它们发送回主题交换器,以便将它们路由到通用交换器。
这是基于备用交换是内部的假设。如果不是内部的,可以直接用铲子瞄准。
正如与 Bogdan 讨论的那样,解决此问题同时确保不会发生消息丢失的另一种方法是执行多个步骤:
- 解除特定队列与交换器的绑定
- 有一些逻辑可以让剩余的消息被消费或重新路由到通用队列
- 如果绑定删除发生在消费者断开连接之前,则只有在队列为空时才让最后一个消费者断开连接
- 如果绑定删除发生在最后一个消费者断开连接之后,则在具有备用交换的消息上设置 TTL 作为通用交换
- 根据之前选择的选项,有一些清理机制来删除挥之不去的空队列
使用 RabbitMQ 3.7.16
,使用 spring-amqp 2.2.3.RELEASE
。
多个客户端使用唯一的路由键将消息发布到我们 RabbitMQ 服务器中的 DataExchange
主题交换。在没有任何绑定的情况下,交换将通过 AE 将所有消息路由到 data.queue.generic
。
当某个客户端(图中的客户端 ID 1
和 2
)发布大量消息时,为了独立于其他客户端扩展其消息的消费,我们开始使用消费者并分配给他们只处理他们的客户 ID。为此,每个客户端消费者都定义了一个新队列,并使用路由键 events.<clientID>
.
所以扩大规模已经涵盖并且效果很好。
现在,当此客户端的消息速率下降时,我们还想缩小其消费者的规模,直至删除所有消费者。目的是将所有这些消息路由到 GenericExchange
,那里有一群通用消费者负责处理它们。
问题是如果我删除data.queue.2
(为了删除它的绑定,这将导致新消息被路由到GenericExchange
)它所有待处理的消息都将丢失。
这是一个简化的架构视图:
让消息在客户端队列中以 TTL 过期是一个可接受的解决方案,然后将它们死信发送到通用交换,但我还需要停止路由主题交换 新 条消息到此 "dying" 队列。
那么,我有什么选择可以阻止主题交换将消息路由到现在没有消费者连接到它的客户端队列?
或者探索另一条路——如何在deleted/expired队列中处理死信消息?
如果正如您的解释所暗示的那样,客户端队列是唯一具有匹配绑定的队列,您可以只删除交换和队列之间的绑定。
从那时起,客户端的所有新消息都将通过备用交换器,您的 "generic exchange",由您的通用消费者处理。
对于客户端队列中剩余的消息,您可以使用铲子将它们发送回主题交换器,以便将它们路由到通用交换器。
这是基于备用交换是内部的假设。如果不是内部的,可以直接用铲子瞄准。
正如与 Bogdan 讨论的那样,解决此问题同时确保不会发生消息丢失的另一种方法是执行多个步骤:
- 解除特定队列与交换器的绑定
- 有一些逻辑可以让剩余的消息被消费或重新路由到通用队列
- 如果绑定删除发生在消费者断开连接之前,则只有在队列为空时才让最后一个消费者断开连接
- 如果绑定删除发生在最后一个消费者断开连接之后,则在具有备用交换的消息上设置 TTL 作为通用交换
- 根据之前选择的选项,有一些清理机制来删除挥之不去的空队列