1. 项目背景
中级篇前面把 quorum、TLS、联邦都铺上了。领导下一句是:「4.3 升 4.4,停多久?」有人准备三台一起换镜像;有人听过 Feature Flags,以为enable_all能当后悔药;有人想跳过 4.3 直接从很老的 3.13 空降。升级窗口是运维最高风险:混合版本集群能力收缩、新 flags一旦启用不能关闭(源码写明 currently no way to disable)、支付 Leader 若全堆在正升级那台会双倍抖动。
4.x 系列必须按支持的路径原地升:4.2→4.3→4.4,不要跳大版本。rabbit_release_series给 CLI 留了支持状态接口。混合版本时,未升级节点必须能理解已启用的 flags,否则加不进群或行为分裂。滚动顺序与第 17 章 drain、第 19 章「多数派+1 才下线」绑在一起:rabbit_upgrade_preparation:await_online_quorum_plus_one/1就是等「再少一台仍够票」。
蓝绿是另一条路:新集群并列,Shovel/联邦引流(第 21 章),切流量而不是改同一套 Erlang 节点。适合跨大版本、或磁盘布局要推倒重来。代价是双倍资源和切流对账。推广中台默认同系列滚动;跨系列或存储改造走蓝绿。
痛点:
三台一起停 → 支付无多数派 先 enable 新 flag 再升级旧节点 → 旧节点拒加入 跳版本 → 官方不支持的路径 drain 了但 Leader 没走 → 升级那台仍扛写 蓝绿双写却无对账 → 两边订单对不上本章交付 Runbook 正文,测试把它变成检查单。不在生产第一次练手。
2. 项目设计
小胖把手机系统更新截图甩出来:「夜间自动更新,早上就能用。」
小胖:这不就是打补丁吗?三台轮流重启不就滚动了?Flags 听着像游戏里的开关,开错再关。蓝绿不就是再买三台,有钱任性?为啥还要等 quorum plus one,听着像数学题。
大师:手机是一台,MQ 是投票委员会。轮流重启若不等「还剩足够票」,你会在第二台升级时只剩一台活着,支付 Confirm 全失败。Flags 不是游戏开关:rabbit_feature_flags写明启用后当前不能关,实验 flag 还不会被enable_all误开。蓝绿有钱也要 Shovel 对账和切流窗口,不是复印三台就高可用。await_online_quorum_plus_one是「再摘一台,Khepri/quorum/stream 协调者仍安全」的等待,不是心算。
技术映射:Feature Flag = 集群级不可逆能力开关;drain = 维护模式;quorum+1 = 允许再少一个节点。
小白:稳定与 experimental 怎么列?混合版本能开哪些?4.3 的cluster_partition_handling失效会不会在升级后突然变行为?滚动时应用连 LB 会不会打到 draining 节点?新 flags 什么时候 enable?蓝绿双写和第 21 章 Shovel 如何选?失败怎么回滚镜像?
大师:rabbitmqctl list_feature_flags看 state=enabled/disabled/unavailable。experimental 默认不开。混合版本以最老节点能提供的为准,新能力等全部升级后再 enable。4.3 起分区策略本来就是灰框,升 4.4 不会「突然变好」,也不要指望它。LB 健康检查必须认 drain(第 17 章),否则支付打到已停监听的节点。新 flags全部节点新版本且稳定后再 enable,不要边升边开。切流:同系列滚动;跨系列或存储重做蓝绿+Shovel。回滚:未 enable 新 flag 前,理论上可把节点镜像退回,已 enable 则禁止退回旧二进制。备份 definitions 与数据目录是前置,不是回滚本身。
小胖:Runbook 我记成口令:查版本与 flags → 备份 → 一台 drain → 等 plus one → 换镜像启动 → revive → 下一台 → 全员新版本后 enable flags → 回归。蓝绿另附一页。
大师:再加:升级前rebalance不是必须,但要看 Leader 是否全在第一台;升级后可再平衡。支付路径回归含杀一台仍 Confirm(第 19 章),不只 ping。
技术映射:
enable_feature_flag集群广播;rabbit_prelaunch_feature_flags在 VM 起来前对账磁盘上的 flags。
小白:插件版本与核心不一致怎么办?Khepri 已是默认,还要当 flag 看吗?stream coordinator 也在 plus one 检查里吗?
大师:插件跟镜像走,不要混配。Khepri 在 4.4 默认已启用,list 里确认khepri_dbenabled。await_online_quorum_plus_one把rabbit_stream_coordinator与(Khepri 开启时)rabbitmq_metadata当关键组件,少票就继续等。不要在等的时候强行下一台。
小胖:实验室用三容器改标签模拟滚动,不真的跨小版本也可以走一遍 drain+plus one+回归,正式升 4.3→4.4 在预发做。检查单进 Git。
3. 项目实战
3.1 环境准备
三节点 4.4 实验室(第 17 章)。预发才动真实 4.3。本场把 Runbook 命令跑通,升级包用「重启镜像」代替换版本,重点练顺序与门禁。
dockerexecrabbit1 rabbitmqctl cluster_statusdockerexecrabbit1 rabbitmqctl list_feature_flagsdockerexecrabbit1 rabbitmq-diagnostics--silentcheck_if_node_is_quorum_ready||true运行结果:三人 running;记下 flags 表。
坑:unavailable 的 flag 不要 enable。
坑:实验 flag 不要enable_all。
3.2 步骤一:升级前门禁
步骤目标:没有红灯、没有不可用节点、definitions 已导出。
# promo-mq/ch26/preflight.shdockerexecrabbit1 rabbitmq-diagnostics-qpingdockerexecrabbit1 rabbitmq-diagnostics-qalarmsdockerexecrabbit1 rabbitmqctl export_definitions /tmp/defs.jsondockercprabbit1:/tmp/defs.json ./backup-defs-$(date+%Y%m%d).jsondockerexecrabbit1 rabbitmqctl await_online_quorum_plus_one--timeout120await_online_quorum_plus_one对应rabbit_upgrade_preparation。超时不要下一台。
运行结果:alarms 空;plus one 成功。
坑:两节点集群 plus one 会失败,支付本就不该两节点。
坑:definitions 含密码,备份进密钥库。
3.3 步骤二:单节点维护与「升级」
# 选 Leader 最少的节点,或先 rebalancedockerexecrabbit2 rabbitmq-upgrade drain# LB 摘 rabbit2# 此处生产:换包/换镜像dockerrestart rabbit2dockerexecrabbit2 rabbitmq-diagnostics-qpingdockerexecrabbit2 rabbitmq-upgrade revive运行结果:另两台仍可发布支付测试消息。
坑:drain 后仍有流量=LB 没摘。
坑:restart 不是down -v。
3.4 步骤三:循环至第三台
对 rabbit3、rabbit1 重复步骤二。每台之间再跑 plus one。全部 ping 与cluster_status版本一致后,才进入 flags。
3.5 步骤四:启用新 Feature Flags
dockerexecrabbit1 rabbitmqctl enable_feature_flag all# 仍会跳过 experimental# 或逐个 enable 文档要求的稳定项dockerexecrabbit1 rabbitmqctl list_feature_flags源码:enable_all/0跳过 experimental;启用不可逆。
运行结果:目标 flag enabled。
坑:混合版本时 enable 失败或把旧节点踢出语义——所以必须全员新版本。
坑:不要为「试试」打开 experimental。
3.6 步骤五:回归用例(最小集)
| 项 | 命令/动作 | 期望 |
|---|---|---|
| 健康 | ping/alarms | 通过 |
| 支付 Confirm | 第 19 章脚本 | 成功 |
| 杀一台 | stop 非全部 | 仍 Confirm |
| 联邦 | 若有第 21 章 | status running |
| TLS | 第 25 章 | 5671 可连 |
通过才宣布升级完成。Leader 不均可用rabbitmq-queues rebalance all(窗口内)。
3.7 步骤六:蓝绿对照(文档+选做)
新集群 B 起 4.4,Shovel 从 A 拉历史(on-confirm+冻结写入),应用切 LB 到 B,观察双深度。联邦适合营销 Fanout 而不是支付法定副本。双写要业务幂等,默认不推荐支付。
运行结果:迁完条数对账(第 21 章 TC)。
坑:未冻结写入就delete-after queue-length。
3.8 完整代码清单
promo-mq/ch26/ preflight.sh drain-upgrade-one.sh RUNBOOK.md column/samples/ch26/RUNBOOK.md即本节步骤,签字栏:运维/测试/开发。
3.9 测试验证
| 编号 | 名称 | 期望 |
|---|---|---|
| TC-CH26-01 | preflight | plus one 0 |
| TC-CH26-02 | drain 一台 | 另两台支付成功 |
| TC-CH26-03 | 全员滚动后 | 版本一致 |
| TC-CH26-04 | enable flags | 无 unavailable |
| TC-CH26-05 | 回归表 | 全绿 |
| TC-CH26-06 | 禁止跳版本 | 文档门禁 |
值班检查单:升级窗口禁发版、禁改 Policy、禁 enable experimental;LB 与 drain 联动;备份当天有效。混合版本停留不超过文档建议的短窗口,不要「先升一台观察一周」却仍开新 flag。Runbook 超时(plus one 120s)失败则停止滚动,扩容或修节点,禁止跳过等待。回滚决策树贴在 RUNBOOK 末:未开新 flag 可退镜像;已开则只能向前修。把list_feature_flags升级前后 diff 进工单。测试在窗口内只跑回归表,不做第 14 章拧水位。开发待命看 Confirm 分桶,超时当失败重试,不得改 SENT。
预发至少完整走一遍真实小版本升,实验室「只重启」不能替代兼容性。4.3→4.4 的废弃项(分区策略、transient 默认)在第 3、7 章已写,升级说明里再点名,避免升完行为变化当 Bug。Khepri 已在用则不要在窗口里做元数据后端切换。插件与核心同一镜像哈希。滚动顺序建议先非支付 Leader 密集节点,再动忙节点,可用 list_queues leader 辅助,不要凭感觉。完成后 revive 所有节点,确认无残留 drain。交接班念:今日已升 4.4,flags 列表见工单附件。
蓝绿页单独评审资源与 RPO:支付停写窗口长度、Shovel 追平 SLO、切流开关谁按。没有对账数字不算切流。与滚动二选一写进架构决策记录,避免窗口当天争论。
升级窗口通讯录要提前一天发出:谁值守、谁有权按 revive、谁有权宣布失败停止。停止条件写死:plus one 超时、支付 Confirm 连续失败、Alarm 亮、节点加不回群。满足任一条就冻结滚动,开战争房,而不是「再试一台」。混合版本停留期间禁止 declarations 大变更、禁止新队列类型试验、禁止 enable experimental。窗口结束后的第一份list_feature_flags与cluster_status截图进变更单,缺截图审计视为未完成。回滚决策树要让值班能在两分钟内读完:未开新 flag → 可退该节点镜像并 revive;已开新 flag → 只能打补丁或扩容向前。把这句话印在 RUNBOOK 首页。预发必须用真实 4.3 包升到 4.4 至少一次,实验室重启代替不了 schema 与废弃项。4.3 起分区策略失效、transient 默认拒绝,升完若有人报「以前能声明临时队列」,那是预期,写进升级说明而不是当回归失败乱回滚。插件与核心同一镜像摘要,禁止「只换 server 不换 plugins 目录」。滚动顺序用list_queues name leader避开支付 Leader 扎堆的节点当第一台,减少窗口内选举次数。全部 revive 后看有无残留 draining,有则补 revive,否则第二天 LB 仍摘着那台。交接班口令包含版本号与 flags 附件路径。开发在窗口内只准看分桶、不准发版。测试只跑回归表。安全不在窗口轮换证书,避免变量叠加。这些纪律看起来啰嗦,但升级事故几乎都来自「顺便做另一件事」。
蓝绿若选中,单独冻结滚动 Runbook,避免两套并行。资源申请按双倍集群+Shovel 账号过期时间。切流开关权限与第 21 章铲子删除权限分开,防止一人误删。支付停写公告要给收银台降级文案,不只给 MQ 组。追平 SLO 用条数+抽样 message_id,抽样不足千分之一不算。切读观察期至少覆盖一个业务高峰切片。失败则切回蓝,绿当演练报废,不要在绿上当场修 schema。决策记录写清为什么不滚动:跨系列、磁盘布局、或合规要求可回切。没有 ADR 的蓝绿会在窗口变成现场架构会。
4. 项目总结
优点与缺点
| 策略 | 优点 | 缺点 |
|---|---|---|
| 同系列滚动 | 资源少、flags 连续 | 混合窗口要短 |
| 蓝绿+Shovel | 可推倒存储 | 成本高、切流复杂 |
| 三台齐停 | 心智简单 | 支付停摆 |
优点:1)不可逆 flags 被门禁管住。2)plus one 可脚本化。3)蓝绿有对照。
缺点:1)LB/drain 耦合。2)实验 flag 诱惑。3)真跳版本无官方桥。
对比「只换镜像不管 flags」:新能力不用等于白升,乱 enable 等于无法回滚。
适用场景
- 4.2→4.3→4.4。
- 预发演练。
- 存储改造用蓝绿。
不适用:生产先开 experimental;两节点滚动当 HA;跳大版本碰运气。
注意事项
- flags 不能关。
- 安全:definitions 备份脱敏。
- 版本:按系列升。
- drain 与健康检查。
常见踩坑(生产)
- 升完一半去 enable_all。根因:混合版本。处理:停、等全员。
- LB 打 draining 节点,收银台超时。根因:健康检查不认维护。处理:先摘流量。
- 跳 4.2 到 4.4。根因:抄错文档。处理:停在支持矩阵。
思考题
- 已经 enable 某个 4.4 新 flag 后发现回归失败,为什么通常不能退回 4.3 二进制?你的应急是什么?
- 蓝绿时支付能否继续双写?若不能,停写窗口如何与 Shovel 追平 SLO 对齐?
(回滚决策;第 21 章对账。)
推广计划提示
| 部门 | 本章怎么用 | 协作 |
|---|---|---|
| 运维 | 主签 Runbook | plus one 超时停 |
| 测试 | 回归表 | 窗口内不拧水位 |
| 开发 | Confirm 分桶待命 | 不改 SENT |
| 架构 | 滚动 vs 蓝绿 ADR | 否决跳版本 |
下一章把「升完感觉还行」变成 Prometheus 数字和五条告警。
附录 C:第 25 章思考题参考答案
题 1:authn=OAuth2、authz=internal。
认证只证明 JWT 有效并抽出用户名;授权看 internal 权限表,JWT 里的 scope不再当 configure/write/read 依据。要以 scope 为准就把 authz 也配 oauth2,或不要拆链。拆链用于「IdP 管是谁、Broker 本地管能干什么」,权限变更走set_permissions不是改 token。
题 2:联邦/Shovel URI。
必须amqps://、专用最小权限账号、证书SAN 含对端主机名/LB 名,不要只写 IP(弹性扩容会挂)。与第 21 章明文实验室 URI 在生产检查单里互斥。
延伸阅读与资源
SQLAlchemy 2.0从入门到进阶的实战之旅
Dify 从入门到进阶:LLM 应用平台实战修炼
Java 工程师进阶:从 JVM 生产排障到OpenJDK原理
NumPy 从入门到生产落地:全链路实战指南(科学计算/向量化)
Redis 8 实战精讲:从 CRUD 到源码,构建高可用缓存系统
Redis 实战修炼与原理进阶
Python 3实战精进:从脚本到高并发订单引擎
python入门:Rquests从菜鸟脚本到企业级SDK的网络实战圣经
Milvus向量数据库实战修炼:从 0 到 1精通向量检索与生产落地
MongoDB 实战进阶与内核修炼
后端工程师的 AI 转型第一课:Ollama 与私有化大模型实战
10倍开发者的 Dify 魔法书:从零构建全栈 AI 应用
后端工程师转型AI第一课-Ollama 与私有化大模型实战
大型语言模型(LLM) vLLM 高性能推理落地实战
Agent开发之LlamaIndex 实战修炼与源码进阶
大语言模型Transformers 实战修炼与源码剖析