使用蓝绿部署策略升级 RabbitMQ
蓝绿部署是一种迁移技术,也可以用作一种升级策略。其核心思想是建立一个新环境(“绿色”环境),并在准备就绪时切换到该环境。这种“升级”不是在原有环境上直接进行的(即非“就地”升级),应用程序只是切换到一个不同的环境,该环境可能运行着不同的版本,也可能在其他方面有所不同。
同样的方法可以用于迁移到新的操作系统或新硬件,同时保持 RabbitMQ 版本不变;或者用于从无法直接升级到目标系列的旧版本进行升级,例如从 3.12.x 升级到 4.0.x,或者从启用了 Khepri 的 3.13.x 集群升级到 4.0.x。
迁移完成后,旧的(“蓝色”)集群将被弃用(关闭、删除)。为了简化切换过程,可以使用联合队列 (federated queues) 将“蓝色”集群中已排队的积压消息传输到“绿色”集群。
rabbitmqadmin v2 包含了一些专门为简化蓝绿部署迁移而设计的命令,特别是针对从 RabbitMQ 3.13.x 到 4.x 的迁移。
准备“绿色”集群
部署全新的“绿色”集群后,需要执行以下两个步骤:
- 导入定义,例如交换机、队列、绑定;
- 配置联合机制 (federation) 以便后续转储消息。
导入定义
定义导出/导入的步骤详见备份指南。“蓝色”是源集群,“绿色”是目标集群。
配置队列联合
RabbitMQ Federation 插件可以轻松地将消费者从“蓝色”迁移到“绿色”,而不会中断消息消费或丢失消息。联合队列的原理是:只要“蓝色”集群中没有消费者,连接到“绿色”集群的消费者就会获取发布到“蓝色”集群的消息(本地消费者具有优先权)。
以下是联合所有队列的示例。在此示例中,“绿色”集群是上游,“蓝色”集群是下游。
首先在“蓝色”集群上定义上游,并将其指向“绿色”集群。
- 使用 rabbitmqctl (bash)
- 使用 rabbitmqadmin (bash)
- 使用 rabbitmqctl (PowerShell)
- 使用 PowerShell 的 rabbitmqadmin.exe
rabbitmqctl set_parameter federation-upstream blue \
'{"uri":"amqp://node-in-blue-cluster"}'
rabbitmqadmin federation declare_upstream_for_queues --name blue \
--uri "amqp://node-in-blue-cluster"
rabbitmqctl.bat set_parameter federation-upstream blue ^
'"{""uri"":""amqp://node-in-blue-cluster""}"'
rabbitmqadmin.exe federation declare_upstream_for_queues --name blue ^
--uri "amqp://node-in-blue-cluster"
然后定义一个或多个策略 (policy),统一匹配所有队列,并将 `blue` 配置为上游。
- 使用 rabbitmqctl (bash)
- 使用 rabbitmqadmin (bash)
- 使用 rabbitmqctl (PowerShell)
- 使用 PowerShell 的 rabbitmqadmin.exe
rabbitmqctl set_policy --apply-to queues blue ".*" \
'{"federation-upstream":"blue"}'
rabbitmqadmin policies declare \
--name "blue" \
--pattern ".*" \
--definition '{"federation-upstream":"blue"}' \
--apply-to "queues"
rabbitmqctl.bat set_policy --apply-to queues blue ".*" ^
'"{""federation-upstream"":""blue""}"'
rabbitmqadmin.exe policies declare ^
--name "blue" ^
--pattern ".*" ^
--definition "{""federation-upstream"":""blue""}" ^
--apply-to "queues"
上述示例进行了极大的简化。
在实践中,有些队列可能已经被某个策略匹配,而另一些则没有。
rabbitmqadmin v2 提供了一组命令,允许操作员:
- 修补 (Patch)(部分更新)策略
- 临时覆盖现有策略,以包含开启队列联合功能的键值
- 声明一个覆盖策略 (blanket policy) 以匹配所有其他队列,从而为它们启用联合功能
结合使用这些功能,可以为集群间的所有队列启用队列联合,无论它们是否已经拥有适用的策略。
迁移消费者
现在您可以将消费者切换到新的“绿色”集群。为此,请根据您的架构重新配置负载均衡器或消费者应用程序。升级指南涵盖了一些使客户端能够跨节点切换的功能。
此时,您的生产者仍在向“蓝色”集群发布消息,但得益于 federation 插件,消息会被传输给连接到“绿色”集群的消费者。
转储消息
下一步是将生产者也切换到“绿色”集群。然而,“蓝色”集群中可能仍有积压的消息。对于在“蓝色”集群中不再有消费者的队列,队列联合链接会将消息转移到“绿色”集群及其消费者。
如果积压量较大,在“绿色”集群上使用 Shovel 将所有剩余消息移至“蓝色”集群也是一个值得考虑的选择。
这需要为每个有积压的队列执行类似以下的操作:
- 使用 rabbitmqctl (bash)
- 使用 rabbitmqadmin (bash)
- 使用 rabbitmqctl (PowerShell)
- 使用 PowerShell 的 rabbitmqadmin.exe
rabbitmqctl set_parameter shovel shovel-blue-to-green-queue1 \
'{"src-protocol": "amqp091", "src-uri": "amqp://node-in-blue-cluster", "src-queue": "queue1", "dest-protocol": "amqp091", "dest-uri": "amqp://", "dest-queue": "queue1"}'
rabbitmqadmin shovels declare_amqp091 --name shovel-blue-to-green-queue1 \
--source-uri "amqp://node-in-blue-cluster" \
--destination-uri "amqp://" \
--source-queue "queue1" \
--destination-queue "queue1"
rabbitmqctl.bat set_parameter shovel shovel-blue-to-green-queue1 ^
"{""src-protocol"": ""amqp091"", ""src-uri"": ""amqp://node-in-blue-cluster"", ""src-queue"": ""queue1"", ^
""dest-protocol"": ""amqp091"", ""dest-uri"": ""amqp://"", ""dest-queue"": ""queue1""}"
rabbitmqadmin.exe shovels declare_amqp091 --name shovel-blue-to-green-queue1 ^
--source-uri "amqp://node-in-blue-cluster" ^
--destination-uri "amqp://" ^
--source-queue "queue1" ^
--destination-queue "queue1"
请注意,同时使用 Shovel 和队列联合会并发移动消息,这意味着消息的顺序可能与源队列中的顺序不一致。
迁移生产者
一旦“蓝色”集群中的队列几乎清空,您就可以停止生产者了。如果您对消息顺序有要求,则应多等待片刻,以便 federation 或 Shovel 插件完成“蓝色”集群队列的转储。
当队列为空时,像迁移消费者那样重新配置您的生产者并重新启动。此时,所有内容已迁移至“绿色”集群。
弃用“蓝色”集群
现在您可以自由地关闭“蓝色”集群中的节点了。
实际案例
来自 Pivotal 的 Dan Baskette、Gareth Smith 和 Claude Devarenne 发表了一篇文章,介绍了这种生产者和消费者均为 CloudFoundry 应用程序的方法。该文章非常详尽,并使用图表描述了该过程。他们还制作了一个视频来演示其实际操作。
本指南的灵感来源于他们的杰出工作。