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