一次因重启引发的连锁故障
T+0: 用户反馈页面加载但无响应
T+5: 监控显示 CPU、内存正常
T+8: 消息队列积压开始轻微上升
T+12: 重启应用
T+15: 短暂恢复,误以为问题解决
T+20: 连锁故障爆发——积压激增、超时告警涌现、多个下游服务受影响
重启触发了连锁反应:队列里的消息没有消失,消费模式重置,重试逻辑叠加,下游系统被原始流量加积压恢复流量同时冲击。
重启不解决根本问题,只会清除诊断所需的现场证据。
为什么重启会让情况更糟
- 队列积压不会消失:重启后消费者重新上线,积压的消息会集中涌入
- 重试逻辑叠加:上游系统的重试请求 + 积压消息 = 流量翻倍
- 现场被清除:线程快照、内存状态、连接信息全部丢失,根因无从追查
- 假恢复信号:重启后短暂正常,掩盖了真正的问题
重启前必做的 7 件事
1. 记录故障时间窗口
记录问题开始时间、影响范围、受影响的组件。
2. 截图关键指标
保存延迟、队列深度、下游错误率的截图,这些数据重启后就消失了。
3. 抓取运行时快照
# Java 应用抓线程快照
jstack [PID] > /tmp/thread_dump_$(date +%Y%m%d_%H%M%S).txt
# 查看当前连接状态
netstat -antp | grep ESTABLISHED > /tmp/connections.txt
4. 检查重试和积压配置
了解当前队列积压量和重试策略,评估重启后的冲击。
5. 先限流,再重启
在重启前先对入口限流,避免重启后被积压流量冲垮。
6. 灰度重启
不要一次性重启所有实例,先重启一个节点,观察稳定后再继续。
7. 记录重启时间戳
精确记录重启时间,便于后续关联日志和指标进行根因分析。
核心原则
保留现场,再采取行动。
诊断信息的价值往往高于快速恢复的价值。一次彻底的根因分析,能防止同类问题反复发生。