什么是混沌工程 (Chaos Engineering)? 为什么业界都在用?
2026年4月26日
当提到混沌工程,最可能会联想到的词是混沌猴 (Chaos Monkey) 与猿猴大军 (Simian Army) 等一系列由 Netflix 开源的混沌工程工具。虽然早在 Netflix 推出混沌猴之前,业界早已有类似的实践方式,但最早开始使用混沌 (chaos) 这个名词,甚至让混沌工程成为业界显学的,仍然是 Netflix。
Netflix 在 2010 年开始在内部推出混沌猴。这个名字来自一个想象:有一只狂暴的猴子冲进数据中心搞破坏,比如拔掉服务器电源线、把磁盘咬坏。而 Netflix 可靠性工程团队的目标是,即使出现这样一只混沌猴,也要确保 Netflix 提供给终端用户的服务不中断。
由于 Netflix 整体架构依赖 AWS,所以最早的混沌猴主要模拟 AWS 服务实例故障。但在实务中,导致事故的原因有很多种,所以除了最初的混沌猴,Netflix 进一步推出了猿猴大军。例如延迟猴 (Latency Monkey) 用来模拟某个 RESTful API 延迟升高后,是否会影响整体服务。
在混沌猴被证明有效后,Netflix 团队继续扩展,把混沌猴升级成混沌金刚 (Chaos Kong)。原本混沌猴是终止单一实例,而混沌金刚则模拟整个 AWS 区域被关闭,确保当 AWS 某个区域宕机时(历史上确实发生过数次全球级事故),系统仍能顺畅切换到其他区域,让服务不受影响。
前面提到,在混沌工程这个词被标准化之前,各家公司也有相似实践。比如 Amazon 著名的“灾难大师” (Master of Disaster) Jesse Robbins 曾在 Amazon 推出 GameDay 演练,在演练中模拟数据中心遭灾、服务依赖被阻断、网络被切断等不同场景,观察系统是否具备足够韧性来应对。
混沌工程的价值是什么?
在初步了解混沌工程的简史后,我们进一步来看混沌工程能为软件团队带来什么价值。
混沌工程很像软件系统的疫苗。打疫苗是刻意注入病毒,而混沌工程是刻意注入故障。这个“有意为之”的过程,反而能提升系统免疫力。在可控范围内刻意注入故障,无论是终止实例、错误配置文件还是注入延迟,都能帮助团队判断当前系统韧性是否足够。
在实务中,事故可能发生在任何想得到或想不到的地方:机器所在的数据中心、网络传输链路、第三方依赖,或者某个配置错误都可能出问题。因此,通过混沌工程去验证,可以让团队在面对事故时更有信心。
例如,在混沌猴“捣乱”后系统依然能稳定运行(比如某个 AWS 区域整体关闭时,Netflix 仍能顺利向观众提供视频流),软件团队就能更有底气地说:我们对系统韧性有足够信心。
再进一步说,混沌工程通常是预先规划的,因此通常在可靠性工程团队上班时间执行。即使注入故障真的引发事故,团队也能第一时间处理。这通常比事故在下班后发生、临时叫醒值班工程师要好得多。
对于达到一定规模的软件产品来说,生产环境中的任何事故都可能造成巨大损失。因此,混沌工程带来的信心,让 Netflix 等公司在软件工程部门内设置了专门的混沌工程师 (Chaos Engineer) 团队。
混沌工程如何帮助 Netflix 度过大规模实例重启
前面提到,混沌工程能为软件工程团队带来信心。Netflix 团队曾在 Cassandra Summit 分享过一个案例(链接):当年 AWS 告知 Netflix 团队,由于发现某个安全漏洞,需要重启所有 EC2 实例,这意味着 Netflix 运行在 EC2 上的 Cassandra 节点都要重启。
这种大规模重启对可靠性工程团队来说是非常紧张的事件,因为无法保证所有实例在重启过程中都不会出错。如果有实例未能成功重启,Netflix 团队需要及时检测并把导向该实例的请求切换到其他实例。
这件事听起来简单,但如果没有完整跑过流程,就无法保证检测与流量切换真的顺畅。为了在真正重启日前积累足够信心,Netflix 团队通过混沌工程,先小规模模拟部分 Cassandra 节点故障,并确保故障节点能被检测到、新实例会被拉起、请求能被顺利导向新实例。
在实际演练后,他们确实发现流程中存在一些问题,并在正式重启日前修复。到了真实重启日,全球 218 个节点被重启,结果确实有 22 个出现问题,但因为流程已经提前跑通,未成功重启的节点也都被顺利处理。
从这个案例中,可以清楚看到混沌工程的价值:因为提前做了混沌工程,Netflix 工程师在真实重启日才能更从容、更不焦虑。
如何执行混沌工程?
Netflix 工程团队出版过《Chaos Engineering》一书(链接),书中提到可以通过四个步骤执行混沌工程。
第一步是定义稳定状态 (steady state),理想上是写下可量化指标。比如 Netflix 团队会看每秒视频播放数、上游服务 API 延迟与错误率、系统吞吐量等。这有点类似 SLO 的设定(不熟悉 SLO 的读者,推荐回顾 SLO 是什么? 如何为团队设定 SLO? 一文)。
此外,在决定优先做哪类故障注入时,可以先思考“哪个面向最可能出问题”以及“哪个面向一旦出问题影响最大”。用批判性视角审视自己的系统,找出潜在弱点,并优先作为混沌工程的核心聚焦点。
定义完稳定状态后,下一步是建立假设。这个步骤类似做实验,需要建立所谓的虚无假设 (null hypothesis);也就是假设在注入故障后,稳定状态不会被影响。比如可以设定“即使向主缓存注入故障,也不会影响系统延迟”。
建立虚无假设后,需要寻找足够证据来拒绝它。如果无法拒绝,假设就成立。所以在执行混沌工程时,要尽可能去打破“即使向主缓存注入故障,也不会影响系统延迟”这个假设;如果打不破,就代表系统确实有韧性。
接下来就要通过注入不同故障来尝试打破前一步建立的假设。以上述假设为例,可以用不同方式影响主缓存,比如大量增加缓存未命中请求,或者用大规模请求冲击主缓存负载。
在实际采取不同手段后,最后一步是具体评估,判断假设是否被打破。以上面的例子来说,如果在多种方式影响主缓存后,系统延迟依旧不受影响,就能证明“即使向主缓存注入故障,也不会影响系统延迟”这个假设成立。
当然,如果在尝试打破假设的过程中,假设真的被打破了,比如系统延迟真的上升,这时就要立即停止实验。同时团队需要开复盘会,讨论系统为何受影响,以及后续如何改进。
阅读更多
在了解完混沌工程的执行流程后,你可能会想知道实作时还有哪些注意事项。我们在 E+ 成长计划的主题文中有更详细说明,感兴趣的读者欢迎加入 E+ 后阅读。对更深入了解这个主题,以及其他前后端开发、软件工程、AI 工程主题感兴趣的读者,欢迎加入 E+ 成长计划一起成长 (链接)。