Skip to content

案例:负载很高但 CPU 空闲 ​

现象 ​

监控告警:load average > 30。但登录机器后 top 显示 CPU 空闲 70%,业务接口也没有明显变慢。

bash
uptime
nproc
text
 03:12:41 up 3 days,  2:04,  load average: 34.21, 31.88, 28.42
8

8 核机器,load 34,约为 CPU 数的 4 倍。

定位过程 ​

第一步:区分是 CPU 排队还是 IO 等待 ​

bash
vmstat 1 5
text
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 1 26      0 184320  12800 512000    0    0   240  1024 4200 8100  3  2 18 77  0
 0 27      0 182112  12800 508800    0    0   120   512 4100 7800  2  1 20 77  0

关键三列:

  • r=0:没有进程在等 CPU。
  • b=27:27 个进程处于不可中断睡眠。
  • wa=77:CPU 有 77% 时间在等 IO。

第二步:找出 D 状态进程 ​

bash
ps -eo pid,stat,wchan:28,etime,cmd | awk '$2 ~ /^D/' | head -30
text
   PID STAT WCHAN                        ELAPSED CMD
 12841 D    rpc_wait_bit_killable        03:12:44 java -jar /app/app.jar
 12842 D    rpc_wait_bit_killable        03:12:44 java -jar /app/app.jar
 12902 D    nfs_file_direct_read         01:42:11 tar -czf /backup/app.tar.gz /data
 12903 D    rpc_wait_bit_killable        01:42:10 tar -czf /backup/app.tar.gz /data

wchan 全是 rpc_* / nfs_* —— 卡在 NFS 上。

第三步:确认 NFS 状态 ​

bash
mount | grep nfs
text
10.0.0.200:/export/backup on /backup type nfs4 (rw,relatime,vers=4.1,rsize=1048576,wsize=1048576,hard,proto=tcp,timeo=600,retrans=2)

hard + timeo=600(60 秒)+ retrans=2:服务端不可达时,进程会无限重试,永远卡在 D 状态。

bash
showmount -e 10.0.0.200
ping -c 3 10.0.0.200
text
clnt_create: RPC: Port mapper failure - Unable to receive: errno 113 (No route to host)

NFS 服务器不可达。

bash
df -h /backup

卡住十几秒后:

text
df: /backup: Input/output error

确认。

处置 ​

立即止血 ​

bash
# 1. 杀掉备份任务(D 状态可能杀不掉,先试 TERM)
kill -15 12902
# 若仍不退出,需等 RPC 超时,或强制卸载

# 2. 强制卸载(会失败,如果仍有进程占用)
umount -f /backup

如果 umount -f 失败:

bash
# 找占用进程
lsof /backup
# 杀掉后重试
umount -l /backup      # 懒卸载:立刻从命名空间摘掉,等引用释放后真正卸载

umount -l 之后,D 状态进程会很快收到错误返回并退出,load 随之下降。

bash
uptime
text
 03:21:12 up 3 days,  2:13,  load average: 2.41, 18.88, 26.42

根治 ​

  1. 备份目标改到本地盘或对象存储,不要写 NFS。
  2. 如果必须用 NFS,挂载参数加容错:
ini
10.0.0.200:/export/backup /backup nfs4 rw,soft,timeo=30,retrans=3,_netdev 0 0
参数作用
soft超时后返回错误,而不是无限重试
timeo=3030 个 0.1 秒 = 3 秒超时
retrans=3重试 3 次
_netdev等网络就绪再挂载

soft 可能导致数据损坏

soft 会让写操作在超时后返回失败,如果应用没检查返回值,可能产生不完整文件。数据库、日志类写入不要用 NFS+soft,宁可本地盘。

  1. 备份任务加超时:
bash
timeout 3600 /opt/backup/run.sh || echo "backup timeout" | mail -s alert ops@example.com
  1. 监控 D 状态进程数:
bash
ps -eo stat | grep -c '^D'

持续 > 5 就告警。

复盘 ​

问题根因改进
load 高但 CPU 空闲27 个 D 状态进程监控 b 列和 D 状态数
D 状态卡死NFS hard 挂载 + 服务端不可达改 soft 或换存储
备份拖垮业务备份直接写共享 NFS先写本地再异步上传
没人发现 NFS 挂了只监控了 load加 NFS 可达性探测
bash
# 探测 NFS
timeout 5 showmount -e 10.0.0.200 >/dev/null || echo "NFS DOWN"

load average 的正确解读

load 统计的是 R(等 CPU)+ D(等 IO) 的进程数。

  • load 高 + CPU 高 → 计算瓶颈。
  • load 高 + CPU 低 + b 高 → IO/锁/网络文件系统。

第二种最容易被误判成"CPU 不够,扩容",扩了也没用。