服务器负载(Load)高不等于 CPU 使用率高。排查时应先看 load average 三个数值与 CPU 核心数的关系,再结合 top、vmstat、iostat 等工具区分是 CPU 争用、I/O 等待还是 D 状态进程导致。

先说结论:负载高需先判断是否超过 CPU 逻辑核数,再根据 CPU 状态分布(us/sy/wa)定位是计算瓶颈还是 I/O 瓶颈,最后针对具体进程或设备处理。

  • 先定位:用 uptime 或 top 查看 load average 三个数值,对比 CPU 核心数判断是否异常
  • 先做:通过 top 的%CPU 状态分布(us/sy/wa)和 ps 命令排查 D 状态进程
  • 再验证:处理后观察 load1/load5/load15 是否下降,确认 iostat 中 await 和%util 恢复正常

核心概念与负载阈值

负载(Load)是 Linux 系统的重要指标,但它和 CPU 使用率不是一回事。在 UNIX 系统中,系统负载是对当前 CPU 工作量的度量,被定义为特定时间间隔内运行队列中的平均线程数。load average 通常显示三个数字,分别代表 1 分钟、5 分钟、15 分钟内的平均负荷。

负载值反映的是单位时间内处于运行态或不可中断睡眠态(D 状态)的平均进程数。比如单核 CPU 上 load=3,意味着平均有 3 个进程在争抢 CPU 或等待磁盘 I/O,其中 2 个大概率在排队。关键点是:load 高不等于 CPU 满,可能是大量进程卡在磁盘读写、NFS 挂载、锁竞争或内核态等待中。

判断负载是否过高,需结合 CPU 逻辑核心数。以下是常见阈值参考:

CPU 逻辑核心数 负载警戒值 (Load) 状态说明
1 核 > 1.0 开始出现排队
2 核 > 2.0 开始出现排队
4 核 > 4.0 开始出现排队
8 核+ > 核心数 开始出现排队
任意 > 核心数 * 2 严重拥堵,需立即排查

当负载值超过 CPU 逻辑核数时,说明系统存在资源争用;如果负载长期高于 CPU 核心数的 2 倍,需立即排查。

常用命令与输出示例

以下是排查负载问题时最常用的命令,可直接在终端执行。部分命令可能需要 sudo 权限。

# 查看系统负载和运行时间
uptime
# 示例输出:10:30:01 up 10 days,  1:00,  1 user,  load average: 4.50, 3.20, 2.10
# 注意:若 CPU 为 2 核,load average 4.50 表示严重过载

# 查看负载和进程详情
top
# 关注行:Cpu(s):  2.0 us,  1.0 sy,  0.0 ni, 90.0 id,  7.0 wa
# wa 高表示 IO 等待,us 高表示用户态计算多

# 查看 D 状态进程(不可中断睡眠)
# 说明:$8 代表 ps aux 输出的 STAT 列,需 root 权限查看详细信息
sudo ps aux | awk '$8 ~ /D/ { print $0 }'

# 查看 I/O 等待情况
vmstat 1
# 关注列:r (运行队列), b (阻塞进程), wa (IO 等待%)

# 查看磁盘 I/O 性能
iostat -x 1
# 关注列:await (平均响应时间), %util (设备利用率)

# 查看进程 I/O 使用
pidstat -d 1

# 查看内存情况
free -h

分步排查流程

第一步:确认系统整体负载情况

使用 uptime 或 top 命令查看 load average 三个数值。对于 N 核 CPU,负载>N 表示有进程在等待。对比 uptime 和 mpstat -P ALL 1,若 CPU 空闲率高但 load 飙升,基本可排除纯 CPU 瓶颈。

在 top 交互界面关注 CPU 状态分布:us(用户空间)、sy(内核空间)、wa(IO 等待)的占比。us 高可能是应用代码逻辑复杂;sy 高可能是内核调用频繁;wa 高可能是磁盘 IO 瓶颈。

第二步:定位高负载进程

在 top 中找到 CPU 使用率最高的进程 PID,用 ps -ef | grep PID 查看进程所属用户和命令行,判断是否为核心业务进程。若为 Java 进程,可结合 jps -l 确认进程名称。

特殊情况:若 top 中无高 CPU 进程但 Load 很高,可能是内核线程或僵尸进程导致,可用 ps -e -o stat,ppid,pid,command | grep -w defunct 检查僵尸进程。

第三步:排查 D 状态进程

D 状态进程无法被信号中断,通常卡在内核 I/O 路径(如坏盘、NFS 超时、RAID 重建、cgroup 限制、ext4 journal 阻塞)。它们不消耗 CPU,却持续计入 load,是 load 虚高主因。

执行 sudo ps aux | awk '$8 ~ /D/ { print $0 }' 列出所有 D 状态进程。重点检查其 WCHAN 列(内核等待函数),常见如 nfsservd、ext4_journal_start。

风险提示:查看进程内核栈 cat /proc/<PID>/stack 时,若进程处于深度死锁状态,该命令可能导致当前终端阻塞。建议先在测试环境验证,生产环境谨慎操作。

第四步:检查 I/O 延迟与存储瓶颈

即使没有 D 状态进程,高 I/O 等待(%iowait)也会推高 load。用 iostat -x 1 查看 await(平均 I/O 响应时间)、%util(设备忙时百分比)和 avgqu-sz(平均队列长度)。

await 过高表明 I/O 响应变慢,%util 接近 100% 且 avgqu-sz 持续过高,说明设备已饱和。用 lsof +D /path 或 pidstat -d 1 定位高 I/O 进程。

第五步:特定业务场景排查

Java 应用:若负载高但 CPU 不高,可能是线程阻塞或 GC 频繁。使用 jstack <PID> 查看线程状态,检查是否有大量 WAITING 或 BLOCKED 线程。结合 GC 日志查看 Full GC 频率。

MySQL 数据库:检查慢查询日志 slow_query_log,确认是否有全表扫描或锁等待。使用 show processlist 查看是否有大量进程处于 Sending data 或 Locked 状态。

第六步:排查其他隐蔽因素

内存严重不足时,触发直接回收或 OOM Killer 前,进程频繁进入 D 状态等待内存页释放,查 free -h、cat /proc/meminfo | grep -i "oom|commit"。

在虚拟机中,负载可能因宿主机资源竞争而升高。检查 top 中的 st(steal time),高值表示宿主机过载。

验证与自动化监控

处理后持续观察 uptime 输出的 load average 三个数值,确认 load1/load5/load15 呈下降趋势。使用 vmstat 1 查看 r 列(运行队列长度),如果持续小于 CPU 核心数,说明争用减少。

检查 iostat -x 1 中的 await 和%util,确认磁盘 I/O 响应时间恢复正常,设备利用率下降。对于业务服务,观察 SSH 远程连接响应、网站或应用程序响应时间是否改善,请求超时和接口返回失败是否减少。

可部署以下简单脚本进行负载监控告警:

#!/bin/bash
# 简单负载监控脚本示例
CORES=$(nproc)
LOAD=$(uptime | awk -F'load average:' '{ print $2 }' | cut -d',' -f1 | tr -d ' ')
# 判断负载是否超过核心数的 1.5 倍
THRESHOLD=$(echo "$CORES * 1.5" | bc)
if [ $(echo "$LOAD > $THRESHOLD" | bc) -eq 1 ]; then
    echo "Warning: Load $LOAD exceeds threshold $THRESHOLD"
    # 此处可添加告警发送逻辑
fi

常见风险与坑

负载高不等于 CPU 使用率高,直接看 top 或 htop 里的%CPU 容易误判。wa(I/O wait)在现代内核中统计口径有变化,不能单独依赖它判断 I/O 瓶颈,更可靠的是看 iostat -x 1 中的 await、%util 与 avgqu-sz。

重要警告:D 状态进程无法被 kill 终止,大量 D 状态进程堆积表明磁盘响应缓慢,此时强行重启可能加重 I/O 压力甚至导致文件系统损坏。需优先排查存储硬件状态(如 smartctl 检查磁盘健康)。

部分场景下 load 升高与常规资源无关,需针对性验证内核 bug 或驱动异常,如某些在高包量下导致软中断堆积,用 cat /proc/interrupts 观察 CPU 间中断分布是否严重不均。

在虚拟化环境中,steal time 高表示宿主机过载,此时在虚拟机内优化效果有限,需联系云服务商检查宿主机资源。

来源 https://www.zjcp.cc/ask/10912.html

Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐