Load Average 都到 20 了CPU 为什么只有 30%线上告警显示load average: 20.18, 18.62, 15.41但监控里的CPU使用率只有30%。很多人看到这里会怀疑监控是不是坏了 Load Average不是CPU负载吗 负载都到20了CPU为什么还没跑满答案是Linux的Load Average从来不只是CPU使用率。它统计的不仅包括正在运行和等待CPU的任务还包括处于不可中断睡眠状态、通常正在等待I/O的任务。所以“Load很高、CPU不高”完全可能同时发生。说明文中命令以常见Linux环境为例pidstat、iostat等工具通常来自sysstat软件包。生产操作前请确认权限和系统发行版差异。一、Load Average 三个数字分别是什么执行uptime可能看到10:21:06 up 37 days, 4 users, load average: 20.18, 18.62, 15.41三个数字分别表示最近1分钟平均负载 5分钟平均负载 15分钟平均负载它们不是CPU百分比也不是单纯的进程数量。Linux的/proc/loadavg统计正在运行或等待运行的任务状态R 等待磁盘I/O等资源的任务状态D因此下面两种情况都可能让Load上升大量线程在等待CPU 大量线程在等待I/O第一种往往伴随CPU升高。第二种可能出现CPU并不高但Load持续上升。二、Load 20 到底算不算高不能脱离CPU核心数判断。先看逻辑CPU数量nproc如果机器只有4个逻辑CPULoad 20意味着平均有大量任务正在运行或等待资源压力很大。如果机器有64个逻辑CPULoad 20仅凭这个数字还不能判断CPU已经过载。可以先粗略计算单位CPU负载 Load Average / 逻辑CPU数量例如4核机器20 / 4 5 64核机器20 / 64 0.3125但这只是第一步。即使单位CPU负载不高如果大量任务处于D状态系统仍然可能卡顿。三、先用 vmstat 判断是在等CPU还是等I/O执行vmstat1重点看r正在运行或等待CPU的任务数 b处于不可中断睡眠、通常等待I/O的任务数 us用户态CPU使用率 sy内核态CPU使用率 waCPU等待I/O的时间比例情况一r很高us或sy也很高例如r b us sy wa id 28 0 72 18 1 9说明主要是CPU竞争可运行线程太多 CPU密集计算 频繁系统调用 线程池并发过大情况二b很高CPU还有大量空闲例如r b us sy wa id 2 23 18 5 31 46说明大量任务被I/O阻塞。CPU没有跑满是因为线程在等磁盘、网络文件系统或块设备返回。这正是“Load 20、CPU 30%”最常见的原因之一。四、直接找出R状态和D状态的进程先看当前任务状态ps-eostate,pid,ppid,comm,wchan:32\|awk$1 ~ /^[RD]/ {print}常见状态R正在运行或等待CPU D不可中断睡眠通常正在等待I/O S可中断睡眠如果出现大量D状态进程要继续看它们是不是同一个Java进程的线程 是否都在访问同一个挂载目录 是否集中在磁盘、NFS或块设备调用 wchan显示在等待哪个内核函数也可以快速统计ps-eostate|sort|uniq-c如果D状态数量与Load同步增长方向基本就明确了。五、用 pidstat 判断具体进程在消耗什么执行pidstat-u-d-w1它可以同时观察CPU使用 磁盘读写 上下文切换重点关注%CPU进程CPU占用 kB_rd/s每秒读取 kB_wr/s每秒写入 cswch/s主动上下文切换 nvcswch/s非主动上下文切换几种典型信号现象可能方向%CPU持续很高CPU密集或忙循环读写速率很高磁盘吞吐压力读写不高但等待严重存储延迟、锁或远端文件系统上下文切换非常高线程过多、锁竞争或频繁阻塞唤醒不要只看Java进程总CPU。一个拥有几百个线程的进程可能总体CPU不高但大量线程都堵在同一个I/O点上。六、用 iostat 判断是不是磁盘把任务堵住了执行iostat-xz1重点看%util设备忙碌程度 awaitI/O平均等待时间 avgqu-sz平均队列长度 r/s、w/s每秒读写次数 rkB/s、wkB/s每秒吞吐量不要单独盯着%util。不同存储设备、虚拟化环境和并行能力下%util的含义并不完全相同。更重要的是结合await是否明显高于正常基线 队列是否持续增长 业务响应时间是否同步上升 是否只有某块盘异常如果日志目录、临时目录和业务数据都在同一块盘上一次日志暴涨就可能拖慢整个服务。七、Java服务还要看线程到底卡在哪里先找到Java进程jcmd假设PID是28431查看线程top-H-p28431如果是CPU问题找到占CPU较高的线程ID转成十六进制printf%x\n线程ID再在线程栈中查找jstack28431/tmp/jstack-$(date%s).log如果是I/O等待要关注大量线程是否集中在文件读写 网络文件系统 日志输出 数据库驱动 Socket读取 进程外部命令Load Average告诉你“系统里等待的任务多”。线程栈才告诉你“Java线程到底在等什么”。八、这次事故的根因日志写入远程挂载目录这次故障里CPU长期只有30%左右。但系统中出现了大量D状态线程。继续排查发现应用日志目录挂载在远程文件系统 远端存储出现延迟抖动 同步日志写入线程被阻塞 大量业务线程又在等待日志锁最终形成远程存储变慢 → 日志写入阻塞 → Java线程不断堆积 → D状态任务增加 → Load Average持续上升 → 接口响应越来越慢CPU并不需要跑满。线程只是都在等待。将日志切回本地磁盘、恢复异步采集后D状态任务下降Load也逐步恢复。如果你身边有人一看到Load升高就准备加CPU可以把这篇转给他先分清R队列和D状态再决定要不要扩容。九、另外三种容易忽略的情况1. 容器CPU配额宿主机CPU可能只有30%但某个容器已经用满自己的CPU配额。这时需要同时检查宿主机CPU 容器CPU限制 容器throttling指标 Java可见处理器数量2. 短时高峰已经过去CPU监控可能展示当前值而Load Average是1、5、15分钟平均值。短时CPU高峰刚结束后CPU可以迅速下降但5分钟、15分钟Load不会立刻归零。3. 大量线程频繁切换线程数过多、锁竞争严重时系统可能花费大量成本在线程调度和上下文切换上。此时单看业务CPU利用率很容易低估调度压力。十、我的排查顺序遇到“Load高、CPU不高”我会按这个顺序检查1. uptime确认1、5、15分钟趋势 2. nproc确认CPU核心数 3. vmstat 1区分r队列和b队列 4. ps统计R状态和D状态任务 5. pidstat定位具体进程与切换情况 6. iostat检查设备延迟和队列 7. top -H定位Java热点线程 8. jstack确认线程到底在等待什么 9. 检查容器CPU配额和throttling 10. 与发布、备份、日志和存储变更对齐时间线Load Average不是结论只是入口。写在最后看到Load高不要立刻得出“CPU不够”的结论。先回答两个问题有多少任务在等CPU 有多少任务在等I/OCPU使用率回答的是处理器有多忙。Load Average回答的是系统中有多少任务正在运行或等待资源。两者相关但从来不是同一个指标。本文归入「生产环境保命清单」系列后续会继续整理Linux资源、JVM和线上卡顿排查案例。你遇到过CPU不高、Load却持续飙升的情况吗最后根因是磁盘、NFS、容器限额还是线程竞争欢迎在留言区留下你的答案。系列导航上一篇《HikariCP可用连接从30掉到0一次连接泄漏的完整排查》下一篇预告《Nginx报upstream timed out3个timeout到底该改哪个》关注我回复关键词保命获取「生产环境保命清单」全部文章。也可以把脱敏后的uptime、vmstat、iostat和线程状态发来我会尽量帮你判断下一步应该查哪里。