故障排查思路
方法论
系统化的故障排查方法可以显著缩短平均修复时间 (MTTR)。以下是几种经典方法。
1. 自上而下法
从应用层 → 系统层 → 硬件层逐步排查,适合对系统架构不熟悉时使用。
应用日志 → 中间件 → 操作系统 → 硬件/网络
2. 自下而上法
从硬件 → 系统 → 应用,适合有明显硬件问题时使用。
硬件/网络 → 操作系统 → 中间件 → 应用日志
3. 二分法
将排查范围不断对半缩小,适合大规模分布式系统。
整体故障 → 50% 节点 → 25% 节点 → 定位目标
通用排查流程
发现问题
│
▼
影响评估(范围、严重程度)
│
▼
收集信息(日志、指标、现场)
│
▼
提出假设
│
▼
验证假设
├── 正确 → 修复/回滚
└── 错误 → 新假设
│
▼
验证修复
│
▼
复盘总结
常见故障场景
CPU 负载过高
# 1. 确认现象
uptime # 负载值
top # 查看 CPU 最高的进程
# 2. 定位进程
top -bn1 | head -20 # CPU 排序
ps aux --sort=-%cpu | head -10
# 3. 深入分析
perf top -p <PID> # 热点函数
strace -p <PID> -c # 系统调用统计
gdb -p <PID] # 动态调试(谨慎)
# 4. 常见原因
- 无限循环(死循环、空转)
- 密集计算(压缩、加密、图片处理)
- GC 频繁(内存不足导致的 Full GC)
- 线程数过多导致上下文切换
内存泄漏
# 1. 确认内存持续增长
pidstat -r 5 | grep <PID>
# 2. 查看堆内存
pmap -x <PID> | sort -k3 -rn | head
# 3. 生成堆转储分析
jmap -dump:live,format=b,file=/tmp/heap.hprof <PID> # Java
# 4. 常见原因
- 全局集合(HashMap、ArrayList)无限增长
- 未关闭的连接(数据库、HTTP、文件流)
- 缓存未设置过期策略
- 事件监听器未正确移除
磁盘 I/O 高
# 1. 确认磁盘压力
iostat -x 1 # %util, await, r/s, w/s
iotop # 按进程查看
# 2. 定位 I/O 来源
lsof /data # 哪些进程在访问
fatrace # 文件系统事件追踪
# 3. 分析 I/O 模式
blktrace -d /dev/sda -o trace
blkparse trace -o trace.txt
# 4. 常见原因
- 大量日志写入未缓冲
- Swap 频繁(内存不足)
- 数据库全表扫描
- 定时任务集中执行
网络故障
# 1. 基础连通性检查
ping <target>
tcping <host> <port> # TCP ping
# 2. 路由追踪
traceroute -n <target>
mtr -r <target>
# 3. 端口与服务
ss -tlnp # 监听端口
curl -v http://<host>:<port> # HTTP 测试
# 4. DNS 检查
dig <domain>
nslookup <domain>
# 5. 抓包分析
tcpdump -i eth0 host <ip> -w capture.pcap
tshark -r capture.pcap -Y "http.response.status >= 500"
# 6. 常见原因
- DNS 解析失败或缓存污染
- 防火墙/安全组规则拦截
- SSL 证书过期
- 连接数耗尽(TIME_WAIT 过多)
- MTU 不一致导致分片问题
应用响应慢
# 1. 端到端延迟测量
time curl -o /dev/null https://api.example.com
# 2. 逐层排查
- 浏览器 F12 → 网络请求耗时
- 反向代理日志 → upstream_response_time
- 应用日志 → 请求处理耗时
- 数据库慢查询日志
# 3. 应用 Profiling
# 使用 async-profiler(Java)
./profiler.sh -d 30 -o flamegraph -f profile.html <PID>
# 4. 常见原因
- 数据库查询慢(缺少索引、锁等待)
- 外部 API 调用超时
- 线程池耗尽
- GC 停顿
- 缓存未命中
故障复盘模板
事故事实
- 时间:2024-01-15 14:30-15:10 UTC+8
- 影响:订单服务不可用 40 分钟
- 范围:影响所有线上用户下单功能
- 等级:P0 核心故障
时间线
14:30 告警触发:订单接口 5xx 错误率 > 10%
14:32 值班工程师确认告警
14:35 定位到数据库连接池耗尽
14:40 发现慢查询阻塞连接释放
14:45 终止慢查询,连接池恢复
14:50 订单服务恢复正常
15:10 根因定位完成
根因分析
- 直接原因:新发布的报表查询未加 LIMIT,扫描 500 万行数据
- 根本原因:代码审查未发现 SQL 问题,缺乏慢查询监控告警
- 系统原因:无 SQL 审核流程,无压测环节
改进措施
- 短期:增加慢查询自动 Kill 机制
- 中期:上线 SQL 审核平台
- 长期:建立性能回归基线,压测纳入 CI
总结
故障排查的核心是方法论而非运气。建立标准化的排查流程,积累常见场景的快速诊断命令,维护故障知识库,持续改进系统可观测性,才能逐步缩短 MTTR。每次故障都是改进的机会,做好复盘,让系统越来越健壮。