这是《Spring Boot 与 Spring Cloud 零基础实战指南》的独立章节版。本章从概念、实操和生产排查三个视角展开,代码块保留了原书可直接运行的版本。 故障排查的目标是快速恢复,其次才是找根因。先止血、保留证据、再修复和复盘。微服务故障往往跨多层,需要同时看入口、服务、依赖和平台。
26.1 应急流程
1. 发现和确认影响
2. 通知相关团队
3. 保留现场证据
4. 尝试止血
5. 验证恢复
6. 根因分析
7. 修复和发布
8. 复盘和预防
止血方式:
- 回滚版本;
- 扩容;
- 降级非核心功能;
- 切换流量;
- 重启实例;
- 限流;
- 修复配置;
- 数据库紧急处理。
26.2 分层排查
入口
-> DNS / LB / Gateway
-> Service
-> Controller
-> Service Layer
-> DB / Cache / MQ / Downstream
-> Platform
-> Pod / Node / Network
先确认影响范围:
| 范围 | 方向 |
|---|---|
| 单实例 | 节点或实例问题 |
| 某服务所有实例 | 代码、配置、依赖 |
| 某机房 | 网络、依赖、云资源 |
| 全站 | 网关、DNS、核心依赖 |
| 某用户 | 权限、数据、缓存 |
| 某接口 | SQL、下游、业务逻辑 |
26.3 接口 5xx
排查:
1. 网关访问日志
2. 服务错误日志
3. traceId 链路
4. 异常类型和堆栈
5. 发布和配置变更
6. 依赖健康状态
常见原因:
| 异常 | 方向 |
|---|---|
| NullPointerException | 代码和数据边界 |
| SQLSyntaxErrorException | 发布脚本或实体映射 |
| ConnectTimeoutException | 下游不可用 |
| Pool exhaustion | 慢 SQL 或下游慢 |
| ClassNotFoundException | 依赖或打包问题 |
| IllegalStateException | 状态机和初始化顺序 |
26.4 接口慢
查看分段耗时:
总耗时
网关耗时
服务内部耗时
SQL 耗时
RPC 耗时
Redis 耗时
锁等待
线程池排队
常见瓶颈:
- N+1 查询;
- 缺索引;
- 下游超时;
- 缓存失效;
- 大 JSON;
- synchronized 竞争;
- GC 停顿;
- CPU throttling。
26.5 服务不可用
应用检查:
curl http://host:8080/actuator/health
ps -ef | grep java
jcmd <pid> Thread.print
ss -lntp | grep 8080
容器检查:
kubectl get pod -o wide
kubectl describe pod <pod>
kubectl logs <pod> --previous
kubectl exec -it <pod> -- sh
常见问题:
| 现象 | 原因 |
|---|---|
| OOMKilled | 容器内存 |
| CrashLoopBackOff | 启动异常 |
| ImagePullBackOff | 镜像或凭证 |
| Pending | 资源或调度 |
| readiness fail | 健康检查 |
| restart count 高 | 异常退出 |
26.6 线程池耗尽
现象:
- 请求排队;
- rejected 增长;
- CPU 低;
- 大量线程 BLOCKED 或等待 IO。
排查:
jcmd <pid> Thread.print > thread.txt
方向:
- 下游超时缺失;
- 数据库连接不足;
- 锁竞争;
- 任务执行慢;
- 队列无界;
- 流量突增。
处理:
- 限流;
- 降级;
- 设置超时;
- 隔离线程池;
- 修复慢依赖;
- 再评估容量。
26.7 数据库故障
现象:
- 连接池 pending;
- SQL 超时;
- 锁等待;
- 主从延迟;
- 磁盘 IO 高。
排查:
show processlist;
show engine innodb status;
select * from information_schema.innodb_trx;
处理:
- kill 明确异常的长时间事务;
- 回滚问题 SQL;
- 限流写入;
- 切换读库;
- 联系 DBA;
- 事后补索引和优化。
26.8 消息积压
排查:
- consumer lag;
- 消费耗时;
- 重试和死信;
- 分区分布;
- 消费实例数;
- 下游状态。
处理:
- 扩容消费者,不能超过有效并发能力;
- 临时降级非关键逻辑;
- 修复慢消费;
- 跳过无效死信,必须记录;
- 提高下游吞吐;
- 观察消费幂等。
26.9 保留证据
必须保存:
时间线
告警截图
监控快照
trace 链接
GC 日志
线程 dump
堆 dump
应用日志
网关日志
平台事件
变更记录
聊天记录
重启前优先保留:
jcmd <pid> Thread.print > thread.txt
jcmd <pid> GC.heap_dump heap.hprof
jcmd <pid> VM.flags > flags.txt
注意 heap dump 会 STW,要评估影响。
26.10 故障复盘
模板:
故障编号
时间
影响
时间线
根因
触发条件
为什么没有提前发现
为什么没有自动恢复
应急过程
改进项
负责人和截止时间
改进动作要具体、可测量、有负责人和截止时间。
本章小结
故障排查要先确认影响范围,再按入口、服务、依赖和平台分层定位。常见故障集中在 5xx、慢请求、线程池耗尽、数据库、消息积压和容器资源。应急时先止血并保留证据,恢复后通过复盘把发现和恢复能力产品化。
思考题
- 为什么先止血再根因分析?
- 如何确认故障影响范围?
- CPU 低但请求排队说明什么?
- 消息积压时如何安全扩容?
- 故障复盘最重要的输出是什么?