队列绑定可以在运行时添加和删除,而不会对客户端产生任何影响,除非客户端手动修改绑定。因此,如果您的问题只是关于绑定的问题,只需通过 CLI 或 Web 管理面板更改它们并跳过下面写的内容。
进行向后不兼容的更改是一个常见问题,尤其是在异构环境中,尤其是当多个应用程序尝试以自己的方式(使用其特定设置)声明同一实体时。没有简单的方法可以在多个应用程序中同时更改队列声明,这在很大程度上取决于整个工作流程的组织方式、应用程序的重要性、基础架构等。
快速而肮脏的方式:
虽然发布者不处理队列声明和绑定(至少他们不应该这样做),但您可以专注于消费者。在 try-except 块中包装队列声明可能是快速而肮脏的选择。此外,大多数项目,甚至许多项目都可以在短暂的停机时间内幸存下来,因此您可以在一个 shell 中阻止 rabbitmq 用户,根据需要更改队列(创建新的并让您的消费者使用它而不是旧的),然后取消阻止用户并让消费者像之前(你的工人在主管或监控之下,对吧?)。然后手动将消息从旧队列迁移到新队列。
快速安全的解决方案:
这有点棘手,并且基于如何将消息从一个队列迁移到单个 vhost 中的另一个队列。整个解决方案在单个 vhost 中工作,但您要修改的每个队列都需要额外的队列。在源队列上设置死信交换并将其指向将过期消息路由到新目标队列。然后将Per-Queue Message TTL应用到源队列,设置x-message-ttl=0
(设置为最小值,请参阅No Queuing at all关于立即交货的说明)。这两个操作都可以通过 CLI 或管理面板完成,并且可以在已声明的队列上完成。通过这种方式,您的发布者可以像往常一样发布消息,甚至老消费者也可以首次按预期工作,但同时新消费者可以从新队列中消费,该队列可以手动或以其他方式使用新参数预先声明。
请注意,在具有大量消息数和大量消息流的队列上,存在满足流控制限制的一些风险,尤其是如果您的服务器几乎利用了所有资源。
更复杂但更安全的方法(对于整个消息工作流逻辑发生变化的情况):
对应用程序进行所有必要的更改并与现有代码库并行运行新代码库,但在不同的 RabbitMQ 虚拟主机上(甚至使用单独的服务器,这取决于您的应用程序负载和硬件)。实际上,可能可以在同一个虚拟主机上运行,但更改交换和队列名称,但它甚至听起来并不好,即使是书面形式也有异味。设置新应用程序后,将它们与旧应用程序切换并运行消息从旧队列迁移到新应用程序(或让旧系统清空队列)。它保证以最少的停机时间进行无缝迁移。如果您的部署自动化,整个过程将不会花费太多精力。
PS:在以上任何情况下,如果可以的话,让老消费者清空队列,这样你就不需要手动迁移消息了。
更新:
您可能会发现非常有用的Shovel 插件,尤其是Dynamic Shovel,用于在交换和队列之间移动消息,甚至在不同的虚拟主机和服务器之间移动消息。这是在队列/交换之间迁移消息的最快和最安全的方式。