线上故障排查与应急响应实战:从零开始建立你的SRE体系
大家好,我是迪哥。2024 年我们的线上故障平均恢复时间(MTTR)是 45 分钟,2025 年降到了 10 分钟,怎么做到的?靠的是完善的应急响应机制和故障排查手册。今天就把压箱底的经验分享给大家。
故障分级:优先级明确
| 级别 | 定义 | 响应时间 | 负责人 |
|---|---|---|---|
| P0 | 全站不可用/核心交易链路不可用 | 立即,5分钟内响应 | 技术负责人 + 各模块负责人 |
| P1 | 重要功能不可用/用户大面积受影响 | 15分钟内响应 | 对应模块负责人 |
| P2 | 小范围功能异常/不影响核心流程 | 1小时内响应 | 开发工程师 |
| P3 | 提示性问题/UI 小瑕疵 | 1天内响应 | 前端/产品 |
应急响应流程(P0 级)
1. 接警与确认(0-5 分钟)
-
告警来源:
- Prometheus 告警(系统级)
- SkyWalking 告警(链路级)
- 监控大盘(业务级)
- 用户反馈
-
确认动作:
bash# 1. 检查服务状态 kubectl get pods -n prod # 2. 查看日志(最近 500 行) kubectl logs --tail=500 -n prod deploy/order-service # 3. 检查错误率 curl http://prometheus/api/v1/query?query=error_rate
2. 止血(5-15 分钟)
优先用这三招:
-
回滚: 新版本上线后出问题,立即回滚上一版本
bashkubectl rollout undo deployment/order-service -n prod -
限流熔断: 流量过大导致雪崩,立即限流
- Sentinel 控制台调整限流规则
- 网关层面限流
-
降级: 非核心功能直接关掉
java
@GetMapping("/api/feature-not-important")
public Result feature() {
if (isDegrade()) {
return Result.success("功能维护中,暂不可用");
}
// 正常逻辑
}
3. 排查(15-30 分钟)
黄金 5 条命令:
bash
# 1. 看 CPU/内存
top
htop
# 2. 看日志
tail -f /var/log/app/error.log
grep "Exception" /var/log/app/error.log
# 3. 看网络
netstat -anp
ss -s
# 4. 看 GC
jstat -gcutil <pid> 1000 10
# 5. 看线程堆栈
jstack <pid> > thread.dump
jmap -dump:format=b,file=heap.hprof <pid>
排查思路:
- 看监控:从大盘找到异常指标
- 看日志:找到错误堆栈
- 看链路:用 SkyWalking 找到慢/错误 Trace
- 想变更:最近上线了什么?
- 查依赖:数据库/MQ/Redis 挂了吗?
4. 恢复与复盘(30+ 分钟)
- 问题解决,验证业务正常
- 复盘会:24 小时内完成
- 5 Whys 分析法
- 写出详细故障报告
- 制定改进计划
常见故障排查手册
故障 1:OOM(内存溢出)
现象:
- Pod 反复 Crash,状态是 OOMKilled
- JVM 日志有
OutOfMemoryError
排查:
bash
# 1. 导出堆
kubectl cp <pod>:/app/dump.hprof ./dump.hprof
# 2. MAT 分析
# 重点看:大对象、内存泄漏
解决:
- 短期:调大
-Xmx - 长期:修复内存泄漏
故障 2:数据库慢查询导致雪崩
现象:
- 数据库 CPU 100%
- 应用请求超时
- 错误率飙升
排查:
sql
-- 1. 查慢日志
SHOW VARIABLES LIKE 'slow_query%';
-- 2. 查正在执行的 SQL
SELECT * FROM information_schema.processlist
WHERE command != 'Sleep'
ORDER BY time DESC;
-- 3. EXPLAIN 分析
EXPLAIN SELECT * FROM orders WHERE status = 0;
解决:
- 加索引
- 优化 SQL
- 限流或降级该功能
故障 3:微服务雪崩
现象:
- A 服务挂了,导致 B、C 都跟着挂
- 连接池耗尽
排查:
- SkyWalking 看拓扑图
- 看哪个服务错误率最高
解决:
- 熔断降级
- 快速扩容
- 优先恢复核心服务
演练:定期做 Chaos Monkey
java
// Chaos Monkey 测试:随机杀 Pod
public class ChaosMonkey {
public static void main(String[] args) {
// 每 10 分钟随机杀一个 Pod(仅在测试环境!)
while (true) {
killRandomPod();
Thread.sleep(TimeUnit.MINUTES.toMillis(10));
}
}
}
应急响应 CheckList
| 序号 | 检查项 | 状态 |
|---|---|---|
| 1 | 核心服务是否正常? | ⬜ |
| 2 | 最近是否有变更? | ⬜ |
| 3 | 数据库/Redis/MQ 是否正常? | ⬜ |
| 4 | 错误率/延迟是否有异常? | ⬜ |
| 5 | 日志中是否有明显报错? | ⬜ |
| 6 | 是否已尝试回滚/限流/降级? | ⬜ |
| 7 | 是否已通知相关人员? | ⬜ |
经验总结
- 止血优先! 不要死磕根因,先恢复服务
- 回滚是第一选择! 大部分故障由变更导致
- 平时要演练! 不要到故障时才发现命令不会敲
- 文档要完善! 尤其是应急手册
- 复盘要落地! 只说不做,下次还会出同样问题
说到故障排查,我家那只叫 Docker 的哈士奇最近拆家越来越有经验,先咬沙发腿(核心服务),再咬靠垫(非核心),我现在练出 5 分钟内就能制止它的应急响应能力 😂
我是迪哥,我们下期再见!
往期推荐: