Chaos Engineering: System Resiliency in Practice · Ch 16 · Continuous Verification · 2020
这一章讲什么?
你刷视频时,背后那家公司一天可能要改几百次代码。每次改完都有一套自动流程负责「检查能不能合进去、能不能发出去」。这一章问的是下一步:发出去以后,系统遇到故障还扛不扛得住——能不能也让机器每天自动去查? 作者给这件事起了个名字:持续验证。
打个比方
一栋大楼的消防演习。老办法是一年一次:提前通知、全员下楼、写份报告。可楼里每周都在装修、改隔墙、换电梯,一年前的演习结论早就不准了。持续验证就像在楼里装了一个自动演习员 :每天挑一层、只拉上几个人,悄悄试一下「这条走廊堵了,大家还能不能从另一边出去」,有人被困就马上停手,结果每天自动出报告。
旧世界为什么难
演练太稀。 人工组织的故障演练几个月一次,可系统每天都在变,上次的「没问题」很快就过期了。
演练太贵。 每次都要专人设计、盯屏幕、判断结果,做多了没人有精力。
不知道该演哪个。 一个大系统有成百上千条「谁依赖谁」的线,靠人挑,只会挑自己想得到的那几条。
核心机制直觉
机器帮你挑题。 它读每个服务「等多久算超时、失败了重试几次、出错后有没有备用方案」这些设置,自动列出值得试的故障,按影响大小排队。连「没有备用方案」这种一看就知道会出事的,它直接报告,不用真去试。
只拿一小撮真实用户做实验,再配一组对照。 像药物试验:从真实访问里切出两小份,一份照常、一份故意让某个依赖出错,其余绝大多数用户完全不受影响。
看用户结果,不看机器忙不忙。 比较两组「有多少人成功点开了视频」。实验组明显变差,就自动喊停,并告诉团队哪里有弱点。
天天跑、自己跑。 做成流水线上的一道固定工序,而不是一次活动。
带来了什么 / 该怎么选
演练从「一年几次的大活动」变成「每天自动发生的小检查」,系统改了什么,第二天就知道有没有把抗打击能力改坏。新团队可以先从测试环境里定时跑起,等有了自动喊停再进真实环境。一句诚实的代价:这套自动化本身要花大力气搭和维护,而且它只能验证你想到要验的那些事。
一句话记住
代码有人每天自动检查,系统抗故障的本事也该每天自动检查 ——挑题、分组、判定、喊停,全交给机器。
想看 CI/CD/CV 的分工、Netflix 的 ChAP 和 Monocle 具体怎么分流与挑实验,以及什么时候该把它设成发布关卡? → 切到精读版
一句话
你以为混沌工程是「定期办一次演练」,其实它的终点是持续验证(Continuous Verification,CV) :像 CI 持续检查代码一样,由工具持续、自动、在生产里 验证系统行为——挑实验、分流量、比指标、判结论、叫停,全不靠人盯。
Glossary · 术语表
持续集成(continuous integration,CI) :每次提交代码都自动构建、跑测试,尽早发现「合不到一起」的问题。
持续交付(continuous delivery,CD) :通过测试的代码自动走完部署流水线,随时可以安全上线。
流水线(pipeline) :代码从提交到上线要依次经过的一串自动化步骤,每一步都可以设成「过了才放行」的关卡。
金丝雀发布(canary) :先让新版本只接一小部分流量,与旧版本对比指标,没问题再全量。
依赖调用(RPC / IPC) :一个微服务调用另一个微服务;混沌实验常在这里注入失败或延迟。
超时 / 重试 / 降级(timeout / retry / fallback) :等多久放弃、失败后再试几次、彻底失败时返回什么备用结果——三者是服务抗依赖故障的主要手段。
稳态指标(steady-state metric) :系统正常时稳定的业务量,Netflix 用每秒播放启动数(SPS,stream starts per second)。
爆炸半径(blast radius) :一次实验最多影响多少用户或请求。
坐标
全书第 16 章,Part V「演进」的开篇,作者 Casey Rosenthal。上接 Ch15 成熟度模型——CV 正是「精细度」轴的顶端(自动化、进流水线、对照组比业务指标);也是 Ch3 原则里「持续自动化运行实验」那条的工程落地。下启 Ch17–20 对混沌边界的外推。
这章要解决什么
假设一个中型微服务系统:200 个服务、每天部署 100 次以上、服务间依赖边上千条。人工混沌演练(Game Day)一个季度办一次,每次覆盖 5–10 个场景。问题很明显:
结论过期快。 上季度验证过「推荐服务挂了首页能降级」,这季度有人改了超时配置,结论就不再成立,而没人知道。
覆盖面太窄。 一千条依赖边 × 失败 / 延迟两类故障,人工每季度十来个场景,几十年也排不完。
人是瓶颈。 设计、执行、盯盘、判读全靠少数混沌工程师,团队一多就排不上队。
软件业解决过一模一样的问题:手动集成、手动部署也曾是「几个月一次的大事件」,后来被 CI/CD 变成每次提交都自动发生的小事。本章的主张是:系统性质(可用性、韧性、性能)的验证,也必须走这条路 ,否则验证速度永远追不上变更速度。
核心内容,讲透
一、从 CI/CD 到 CV:验证的对象换了
书中把 CV 定义为一门在软件中主动做实验的学科,以工具的形式落地,用来验证系统行为。关键区别在验证对象:
CI 验证代码 :这段代码对不对,单元 / 集成测试过不过。结果是确定的通过 / 失败。
CD 验证交付 :能不能自动、可回滚地把它发出去。
CV 验证系统行为 :整套系统在真实流量、真实故障下是否仍维持稳态。这是涌现性质 ——没有哪一行代码「拥有」可用性,所以单元测试测不到,只能在系统层面做实验。
因此 CV 的结论不是断言式的 pass/fail,而是带统计置信度的比较 :实验组与对照组的业务指标差多少、是否超出噪声。
CI · 持续集成
验代码:测试过没过
确定的 通过 / 失败
每次提交
CD · 持续交付
验交付:能否安全发出
金丝雀、可回滚
每次部署
CV · 持续验证
验系统行为:故障下
稳态还在不在
统计比较,非断言
发现的弱点变成修复与回归实验,回到下一次提交
CI 管代码、CD 管交付、CV 管系统行为;CV 不只在上线前跑一次,而是持续在生产里跑,发现的弱点回流到开发。
二、ChAP:把一次实验做成可自动执行的流程
本章的主案例是 Netflix 的 ChAP(Chaos Automation Platform,混沌自动化平台) 。它把 Ch3 那套「假设稳态 → 注入真实故障 → 生产里跑 → 控制爆炸半径」变成一个按钮:
建两组一模一样的集群。 基于当前生产版本,各起一个小的对照集群 和实验集群 ,配置完全相同。
切一小份真实流量。 把很小比例的生产请求平均分给两组,其余用户走正常生产集群、毫无感知。
只在实验组注入。 借助 Netflix 的故障注入框架 FIT,给实验组的请求打标记,让它在调用某个依赖时被注入失败或延迟。
比业务指标、自动叫停。 持续对比两组的 SPS;一旦实验组偏离超过阈值,平台自动中止 实验、把流量收回。
为什么必须有对照组?因为生产流量本身在波动——晚高峰 SPS 上升、某地区网络抖动。只盯实验组看「降了没」,分不清是故障造成的还是大盘本来就在动。同时段、同版本、同流量形态的对照组 把这些噪声抵消掉,剩下的差就是故障的效应。这与金丝雀分析同构,只是金丝雀比的是新旧版本,ChAP 比的是有无故障。
真实用户
生产请求
流量路由
按标记分流
正常生产集群
绝大多数流量,不受影响
对照集群
一小份流量,不注入
实验集群
等量流量,注入依赖故障
比较 SPS
差距超阈值
→ 自动中止
ChAP 的分流:对照组与实验组各拿一小份等量真实流量,只有实验组被注入故障;两组业务指标一旦拉开超过阈值就自动中止。
三、Monocle:让机器决定「先做哪个实验」
ChAP 解决了「怎么跑」,但每个实验仍要人来配:选哪个服务、注入哪个依赖、注入失败还是延迟。服务一多,人又成了瓶颈。Netflix 于是在 ChAP 上加了 Monocle ,自动生成并排序实验:
读配置。 从服务的调用框架与监控里收集每条依赖的超时、重试次数、有无降级、调用量。
生成候选。 每条依赖 × 「失败」「延迟」两类注入,组成候选实验清单。
按影响排序。 调用量越大、重试越多、越可能拖垮上游的依赖,排得越前。
跳过「已知会失败」的实验。 例如某依赖根本没有降级,注入失败必然导致错误——这时不必真的拿用户去试,直接作为弱点报告 。配置之间的矛盾也能静态看出来:客户端「超时 × 重试」的总时长超过了外层的总超时,重试就永远轮不到。
这一步的意义是把实验选择 从人的直觉换成对系统结构的系统性扫描,呼应 Ch12 的实验选择问题:故障空间太大,自动化的价值首先在「挑」,其次才在「跑」。
读配置
超时·重试·降级
生成候选
依赖 × 失败/延迟
按影响排序
调用量·重试数
ChAP 执行
分流·对比·叫停
报告弱点
交给服务团队
已知必败(如无降级):不跑实验,直接报告
Monocle 的自动挑题:从配置生成候选实验、按影响排序后交给 ChAP;能静态判定必败的,跳过注入直接报弱点。
四、什么让它算「持续验证」
ChAP + Monocle 同时满足 Ch3 的进阶原则:以业务稳态为假设 (SPS)、注入真实世界事件 (依赖失败与延迟)、在生产里跑 、持续自动化 、最小化爆炸半径 (小比例流量 + 自动中止)。缺任何一条都退回成「自动化的演练」:不在生产跑,结论不真;没有自动中止,就不敢常跑;不持续,结论就过期。本章末尾还预言 CV 的思路会扩展到性能测试、数据产物、正确性等其它系统性质的验证。
关键权衡与选型
CV 的核心取舍是:验证放在哪、跑多频、谁来判 。越靠近生产、越自动,结论越真,前期投入和出错风险也越高。
三种验证方式对比(量级为示意)
方式 频率 覆盖 结论可信度 代价
人工 Game Day 月 / 季度一次 每次数个场景 高,但很快过期 人力密集;能顺带练人
非生产环境定时实验 每天 / 每次构建 可覆盖大量依赖 中:流量与配置不等于生产 维护环境与流量回放;对生产风险为零
生产 CV(ChAP 式) 持续 按优先级自动挑 高,且随系统更新 要分流、对照、自动中止等平台能力;仍有少量真实用户受影响
CV 结果要不要做成发布关卡
做法 适合 代价
硬关卡:不过不让上线 关键路径服务、已稳定的实验 实验噪声会误挡发布,拖慢交付;需控制误报率
软信号:报告给团队 新实验、指标噪声大的服务 容易变成没人看的告警,弱点长期不修
定时巡检:与发布解耦 验证配置漂移、依赖变化 发现时问题可能已上线一段时间
判据:先有自动中止,再进生产;先当软信号积累误报率数据,再升级为硬关卡。 一个误报率 5% 的关卡,对每天 100 次部署意味着每天约 5 次被无辜拦下——团队会很快学会绕过它。
为什么重要 / 落到真实系统
架构评审里被问「你们怎么知道降级真的有效」,CV 给出的回答是:不是「上次演练时有效」,而是「昨天自动验证过」 。今天这套思想已散落在常见工具里:Spinnaker 的自动金丝雀分析、LitmusChaos / Chaos Mesh 的定时实验与稳态探针、云厂商托管的故障注入服务。
大厂实证
Netflix:自动生成并执行生产混沌实验。 Netflix 的 Basiri、Hochstein、Jones、Tucker 在论文中描述 ChAP 与 Monocle:「a platform for automatically generating and executing chaos experiments, which check how well the production system can handle component failures and slowdowns」。Netflix · Automating Chaos Experiments in Production · ICSE-SEIP 2019
Google + Netflix:把「对照比较、统计判定」做成开源服务。 Kayenta「fetches user-configured metrics from their sources, runs statistical tests, and provides an aggregate score」,并能据此自动放行或判败;Netflix 当时预计它将「making thousands of canary judgments per day」。这与 ChAP 的对照判定是同一类能力。Google Cloud 博客 · 2018(Introducing Kayenta )
Netflix:故障注入接进持续交付平台。 Chaos Monkey 仓库写明:「This version of Chaos Monkey is fully integrated with Spinnaker, the continuous delivery platform that we use at Netflix.」Netflix · Chaos Monkey README(github.com/Netflix/chaosmonkey )
易错点与争议
「CV 就是把混沌实验放进 CI」。 在构建阶段跑几个故障测试只是起点;CV 的要害是持续、在生产、对照比较、自动中止 。少了生产与对照,验证的仍是测试环境。
「自动化后就不需要人」。 机器能挑题和判定,但弱点的修复、实验假设的设计、结果的解读仍靠人;Ch10–11 讲的人的因素并没有消失。
「指标没变 = 系统没问题」。 SPS 是粗粒度指标,小比例流量下统计功效有限,小幅退化可能被噪声淹没;稳态指标也只验证「活着」,不验证「数据对」。
只验证想到的。 Monocle 扫的是依赖配置,覆盖的是单依赖失败 / 延迟;多故障组合、流量形态变化等仍需另外设计。
门槛与时代局限。 ChAP 建立在 Netflix 自研的流量路由、FIT、部署平台之上,小团队难以复制;今天开源与托管工具降低了门槛,但「对照组 + 自动中止」仍是大多数团队缺的那块。
要点
① CV 是混沌工程的终点形态:像 CI 验代码一样,持续自动地验证系统行为。
② CI 验代码、CD 验交付、CV 验涌现性质;CV 的结论是统计比较,不是断言。
③ ChAP:同版本的对照组与实验组各拿一小份真实流量,只对实验组注入。
④ 对照组用来抵消生产流量本身的波动,剩下的差才是故障效应。
⑤ 看业务指标(SPS),偏离超阈值自动中止——这是敢在生产常跑的前提。
⑥ Monocle 从超时 / 重试 / 降级配置自动生成、排序实验;必败的直接报告不必跑。
⑦ 选型:先自动中止再进生产,先软信号再硬关卡,警惕误报率拖垮交付。
⑧ 局限:只验证想到的、稳态只证明「活着」、平台门槛高。