RabbitMQ-在删除队列之前移动消息

时间:2020-02-11 23:50:55

标签: rabbitmq amqp spring-amqp spring-rabbitmq rabbitmq-exchange

使用RabbitMQ 3.7.16spring-amqp 2.2.3.RELEASE

多个客户端使用唯一的路由密钥将消息发布到RabbitMQ服务器中的DataExchange主题交换。在没有任何绑定的情况下,交换将通过AE将所有消息路由到data.queue.generic

当某个客户端(图中的客户端ID为12)发布大量消息时,为了独立于其他客户端扩展其消息的使用量,我们将启动使用者并分配他们只处理其客户ID。为了实现这一点,每个客户端消费者都定义了一个新队列,并使用路由键events.<clientID>将其绑定到主题交换。

因此覆盖范围很广,并且效果很好。

现在,当此客户端的消息速率下降时,我们还希望缩减其使用者,直至删除所有使用者。这样做的目的是将所有这些消息路由到GenericExchange,那里有一群普通的消费者来照顾它们。

问题是,如果我删除data.queue.2(为了删除其绑定,这将导致新邮件路由到GenericExchange),则所有待处理的邮件迷路了。

这是简化的架构视图:

Dead letter messages from expired/deleted queue

让消息在客户端队列中以TTL过期,然后将其以死信的方式发送给通用交换机,这将是一种可接受的解决方案,但是我还需要阻止主题交换机路由 new 消息发送到此“垂死”队列。

那么,我必须采取什么选择来阻止主题交换从将消息路由到客户端队列,而现在没有用户与其连接?

还是要探索另一条路径-如何在已删除/已过期的队列中使邮件死信?

1 个答案:

答案 0 :(得分:1)

如果您的解释似乎表明,如果客户队列是唯一一个具有绑定绑定的队列,则只需删除交换机和队列之间的绑定即可。

从那时起,所有给客户的新消息将通过备用交换(即您的“通用交换”),由通用使用者处理。

对于客户端队列中剩余的消息,您可以使用铲子将它们发送回主题交换,以便将其路由到通用交换。

基于备用交换是内部交换的假设。如果不是内置的,则可以直接用铲子瞄准。

正如与Bogdan讨论的那样,在确保不丢失消息的情况下解决此问题的另一种方法是执行多个步骤:

  • 删除特定队列和交换之间的绑定
  • 具有某种逻辑,可以将剩余消息消耗掉或重新路由到通用队列
    • 如果绑定删除是在使用者断开连接之前发生的,则只有在队列为空时才让最后一个使用者断开连接
    • 如果绑定删除是在上一个使用者断开连接后发生的,则在消息上设置TTL,并将备用交换作为通用交换
  • 根据之前选择的选项,进行一些清理,以消除挥之不去的空队列