线上故障处理流程
线上 JVM 故障处理要兼顾恢复和定位。资深工程师不会一上来就改参数,而是先判断影响范围,保留证据,再选择最小风险动作恢复服务。
# 1. 先判断故障类型
常见 JVM 相关故障:
- CPU 飙高。
- 内存持续增长。
- 频繁 Full GC。
- OOM。
- 线程池耗尽。
- 死锁。
- 响应时间抖动。
- 容器 OOMKilled。
不同故障采集证据不同。
# 2. 保留现场
在重启前尽量保留:
- 线程 dump。
- 堆 dump。
- GC 日志。
- JFR。
- JVM 参数。
- 系统指标。
- 应用日志。
- 容器事件。
如果服务已经严重不可用,要优先恢复,但恢复后要复盘为什么没有自动保留证据。
# 3. CPU 高处理
采集:
top -Hp。jstack多次。- JFR。
- CPU profile。
判断:
- 是否死循环。
- 是否 GC 线程高。
- 是否锁竞争。
- 是否热点接口流量异常。
# 4. 内存问题处理
采集:
- GC 日志。
- 堆 dump。
- 类直方图。
- 容器内存指标。
- NMT。
判断:
- 堆 OOM。
- 元空间 OOM。
- 直接内存 OOM。
- native thread OOM。
- 容器 OOMKilled。
# 5. Full GC 处理
采集:
- GC 日志。
jstat。- 堆 dump。
- 业务流量曲线。
判断:
- 老年代是否回收不掉。
- 是否大对象分配。
- 是否元空间触发。
- 是否显式 GC。
- 是否发布后对象模型变化。
# 6. 恢复动作
可能动作:
- 限流。
- 下线异常实例。
- 临时扩容。
- 重启单个实例。
- 回滚发布。
- 关闭异常任务。
- 降低批处理并发。
恢复动作要尽量可回滚,并记录执行时间点。
# 7. 复盘
复盘要回答:
- 故障根因是什么。
- 为什么监控没有提前发现。
- 为什么自动恢复没有生效。
- 是否缺少 dump 或日志。
- 是否需要容量调整。
- 是否需要代码修复。
- 是否需要压测覆盖。
# 8. 阶段小结
线上 JVM 故障处理要遵循“先稳态、留证据、再定位、后修复”的原则。不要在没有证据的情况下盲目调参,也不要为了保留现场而放任故障扩大。恢复和定位要平衡。
# 9. 故障处理优先级
发现故障
│
├─ 是否影响核心链路?
│ ├─ 是 -> 先止血:限流/摘实例/回滚/扩容
│ └─ 否 -> 保留更多现场
│
├─ 保留证据
│ ├─ jstack
│ ├─ GC 日志
│ ├─ heap dump
│ ├─ JFR
│ └─ 业务日志
│
├─ 定位根因
│
├─ 修复和灰度
│
└─ 复盘与监控补齐
线上处理不是“定位第一”,而是“业务影响第一”。但如果每次都只重启不留证据,问题会反复出现。
# 10. 现场采集清单
| 故障 | 必采 | 可选 |
|---|---|---|
| CPU 高 | top -Hp、多次 jstack | JFR、profiler |
| OOM | heap dump、GC 日志、JVM 参数 | NMT、class histogram |
| Full GC | GC 日志、heap dump | JFR |
| 死锁 | jstack -l | JFR |
| 容器 OOMKilled | 容器事件、RSS、JVM 参数 | NMT |
# 11. Tips 快问快答
Q:线上故障能不能直接重启?
A:严重影响业务时可以,但重启前尽量保留最小证据集,比如线程栈、GC 日志、容器事件。
Q:为什么故障复盘要看监控缺口?
A:如果问题只能靠用户反馈发现,说明可观测性不足,后续还会慢发现。
Q:dump 太大抓不了怎么办?
A:先抓 class histogram、JFR、线程栈、GC 日志,必要时摘流量后再 dump。
Q:临时扩容算修复吗?
A:通常只是止血。根因修复还要回到代码、参数或容量模型。
上次更新: 2026/06/24, 16:03:01