load average 很高但 CPU 很闲:从 D 状态进程到 IO 等待的排查顺序

举报
yd_217417492 发表于 2026/10/30 09:43:00 2026/10/30
【摘要】 load average 把不可中断睡眠的进程也算进去,所以磁盘、NFS 或块存储卡住时,CPU 明明很闲,负载却会飙高。本文按「看队列、找 D 状态、查 IO、定位挂载点」四步排查,并给出监控项建议。

先理解 load average 到底在数什么

很多人把 load average 当成 CPU 使用率,这是排查时第一个误区。Linux 的 load 统计的是处于可运行状态(R)和不可中断睡眠状态(D)的进程数,再取 1、5、15 分钟的平均值。也就是说,一个进程卡在磁盘 IO 或网络文件系统上,同样会把 load 推高,哪怕 CPU 几乎全空闲。

所以看到 load 很高时,先别急着加 CPU,先确认它是「真的在算」还是「在等」。

第一步:看运行队列和阻塞队列

用 vmstat 看 r 和 b 两列,比只看 load 有用得多:

vmstat 1 5
# procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
#  r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
#  2  8      0 512000  12000 980000    0    0  1200  3400  800 1500  5  3 80 12  0

如果 r 很小、b 很大,说明大量进程在等资源,而不是在抢 CPU;如果 wa(IO wait)也高,方向基本就确定了。反过来,r 长期大于 CPU 核数,才是真正的 CPU 不足。

顺便记一下核数,load 要和它比:4 核机器上 load 4 约等于满载,16 核机器上 load 4 很轻松。

第二步:把 D 状态进程揪出来

D 状态是「不可中断睡眠」,普通 kill -9 也杀不掉,通常是在等内核里的 IO 完成。列出它们:

ps -eo state,pid,ppid,wchan:24,comm | awk '$1 ~ /^D/'
# D  18342     1 do_fsync                 python3
# D   9912  9800 nfs_wait_on_request      tar

wchan 显示进程卡在哪个内核函数,do_fsync、nfs_wait_on_request、blkdev_issue_flush 这类名字已经能说明问题。需要更细的内核栈时,root 可以看:

cat /proc/18342/stack

如果 D 状态进程只是零星出现、很快消失,不必紧张;持续几分钟不消失,才是故障。

第三步:确认是本地磁盘还是网络存储

本地块设备看 iostat -x 1,重点不是 %util 一个数字,而是 await 和队列深度:

iostat -x 1 3
# Device  r/s   w/s   rkB/s  wkB/s  await  aqu-sz  %util
# vda    120   340   4800  13600   38.2    12.4   99.0

await 几十毫秒、aqu-sz 持续升高,说明设备已经排队。%util 对 NVMe 和多队列设备并不完全准确,不要只盯它。

如果瓶颈在 NFS 或云厂商的块存储,iostat 可能看不出异常,这时要看挂载点和内核日志:

mount | grep -E 'nfs|cifs'
dmesg -T | tail -50
nfsstat -c

NFS 服务端不响应时,访问该挂载点的进程会集体进入 D 状态,load 瞬间升高,但本地磁盘一切正常。这类问题重启本机没用,要么恢复网络,要么用 umount -f / -l 处理挂载点。

第四步:排除内存和 cgroup 的干扰

内存不足时,进程频繁换入换出,也会表现为 IO 等待和 D 状态。看 vmstat 的 si/so 是否长期非零,以及 free -m 的可用内存:

free -m
vmstat 1 5 | awk 'NR>2 {print $7, $8}'

在容器里,还要看 cgroup 的限流,而不是宿主机总负载:

cat /sys/fs/cgroup/io.stat
cat /sys/fs/cgroup/cpu.stat

容器的 io.stat 里 ios 和 wbytes 增长很快、同时应用变慢,说明是磁盘配额或底层设备在限速。

常见诱因与处理顺序

按出现频率排,大概是这几类:日志同步写太多(每个请求一次 fsync)、数据库刷盘、备份或打包任务在高峰期跑、NFS/对象存储挂载点失联、磁盘本身到了 IOPS 上限。处理时先限流和错峰,再考虑换盘或拆分挂载点;直接加 CPU 对 IO 瓶颈没有帮助。

临时缓解可以把非关键任务 ionice 降级,或把日志改成批量落盘;但这些都是止痛,根因还是要落到具体的 IO 路径上。

监控建议

不要只对 load 设阈值。更实用的组合是:D 状态进程数、iowait 占比、设备 await、以及「load 与 CPU 使用率背离」这个条件。比如 load 超过核数两倍但 CPU 使用率低于 30%,就值得告警——这通常意味着有东西在等 IO,而不是在算。

排查顺序可以记成一句话:先看 vmstat 的 r/b,再找 D 状态和 wchan,然后用 iostat 或挂载点确认 IO 路径,最后才考虑内存和 cgroup。这样就不会被「load 高」这个表象带着去加 CPU 了。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。