Appearance
发布工程与灰度体系
定位:架构方法论深化系列之四。发布不是开发的终点,是风险被批量注入生产的瞬间。这篇整理发布即风险注入的心智模型、灰度维度矩阵、发布火车与 feature flag 的分工、回归回滚自动化。以及 star-site 类多服务系统的发布顺序。
发布即风险注入
线上变更是故障的第一大来源(行业经验里占比常过半)。所以发布工程的第一性原理是:
- 每一次发布都是一次主动的风险注入。变更面积(多少代码/多少机器)× 影响半径(多少用户/哪些链路)= 风险敞口。发布工程做的就是把这个敞口切小、控速、可逆。
- 与之配套的心智:稳定不等于不变,而是变得又快又小。发布越频繁、单次越小,每次注入的风险越小。系统对"发布"这件事本身越不紧张。
- 大促/重大保障期的"封网"不是反对这个原理,是承认灰度能力有覆盖不到的时段。
灰度维度矩阵
灰度是给风险敞口装的分闸刀。可选的维度不是一种,是一组:
| 维度 | 切法 | 典型顺序 | 适用 |
|---|---|---|---|
| 机房/单元 | 按机房或单元化分组逐组发布 | 影响面小的机房先发,观察再推下一组 | 大集群、多机房部署 |
| 比例 | 按流量百分比 | 1% → 3% → 10% → 30% → 50% → 100% | 通用,最常用主轴 |
| 人群 | 按用户属性切 | 内部员工 → 白名单用户 → 新用户 → 全量 | 行为变更大、需回访验证 |
| 白名单 | 显式名单 | 核心开发 → 作者本人 → 种子用户 | 新功能最初验证 |
| 业务线 | 按业务/租户 | 非核心业务先切,核心业务殿后 | 多租户 SaaS、平台型系统 |
维度选择的优先级:先切爆炸半径小的维度,再放大。灰度整体是一个漏斗:
白名单(作者自己) ─> 员工/种子 ─> 1% 真实流量 ─> 10% ─> 50% ─> 100%
│ │ │ │ │
验证语义 验证兼容性 验证容量 验证放量 收尾观察
(能不能跑) (新旧共存) (性能水位) (指标平稳)
每一级都要有"通过判据",判据不满足就停在当前档位,
不允许"看起来没事就继续推"。每一档的通过判据提前写成可观测的指标(错误率、延迟、业务正确性对账),见《观测性三件套》。详细的白名单与百分比切流操作步骤见《系统切流通用方案》。
维度的组合原则:一次只动一个维度。同一发布里既加机器比例又换人群规则,出了问题说不清是哪个维度引入的。先固定机房维度推满比例,再考虑按人群二次切。多维度正交的示意:
比例 1% 10% 50% 100%
机房A ● ──> ● ──> ● ──> ● <- 先在 A 机房走完比例阶梯
机房B 开始 ● <- A 全量平稳后,B 从小比例重启阶梯
机房C ● -> 逐机房滚动
人群维度(可选的第二轴):在比例阶梯走通后,才用人群规则做更细的定向控制发布火车与 feature flag:部署不等于发布
两个机制最容易混,先把词掰开:
- 部署(deploy):把新代码放到机器上,跑起来但不对外生效。
- 发布(release):把功能开放给用户,产生业务影响。
发布火车管前者,feature flag 管后者:
| 发布火车 | Feature Flag | |
|---|---|---|
| 解决什么 | 代码从构建到机器的节奏与秩序 | 功能对用户的可见性与参数 |
| 机制 | 固定节奏(如每周两班),错过等下一班 | 运行时开关,控制面与代码分离 |
| 批量单位 | 一次合入的所有变更(攒车) | 单个功能/策略 |
| 风险控制 | 小批量、周期化,降低单次变更面积 | 独立于代码回滚的秒级止血 |
| 失效形态 | 车太挤导致"扒车"(跳过验证赶车) | flag 蔓延不清理,组合爆炸没人敢删 |
分工边界:火车解决"代码到机器",flag 解决"功能到用户"。两者配合才能做到"部署 ≠ 发布"——未完成的代码可以先上车部署(flag 关闭),产品节奏到了再远程打开。
合入 ──> 构建制品 ──> 上发布火车 ──> 部署到机器 ──┬── flag 关: 用户看到的还是老行为
(攒批量) (唯一制品) (固定节奏) (灰度分组) └── flag 开: 新行为放量
^ flag 开关独立操作、独立审计三条纪律:制品唯一(同一版本号全环境同一制品,环境差异全部走配置)。flag 默认关闭且带 owner 与过期时间(行为兼容的兜底值见《系统设计如何全方位考虑兼容性问题》)。火车误点不扒车——赶不上就等下一班,跳过验证赶车是事故的常见开头。
回归与回滚的自动化
灰度把风险切小,回归验证判断"这一档是否通过",回滚负责失败时止损:
- 回归自动化分层:
- 冒烟:发布后自动跑核心链路用例(下单、支付、登录),不过即拦截。
- 金丝雀比对:灰度组与对照组的指标(错误率/延迟/业务对账)自动 diff,超阈值告警。
- 业务对账:新代码与老代码/影子链路的输出比对,资金类链路必做。
- 回滚自动化:预置触发条件(错误率 > x% 持续 y 分钟、核心接口成功率跌破阈值)。满足即自动回滚或一键回滚,不等会议。回滚必须验证过:没演练过的回滚预案等于没有预案,定期做"回滚日"演练。
- 回滚的优先级高于定位:先止血再查因,"保留现场"靠日志与镜像,不靠拖着不回滚。
star-site 类多服务系统的发布顺序
多服务联动的系统,发布顺序错了会把"兼容期"变成"故障期"。原则:按依赖拓扑排序,先下游后上游,先提供方兼容、后消费方切换。
依赖图(箭头 = 依赖方向:上游调用下游)
入口网关 ──> star-site 应用 ──> 会员服务 ──> 用户库
│ └────> 积分服务
└──> 活动服务 ──> 营销库
拓扑排序得发布顺序(下游先行):
第1批 用户库、营销库 (存储层:只加不改,双写)
第2批 积分服务、会员服务 (基础服务:先上兼容版,新老字段都认)
第3批 活动服务 (中间层服务)
第4批 star-site 应用 (业务主应用)
第5批 入口网关 (入口最后切,爆炸半径最大)
停在任一批,系统都应整体可用 —— 这就是"兼容期不变量"。操作规则:
- 提供方先兼容,消费方后切换:下游先发兼容版(同时认新老格式)。上游再发切换版,最后下游发清理版。三段式的四层检查点见《系统设计如何全方位考虑兼容性问题》。
- 消息消费者先于生产者升级:消费者必须先能处理新旧两种消息格式,生产者再改格式。否则积压的旧消息会打挂新消费者。
- 同批内的服务也要有次序。多服务同机/同分组发布时,先发无状态再发有状态。跨机房按机房灰度逐组走(回到灰度维度矩阵)。
- 发布顺序固化成流水线编排,不靠人口口相传。依赖拓扑写在发布平台上。平台拒绝对"下游未就绪"的服务发起发布。
实践清单
发布前
[ ] 本次变更的灰度维度与阶梯是否明确?每档通过判据是否可观测?
[ ] feature flag 是否默认关、有 owner、有过期时间?
[ ] 多服务变更是否按依赖拓扑排序?兼容期不变量是否逐条核对?
[ ] 消息消费方是否先于生产方升级?
发布中
[ ] 是否同制品逐环境推进(配置差异全部外置)?
[ ] 冒烟与金丝雀指标是否自动比对、超阈值自动告警/回滚?
发布后
[ ] 观察期覆盖至少一个完整业务周期(含定时任务)?
[ ] 老 flag、老版本是否按时间表回收,避免组合腐化?
[ ] 回滚是否真的演练过(不是写在文档里)?与库内其他篇的关系
- 灰度本质是对兼容性假设的最后验证。四层模型见《系统设计如何全方位考虑兼容性问题》。操作步骤见《系统切流通用方案》。
- 灰度判据的指标建设见《观测性三件套》,出问题后的排查节奏见《问题定位步骤》。
- 部署节奏与批量怎么定是架构决策,留痕见《技术决策与ADR》。小步可逆的架构前提见《演进式架构与适应度函数》。
一句话总结
把发布当风险注入来管理:灰度按"白名单→机房/比例→人群"的漏斗切小敞口,每档有可观测判据。部署靠火车管节奏、发布靠 flag 控生效,两者分开。回滚要自动化且演练过。多服务按依赖拓扑排序、提供方先兼容消费方后切换——顺序即安全。
2026-10 新增(架构方法论深化系列)。