RabbitMQ在生产系统上更改队列参数

 可乐加冰2502937787 发布于 2022-12-28 15:47

我在面向服务的体系结构中使用RabbitMQ作为消息队列,其中许多单独的Web服务发布绑定到RabbitMQ队列的消息.这些队列由各种消费者订阅,这些消费者执行后台工作; RabbitMQ的一个漂亮的香草用例.

现在我想改变一些队列参数(具体来说,我想将队列绑定到一个带有某个路由键的新死信交换).我的问题是,由于几个原因,在生产系统上进行这种改变是有问题的.

对于我来说,转换到这些新队列的最佳方式是什么,而不会丢失生产系统中的消息?

我已经考虑了从版本化队列名称到使用新设置创建新vhost以进行所有更改的所有内容.

以下是我面临的一些问题:

    因为RabbitMQ队列是幂等的,所以不同的Web服务在发布之前已经声明了队列(如果它们尚不存在).更改队列参数(但保持相同的路由键)后,队列声明失败,RabbitMQ关闭通道.

    我想在更改队列时不丢失消息(这里我打算订阅一个保存消息然后重新发布到新队列的独占消费者).

    不同出版商与消费者群体之间的一般协调(或者更好的是,避免需要协调他们的方式).

pinepain.. 19

除非客户端手动修改绑定,否则可以在运行时添加和删除队列绑定,而不会对客户端产生任何影响.因此,如果您只关于绑定的问题只是通过CLI或Web管理面板进行更改,请跳过下面的内容.

进行后向不兼容的更改是一个常见的问题,尤其是在异构环境中,尤其是当多个应用程序尝试以自己的方式(使用其特定设置)声明相同的实体时.在多个应用程序中,没有简单的方法可以同时更改队列声明,这在很大程度上取决于整个工作流程的组织方式,应用程序的关键程度,基础架构的内容等.

快速而肮脏的方式:

虽然发布者不处理队列声明和绑定(至少他们不应该这样做),但您可以专注于消费者.在try-except块中包装队列声明可能是快速而肮脏的选择.此外,大多数项目,甚至众多项目都可以在较短的停机时间内存活,因此您可以在一个shell中阻止rabbitmq用户,根据需要更改队列(创建新的并使您的消费者使用它而不是旧的),然后取消阻止用户并让消费者像之前(你的工人在主管或监督下,对吧?).然后手动将消息从旧队列迁移到新队列.

快速安全的解决方案:

是有点棘手,基于黑客如何在单个vhost内将消息从一个队列迁移到另一个队列.整个解决方案在单个vhost中运行,但是对于要修改的每个队列都需要额外的队列.在源队列上设置死信交换并指向它以将过期的消息路由到新的目标队列.然后将Per-Queue Message TTL应用于源队列,设置x-message-ttl=0(对于它的最小值,请参阅关于立即传递的所有注释).这两个操作都可以通过CLI或管理面板完成,并且可以在已声明的队列中完成.通过这种方式,您的发布者可以像往常一样发布消息,甚至老消费者也可以第一次按预期工作,但同时新消费者可以使用新队列消费,新队列可以手动或以其他方式使用新的args预先声明.

请注意,在具有大消息数和大量消息流的队列上,存在一些风险以满足流量控制限制,尤其是在您的服务器几乎使用所有资源的情况下.

更复杂但更安全的方法(对于整个消息工作流逻辑发生变化的情况):

对应用程序进行所有必要的更改并与现有代码库并行运行新代码库,但在不同的RabbitMQ vhost上(或者甚至使用单独的服务器,它取决于您的应用程序负载和硬件).实际上,有可能在同一个虚拟主机上运行,​​但更改交换和队列名称,但它甚至听起来不好,甚至以书面形式闻起来.设置新应用程序后,使用旧应用程序切换它们并运行从旧队列到新队列的消息迁移(或者让旧系统清空队列).它可以保证无缝迁移,最大限度地减少停机时间.如果您的部署自动化,整个过程不会花费太多精力.

PS:无论如何,如果可以的话,让老消费者排空队列,这样你就不需要手动迁移消息了.

更新:

您可能会发现非常有用的Shovel插件,尤其是动态Shovels,用于在交换和队列之间移动消息,甚至可以在不同的vhost和服务器之间移动消息.这是在队列/交换之间迁移消息的最快速,最安全的方法.

1 个回答
  • 除非客户端手动修改绑定,否则可以在运行时添加和删除队列绑定,而不会对客户端产生任何影响.因此,如果您只关于绑定的问题只是通过CLI或Web管理面板进行更改,请跳过下面的内容.

    进行后向不兼容的更改是一个常见的问题,尤其是在异构环境中,尤其是当多个应用程序尝试以自己的方式(使用其特定设置)声明相同的实体时.在多个应用程序中,没有简单的方法可以同时更改队列声明,这在很大程度上取决于整个工作流程的组织方式,应用程序的关键程度,基础架构的内容等.

    快速而肮脏的方式:

    虽然发布者不处理队列声明和绑定(至少他们不应该这样做),但您可以专注于消费者.在try-except块中包装队列声明可能是快速而肮脏的选择.此外,大多数项目,甚至众多项目都可以在较短的停机时间内存活,因此您可以在一个shell中阻止rabbitmq用户,根据需要更改队列(创建新的并使您的消费者使用它而不是旧的),然后取消阻止用户并让消费者像之前(你的工人在主管或监督下,对吧?).然后手动将消息从旧队列迁移到新队列.

    快速安全的解决方案:

    是有点棘手,基于黑客如何在单个vhost内将消息从一个队列迁移到另一个队列.整个解决方案在单个vhost中运行,但是对于要修改的每个队列都需要额外的队列.在源队列上设置死信交换并指向它以将过期的消息路由到新的目标队列.然后将Per-Queue Message TTL应用于源队列,设置x-message-ttl=0(对于它的最小值,请参阅关于立即传递的所有注释).这两个操作都可以通过CLI或管理面板完成,并且可以在已声明的队列中完成.通过这种方式,您的发布者可以像往常一样发布消息,甚至老消费者也可以第一次按预期工作,但同时新消费者可以使用新队列消费,新队列可以手动或以其他方式使用新的args预先声明.

    请注意,在具有大消息数和大量消息流的队列上,存在一些风险以满足流量控制限制,尤其是在您的服务器几乎使用所有资源的情况下.

    更复杂但更安全的方法(对于整个消息工作流逻辑发生变化的情况):

    对应用程序进行所有必要的更改并与现有代码库并行运行新代码库,但在不同的RabbitMQ vhost上(或者甚至使用单独的服务器,它取决于您的应用程序负载和硬件).实际上,有可能在同一个虚拟主机上运行,​​但更改交换和队列名称,但它甚至听起来不好,甚至以书面形式闻起来.设置新应用程序后,使用旧应用程序切换它们并运行从旧队列到新队列的消息迁移(或者让旧系统清空队列).它可以保证无缝迁移,最大限度地减少停机时间.如果您的部署自动化,整个过程不会花费太多精力.

    PS:无论如何,如果可以的话,让老消费者排空队列,这样你就不需要手动迁移消息了.

    更新:

    您可能会发现非常有用的Shovel插件,尤其是动态Shovels,用于在交换和队列之间移动消息,甚至可以在不同的vhost和服务器之间移动消息.这是在队列/交换之间迁移消息的最快速,最安全的方法.

    2022-12-28 15:52 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有