《后端架构设计·高性能与高可用》附录 C 故障演练检查表

卷二的故障演练检查表:演练前必须确认的十项准备、影响范围与审批、观测空跑与数据重置、八个可重复注入的故障场景、每个场景的预期信号与通过标准、中止与回滚条件、执行记录表、时间线复盘与改进项跟踪、演练角色分工、七条禁止事项,以及可以打印的一页清单。

演练不是故障表演

故障演练的目的不是“看系统会不会挂”,而是验证三件具体的事:

  1. 故障是否被及时观测到;
  2. 保护机制是否按设计生效;
  3. 恢复路径是否真的可执行。

如果演练结束只留下一段“服务重启后恢复”的记录,没有观测时间线、没有保护机制的状态变化、没有恢复步骤的实际耗时,这次演练的价值接近于零。

卷二讨论的限流、熔断、舱壁、重试、超时、摘流、切换,都是“平时不生效、故障时才生效”的机制。不演练,就无法确认它们是否真的接线正确。本附录给出一套可重复、可中止、可复盘的检查表。

演练前必须确认的十项

序号项目通过标准
1演练目标一句话说明验证哪个机制,不写“提升稳定性”
2影响范围明确哪些用户、接口、数据会受影响
3审批有负责人书面同意,含时间窗
4通知相关团队、客服、值班已知晓
5观测关键指标、日志、追踪能在同一时间轴查看
6注入方式可重复、可停止、作用范围明确
7中止条件写清什么情况下立即停止,谁有权停止
8回滚步骤每一步有命令、有验证、有预计耗时
9数据准备演练数据可重置,不影响真实业务
10记录人有人专门记录时间线,不参与操作

十项里最容易缺的是第 7 和第 10。没有中止条件,演练会从“受控实验”变成“真实事故”;没有记录人,事后只能凭记忆复盘,时间线一定失真。

目标要具体

不好的目标:

  • 验证系统高可用;
  • 提升故障处理能力;
  • 看看会不会挂。

好的目标:

  • 验证库存服务超时 2 秒时,订单接口在 500ms 内返回降级结果;
  • 验证摘除一台实例后,负载在 30 秒内重新均衡,错误率不超过 0.1%;
  • 验证主备切换后,写请求在 60 秒内恢复,丢失数据为零。

目标越具体,通过标准越容易写,演练结束后也越容易判断“到底验没验成”。

八个可重复场景

下面八个场景都可以用进程内注入、配置开关或受控的依赖故障实现,不依赖随机网络故障。

场景 1:实例宕机

项目内容
注入方式停止一个应用实例,或让健康检查失败触发摘流
预期信号该实例从负载均衡移除;其他实例 QPS 上升;错误率短时上升后回落
通过标准30 秒内流量重新均衡;无持续 5xx;在途请求有明确结果
中止条件剩余实例错误率超过 5%,或队列持续增长
观察重点摘流是否等待在途请求;客户端是否重试到其他实例

场景 2:依赖变慢

项目内容
注入方式在支付或库存适配器注入固定延迟,例如 2 秒
预期信号调用方超时率上升;熔断器进入打开状态;降级逻辑生效
通过标准订单接口在预算内返回;熔断后不再持续打下游;恢复后自动半开
中止条件线程/协程数持续增长,或连接池耗尽
观察重点超时是否沿调用链传播;重试是否放大流量

场景 3:依赖返回错误

项目内容
注入方式按比例返回 500 或业务错误码,例如 30%
预期信号错误率上升;重试次数上升;熔断阈值被触发
通过标准错误被分类;可重试错误有限次重试;不可重试错误快速失败
中止条件错误扩散到非相关接口
观察重点错误码是否被正确映射;幂等是否防止重复副作用

场景 4:缓存失效

项目内容
注入方式清空本地缓存,或让 Redis 不可用
预期信号回源量上升;数据库 QPS 上升;延迟上升
通过标准回源被限流或合并;数据库不被打穿;延迟在预算内
中止条件数据库连接池耗尽或慢查询激增
观察重点singleflight 是否生效;热点 key 是否被保护

场景 5:消息积压

项目内容
注入方式暂停消费者,或降低消费速率
预期信号积压量上升;消费延迟上升;告警触发
通过标准积压可观测;扩容或提速后能恢复;重复消费不产生重复副作用
中止条件积压超过预设上限,或磁盘将满
观察重点顺序是否保持;死信是否有归处;对账是否能补齐

场景 6:数据库主备切换

项目内容
注入方式在受控环境中停止主库,触发切换
预期信号写请求短时失败;连接重建;读请求可能读到旧数据
通过标准切换在预定时间内完成;数据丢失为零;应用自动重连
中止条件切换后数据不一致,或无法确认新主
观察重点应用是否有重连退避;读写分离的延迟兜底是否生效

场景 7:限流触发

项目内容
注入方式把限流阈值调低,或把流量提高到阈值以上
预期信号拒绝率上升;通过量稳定在上限;延迟不再随流量上升
通过标准拒绝返回明确错误码;核心接口优先;限流解除后自动恢复
中止条件误伤核心链路,或拒绝比例超过业务可接受范围
观察重点限流维度是否合理;客户端是否尊重 Retry-After

场景 8:发布与回滚

项目内容
注入方式发布一个带已知缺陷的版本,再执行回滚
预期信号金丝雀指标异常;发布暂停;回滚后指标恢复
通过标准异常在影响扩大前被发现;回滚在预定时间内完成;数据兼容
中止条件回滚后错误率不降,或数据出现不可逆变化
观察重点兼容窗口是否足够;开关能否独立关闭新逻辑

观测信号对照

演练时最怕“感觉有问题但拿不出证据”。下面是最小信号集,演练前确认每一项都能查到。

层信号在哪看
业务下单成功率、支付成功率业务仪表盘
接口QPS、P99、错误率、超时率、拒绝率应用指标
依赖下游延迟、错误率、连接池占用依赖指标
保护熔断状态、限流拒绝数、重试次数治理指标
资源CPU、内存、GC、协程数主机/运行时指标
链路单笔订单的 span 时间线追踪系统
日志错误码、状态迁移、降级原因结构化日志

演练前做一次“空跑”:不注入故障,只确认这些信号在同一时间窗口内都能看到。空跑能发现大部分采集配置问题,比演练中临时找指标高效得多。

中止与回滚

中止不是失败,是演练的一部分。以下情况应立即停止:

  • 影响范围超出审批范围;
  • 错误率或延迟超过预设上限;
  • 保护机制未生效,且流量持续打向下游;
  • 数据出现不一致或不可逆变化;
  • 值班人员无法判断当前状态。

回滚步骤要写成可执行的命令,而不是“恢复配置”。例如:

# 1. 停止注入
kill -TERM "$(cat .local/drill/inject.pid)"

# 2. 恢复限流阈值
curl -X POST localhost:8080/admin/ratelimit -d '{"rate":200}'

# 3. 确认指标恢复
curl -s localhost:8080/metrics | grep 'order_http_errors_total'

# 4. 恢复流量
curl -X POST localhost:8080/admin/traffic -d '{"weight":100}'

每一步都要有验证,不能一口气执行完再检查。回滚本身也可能失败,因此要准备“回滚的回滚”——最坏情况下如何回到演练前状态。

执行记录表

演练过程中由记录人填写,不做事后补记。

时间事件操作人观测到的信号结果
14:00:00开始注入张三延迟开始上升符合预期
14:00:30熔断打开系统下游错误率 0保护生效
14:01:10开始回滚李四延迟回落符合预期
14:02:00指标恢复系统P99 回到基线演练结束

时间要精确到秒,信号要写具体数值,不写“正常/异常”。事后复盘时,这张表是唯一可靠的事实来源。

演练后复盘

复盘回答四个问题,不追责个人:

  1. 目标验证了吗?通过标准是否达成?
  2. 观测是否及时?从故障发生到被发现用了多久?
  3. 保护机制是否按设计生效?没有生效的原因是什么?
  4. 恢复步骤是否可执行?实际耗时与预计差多少?

输出至少包含:

  • 一条时间线;
  • 一组前后指标对比;
  • 一份改进项清单,每项有负责人和截止时间;
  • 对检查表本身的修订建议。

改进项要能验证。“加强监控”不是改进项,“为支付超时增加 P99 告警,阈值 800ms,持续 2 分钟”才是。

演练频率与范围

级别频率范围例子
单机制验证每次相关改动后一个接口、一个实例改熔断阈值后验证半开恢复
单场景演练每月或每季度一个服务、一个依赖缓存不可用、消息积压
链路演练每半年一条核心链路下单链路的依赖超时与切换
全站演练每年,谨慎多服务、基础设施区域级切换,通常由专门平台执行

频率不是越高越好。每次演练都有成本和风险,关键是“改动之后有没有验证”。改了限流逻辑却不演练,等于把新逻辑直接交给生产验证。

演练范围应该从单机制开始,逐步扩大。跳过单机制直接做全链路,问题会叠加在一起,既难定位也难中止。

谁应该参加

角色职责不做什么
演练负责人决定开始、中止和结束不亲自操作注入
操作人执行注入与回滚不判断是否继续
记录人记录时间线与信号不参与操作
观察人看指标、日志、追踪不改配置
业务代表判断用户影响是否可接受不指挥技术操作
值班接住演练外的真实告警不被拉进演练操作

负责人和操作人分开,是为了避免“操作顺利就继续加码”的惯性。记录人独立,是为了保证时间线不被事后解释覆盖。

七条禁止事项

第一,不在生产环境做未经审批的演练。

第二,不注入无法停止的故障。任何注入都必须有对应的停止手段。

第三,不在没有观测的情况下演练。看不到信号,等于制造事故。

第四,不在流量高峰或大促前演练。

第五,不把演练脚本写成随机破坏。随机性留给专门的混沌平台,卷二强调可重复。

第六,不让同一个人既操作又记录。记录会被操作节奏带偏。

第七,不把演练结果当成“系统没问题”的证明。一次通过只说明这次场景、这次配置、这个时间点通过。

一页清单

打印或复制到演练工单里:

[ ] 目标一句话,含验证的机制
[ ] 影响范围与审批
[ ] 相关团队已通知
[ ] 关键信号空跑可见
[ ] 注入方式可停止
[ ] 中止条件与有权停止的人
[ ] 回滚步骤逐步可执行
[ ] 数据可重置
[ ] 记录人就位
[ ] 时间线开始记录
[ ] 演练后复盘会议已排期
[ ] 改进项有负责人和截止时间

常见错误与边界

第一,只演练“服务挂掉”。真实故障更多是变慢、部分失败和依赖超时;这些场景不会让健康检查失败,却会拖垮调用方。

第二,没有基线。演练前不记录正常指标,事后无法判断“恢复了没有”。

第三,把保护机制当成必然生效。限流、熔断、舱壁都需要配置正确、依赖可用、指标可观测,任何一环缺失都会失效。

第四,演练范围过大。一次只验证一个机制,多个故障叠加会让归因变得不可能。

第五,忽略客户端行为。服务端降级了,客户端是否重试、是否尊重错误码,决定最终用户体验。

第六,复盘没有改进项,或者改进项没有截止时间。这样的复盘只是写了一份文档。

小结

故障演练验证的是观测、保护和恢复三件事,不是“系统会不会挂”。演练前确认十项准备,选择可重复的注入方式,写清中止条件和回滚步骤;演练中由专人记录时间线;演练后输出时间线、指标对比和改进项。

八个场景覆盖实例宕机、依赖变慢、依赖报错、缓存失效、消息积压、主备切换、限流触发和发布回滚。它们都不依赖随机网络故障,适合在受控环境中反复执行。卷四会把其中一部分平台化、自动化,卷二先确保每一次演练都是可控、可观测、可复盘的。

继续阅读

探索更多技术文章

浏览归档,发现更多关于系统设计、工具链和工程实践的内容。

全部文章 返回首页

「books」更多文章

  1. 《互联网产品的 AI 架构·平台化与治理》附录 C 平台化评审清单
  2. 《互联网产品的 AI 架构·平台化与治理》附录 B 能力目录与配额字段速查
  3. 《互联网产品的 AI 架构·平台化与治理》附录 A 治理角色与职责速查