一次完整的生产故障复盘(STAR:现象/工具/根因/修复/预防)

一句话速记

生产故障复盘用 STAR 框架(Situation 现象 → Tools 工具 → Analysis 根因 → Resolution 修复 → Prevention 预防),不是追责会,是补流程的输入。复盘产出:① 时间线(精确到分钟);② 根因(到代码行/配置项);③ 修复方案(短期止血 + 长期根治);④ 改进清单(每项配 Owner + 截止日期,不设期限的改进项等于没提)。

通俗解释(5 分钟版)

一次完整的故障复盘应该回答:

1. 发生了什么?(现象 + 时间线)
2. 怎么发现的?(报警 还是 用户投诉?——区别很大)
3. 怎么定位的?(用了什么工具、做了什么假设、排除了什么)
4. 根因是什么?(到代码行/配置项粒度)
5. 怎么修的?(短期止血 和 长期根治)
6. 以后怎么不让他发生?(监控/流程/规范/架构)
7. 同类问题存在吗?(排查其他服务是否有同样隐患)

复盘不是写作文,是补流程的扳手——每次复盘至少要产生 1-3 条可落地的改进项。

关键细节

复盘模板(STAR 结构)

S - Situation(现象 + 时间线)

【发现方式】
用户投诉/监控报警/巡检发现/下游反馈
(报警发现的 > 用户投诉发现的,前者说明监控合格)

【时间线】(精确到分钟)
14:25  用户开始投诉"下单失败"
14:28  值班人员打开监控大盘,发现订单服务错误率从 0.1% → 15%
14:30  确认受影响范围:所有实例、/api/order/create 接口
14:32  检查最近上线记录:14:20 有一个配置变更(灰度放量)
14:35  回滚配置变更
14:38  错误率恢复到 0.1%
14:40  开始排查根因

【影响范围】
受影响接口:/api/order/create
受影响时间:14:20 - 14:35(共 15 分钟)
受影响请求:约 3000 次请求失败
用户感知:用户看到"下单失败",部分用户重复提交

T - Tools(使用的工具和排查过程)

【工具清单】
- Grafana 监控大盘:确认错误率飙升
- SkyWalking:找到错误 trace,定位到 CouponService 返回 500
- arthas trace:追踪 CouponService.matchRule() 耗时
- git log:反查最近的配置变更记录
- 配置中心(Apollo/Nacos):查 14:20 的变更记录

【排查路径】
1. 监控大盘 → 确认错误率飙升范围
2. SkyWalking → 错误 trace → CouponService 是下游故障
3. CouponService 日志 → NullPointerException at matchRule()
4. git log + 配置中心 → 14:20 改了优惠券规则配置
5. 分析配置变更内容 → 新增了一个规则,缺少必填字段

【排查耗时】10 分钟
【有无走弯路】有。最初以为订单服务自身的代码有问题,看了 3 分钟才转向下游

A - Analysis(根因分析)

【直接原因(第二根因)】
CouponService.matchRule() 处理新配置的优惠券规则时 NPE
代码行:CouponService.java:156
  Rule rule = loadRule(config);
  String type = rule.getType();  // ← NPE:rule 为 null
                                  // 因为配置里缺少必填字段,loadRule() 返回了 null

【流程原因(第一根因)】
Q: 为什么改配置会导致服务异常?
A: 配置中心变更没有校验机制,任何格式的配置都能发布

Q: 为什么上线后没马上发现?
A: 灰度放量从 1% → 10% 时错误率已经异常,但告警阈值设的 5% 太高

Q: 为什么代码没处理 null?
A: Code Review 时没检查 null-safe

【结构性原因(超前 2 年)】
整个公司的配置中心缺少:
  1. 配置格式校验(schema validation)
  2. 配置变更灰度放量的自动化观察(自动看错误率,异常自动回滚)
  3. 配置变更的 code review 机制

R - Resolution(修复方案)

【短期止血(马上做,已经在做)】
- 回滚配置变更 → 服务恢复正常 ✓(14:35 完成)
- 扩大告警范围:错误率告警从 5% → 1% ✓(14:40 完成)

【长期根治(需开发,排期)】
- CouponService 代码加 null-safe 处理 + 单测覆盖(Owner: 小明, 截止: 1/17)
- 配置中心加 JSON Schema 校验,缺少必填字段时拒绝发布(Owner: SRE 团队, 截止: 1/20)
- 灰度放量增加自动观察窗:每步放量观察 5 分钟,错误率 > 1% 自动回滚(Owner: 发布系统, 截止: 1/25)

P - Prevention(预防措施)

【监控/告警改进】
□ 所有服务都加入 P99 错误率告警,阈值 1%
□ 配置变更事件接入监控大盘(能关联变更时间与异常时间)

【流程改进】
□ 配置变更纳入常规 Change Request 流程,需要 review
□ 灰度放量规则改为自动观察,不再依赖人工确认

【代码规范】
□ 所有外部配置解析代码必须 null-safe
□ Code Review Checklist 增加一条:外部输入是否做了 null 检查

【同类问题排查】
□ 排查所有服务是否也有类似的配置解析没做 null-safe
□ 排查其他依赖外部配置的服务是否有配置校验

复盘会的组织

不要做的

❌ 追责:"这是谁写的代码?"
❌ 形式主义:"我们以后要注意"(没有具体行动项)
❌ 开完不发纪要(会议内容只存在于参会者脑子里)
❌ 改进项全扔到"技术债" backlog 里永远不做
❌ 只有当事人在讲,其他人刷手机

应该做的

✅ 聚焦流程和系统,不聚焦个人
✅ 每个改进项配 Owner + 截止日期
✅ 下次复盘会先回顾上次的改进项完成情况
✅ 故障复盘文档公开,全团队可见(包括其他团队)
✅ 每个季度统计:故障次数、平均修复时间、最多故障的服务 → 趋势分析

复盘后的持续跟踪

改进项跟踪表:

改进项                      Owner      截止日期    状态        验收标准
──────────────────────────────────────────────────────────────
配置中心 JSON Schema 校验    SRE 团队    1/20      进行中      发布无 schema 的
                                                              配置时被拒绝
灰度自动观察 + 回滚          发布系统    1/25      未开始      错误率 > 1% 自动
                                                              暂停并通知
null-safe 代码修复           小明        1/17      ✅ 已完成   单测覆盖了 null
                                                              场景

延伸追问

  • Q:故障复盘应该多久做一次? → 每次 P0/P1 故障后 48 小时内必须做(趁记忆新鲜)。P2 及以下可以周复盘时统一回顾。不需要为每个小问题开专项复盘会,但有用户影响的故障必须单独复盘。
  • Q:复盘文档写多长合适? → 一页纸原则(A4 一页,约 500-800 字)。时间线、根因、改进项必须写清楚。排查过程可以不写得过于详细(工具和命令在个人笔记里记录就行)。重点是”以后怎么不让他发生”。
  • Q:复盘后发现改进项太多做不完怎么办? → 排序:按”再发生一次的影响 × 再发生的概率”。Top 3 必须做,其余的可以放到技术改进 Sprint 里分批消化。但必须定优先级,不能全扔 backlog。

我的记法

  • STAR 五步:现象(时间线)→ 工具(排查路径)→ 根因(到代码行)→ 修复(短期 + 长期)→ 预防(改进项 + Owner + 截止日)
  • 复盘不是追责,是补流程的输入材料
  • 改进项三要素:Owner + 截止日期 + 验收标准,缺一不可
  • 一句话:「复盘的价值不在复盘本身,在于它产出的 1-3 条改进项有没有真的落地」

状态

  • 已背速记
  • 能讲通俗版
  • 能答追问