灰度发布的质量保障:从金丝雀到全量 — editorial cover photo

发布是事故高发时刻,灰度怎么兜底

发布是质量事故的高发时刻,灰度让风险可控,是质量保障的关键手段。

2025年11月14日·返回文章列表
文章大纲

线上故障的统计里有一个反复出现的数字,大部分生产事故由变更引起,发布是其中最大头。这个比例各家统计口径不同,有说六成有说七成,但方向一致,发布是质量风险最集中的时刻。原因不复杂,新版本的 bug、配置错误、兼容性问题,在代码合入主干的那一刻都还藏着,直到部署上线才暴露。全量发布等于把这些潜在风险一瞬间铺给所有用户,一个边界条件没处理好,就是全量故障。

灰度发布要解决的就是这个问题,它把一次大的赌博切成一系列小的实验。先让一小部分流量走新版本,观察没问题再扩大,发现异常立刻回滚到旧版本。新版本的 bug 在小流量阶段就暴露,影响范围被限制住,回滚也快。这把发布的风险从全量降到了可控。下面把灰度发布里真正容易翻车的几个点讲透。

渐进路径不是走过场,每一档都在筛不同的问题

灰度发布的标准做法是分档放量,但很多人把它理解成机械地按比例往上推,1% 到 5% 到 20% 到 50% 到全量,每一档待一会儿就进下一档。这种走流程式的灰度意义不大,因为每一档真正要验证的东西是不同的,不理解这一点就不知道该盯什么。

PlantUML
正在加载图表…
PlantUML diagram

图:灰度五档各有验证重点,指标确认通过才进下一档,异常即停即回滚

最早期是内部用户先上,公司自己的员工先用新版本。这一档暴露的是最粗放的问题,启动报错、明显的功能不可用、配置没生效,这些低级问题应该在内部用户阶段就拦住。接下来是白名单,放给少量真实用户。这一档验证的是真实环境下的基本功能,内部测试环境再像也替代不了真实数据和生产配置。再往后是小比例放量,1% 到 5%,这一档开始观察技术指标,新版本的错误率和 RT 有没有劣化。中比例 20% 到 50% 验证的是更大流量下的稳定性和资源表现,内存泄漏这种问题在小流量下看不出来,流量一放大才暴露。最后全量。

关键在于每一档都要等指标确认没问题才进,不能等时间到了就机械推进。任何一个指标异常,立刻停在这档回滚排查。把档位当成自动扶梯一路上升,就丧失了灰度本身的意义。

只盯技术指标会漏掉业务问题

灰度期间观察哪些指标,是新手最容易做错的地方。大多数人盯着技术指标,错误率、RT、QPS,看着这些没异常就觉得灰度通过了。这个判断是危险的。

技术指标正常不代表业务正常。新版本错误率是 0,RT 也正常,但下单转化率悄悄掉了三成。怎么回事?可能是某个优惠券计算的逻辑改错了,金额算出来偏高,用户看到价格不划算就放弃了。这种业务逻辑 bug 不会触发技术层面的错误,接口照样返回成功,但业务结果已经偏了。

所以灰度期间的指标观察必须技术指标和业务指标双管齐下。技术指标看错误率、RT、资源使用,业务指标看核心业务的成功率和转化,下单成功率、支付成功率、注册完成率这些。两套指标一起对比新旧版本,任何一个方向出现劣化都要停下来查。

业务指标劣化比技术报错更难发现

技术报错是显性的,错误率一飙升立刻报警。业务指标的劣化是隐性的,系统不报错,日志没异常,唯一的表现是某个转化数字在悄悄下滑。如果灰度时没有把新旧版本的业务指标做对比看板,这种问题会一路漏到全量,等业务方发现转化掉了再回头查,黄花菜都凉了。灰度大盘里业务指标必须和技术指标并排,缺一不可。

数据库变更是灰度翻车的重灾区

灰度期间新旧版本是共存的,V1 和 V2 同时在跑,共享同一套数据库。这个前提对 schema 变更提出了一个硬约束,变更必须向前兼容,新版本能读旧版本写的数据,旧版本也要能读新版本写的数据。

PlantUML
正在加载图表…
PlantUML diagram

图:DB 变更拆成"加字段→回填→验证→清理"四步,破坏性操作推迟到旧版本下线后

破坏兼容性的操作有很多。改字段类型,把 varchar 改成 int,旧版本按字符串读会报错。删字段,旧版本还在往这个字段写,新版本已经不认了。加非空约束,旧版本写入的旧行数据不符合新约束。

正确的 DB 变更要拆成多步。第一步只加新字段,不删旧的,新版本同时写新旧两套字段,旧版本继续写旧字段。第二步跑数据迁移,把旧字段的值回填到新字段。第三步灰度验证新字段读写正常。第四步等新版本全量之后,再清理旧字段。整个过程里破坏性的变更(删字段、改类型)只允许在确认旧版本完全下线之后做,绝不在 V1V2 共存的灰度期动。

这一套流程慢,但它保证了任何时刻回滚都不会因为数据不兼容而卡死。灰度最大的底气来自能随时回滚,DB 变更破坏了回滚能力,灰度的安全网就破了。

功能开关,比实例级灰度更轻量的另一条路

传统的灰度发布靠多版本实例共存,V1 部署一部分实例,V2 部署一部分,网关按规则把流量路由到不同版本。这套方案能做,但运维成本高,要维护两套部署、做版本标识、管流量切分。

PlantUML
正在加载图表…
PlantUML diagram

图:两种灰度路线各有适用场景,基础设施层用实例级,业务逻辑层用功能开关

更轻量的替代是功能开关。新版本的代码里同时包含新旧两套逻辑,部署到所有实例,但用一个配置开关控制哪些用户走新逻辑、哪些走旧逻辑。开灰度就是改配置中心的一个开关,让 1% 的用户命中新逻辑,不涉及多版本实例。

功能开关的好处是切换快,改个配置秒级生效,不用等实例拉起。回滚也快,把开关关掉所有流量立刻回到旧逻辑。它特别适合做业务逻辑层面的灰度,比如一个新的推荐算法、一个新的计费规则。

但功能开关也有它的代价。代码里长期堆着新旧两套逻辑,维护负担会变大,用完的开关要及时清理,否则代码会越来越臃肿。另外它解决不了基础设施层面的变更,比如新版本依赖了新的中间件版本,这种还是得靠实例级灰度。

回滚方案必须在发布前就绪

灰度发布有一条铁律,回滚方案必须在发布之前就准备好,不能等问题出现再去想怎么回滚。

回滚的难度和灰度阶段有关。小流量阶段,回滚很简单,把流量切回 V1 就行,秒级无损。但到了大流量阶段,或者 V2 已经做了数据变更,回滚就复杂了。最棘手的是 V2 改了数据无法回滚的情况,比如 V2 给某个字段做了不可逆的转换,回滚到 V1 后旧代码读不了转换后的数据。

所以灰度的设计原则里有一条,V2 尽量不做不可逆的数据变更,宁可新写字段不动旧字段。这样哪怕 V2 跑了一段时间,回滚时旧版本依然能正常读旧字段工作。如果业务上实在避免不了不可逆变更,那就要提前设计好数据回滚方案,而不是临时抱佛脚。

灰度是流程也是文化

灰度发布做到最后,技术手段之外还有一层文化和流程的约束。默认灰度要成为团队的习惯,所有发布都走灰度流程,而不是觉得稳就跳过。小步快跑,每次发布变更尽量小,变更越小越容易验证、越容易回滚。

还有一条是回滚无罪。团队文化里要鼓励发现问题快速回滚,而不是硬扛着排查。回滚的成本低,一次误回滚顶多浪费几小时,硬扛的风险高,一个小问题可能拖成大故障。让值班的人敢于回滚、回滚不追责,灰度这套机制才能真正跑起来。发布从一次赌博变成一系列可控实验,靠的就是这套流程和文化兜底。

Continue Reading

关联文档推荐

查看全部
灰度发布:金丝雀、蓝绿与流量切分的工程实践 — vibrant cover for technical blog article配置中心设计:动态配置与灰度发布 — editorial cover photo优化前:同步写入所有数据源 — editorial cover photo
作者:archy.shawn
声明:本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。