外观
案例:负载很高但 CPU 空闲
现象
监控告警:load average > 30。但登录机器后 top 显示 CPU 空闲 70%,业务接口也没有明显变慢。
bash
uptime
nproctext
03:12:41 up 3 days, 2:04, load average: 34.21, 31.88, 28.42
88 核机器,load 34,约为 CPU 数的 4 倍。
定位过程
第一步:区分是 CPU 排队还是 IO 等待
bash
vmstat 1 5text
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 -30text
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 /datawchan 全是 rpc_* / nfs_* —— 卡在 NFS 上。
第三步:确认 NFS 状态
bash
mount | grep nfstext
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.200text
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
uptimetext
03:21:12 up 3 days, 2:13, load average: 2.41, 18.88, 26.42根治
- 备份目标改到本地盘或对象存储,不要写 NFS。
- 如果必须用 NFS,挂载参数加容错:
ini
10.0.0.200:/export/backup /backup nfs4 rw,soft,timeo=30,retrans=3,_netdev 0 0| 参数 | 作用 |
|---|---|
soft | 超时后返回错误,而不是无限重试 |
timeo=30 | 30 个 0.1 秒 = 3 秒超时 |
retrans=3 | 重试 3 次 |
_netdev | 等网络就绪再挂载 |
soft 可能导致数据损坏
soft 会让写操作在超时后返回失败,如果应用没检查返回值,可能产生不完整文件。数据库、日志类写入不要用 NFS+soft,宁可本地盘。
- 备份任务加超时:
bash
timeout 3600 /opt/backup/run.sh || echo "backup timeout" | mail -s alert ops@example.com- 监控 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 不够,扩容",扩了也没用。