生产故障排查总纲:先止血再定位

生产故障排查总流程:先止血,再定位

线上故障和实验室里的性能调优是两件事:系统正在流血、用户正在受损,任何“边查边改”都会搅乱现场,让后面的定位失去依据。本章给出排查的总原则——先恢复可用性再找根因,先看变更再看指标,先摘流量再动现场。

止血优先于定位

排查的第一个动作不是打开终端敲命令,而是判断“能不能先让用户好起来”。可用性每多损失一分钟的代价,都远高于根因晚知道十分钟。

手段适用场景生效速度代价与前提
回滚故障紧跟发布、配置、DDL 变更分钟级丢失新功能,必须先确认变更是可逆的
摘流量单实例或单机房异常,多实例部署秒级容量下降,必须先确认剩余容量扛得住
降级依赖(DB、缓存、三方接口)故障秒级到分钟级非核心功能不可用,需产品提前约定
扩容容量不足、流量真实增长分钟级成本上升,且掩盖不了代码缺陷

选择标准只有两条:能不能在 1 分钟内生效、能不能回退。做不到这两点的“救火方案”,本身就是新的风险。

止血动作的推荐顺序

故障发生
  ├─ 最近 30 分钟内有发布/配置/DDL 变更? → 有:立即回滚,回滚之后再来查
  ├─ 只有部分实例异常?                  → 是:先从负载均衡摘除异常实例,保留现场
  ├─ 核心依赖超时或报错?                → 是:降级非核心链路,只保登录/下单/支付
  └─ 流量真实超出容量?                  → 是:扩容 + 限流,按业务优先级放行

顺序反了代价很高:一边扩容一边等根因,流量持续压在坏实例上,用户照样报错,而扩容还把费用花掉了。

黄金四指标

任何线上系统,先看这四个信号就够了,其余指标都是它们的下钻。

指标含义观察形式异常时的第一反应
延迟 Latency请求处理耗时P95/P99,不要看均值区分是自身慢还是依赖慢
流量 TrafficQPS/TPS、并发连接数按接口、按实例拆开看是真涨了还是重试放大
错误 Errors错误率、超时率按状态码与异常类型分先看错误类型,不看错误总数
饱和度 SaturationCPU/内存/连接池/队列水位百分比与排队长度找最先逼近 100% 的那一项

平均延迟是故障排查中最没用的数字之一:9 个请求 10ms、1 个请求 10s,均值只有 1s,而投诉已经来了。

三分钟内要回答的六个问题

  1. 谁受影响:哪些用户、哪些接口、哪个地域或机房?
  2. 什么时候开始:精确到分钟,与最近一次变更是前是后?
  3. 范围多大:全量故障,还是单实例、单机房、单租户?
  4. 趋势如何:正在恶化、保持持平,还是已经自愈?
  5. 有没有变更:发布、配置、开关、DDL、数据订正、证书、依赖方升级?
  6. 有没有止血手段:能否回滚、摘流量、降级、扩容?

这六个问题答不上来就动手,大概率会把故障范围扩大一倍。

定位的推荐路径

用户反馈/告警 → 看大盘(延迟 + 错误率 + QPS)→ 确认影响面与开始时间
      ↓
比对变更记录(发布、配置、依赖、数据)
      ↓
应用层:日志关键字 + TraceID 全链路
      ↓
主机层:CPU / 内存 / 磁盘 / 网络 / 句柄
      ↓
确认根因 → 临时补丁 → 长期修复 → 复盘归档

路径是从上到下,不是从下到上。主机层是最后一站:多数“CPU 飙高”只是上游流量或自身代码问题在主机上的投影。

典型误操作

误操作为什么错正确做法
一上来就重启现场没了,根因无从查起,问题大概率复发先摘流量保住现场,再决定是否重启
一边查一边改配置指标基线被自己改掉,前后数据不可比一次只改一个变量,改前记录基线
忘了看变更多数故障与变更相关,白查一小时第一件事查发布与配置变更记录
只看均值不看分位P99 已经爆炸,大盘看起来依然“正常”看 P95/P99 与分接口错误率
直接连生产库查大表二次故障,慢查询把库打挂走只读从库、加 limit、避开业务高峰
群里只说“在查了”信息不同步,重复排查、决策冲突固定节奏同步影响面、已做动作、结论

重启前必须留下的现场

  • 线程栈:连续采 3 次,间隔 5 秒,用来看线程是否卡在同一处。
  • 火焰图:CPU 型故障采 30 秒,通常足够定位热点函数。
  • 堆快照:内存型故障先 dump 再重启,否则泄漏证据丢失。
  • 日志与指标:重启会清空本地日志,先转存到别处。
  • 连接与句柄快照:ss -slsof -p <pid> | wc -l
# 重启前的现场保存清单,按顺序执行
ss -s > /tmp/snap_ss.txt 2>&1
lsof -p <pid> | wc -l >> /tmp/snap_ss.txt
top -Hp <pid> -b -n 1 > /tmp/snap_threads.txt
kill -3 <pid>            # JVM 打印线程栈到应用日志
dmesg -T | tail -200 > /tmp/snap_dmesg.txt

预防与巡检

  • 每次变更都有回滚方案,并且回滚方案被演练过,不是纸面存在。
  • 核心接口的告警阈值按 P99 设置,而不是按平均值设置。
  • 容量水位常态化巡检:CPU、内存、磁盘、inode、连接数、句柄数。
  • 故障处置流程写在文档里并定期演练,避免凌晨三点靠人回忆。

复盘:把故障变成资产

故障恢复不等于结束。复盘只回答四个问题:什么现象、什么根因、为什么没被提前发现、下次怎么更快恢复。不追责,但必须落到具体的监控项、代码改动或流程修改上,否则同样的故障一年内一定重来。

小结:故障现场的第一优先级是恢复可用性,回滚、摘流量、降级、扩容四选一或组合,动作必须一分钟内生效且可回退;定位按变更、指标、日志、链路、主机的顺序自上而下推进,重启前先保存线程栈与火焰图,最后用复盘把根因变成长期监控与代码改动。

笔记加载中…