2. 混沌工程核心原则:稳态、半径与安
聊完混沌工程是什么,咱们得钻进它的骨架里看看。
说白了,混沌工程不是让你在线上乱搞。它有一套自己的底层逻辑。
你可以把这三个原则当成演练的「交通规则」。不懂规则就上路,迟早翻车。
核心三原则:
- 稳态假设 — 你得知道「正常」长什么样。
- 爆炸半径 — 搞事情之前,先划好安全区。
- 最小化影响 — 能死一只鸡,别杀一头牛。
2.1 稳态假设 — 给系统画一幅「健康画像」
你想想看,如果你连系统「正常」的样子都说不清楚,那怎么判断故障演练是有效还是无效?
稳态假设就是这个道理。它指的是:系统在稳定运行时,有一组可观测、可量化的指标。这些指标构成了你对「健康」的定义。
我个人习惯的做法:
每次做演练前,我会提前一周记录黄金指标。比如:
- 95% 分位响应延迟 < 200ms
- 每分钟错误数 < 5
- CPU 使用率波动不超过 20%
把这些写成断言。演练只观测这些指标是否偏离。
我在项目中遇到过一种情况。当时负责一个支付核心系统,团队直接把「接口返回 HTTP 200」当成稳态。结果演练杀了一个依赖服务,接口确实返回 200,但里面塞满了兜底 mock 数据。你想想,这不就是典型的「仪表盘正常,船已经沉了」吗?
所以,好的稳态假设要满足三点:
- 可观测 — 能从监控、日志、链路追踪里拉出来。
- 可量化 — 不能是「响应快」,得是「P99延迟 < 500ms」。
- 有业务含义 — 不只是技术指标,比如「每分钟完成支付的订单数」。
避坑指南:
我曾经在选稳态指标时,只盯着 CPU 和内存看。结果演练把数据库连接池打满了,CPU 没怎么跳,但大量请求在排队超时。从那以后,我要求稳态指标里必须包含业务流量入口的吞吐量。
2.2 爆炸半径 — 炸也要炸得「可控」
爆炸半径,就是一次故障演练「最多只能伤到多大范围」。
说白了,你不能因为想测试一个缓存节点,就把整个集群搞崩了。那就不是演练,是事故。
控制爆炸半径的常用手段:
| 方法 | 说明 | 我见过的问题 |
|---|---|---|
| 环境隔离 | 先用预发/灰度环境验证,再放大到生产 | 预发环境和生产流量模型差太多,测不出真实问题 |
| 用户隔离 | 只影响内部测试账号或特定白名单用户 | 全量用户不可控,容易误伤 |
| 实例限制 | 比如只杀掉 1 个 Pod,而不是整个 Deployment | 一开始就搞大比例,直接雪崩 |
| 熔断开关 | 一旦指标越线,自动终止演练 | 开关没联调,演练时手动关都来不及 |
我记得有一次,团队想验证限流组件的有效性。有人直接提议「把流量网关全部挂掉看看」。我说等等,这么做爆炸半径太大了。最后我们只关了 10% 的网关实例,并观察了 5 分钟。效果很好,找到了一个限流配置的 bug,而且业务方完全没感知。
我自己的原则:
爆炸半径从「最小」开始。先杀一个实例,观测 2-3 分钟。没问题,再杀 10%、20%。别一上来就搞 50% 以上。安全第一,演练第二。
2.3 最小化影响 — 温柔地捅刀子
最小化影响,不是指「不产生影响」,而是指「用最小的代价获取最大的学习价值」。
你想想看,如果可以花 10 秒钟模拟一次 CPU 抖动就能验证限流策略,就没必要花 10 分钟去跑一个全链路压测。
实现最小化影响的两条路:
2.3.1 渐进式演练
从一个低压力、低覆盖率的点开始,逐步扩大。这有点像外科手术,先开个小口,确认方向对了,再扩大切口。
- 第 1 步:单机、单进程。
- 第 2 步:多机、单可用区。
- 第 3 步:多区、非核心业务。
- 第 4 步:核心业务,但有熔断底线。
2.3.2 自动化中止条件
演练不是无限期的。你必须明确「什么时候该停」。我和团队每次演练前,都会在平台上配置一个「中止阀门」。
// 假代码:中止条件配置示例
stop_conditions:
- metric: "error_rate"
threshold: 0.01 # 错误率超过 1% 立刻停止
duration: "10s" # 持续 10 秒触发
- metric: "p99_latency"
threshold: 1000 # P99 延迟超过 1000ms 停止
duration: "30s"
- metric: "success_rate"
threshold: 0.95 # 成功率跌到 95% 以下停止
action: "abort"
我曾经在一次演练里,就因为自动中止条件没配好,导致一个关键服务熔断了 20 分钟。虽然最后系统自动恢复了,但影响了大约 2% 的活跃用户。嗯,从那以后,我每次演练前都会亲自检查这三个条件:错误率、P99 延迟、成功率。
一个省钱省力的技巧:
如果你用的是 Kubernetes,可以利用 Pod 的 livenessProbe 和 readinessProbe 来控制演练的影响范围。比如注入故障后,让 Pod 从 Service Endpoint 中摘除,用户流量就不会打到这台有问题的机器上。这算是最低成本的爆炸半径控制之一。
2.4 三个原则的关系
这三个原则不是孤立的。它们是递进关系:
- 先定义稳态 — 你才知道系统现在是不是「健康」。
- 再控制爆炸半径 — 你才能在不失控的前提下做实验。
- 最后追求最小化影响 — 你才能在真实生产环境中重复演练,而不是搞一次就跑路。
说白了,没有稳态假设,你分不清故障是被触发的还是本来就有的。没有爆炸半径,你不敢在生产环境动手。没有最小化影响,你根本得不到持续演练的许可。
一句话总结本章:
混沌工程的高明之处,不在于「敢搞破坏」,而在于「在明确的假设、可控的范围内,用最小的代价搞清楚系统的薄弱点」。