3. 混沌工程实验设计:假设驱动实验、实验对象选择、实验计划制定

好,咱们进入正题。实验设计这块,说白了就是回答三个问题:炸什么?怎么炸?炸完怎么收场? 我见过太多团队,一上来就搞个大新闻——直接把数据库主库给 kill 了,结果线上告警炸锅,老板拎着刀来找你。嗯,这其实不是混沌工程,这是自杀式袭击。

我个人习惯,做实验之前先问自己一句:“我想验证什么?” 而不是“我想搞坏什么”。这个心态的转变,是专业和业余的分水岭。

3.1 假设驱动实验:先有猜想,再动手

混沌工程不是瞎搞。它本质上是一种科学实验。科学实验的第一步是什么?是提出假设。

举个例子。你写了一个交易系统,核心链路是:
客户端 -> 网关 -> 订单服务 -> 数据库。

你的假设可能是:
“当订单服务响应变慢(延迟 500ms),网关的熔断机制能在 3 秒内触发,保护数据库不被拖垮。”

这个假设很具体。它有明确的实验变量(延迟 500ms)、预期行为(熔断触发)、时间窗口(3 秒内)。

好的假设公式:
当 [故障条件] 发生时,[系统组件] 应该能在 [时间/条件] 内,表现出 [预期行为]。

我在项目中遇到过一种情况:团队写了个假设叫“系统应该高可用”。这其实不是假设,这是口号。你没法验证它。你得拆解成“当一台订单服务宕机,Nginx 反向代理能在 5 秒内将流量切到另一台,丢单率不超过 0.1%”。

小技巧: 假设写得越具体,实验设计就越简单。如果你写假设时觉得头疼,说明你对系统的认知还不够深。回去看架构图。

3.2 实验对象选择:服务、数据库、网络

假设有了,接下来选靶子。交易系统里,我一般把实验对象分成三层:服务层、数据层、网络层。每一层的玩法不一样。

3.2.1 服务层:进程、实例、容器

服务层是最容易下手的。说白了就是让某个服务“不好好干活”。

  • 进程级故障: kill -9 杀掉进程。验证进程守护和自动拉起。
  • 实例级故障: 停掉一个 Pod 或虚拟机。验证负载均衡和流量调度。
  • 依赖故障: 让服务 A 调用服务 B 时返回 500 或超时。验证熔断和降级。

我个人建议,先从依赖故障开始。为什么?因为它最接近真实场景。交易系统里,下游的行情服务、风控服务、清算服务,任何一个挂了,你的核心交易逻辑都得扛住。

注意: 别一上来就 kill 主服务。我曾经有个同事,直接 kill 了交易核心进程,结果订单状态机卡死,半小时内产生了 2000 笔“幽灵订单”。嗯,那天的复盘会开了 4 个小时。

3.2.2 数据层:数据库、缓存、消息队列

数据层是交易系统的命根子。这里动手要格外小心。

对象 实验类型 验证目标
MySQL/PostgreSQL 主库延迟、连接池耗尽、磁盘写满 读写分离是否生效、连接池回收机制
Redis 缓存击穿、主从切换、内存淘汰 缓存降级策略、数据一致性
Kafka/RocketMQ Broker 宕机、消息积压、消费延迟 消息不丢失、消费幂等性

我记得有一次做数据库实验,我们模拟了主库 CPU 打满的场景。结果发现,从库的查询延迟从 2ms 飙到了 800ms。为什么?因为主库的 binlog 同步线程抢不到 CPU,导致从库一直等 binlog。这个发现直接让我们优化了主从同步的线程优先级。

3.2.3 网络层:延迟、丢包、分区

网络故障是最隐蔽的。它不像服务宕机那么明显,但破坏力极大。

  • 网络延迟: 给某个服务加 100ms 延迟。验证超时配置是否合理。
  • 网络丢包: 丢包率 1%、5%、10%。验证重试机制和幂等性。
  • 网络分区: 把一组机器从网络上隔离。验证集群脑裂保护。

你想想看,交易系统里最怕什么?不是服务挂了,而是服务半死不活。比如网络延迟 200ms,服务没挂,但所有请求都超时重试,结果流量放大 10 倍,直接把整个集群打崩。这就是典型的“雪崩效应”。

避坑指南: 我曾经在线上做过一次网络延迟实验,只加了 50ms 延迟,结果风控服务的超时时间设置的是 30ms,导致所有风控请求全部超时,交易链路直接熔断。所以,做网络实验前,一定先检查所有下游的超时配置。

3.3 实验计划制定:从爆炸半径到回滚方案

实验计划不是写作文,是操作手册。你得让一个刚入职的运维照着你的计划,也能把实验跑完。

我一般把实验计划分成五个步骤:

  1. 定义爆炸半径: 这个实验会影响多少用户?多少交易?影响面能不能控制在 1% 以内?
  2. 设置观测指标: 成功率、延迟、错误率、吞吐量。每个指标都要有阈值。
  3. 准备回滚方案: 如果指标超过阈值,怎么快速恢复?是重启服务?还是切流量?
  4. 执行实验: 先灰度,再小流量,最后全量。别跳步。
  5. 复盘总结: 实验发现了什么?系统有什么改进点?

这里我画了一张图,帮你理清整个实验设计的流程:

混沌工程实验设计流程 1. 提出假设 “当X发生时,Y应该...” 2. 选择实验对象 服务/数据库/网络 3. 制定实验计划 爆炸半径/观测/回滚 4. 执行 指标异常? 回滚/停止实验 指标正常? 5. 复盘总结 持续迭代,不断改进

这张图的核心逻辑是:实验是一个闭环。你提出假设,选择对象,制定计划,执行,复盘,然后根据复盘结果提出新的假设。如此循环,系统的韧性才会越来越强。

关于爆炸半径,我的经验是:
第一次实验,爆炸半径控制在 1% 以内。比如 100 台机器,先搞 1 台。1000 个用户,先搞 10 个。等你有信心了,再慢慢扩大。别想着一步到位,混沌工程是马拉松,不是百米冲刺。

最后,关于实验计划,我建议你写一个检查清单。每次实验前,逐项确认:

  • ✅ 假设是否清晰可验证?
  • ✅ 实验对象是否明确?
  • ✅ 爆炸半径是否可控?
  • ✅ 观测指标是否到位?
  • ✅ 回滚方案是否就绪?
  • ✅ 是否通知了相关团队?

嗯,这个清单看起来简单,但每次实验前过一遍,能帮你避免 90% 的线上事故。我自己就吃过亏——有一次忘了通知运维团队,结果他们看到告警直接重启了集群,把我的实验给打断了。从那以后,我每次实验前都会在群里吼一声:“兄弟们,我要搞事情了,别慌。”


公众号:蓝海资料掘金营,微信deep3321