一次因重启引发的连锁故障

T+0: 用户反馈页面加载但无响应
T+5: 监控显示 CPU、内存正常
T+8: 消息队列积压开始轻微上升
T+12: 重启应用
T+15: 短暂恢复,误以为问题解决
T+20: 连锁故障爆发——积压激增、超时告警涌现、多个下游服务受影响

重启触发了连锁反应:队列里的消息没有消失,消费模式重置,重试逻辑叠加,下游系统被原始流量加积压恢复流量同时冲击。

重启不解决根本问题,只会清除诊断所需的现场证据。


为什么重启会让情况更糟

  1. 队列积压不会消失:重启后消费者重新上线,积压的消息会集中涌入
  2. 重试逻辑叠加:上游系统的重试请求 + 积压消息 = 流量翻倍
  3. 现场被清除:线程快照、内存状态、连接信息全部丢失,根因无从追查
  4. 假恢复信号:重启后短暂正常,掩盖了真正的问题

重启前必做的 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. 记录重启时间戳

精确记录重启时间,便于后续关联日志和指标进行根因分析。


核心原则

保留现场,再采取行动。

诊断信息的价值往往高于快速恢复的价值。一次彻底的根因分析,能防止同类问题反复发生。