生产环境收到 Load Average 或 CPU 告警时,最忌讳一上来就重启。负载升高不等于 CPU 一定打满:CPU 运行队列、不可中断 I/O、锁等待、内存回收和虚拟机偷取时间都可能推高负载。本文给出一套可直接照着执行的排查、止血、验证与复盘流程。
一、先明确目标与安全边界
目标不是把负载数字降下来,而是恢复业务并找出可复现、可验证的根因。
先保存现场,再做重启、杀进程、清缓存等改变现场的操作。
生产操作要记录时间、操作者、命令、对象、预期效果和回滚方式。
不要只看一个瞬时值;至少观察 1、5、15 分钟趋势,并与同集群正常节点对比。
二、判断业务影响和变更背景
先确认接口延迟、错误率、吞吐量和队列积压;判断是单机、单可用区还是全链路异常;核对告警前 30 分钟内的发布、扩缩容、批处理、备份、流量突增和配置变更。若用户影响正在扩大,应让一人止血、一人保留现场并行进行。
date -Is
uptime
who
last -n 10
systemctl --failed
journalctl --since "30 min ago" -p warning三、理解 Load Average
Linux 负载近似表示正在运行以及处于不可中断等待状态的任务数量。4 核机器的负载持续高于 4 说明任务开始排队,但不能仅凭这个数字判定故障。容器 CPU 限额、虚拟机 steal、I/O 等待都会让“核数比较法”失真。
nproc
lscpu
cat /proc/loadavg
uptime
vmstat 1 10重点关注 vmstat:r 长期大于可用 CPU 数表示运行队列拥堵;b 持续不为 0 表示任务在不可中断等待;us/sy/wa/st 分别帮助判断用户态、内核态、I/O 等待和虚拟化争抢。
四、10 分钟快速分诊
top -b -n 1 | head -40
mpstat -P ALL 1 5
pidstat -u -r -d -w 1 5
iostat -xz 1 5
free -h
swapon --show
ps -eo state,pid,ppid,user,%cpu,%mem,etime,wchan:24,cmd --sort=-%cpu | head -40分诊结论通常落入四类:CPU 饱和、I/O 或 D 状态堆积、内存压力与交换、锁/外部依赖等待。不要因为 top 中某个进程排第一就直接认定它是根因。
五、CPU 分支:找进程、线程和调用栈
ps -eo pid,ppid,user,ni,stat,%cpu,%mem,etime,cmd --sort=-%cpu | head -30
top -H -p <PID>
pidstat -t -p <PID> 1 10
perf top -p <PID>
# Java 可补充
jstack <PID> > /tmp/jstack.$(date +%s).txt单核 100% 可能是串行热点或死循环;多核同时繁忙可能是流量、批任务或线程数失控。%sys 高时检查系统调用、网络包、上下文切换和驱动;%steal 高时应联系云平台或迁移实例。perf、jstack 等采样工具也有开销,应短时间使用并保留结果。
六、I/O 与 D 状态分支
iostat -xz 1 10
pidstat -d 1 10
ps -eo state,pid,ppid,wchan:32,etime,cmd | awk '$1 ~ /^D/'
cat /proc/pressure/io
dmesg -T | tail -100同时看 await、队列、吞吐和设备利用率;云盘还要核对 IOPS、吞吐和突发额度。D 状态常见于磁盘、NFS、块设备或内核路径等待,普通 kill -9 也未必立即生效。不要在未确认挂载关系时强制卸载文件系统。
七、内存、交换与回收压力
free -h
vmstat 1 10
cat /proc/pressure/memory
ps -eo pid,user,%mem,rss,vsz,stat,cmd --sort=-rss | head -30
journalctl -k --since "2 hours ago" | grep -Ei 'oom|out of memory|killed process'关注 available 而不是只看 free。si/so 持续增长说明频繁换入换出;kswapd 高、memory PSI 高可能是直接回收或工作集超出容量。不要在内存紧张时盲目执行 drop_caches,它不能解决泄漏,还可能制造更多 I/O。
八、锁、进程数和外部依赖
pidstat -w 1 10
ps -eLf | wc -l
cat /proc/sys/kernel/pid_max
ss -s
ss -ant state syn-recv
lsof -p <PID> | head
strace -tt -T -p <PID> -o /tmp/strace.<PID>.log大量线程、上下文切换、连接堆积或 futex 等待,可能来自锁竞争、连接池耗尽或下游超时。strace 只做短时间采样,避免在高频系统调用进程上长期挂载。
九、容器和 Kubernetes 场景
docker stats --no-stream
kubectl top node
kubectl top pod -A --sort-by=cpu
kubectl describe node <NODE>
kubectl get events -A --sort-by=.lastTimestamp | tail -50容器内看到的 CPU 核数可能大于实际配额,需要检查 requests、limits、CPU throttling、节点超售和邻居 Pod。节点高负载时先判断是否可以安全 cordon 并迁移工作负载。
十、止血顺序与回滚
暂停刚启动的批任务、备份或异常流量入口。
从负载均衡摘除异常节点,确认健康节点容量足够。
对接口限流、降级非核心功能,或按既定方案扩容。
确认 PID、业务影响和负责人后再优雅终止异常进程;超时才升级信号。
重启应是最后手段,重启前保存日志、指标、进程和内核现场。
kill -TERM <PID>
sleep 10
ps -p <PID>
# 只有确认无法优雅退出且允许中断时再使用:
kill -KILL <PID>回滚条件要提前写明:错误率上升、健康节点容量不足、数据一致性异常或恢复时间超过窗口时,立即恢复流量、回滚版本或启用灾备。
十一、恢复后的验证
uptime
vmstat 1 5
mpstat -P ALL 1 5
iostat -xz 1 5
systemctl --failed
journalctl --since "10 min ago" -p warning至少验证:用户请求恢复、错误率与延迟回归基线、积压开始下降、负载趋势持续回落、异常进程不再出现、监控和告警恢复。不要用“命令执行成功”代替业务验证。
十二、根因报告应包含什么
时间线:首次异常、告警、止血、恢复和完全消除风险的时间。
证据:指标截图、命令输出、日志、变更记录和相关请求 ID。
根因与诱因:为什么发生、为什么没有提前发现、为什么影响扩大。
行动项:负责人、截止时间、验收标准,包括容量、限流、超时、告警和演练。
十三、预防与监控建议
为 CPU、run queue、D 状态、PSI、磁盘延迟、连接池和关键业务 SLI 建立组合告警;容量规划保留故障冗余;批任务设置并发和资源上限;发布后自动观察;在预案中固化摘流、扩容和回滚步骤。
十四、现场检查清单
□ 业务影响、故障范围和最近变更已确认
□ 1/5/15 分钟趋势及 CPU 核数已记录
□ CPU、I/O、内存、D 状态和外部依赖已分支排查
□ 止血操作有负责人、回滚条件并保留现场
□ 恢复后完成业务、系统、监控三层验证
□ 根因和长期行动项已进入复盘跟踪
总结
高负载排查的关键不是背命令,而是把“业务影响—现场证据—资源分支—安全止血—验证复盘”串成闭环。先辨别 CPU、I/O、内存还是等待,再选择最小影响的动作,才能避免重启掩盖根因。