云计算百科
云计算领域专业知识百科平台

Ubuntu零基础入门到精通【10.8讲】:Load Average 深度解析 - 从“系统负载“到真正读懂服务器压力!

🏆 本文收录于 《滚雪球学 Ubuntu》 专栏。 本专栏面向有一定计算机基础,但尚未系统学习 Linux / Ubuntu 的读者,采用“滚雪球式学习法”:先装好、再会用、再理解、再优化、再实战,带你从第一次进入 Ubuntu 桌面 / 终端开始,逐步掌握 Ubuntu 的日常使用、命令操作、软件安装、系统配置、开发环境搭建与服务器部署能力。   🎯 适合人群: Linux 初学者、Ubuntu 新手、计算机专业学生、后端 / 运维 / 测试入门同学、想搭建 Linux 开发环境的开发者、准备学习服务器部署的同学,以及想从 Windows 过渡到 Ubuntu 工作流的用户。

从“会打开终端”到“能管理系统”,从“复制命令”到“理解 Linux 思维”,这一次,我们不零散学,而是一路滚雪球!   🎉 限时福利:当前专栏活动中,一次订阅,终身阅读,后续更新章节全部免费解锁 👉 立即查看 👈️

演示环境说明:

  • 开发工具:Visual Studio Code / JetBrains 系列 IDE / Vim / Nano
  • Ubuntu版本:Ubuntu 22.04 LTS / Ubuntu 24.04 LTS,推荐 Ubuntu 24.04 LTS
  • Linux内核版本:Linux Kernel 6.x 或更高
  • 终端环境:Bash / Zsh
  • 包管理工具:APT / Snap / Flatpak
  • 远程连接工具:OpenSSH / Windows Terminal / MobaXterm / Termius
  • 虚拟化环境:VMware Workstation / VirtualBox / WSL2 / 云服务器
  • 容器环境:Docker / Docker Compose
  • 操作系统:Ubuntu Desktop / Ubuntu Server

全文目录:

    • 一、前言:那个让很多人困惑的数字
    • 二、本文要解决什么问题
    • 三、Load Average 是什么:从定义出发
      • 3.1 官方定义与直白解释
      • 3.2 三个数字分别代表什么
      • 3.3 Load Average 和 CPU 使用率的本质区别
    • 四、CPU 核心数:读懂 Load Average 的关键变量
      • 4.1 为什么核心数那么重要
      • 4.2 怎么查看 CPU 核心数
      • 4.3 Load Average 的"合理范围"
    • 五、哪些进程会贡献到 Load Average
      • 5.1 运行状态(R)
      • 5.2 不可中断睡眠状态(D):最容易被忽视的贡献者
      • 5.3 Load Average 高未必是 CPU 的锅
    • 六、实验环境准备
    • 七、案例一:用 uptime 和 top 读懂 Load Average
      • 7.1 uptime 命令:最快速的负载快照
      • 7.2 top 命令中的 Load Average
      • 7.3 htop 中的直观展示
      • 7.4 命令解析
    • 八、案例二:模拟高负载场景,亲眼看 Load Average 上升
      • 8.1 使用 stress-ng 模拟 CPU 压力
      • 8.2 使用 stress-ng 模拟 I/O 压力
      • 8.3 对比两种负载的区别
      • 8.4 命令解析与观察要点
    • 九、案例三:生产环境中的 Load Average 异常排查
      • 9.1 场景描述
      • 9.2 第一步:确认负载情况
      • 9.3 第二步:判断是 CPU 型还是 I/O 型
      • 9.4 第三步:找出具体进程
      • 9.5 第四步:深入分析
      • 9.6 命令解析与排查思路总结
    • 十、Load Average 的计算原理
      • 10.1 指数加权移动平均
      • 10.2 为什么 1 分钟和 15 分钟的值差异重要
    • 十一、Load Average 与其他监控指标的联合分析
      • 11.1 结合 CPU 使用率
      • 11.2 结合内存使用率
      • 11.3 结合 I/O 状态
      • 11.4 结合进程状态
    • 十二、核心命令与工具汇总解析
      • 12.1 uptime
      • 12.2 top / htop
      • 12.3 vmstat
      • 12.4 iostat
      • 12.5 sar
      • 12.6 /proc/loadavg
    • 十三、常见问题与踩坑总结
    • 十四、最佳实践建议
    • 十五、扩展知识:从 Load Average 延伸出的系统调优方向
    • 十六、完整排查流程回顾
    • 十七、总结
    • 🧧 学习福利 · 限时开放 🧧
    • 🫵 Who am I?

一、前言:那个让很多人困惑的数字

我第一次认真盯着服务器看 uptime 输出的时候,大概是在处理一次生产事故的凌晨两点。屏幕上显示的那三个数字——3.42, 5.17, 4.88——对我来说就像是三个没有单位的谜语。我大概知道这是"系统负载",但我完全不知道这意味着高还是低,也不知道该拿这个数字去做什么判断。

这种困惑并不少见。Load Average(系统平均负载)是 Linux 系统监控中出现频率最高的指标之一,几乎所有服务器监控大盘都会把它摆在显眼位置。但它又是最容易被误读的一个指标。我见过有人看到负载值超过 1.0 就觉得系统快崩了,也见过有人负载跑到 30 还觉得没问题,这两种判断都是错的——关键在于,你有没有把 CPU 核心数这个前提条件纳进来。

Load Average 的理解门槛不高,但它背后涉及的系统原理其实相当有意思:进程状态的分类、内核调度队列的设计、I/O 等待与 CPU 占用的本质区别……这些东西理清楚了,你看系统问题的视角会完全不一样。

这篇文章我想从最朴素的定义讲起,一步步带你真正理解 Load Average 代表什么,怎么读,怎么结合其他指标做判断,以及在真实服务器出问题的时候,它能告诉你什么、又告诉不了你什么。

二、本文要解决什么问题

读完这篇文章,你应该能做到以下几件事:

第一,看到 uptime 或 top 输出的三个负载数字,立刻能判断当前系统是否处于正常区间。这个判断不是凭感觉,而是有明确的参考依据——你会知道这个判断的基准是 CPU 核心数。

第二,理解 Load Average 高不等于 CPU 繁忙。这是很多人长期存在的误区。我会带你搞清楚"不可中断睡眠状态"(D 状态进程)是怎么拉高负载值的,为什么一台磁盘坏掉的服务器 CPU 可以很闲但负载却很高。

第三,当服务器出现负载异常时,知道从哪里入手分析,用哪些工具,按什么顺序排查。盲目重启服务是解决不了问题的,你需要一个系统化的排查思路。

第四,理解 Load Average 的计算方式,知道为什么它是一个"滞后"指标,在使用它做决策时需要注意什么。

第五,掌握 uptime、top、htop、vmstat、iostat、sar 等工具在 Load Average 分析场景下的具体用法,知道每个工具的侧重点和适用场景。

三、Load Average 是什么:从定义出发

3.1 官方定义与直白解释

Linux 内核文档对 Load Average 的定义是:在特定时间间隔内,处于可运行状态(runnable)和不可中断睡眠状态(uninterruptible sleep)的进程数量的指数加权移动平均值。

这句话信息量很大,拆开来理解:

“可运行状态”:包括正在 CPU 上执行的进程,以及已经准备好、正在等待 CPU 调度的进程。换句话说,这是 CPU 调度队列的长度。

“不可中断睡眠状态”:进程在等待某些无法被信号打断的 I/O 操作,最典型的就是磁盘 I/O、某些网络文件系统操作。这类进程不占用 CPU,但它们仍然计入 Load Average。

“指数加权移动平均”:不是简单地统计某一时刻的进程数,而是以特定的衰减权重对过去一段时间的数据进行加权平均。这解释了为什么 Load Average 反应相对迟钝,即便你马上终止了高负载进程,那个数值也不会立刻降下来。

用更直白的话说:Load Average 告诉你的是,在过去的 1 分钟、5 分钟、15 分钟里,平均有多少个任务在"排队等待被处理"或"正在被处理"。

一个类比可以帮助你建立直觉:把 CPU 核心想象成超市收银台,把进程想象成排队结账的顾客。Load Average 是这段时间里平均有多少顾客要么正在结账,要么正在排队,要么在柜台前等待不知道什么原因卡住的操作。

3.2 三个数字分别代表什么

当你执行 uptime 命令,你会看到类似这样的输出:

uptime

14:23:18 up 42 days, 3:17, 2 users, load average: 1.52, 1.34, 0.98

最后那三个数字,从左到右依次是:

  • 1.52:过去 1 分钟内的平均负载
  • 1.34:过去 5 分钟内的平均负载
  • 0.98:过去 15 分钟内的平均负载

1 分钟的值反应的是最近的瞬时压力,波动较大;15 分钟的值反应的是较长时间内的趋势,比较平滑;5 分钟的值介于两者之间。

这三个值之间的相对关系和变化趋势,往往比单个绝对值更有参考意义。后面我会专门讲这个。

3.3 Load Average 和 CPU 使用率的本质区别

这是一个非常值得深入说明的地方,因为它们经常被混为一谈。

CPU 使用率描述的是 CPU 时间被占用的百分比。一台 4 核服务器,如果所有核心都在满负荷运行,CPU 使用率是 100%。CPU 使用率只反映 CPU 这一个资源的忙碌程度。

Load Average 描述的是系统整体的任务排队长度,包含了等待 CPU 和等待 I/O 两种情况。一台 CPU 使用率只有 20% 的服务器,可能因为大量进程卡在磁盘 I/O 等待上,而导致 Load Average 非常高。

这个区别在实际排查中非常关键:

  • 如果 Load Average 高,同时 CPU 使用率也高 → CPU 瓶颈的可能性大
  • 如果 Load Average 高,但 CPU 使用率很低 → 大概率是 I/O 瓶颈(磁盘、网络文件系统等)
  • 如果 CPU 使用率高,但 Load Average 不高 → CPU 密集型任务,但任务数量不多,不一定是问题

我在后面的案例部分会用 stress-ng 分别模拟这两种场景,让你直观地看到它们的区别。

四、CPU 核心数:读懂 Load Average 的关键变量

4.1 为什么核心数那么重要

这是理解 Load Average 最核心的前提,没有之一。

Load Average 的值是一个绝对数量(任务的平均个数),不是一个百分比。所以,同样是 Load Average 为 4.0,在单核 CPU 上意味着系统严重过载(有 4 倍的任务在排队),在 8 核 CPU 上只是轻度负载(每个核心平均处理 0.5 个任务)。

更具体地说:

  • 在一台 1 核 CPU 的机器上,Load Average 为 1.0 表示 CPU 刚好满负荷,是健康上限
  • 在一台 4 核 CPU 的机器上,Load Average 为 4.0 才是满负荷
  • 在一台 8 核 CPU 的机器上,Load Average 为 8.0 才是满负荷
  • 如果值明显超过核心数,说明有任务在持续排队等待,系统已经过载

所以,每次看 Load Average 之前,你都必须先确认这台机器有几个 CPU 核心。这不是可选的,这是必须的前置步骤。

4.2 怎么查看 CPU 核心数

Ubuntu 22.04 / 24.04 上,查看 CPU 核心数有几种方式:

# 方法一:查看逻辑 CPU 核心数(最常用)
nproc

8

# 方法二:通过 /proc/cpuinfo 查看详细信息
grep -c ^processor /proc/cpuinfo

8

# 方法三:通过 lscpu 查看完整 CPU 信息
lscpu | grep -E '^CPU\\(s\\)|^Core|^Socket|^Thread'

CPU(s): 8
Core(s) per socket: 4
Socket(s): 1
Thread(s) per core: 2

这个输出很有意思。lscpu 的结果告诉我们:这台机器有 1 个物理 CPU(Socket),每个 CPU 有 4 个物理核心,每个核心支持 2 个超线程(Hyper-Threading),因此逻辑核心数 = 1 × 4 × 2 = 8。

需要特别说明的是:nproc 和 grep -c ^processor 返回的都是逻辑核心数,也就是包含了超线程之后的数字。这是 Load Average 计算时使用的参考基准。超线程虽然在硬件上共享某些资源,但对操作系统来说,每个逻辑核心都是一个可独立调度的"CPU"。

4.3 Load Average 的"合理范围"

有了核心数这个基准,我们可以建立一个简单的判断框架:

负载 / 核心数比值状态描述处理建议
< 0.7 系统空闲,资源充足 正常观察
0.7 ~ 1.0 系统健康,接近满载 留意趋势
1.0 ~ 1.5 轻度过载,有任务在排队 关注并找原因
1.5 ~ 3.0 中度过载,响应可能开始变慢 尽快排查
> 3.0 严重过载,系统压力极大 立即处理

这里的"比值"是指 load average / CPU核心数。举个例子,8 核机器的 Load Average 为 12,比值就是 1.5,属于中度过载。

不过要注意,这个表格只是参考经验,不是绝对标准。有些系统对高负载的容忍度更强,有些业务场景本身就会有短暂的负载峰值,这些都需要结合实际情况判断。重要的是建立趋势意识,而不是用一个固定阈值去做"正常 / 异常"的二元判断。

五、哪些进程会贡献到 Load Average

理解这一点,你才能真正搞懂为什么"Load Average 高不等于 CPU 忙"。

Linux 内核在计算 Load Average 时,会把以下两类状态的进程都计入统计:

5.1 运行状态(R)

进程状态为 R(Running / Runnable),即进程正在 CPU 上运行,或者已经准备好可以运行但在等待 CPU 调度。这是绝大多数人理解的"CPU 负载"来源。

你可以用以下命令查看当前处于 R 状态的进程数量:

# 统计当前处于 R(运行/就绪)状态的进程数
ps aux | awk '$8 ~ /^R/ {count++} END {print "R 状态进程数:", count}'

或者用 top 的 Tasks 行中的 running 字段,后面案例部分会详细演示。

5.2 不可中断睡眠状态(D):最容易被忽视的贡献者

进程状态为 D(Uninterruptible Sleep),这类进程正在等待某种 I/O 操作完成,而且这种等待无法被信号中断——哪怕你发送 kill -9 也杀不掉它,它只会在 I/O 完成后自然醒来。

最常见的触发场景包括:

  • 进程在等待磁盘 I/O 完成(读写慢盘、坏盘)
  • 进程在等待 NFS(网络文件系统) 的响应
  • 进程在等待某些内核锁
  • 一些低质量的设备驱动程序导致进程卡住

这些进程虽然完全不占用 CPU(它们在"睡觉"),但依然被计入 Load Average。这就是为什么你有时候会看到服务器 CPU 使用率才 10%,但负载却高达 20 的怪异现象——所有的锅都是 D 状态进程背的。

你可以用以下命令查看当前是否存在 D 状态进程:

# 查看处于 D 状态(不可中断睡眠)的进程
ps aux | awk '$8 ~ /^D/ {print $0}'

# 或者用更简洁的方式,统计数量
ps -eo state | grep -c '^D'

如果这个命令返回的数字不是 0,而且 Load Average 很高但 CPU 使用率很低,那大概率是 I/O 问题导致的。

5.3 Load Average 高未必是 CPU 的锅

为了让这个结论更直观,我整理了一个分析框架:

相关示意图绘制如下,仅供大家保存查阅:

这张图是整个 Load Average 排查思路的核心框架,我们后面的案例三会完整走一遍这个流程。

六、实验环境准备

在正式进入案例之前,先确认一下实验环境。本文的所有命令都在以下环境中验证过:

操作系统:Ubuntu 22.04 LTS / Ubuntu 24.04 LTS
环境类型:Ubuntu Server 或 Ubuntu Desktop 均可
CPU:推荐至少 2 核(单核机器也可以,但观察效果不如多核直观)

首先,确认你的系统版本:

# 查看系统版本
lsb_release -a

No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 22.04.4 LTS
Release: 22.04
Codename: jammy

安装本文实验需要用到的工具:

# 更新软件源索引
sudo apt update

# 安装监控工具和压测工具
sudo apt install -y \\
htop \\ # 增强版 top,界面更友好
sysstat \\ # 包含 iostat、sar、pidstat 等工具
stress-ng \\ # 系统压力测试工具
procps # 包含 vmstat、ps、uptime 等核心工具(通常已内置)

安装完成后,验证各工具是否可用:

# 验证各工具版本
uptime –version 2>/dev/null || uptime # uptime 不支持 –version,直接运行即可
htop –version
iostat -V
sar -V
stress-ng –version

# 确认本机 CPU 核心数,后续分析的基准
nproc

记住这个数字,后面所有的负载判断都要以它作为参考。

七、案例一:用 uptime 和 top 读懂 Load Average

7.1 uptime 命令:最快速的负载快照

uptime 是查看系统负载最快的方式,没有之一。它的输出简洁,几秒钟就能让你对系统整体状态有个基本判断。

# 查看系统运行时间和平均负载
uptime

输出示例:

15:42:07 up 12 days, 6:35, 3 users, load average: 0.52, 0.48, 0.43

逐字段解读:

  • 15:42:07:当前时间
  • up 12 days, 6:35:系统已连续运行 12 天 6 小时 35 分钟
  • 3 users:当前登录用户数(包含 SSH 会话)
  • load average: 0.52, 0.48, 0.43:1 分钟、5 分钟、15 分钟的平均负载

假设这台机器是 4 核 CPU:

  • 0.52 / 4 = 0.13 → 系统非常空闲,负载只有 CPU 容量的 13%
  • 三个值非常接近 → 系统负载稳定,没有突然的异常

如果你只想看负载数字,可以加 -p 参数(在某些版本上有效)或者直接用 cat /proc/loadavg:

# 直接读取内核暴露的负载数据
cat /proc/loadavg

0.52 0.48 0.43 2/312 18547

这里的内容比 uptime 更丰富一点:

  • 前三个数字:1、5、15 分钟负载
  • 2/312:当前活跃进程数 / 系统总进程数
  • 18547:最近创建的进程的 PID

这个文件是内核直接暴露的,uptime、top、htop 等工具都是从这里读数据的。在脚本中做监控判断时,直接 cat /proc/loadavg 效率最高。

7.2 top 命令中的 Load Average

top 命令的第一行就显示了 Load Average,和 uptime 的输出内容完全相同:

# 启动 top
top

top – 15:42:07 up 12 days, 6:35, 3 users, load average: 0.52, 0.48, 0.43
Tasks: 312 total, 2 running, 310 sleeping, 0 stopped, 0 zombie
%Cpu(s): 3.2 us, 1.1 sy, 0.0 ni, 94.8 id, 0.7 wa, 0.0 hi, 0.2 si, 0.0 st
MiB Mem : 7852.4 total, 2143.2 free, 3124.8 used, 2584.4 buff/cache
MiB Swap: 2048.0 total, 2048.0 free, 0.0 used. 4123.5 avail Mem

top 输出中有几个字段和 Load Average 分析直接相关,值得仔细看:

第二行 Tasks(进程状态统计):

Tasks: 312 total, 2 running, 310 sleeping, 0 stopped, 0 zombie

  • 312 total:系统总进程数
  • 2 running:处于 R 状态(运行/就绪)的进程数
  • 310 sleeping:处于 S 状态(可中断睡眠,等待事件)的进程数,这类进程不计入 Load Average
  • 0 stopped:被暂停的进程(Ctrl+Z 或 SIGSTOP)
  • 0 zombie:僵尸进程

这里的关键是:running 的进程是计入 Load Average 的;sleeping 的进程通常不计入(S 状态不计入,D 状态计入,但 top 的 Tasks 行没有单独显示 D 状态数量,这是一个小缺陷)。

第三行 %Cpu(s)(CPU 使用率细分):

%Cpu(s): 3.2 us, 1.1 sy, 0.0 ni, 94.8 id, 0.7 wa, 0.0 hi, 0.2 si, 0.0 st

  • us(user):用户态 CPU 使用率,应用程序本身的运算
  • sy(system):内核态 CPU 使用率,系统调用、内核操作
  • ni(nice):调整了优先级(nice 值)的进程的 CPU 使用率
  • id(idle):CPU 空闲率,越高说明 CPU 越闲
  • wa(iowait):CPU 等待 I/O 完成的时间占比——这个值非常关键!
  • hi(hardware interrupts):硬件中断处理时间
  • si(software interrupts):软件中断处理时间
  • st(steal):被虚拟机管理程序"偷走"的 CPU 时间(虚拟机环境下有意义)

wa(iowait)是分析 Load Average 是否由 I/O 引起的重要线索。 如果你看到 Load Average 高但 CPU id(idle)也高,同时 wa 比较高(比如超过 10%),那 I/O 等待的嫌疑就很大了。

在 top 运行中,你可以按以下快捷键进行操作:

  • 1:展开每个 CPU 核心的使用情况(多核机器必用)
  • M:按内存使用量排序
  • P:按 CPU 使用率排序
  • q:退出

7.3 htop 中的直观展示

如果你安装了 htop(前面已安装),它提供了更直观的可视化界面:

htop

htop 界面的左上角会以彩色进度条形式展示每个 CPU 核心的使用率,右上角显示 Load Average。对于多核机器,这比 top 的单行 CPU 显示更直观——你一眼就能看出是所有核心都忙,还是只有个别核心跑满了。

另外,htop 的进程列表中,处于不同状态的进程会用不同颜色标注,D 状态的进程(如果存在)会特别显眼。

7.4 命令解析

这几个工具之间的关系和使用场景值得梳理一下:

uptime 最轻量,适合登录服务器后的第一眼确认,或者在 shell 脚本里做快速检查。它不需要保持交互,一条命令立刻返回结果。

top 是中等深度的实时监控工具,内置于所有 Linux 系统,无需额外安装。它的优点是可以同时看到进程列表和系统资源摘要,缺点是界面相对不那么友好,且默认排序对初学者不够直观。

htop 是 top 的增强版,界面更友好,支持鼠标操作,对多核 CPU 的展示更清晰。在有条件的情况下,我更习惯用 htop 做日常监控。但它不是所有系统的标准安装,生产服务器上不一定有,这时候还得用 top。

/proc/loadavg 是上述所有工具的数据来源,适合写监控脚本时直接读取,避免解析命令输出的麻烦。

八、案例二:模拟高负载场景,亲眼看 Load Average 上升

光靠理解概念还不够。我建议你一定要亲手做这个实验——亲眼看着 Load Average 从低到高,再从高降回来,你对这个指标的理解会完全不同。

8.1 使用 stress-ng 模拟 CPU 压力

stress-ng 是一个功能强大的系统压力测试工具,可以针对 CPU、内存、I/O 等各种子系统施加压力。

先开两个终端窗口(或者用 tmux),一个用来跑压力测试,一个用来持续观察负载变化。

终端 1:开始 CPU 压力测试

# 启动 CPU 压力测试
# –cpu 4:启动 4 个 CPU 密集型 worker 进程
# –timeout 60s:持续运行 60 秒后自动停止
# –metrics-brief:打印简单的性能统计
stress-ng –cpu 4 –timeout 60s –metrics-brief

终端 2:持续观察负载变化

# 每 2 秒刷新一次 uptime 输出,持续观察负载变化
watch -n 2 uptime

你会看到 1 分钟负载开始缓慢上升,5 分钟和 15 分钟的值因为时间窗口更长,变化更慢。等 60 秒的压力测试结束后,1 分钟的负载会率先开始下降,而 5 分钟和 15 分钟的值还会在高位持续一段时间——这就是"指数加权移动平均"带来的滞后效应。

与此同时,在终端 2 中换用 top 观察,你会看到 CPU us(user)使用率明显上升,而 wa(iowait)基本不变。这是典型的 CPU 密集型负载特征:

# 用 top 观察,按 1 展开每个 CPU 核心
top

%Cpu0 : 98.3 us, 0.7 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 1.0 si
%Cpu1 : 97.8 us, 0.9 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 1.3 si
%Cpu2 : 98.1 us, 0.6 sy, 0.0 ni, 0.0 id, 0.3 wa, 0.0 hi, 1.0 si
%Cpu3 : 97.5 us, 1.2 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 1.3 si

CPU 使用率接近 100%,wa 接近 0。Load Average 上升是因为这 4 个 CPU worker 进程都处于 R(运行/就绪)状态,持续占用 CPU 调度资源。

8.2 使用 stress-ng 模拟 I/O 压力

现在来模拟一个截然不同的场景:I/O 密集型负载。

# 启动 I/O 压力测试
# –iomix 4:启动 4 个混合 I/O worker,模拟读写压力
# –iomix-bytes 10%:每个 worker 每次操作 10% 的可用内存大小
# –timeout 60s:持续 60 秒
stress-ng –iomix 4 –iomix-bytes 10% –timeout 60s –metrics-brief

同样在另一个终端观察:

watch -n 2 uptime

你会发现 Load Average 也在上升,但这时候再看 top:

%Cpu(s): 2.1 us, 8.3 sy, 0.0 ni, 72.4 id, 16.8 wa, 0.0 hi, 0.4 si

注意几个关键变化:

  • id(idle)还有 72%,CPU 远没有满
  • wa(iowait)上升到了 16.8%
  • sy(system)也比平时高,说明内核在频繁处理 I/O 相关的系统调用

这就是 I/O 密集型负载的典型特征:CPU 很闲,但系统在大量等待 I/O,Load Average 依然会上升(因为 D 状态进程被计入统计)。

你还可以结合 ps 来观察当前是否存在 D 状态进程:

# 在压力测试运行中,查看 D 状态进程
ps -eo pid,stat,comm | awk '$2 ~ /^D/ {print}'

如果压力足够大,你应该能看到部分 stress-ng 的 worker 进程处于 D 状态。

8.3 对比两种负载的区别

把两个场景的特征整理成对比表:

指标CPU 密集型负载I/O 密集型负载
Load Average 上升 上升
CPU us / sy 非常高 较低
CPU id(空闲) 接近 0% 可能仍然较高
CPU wa(iowait) 接近 0% 明显升高
D 状态进程数 少 多
主要瓶颈 CPU 计算能力 磁盘/I/O 子系统
优化方向 减少计算量、优化算法、扩 CPU 优化 I/O 模式、升级磁盘、调整 I/O 调度器

这张对比表在真实排查中非常实用。拿到一台负载异常的服务器,你要做的第一件事就是判断它属于哪种类型,然后才能决定下一步的排查路径。

8.4 命令解析与观察要点

stress-ng 是一个非常专业的系统压力测试工具,比早期常用的 stress 功能更丰富,支持的压力类型更多。在 Ubuntu 22.04 / 24.04 的官方仓库中可以直接安装,无需添加第三方源。

关于实验中的一个容易被忽略的细节:Load Average 的变化并不是实时的。即便你立刻启动高负载,1 分钟的值也需要大约 1~2 分钟才会显著上升,这是指数加权移动平均的特性决定的。同样地,负载恢复正常后,1 分钟的值大约需要 1~2 分钟才能明显下降,5 分钟和 15 分钟的值则需要更长时间。

在真实的故障处理中,这意味着一件事:你看到负载高,不代表问题现在还在发生。可能故障进程已经结束了,但 15 分钟的负载均值还在高位。这就是为什么要三个值都看,而不是只看一个。

九、案例三:生产环境中的 Load Average 异常排查

这个案例模拟的是最接近真实运维场景的情况——一台服务器的监控告警触发了,你通过 SSH 登录进去,从零开始排查 Load Average 异常的原因。

9.1 场景描述

假设你收到告警:某台 Ubuntu 22.04 服务器的 Load Average 触发了阈值,15 分钟均值超过了 CPU 核心数的 2 倍。这台服务器运行着 Nginx + Python Web 应用,平时 Load Average 在 0.5~1.0 之间。

你的目标:找出负载升高的根本原因,判断是否需要立即干预。

9.2 第一步:确认负载情况

登录服务器后,第一件事是快速确认当前的负载状态:

# 第一眼:查看当前负载和系统运行时间
uptime

16:30:22 up 35 days, 2:14, 1 user, load average: 14.23, 12.87, 9.41

# 确认 CPU 核心数,建立判断基准
nproc

4

数学计算:14.23 / 4 = 3.56,是 CPU 容量的 3.56 倍,这是严重过载状态。

从三个值的趋势来看:1 分钟 > 5 分钟 > 15 分钟,而且 1 分钟的值明显更高,说明问题是在最近突然恶化的,不是一个缓慢积累的趋势。这个信息很重要,意味着可能有某个进程或任务突然发起了。

9.3 第二步:判断是 CPU 型还是 I/O 型

# 查看 CPU 使用率细分,重点看 id 和 wa
top -b -n 1 | head -5

top – 16:30:25 up 35 days, 2:14, 1 user, load average: 14.31, 12.89, 9.44
Tasks: 387 total, 12 running, 364 sleeping, 0 stopped, 1 zombie
%Cpu(s): 8.2 us, 15.1 sy, 0.0 ni, 15.3 id, 61.2 wa, 0.0 hi, 0.2 si
MiB Mem : 7852.4 total, 312.4 free, 5124.8 used, 2415.2 buff/cache
MiB Swap: 2048.0 total, 512.3 free, 1535.7 used. 823.2 avail Mem

这个输出非常能说明问题:

  • id(空闲)只有 15.3%,说明 CPU 确实有压力
  • wa(iowait)高达 61.2%,CPU 有大量时间在等待 I/O
  • us + sy 加起来只有 23.3%,实际运算不多
  • 内存使用了大量 Swap(已用 1535MB),说明物理内存可能不够用了

结论:这是一个典型的 I/O 密集型高负载问题,很可能伴随着内存压力导致的大量 Swap 交换。

还需要注意 Tasks 行:12 running 在 4 核机器上意味着有 12 个进程在竞争 CPU,这正是 Load Average 高达 14 的主要原因之一。另外有 1 zombie,这是个小问题,后面可以单独处理(见本专栏第9节)。

9.4 第三步:找出具体进程

现在知道是 I/O 问题了,需要进一步定位到具体是哪些进程在消耗 I/O 资源:

# 查看 D 状态(不可中断睡眠)的进程,这些是 I/O 等待的直接体现
ps -eo pid,ppid,stat,pcpu,pmem,comm –sort=stat | grep '^.\\{0,30\\}D'

或者更直观的方式:

# 查看所有 D 状态进程的详细信息
ps aux | awk 'NR==1 || $8 ~ /^D/ {print}' | head -20

USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
www-data 3842 0.0 2.1 256432 83124 ? D 14:22 0:08 python3 app.py
www-data 3843 0.0 2.0 254122 81044 ? D 14:22 0:07 python3 app.py
www-data 3844 0.1 2.1 256892 83344 ? D 14:22 0:09 python3 app.py
…(类似的进程有 8-10 个)

找到了:有大量 Python 应用进程处于 D 状态。接下来用 iostat 确认 I/O 状态:

# 查看磁盘 I/O 统计,每 2 秒刷新一次,共看 3 次
# -x:显示扩展统计
# -d:只显示磁盘统计(不显示 CPU)
iostat -xd 2 3

Device r/s w/s rkB/s wkB/s await r_await w_await svctm %util
sda 45.2 312.8 1824.4 9847.2 186.4 12.3 215.7 2.8 100.0

%util 为 100%,说明磁盘已经满负荷,await(平均 I/O 等待时间)高达 186ms,正常情况下这个值应该在几毫秒以内。磁盘是明确的瓶颈。

9.5 第四步:深入分析

磁盘满负荷的原因可能有多种:应用日志疯狂写入、某个大型文件操作、数据库在做大量写入……我们需要进一步确认:

# 查看是哪些进程产生了最多的 I/O(需要 root 权限)
sudo iotop -b -o -n 3 2>/dev/null || \\
sudo apt install -y iotop && sudo iotop -b -o -n 3

如果 iotop 不可用,也可以用 pidstat:

# 用 pidstat 查看各进程的 I/O 统计
# -d:显示 I/O 统计
# 2 3:每 2 秒采样一次,共 3 次
pidstat -d 2 3

16:31:42 UID PID kB_rd/s kB_wr/s kB_ccwr/s Command
16:31:44 1000 3842 0.00 4823.45 0.00 python3
16:31:44 1000 3843 0.00 4721.33 0.00 python3
…

Python 应用在疯狂写磁盘。结合之前看到的内存不足(大量使用 Swap),现在可以推断出原因链:

推断原因链:内存使用量超出物理内存 → 系统开始大量使用 Swap(将内存数据换出到磁盘)→ 磁盘 I/O 大幅增加 → 应用进程等待磁盘操作,进入 D 状态 → Load Average 飙升

# 进一步确认内存和 Swap 的使用情况
free -h

total used free shared buff/cache available
Mem: 7.7G 6.9G 312M 234M 522M 312M
Swap: 2.0G 1.5G 512M

确认:物理内存几乎耗尽,Swap 已用了 75%。这是一个典型的内存泄漏或内存配置不足导致的连锁故障。

# 按内存使用量排序,找出内存消耗最大的进程
ps aux –sort=-%mem | head -15

# 查看某个具体进程的内存使用详情(替换 3842 为实际 PID)
cat /proc/3842/status | grep -E 'VmRSS|VmSwap|VmSize'

9.6 命令解析与排查思路总结

这个案例走完了一个完整的排查流程,背后的思路值得总结一下:

排查的核心原则是"逐步缩小范围"。从系统整体状态(uptime)→ 资源类型判断(top 的 wa、id)→ 进程状态确认(ps 的 D 状态)→ I/O 子系统详情(iostat)→ 具体进程的 I/O 行为(pidstat/iotop)→ 根本原因(内存不足导致 Swap 风暴)。

每一步的结论都是下一步的前提。如果你一开始就去看某个具体进程的日志,可能完全找不到方向——因为问题根本不在日志里,在内存配置上。

相关示意图绘制如下,仅供大家保存查阅:

十、Load Average 的计算原理

理解了"是什么"和"怎么用",我们来稍微深入一下原理。不需要你去读内核源码,但知道这个机制,会帮助你理解 Load Average 的一些"反直觉"行为。

10.1 指数加权移动平均

Linux 内核每 5 秒对活跃进程数做一次采样,然后用指数加权移动平均(Exponentially Weighted Moving Average, EWMA)算法来计算 Load Average。

EWMA 的特点是:越近的采样权重越大,越远的采样权重越小,但历史数据永远不会被完全丢弃,只是权重越来越小。

三个时间窗口对应三个衰减系数:

时间窗口衰减系数(近似)半衰期(近似)
1 分钟 0.9200 ~46 秒
5 分钟 0.9835 ~4 分钟
15 分钟 0.9945 ~12 分钟

"半衰期"的意思是:一个突然发生的负载峰值,经过这段时间后,它对 Load Average 的贡献会衰减到原来的一半。

这解释了一个常见现象:你刚刚 kill 了一个占用大量资源的进程,1 分钟负载差不多要 1~2 分钟才会明显下降,而 15 分钟负载可能要十几分钟才能恢复到正常水平。这不是 kill 没生效,而是 EWMA 算法的正常行为。

10.2 为什么 1 分钟和 15 分钟的值差异重要

三个 Load Average 值之间的相对关系是非常有价值的信号:

情况一:1 分钟 >> 5 分钟 ≈ 15 分钟

load average: 8.24, 1.32, 1.15

负载是突然升高的,刚刚发生了某个高负载事件。这可能是某个批量任务启动了,或者某个请求峰值到来了,或者某个进程突然失控。需要立即关注,但也可能只是一个短暂的尖峰。

情况二:1 分钟ᅠ≈ 5 分钟 ≈ 15 分钟(都很高)

load average: 12.3, 11.8, 12.1

负载持续高位运行了很长时间,系统长期处于过载状态。这是最需要紧急处理的情况,意味着不是偶发峰值,而是持续性的资源不足。

情况三:1 分钟 << 5 分钟 ≈ 15 分钟

load average: 0.82, 5.43, 6.12

高负载刚刚结束,系统正在恢复中。可能你之前的某个处理操作已经见效了,也可能是高负载任务自然结束了。继续观察,确认 1 分钟的值能稳定下来。

情况四:三个值都很低

load average: 0.12, 0.18, 0.21

系统非常空闲,不需要担心。这是正常的服务器空闲状态。

十一、Load Average 与其他监控指标的联合分析

Load Average 单独看是一个很粗糙的信号,它只告诉你"系统有压力",但不告诉你压力来自哪里。真正有价值的判断,总是把它和其他指标联合起来看的。

11.1 结合 CPU 使用率

# 用 vmstat 同时看负载和 CPU 使用情况
# 1:每 1 秒采样一次
# 5:共采样 5 次
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
3 1 1572864 318924 12184 2482644 124 256 4832 12441 1843 3254 8 15 15 62 0
2 2 1572864 312344 12184 2482644 132 248 5124 13284 1923 3382 7 16 14 63 0

vmstat 的输出很密集,但关键字段是:

  • r:处于 R 状态(就绪/运行)的进程数,这是 Load Average 的"CPU 部分"
  • b:处于 D 状态(不可中断睡眠)的进程数,这是 Load Average 的"I/O 部分"
  • wa:CPU iowait 百分比
  • si / so:每秒 Swap 读入 / 写出的量(KB),如果这个值持续非零,说明有 Swap 风暴

vmstat 的 r + b 就是大致的当前活跃进程数,和 Load Average 有很强的对应关系(Load Average 是这个的时间加权平均)。

11.2 结合内存使用率

# 查看内存使用详情
free -h

# 查看更详细的内存统计(直接读取内核数据)
cat /proc/meminfo | grep -E 'MemTotal|MemFree|MemAvailable|SwapTotal|SwapFree|Dirty|Writeback'

MemTotal: 8040512 kB
MemFree: 318924 kB
MemAvailable: 843256 kB
SwapTotal: 2097148 kB
SwapFree: 524288 kB
Dirty: 124832 kB ← 待写入磁盘的脏页,值很高说明有大量写入等待
Writeback: 23456 kB ← 正在回写磁盘的数据

Dirty 值如果持续很高(比如超过几百 MB),说明有大量数据在等待写入磁盘,这会导致 I/O 压力增大,进而推高 Load Average 中的 D 状态进程数量。

11.3 结合 I/O 状态

# 查看各磁盘设备的详细 I/O 统计
iostat -xd 1 5

重点关注的字段:

字段含义异常阈值参考
%util 磁盘使用率 > 80% 需要关注,接近 100% 基本饱和
await 平均 I/O 等待时间(ms) HDD > 20ms,SSD > 2ms 需要关注
r/s / w/s 每秒读/写请求数 取决于设备类型
rkB/s / wkB/s 每秒读/写数据量(KB) 对比设备的理论带宽

11.4 结合进程状态

# 全面查看进程状态分布
ps -eo stat | sort | uniq -c | sort -rn

298 Ss ← 可中断睡眠(后台服务,等待事件),正常
42 S ← 可中断睡眠
12 R ← 运行/就绪,计入 Load Average
8 D ← 不可中断睡眠,计入 Load Average,需要关注
1 Z ← 僵尸进程

这个命令给了你一个清晰的进程状态分布快照。在排查 Load Average 异常时,关注 R 和 D 的数量。

十二、核心命令与工具汇总解析

12.1 uptime

# 基础用法
uptime

# 输出格式示例
# 16:42:07 up 35 days, 2:14, 1 user, load average: 1.52, 1.34, 0.98

适用场景:登录服务器后的第一眼检查,脚本中的快速监控检测。

uptime 的优点是无需额外安装,几乎在所有 Linux 发行版上都有,输出简洁,一行完成。缺点是无法持续刷新,只是一个快照。

12.2 top / htop

# 基础 top(按 q 退出)
top

# top 一次性输出(适合脚本使用,不进入交互界面)
top -b -n 1

# 指定刷新间隔(3 秒刷新一次)
top -d 3

# htop(需要安装)
htop

# htop 以指定刷新间隔运行
htop -d 10 # 单位是 1/10 秒,10 = 1 秒刷新一次

top 和 htop 的核心区别:top 是系统内置工具,永远可以依赖;htop 需要安装,但提供更友好的界面和颜色标注,在开发机或配置较完善的服务器上推荐使用。

12.3 vmstat

# 每 1 秒输出一次,共 10 次
vmstat 1 10

# 查看内存统计(不同于默认的进程/CPU 视图)
vmstat -s

# 查看磁盘 I/O 统计(类似 iostat 的简化版)
vmstat -d

vmstat 的优势是在一行里呈现了内存、Swap、I/O、系统调用和 CPU 的综合信息,特别适合快速做"全局健康检查"。R 列(运行队列)和 B 列(阻塞进程数)是和 Load Average 最直接相关的两个字段。

12.4 iostat

# 安装(sysstat 包)
sudo apt install -y sysstat

# 每 2 秒输出一次磁盘 I/O 扩展统计,共 5 次
iostat -xd 2 5

# 只查看特定磁盘
iostat -xd sda 2 5

# 同时显示 CPU 统计
iostat -x 2 5

iostat 是排查 I/O 型 Load Average 问题时不可缺少的工具。如果 top 的 wa 很高,下一步就应该用 iostat 找出是哪块磁盘在成为瓶颈。

12.5 sar

sar(System Activity Reporter)是 sysstat 包里功能最强大的工具,它不仅能实时采样,还能保存历史数据,让你事后回溯某个时间点的系统状态——这在生产环境排查"为什么昨晚 3 点告警了"这类问题时非常有价值。

# 查看 CPU 使用率历史(从 sysstat 保存的日志中读取)
sar -u

# 查看 Load Average 历史
sar -q

# 查看内存使用历史
sar -r

# 查看磁盘 I/O 历史
sar -d

# 实时采样(每 2 秒,共 5 次)
sar -u 2 5

sar 的历史数据保存在 /var/log/sysstat/ 目录下,按日期命名。要启用这个功能,需要确认 sysstat 的定时采集是开启的:

# 查看 sysstat 数据收集状态
sudo systemctl status sysstat

# 如果未运行,启动并设置开机自启
sudo systemctl enable –now sysstat

# 查看 sysstat 的数据收集配置
cat /etc/sysstat/sysstat

# 查看指定日期的历史负载数据(YYYY-MM-DD 格式)
# 先确认历史文件存在
ls /var/log/sysstat/

# 查看今天的 Load Average 历史记录
sar -q -f /var/log/sysstat/sa$(date +%d)

这个功能在处理"事后"告警时特别有价值。很多时候,等你登录上服务器,负载已经恢复正常了,sar 的历史记录让你能重建当时的状态。

12.6 /proc/loadavg

# 直接读取内核暴露的负载数据
cat /proc/loadavg

1.52 1.34 0.98 3/312 18547

字段含义:

  • 1.52 1.34 0.98:1、5、15 分钟 Load Average
  • 3/312:当前活跃进程数(3)/ 系统总进程数(312)
  • 18547:最近一个创建的进程的 PID

在 Shell 脚本中做监控时,直接读这个文件最高效:

# 在脚本中获取 1 分钟负载值
load_1min=$(awk '{print $1}' /proc/loadavg)

# 获取 CPU 核心数
cpu_cores=$(nproc)

# 计算负载比率(用 awk 做浮点运算)
ratio=$(awk "BEGIN {printf \\"%.2f\\", $load_1min / $cpu_cores}")

echo "1分钟负载: $load_1min,CPU核心数: $cpu_cores,负载比率: $ratio"

# 判断是否超过阈值
awk "BEGIN {
if ($load_1min / $cpu_cores > 2.0) {
print \\"警告:系统负载过高!\\"
exit 1
} else {
print \\"系统负载正常\\"
exit 0
}
}"

十三、常见问题与踩坑总结

Q1:Load Average 为什么不是百分比,而是一个绝对数字?

这是一个设计上的选择。Load Average 表示的是活跃任务的平均数量,而不是资源使用率。这意味着它本身没有"上限"——理论上可以无限增大。这也是为什么必须结合 CPU 核心数才能做出有意义的判断:核心数是你的"处理能力基准",负载值是"需求量",两者相除才能知道需求是否超过了供给。

Q2:为什么刚刚 kill 了高负载进程,Load Average 还是很高?

EWMA 算法的滞后特性导致的。1 分钟的负载值有大约 46 秒的"半衰期",意味着你刚刚消灭的负载,需要大约 1~2 分钟才能明显从 1 分钟均值中退出;而 15 分钟的值可能需要 10~15 分钟才会明显下降。这不是工具的 bug,是设计如此。继续观察,等它自然下降。

Q3:为什么单核 CPU 的 Load Average 长期为 0.7 就开始有性能感知了?

当负载率超过 70% 时,调度队列开始积累,任务等待时间开始上升。对于延迟敏感的服务(比如 Web 请求),用户可能已经感受到响应变慢了。0.7 是一个经验阈值,不是绝对数字,但在运维实践中被广泛用作"开始关注"的警戒线。

Q4:Load Average 能反映内存压力吗?

间接可以。当内存不足导致系统大量使用 Swap 时,进程会频繁处于等待磁盘 I/O(读写 Swap)的 D 状态,这会推高 Load Average。但 Load Average 本身并不直接测量内存,你需要同时看 free 或 vmstat 的内存统计来确认内存是否是问题根源。

Q5:在虚拟机里看 Load Average 准吗?

在虚拟机(比如 KVM、VMware、VirtualBox)里,Load Average 反映的是从虚拟机视角看到的负载,即虚拟机内的进程排队情况。top 的 st(steal time)字段可以告诉你有多少 CPU 时间被宿主机"偷走"了——如果 steal time 很高,即便你的虚拟机 Load Average 看起来合理,实际性能也可能很差,因为你分配到的 CPU 时间实际上在缩水。

在云服务器(AWS EC2、阿里云 ECS 等)上,这个问题同样存在,尤其是在"突发型"实例上,CPU 配额用完后会有严重的 CPU 节流。

Q6:D 状态进程持续存在怎么处理?

首先要确认原因。如果是因为正常的磁盘 I/O(比如大文件拷贝),等操作完成进程会自动恢复;如果是因为 NFS 连接断掉导致进程无法唤醒,需要修复 NFS 连接或者卸载 NFS 挂载点;如果是内核 bug 或驱动问题,可能需要重启才能解决——D 状态进程是无法被 kill -9 杀死的,这一点很多人不知道,耗费大量时间尝试各种 kill 方式都无效。

Q7:top 显示的 running 进程数和 Load Average 不对应怎么回事?

top 的 running 字段是当前瞬间的 R 状态进程数,而 Load Average 是时间加权平均值。瞬间值和历史均值本来就不会完全对应。另外,top 的 Tasks 行没有单独显示 D 状态进程数(它们被归入 sleeping),所以你可能看到 running 数量不多,但负载依然很高——别忘了检查 D 状态进程的数量。

Q8:Watch 命令怎么用来持续观察 Load Average?

# 每 2 秒刷新一次 uptime 输出
watch -n 2 uptime

# 结合 date 显示时间戳,方便记录观察时间
watch -n 2 'date; uptime'

# 高亮显示变化的内容
watch -n 2 -d uptime

Q9:Load Average 和 Kubernetes 的节点资源有什么关系?

在 Kubernetes 环境里,节点的 Load Average 依然有参考意义,但 Pod 的资源调度基于 CPU Request / Limit,而不是 Load Average。一个节点的 Load Average 很高,不一定会触发 Kubernetes 的调度干预;但如果 CPU 节流(throttling)或内存 OOM 发生,Kubernetes 会有对应的事件和指标。不能用 Load Average 直接替代 Kubernetes 的 metrics-server 指标来做资源决策。

Q10:为什么同样是 4 核机器,有些服务 Load Average 为 3 也没问题,有些到 1.5 就很慢?

这取决于服务的延迟容忍度和任务特性。批处理任务(比如离线数据处理)对延迟不敏感,即便排队等待,最终完成就行,所以 Load Average 为 3~4 也可以接受。在线服务(Web API、数据库查询)对延迟极敏感,任何排队都会直接表现为用户侧的响应时间上升,所以它们的"合理负载"阈值要设置得更保守。运维中针对不同类型的服务设置不同的告警阈值是很正常的做法。

Q11:服务器的 Load Average 一直是 0,正常吗?

完全正常,甚至是很多空闲服务器的常态。Load Average 为 0 或接近 0 说明系统非常空闲,没有什么任务在竞争资源。这不代表服务器"没在工作",有些服务本身就是低频运行的,比如纯粹的定时任务服务器或者开发测试机。

Q12:nproc 和 lscpu 返回的数字不一样怎么办?

nproc 返回的是当前进程可以使用的 CPU 数量,可能受 cgroups(容器环境)或 taskset 的限制。lscpu 返回的是系统实际的逻辑 CPU 数量。在容器或 Docker 内,nproc 可能会返回一个比宿主机小的值(如果做了 CPU 限制),用 nproc 更符合实际可用资源;在物理机上,两者通常一致。

Q13:top 里的 iowait 是整个系统的,如果我想知道具体是哪个进程产生了 iowait 该怎么做?

iowait 本质上是 CPU 在某个时刻没有可运行的进程,同时又有进程在等待 I/O——所以它是一个 CPU 视角的统计,不能直接映射到某个进程。但你可以通过以下方式间接定位:

# 方法一:iotop 直接显示各进程的实时 I/O 读写速率
sudo apt install -y iotop
sudo iotop -o # -o 只显示有 I/O 活动的进程

# 方法二:pidstat 按进程统计 I/O
pidstat -d 1 5

# 方法三:结合 D 状态进程,找出被 I/O 阻塞的进程
ps -eo pid,stat,comm | awk '$2 ~ /^D/'

Q14:Load Average 高但系统响应还挺快,这说明什么?

两种可能:第一,虽然任务数量多,但每个任务都很短暂,很快完成后退出,系统在高速流转;第二,你的 CPU 核心数足够多,即便 Load Average 的绝对值看起来高,实际上每个核心的负担并不重。记住,判断标准永远是 load average / nproc 的比值,不是 Load Average 的绝对值。

Q15:能不能写一个简单的 Shell 脚本来自动检测 Load Average 并发告警?

完全可以,这是运维自动化的基础技能。以下是一个简单示例:

#!/bin/bash
# 文件路径:/usr/local/bin/check_load.sh
# 功能:检查系统负载,超过阈值时输出告警信息

# 获取 CPU 核心数
CPU_CORES=$(nproc)

# 获取 1 分钟负载值
LOAD_1MIN=$(awk '{print $1}' /proc/loadavg)

# 设置告警阈值:核心数的 1.5 倍
THRESHOLD=$(awk "BEGIN {printf \\"%.1f\\", $CPU_CORES * 1.5}")

# 比较负载和阈值
ALERT=$(awk "BEGIN {
if ($LOAD_1MIN > $THRESHOLD) print \\"YES\\"
else print \\"NO\\"
}"
)

if [ "$ALERT" = "YES" ]; then
echo "[$(date '+%Y-%m-%d %H:%M:%S')] 警告:1分钟负载 $LOAD_1MIN 超过阈值 $THRESHOLD(${CPU_CORES} 核心 × 1.5)"
# 这里可以加入发送邮件或调用告警 API 的逻辑
exit 1
else
echo "[$(date '+%Y-%m-%d %H:%M:%S')] 正常:1分钟负载 $LOAD_1MIN,阈值 $THRESHOLD"
exit 0
fi

# 给脚本添加执行权限
chmod +x /usr/local/bin/check_load.sh

# 测试运行
/usr/local/bin/check_load.sh

# 添加到 crontab,每 5 分钟检查一次
crontab -e
# 添加这一行:
# */5 * * * * /usr/local/bin/check_load.sh >> /var/log/load_check.log 2>&1

十四、最佳实践建议

这一节总结了在真实服务器运维中关于 Load Average 监控和高负载处理的经验做法。

建立基线,而不是使用固定阈值

每台服务器的正常负载水平都不一样。一台 Web 服务器在业务高峰期负载为 3.0 可能完全正常;而一台只跑 Nginx 静态文件服务的机器,负载超过 1.0 就值得关注了。我建议在新服务器上线后,观察一到两周的正常业务周期,记录负载的典型范围(包括日常低谷和业务高峰),以此作为告警阈值的设定依据。用固定的"核心数 × 1.5"这类公式只是起点,不是终点。

三个值一起看,不要只盯着一个

很多监控大盘只展示 1 分钟负载,这是有局限性的。真正有价值的判断需要同时看三个值的相对关系和变化趋势。如果你只有一个值可以选,选 5 分钟的——它比 1 分钟的稳定,比 15 分钟的更及时。

负载高时,先判断类型再采取行动

高负载的处理方式完全取决于它的类型。CPU 密集型和 I/O 密集型的优化思路完全不同:前者考虑减少计算量、拆分任务、扩充 CPU;后者考虑优化 I/O 模式、换用更快的磁盘、增加内存减少 Swap 使用。盲目重启服务不会解决根本问题,有时甚至会让情况更糟(比如重启会触发更多的磁盘操作,加剧 I/O 压力)。

iowait 高时,先检查内存,再检查磁盘

这是一个从实战中总结出来的经验。大量的"磁盘 I/O 问题"实际上是内存问题触发的:物理内存不足 → 大量 Swap 换出换入 → 磁盘 I/O 暴增 → iowait 上升。如果你直接去检查磁盘,可能发现磁盘本身是健康的,但就是很忙。这时候 free -h 一看,发现 Swap 用了 80%,真正的解法是给系统加内存或者找出内存泄漏的进程,而不是换磁盘。

在生产环境使用 sar 留存历史数据

我强烈建议在所有生产服务器上启用 sysstat 的定时数据收集,特别是 sar。告警往往在你最忙或者最不注意的时候触发,事后回溯需要历史数据。sar 的数据占用空间很小,但在事故复盘时价值极大。确认 sysstat 服务正在运行:

# 确认 sysstat 数据收集服务正常运行
sudo systemctl status sysstat

# 查看数据收集的 cron 配置
cat /etc/cron.d/sysstat

不要轻易修改内核的负载计算参数

Linux 内核允许通过 /proc/sys/ 调整某些调度参数,但 Load Average 的计算参数(EWMA 的衰减系数)是硬编码在内核里的,普通用户无法修改。网络上偶尔有人建议通过修改 vm.dirty_ratio、vm.swappiness 等参数来"间接改善负载",这些有一定道理,但属于进阶调优,不是初学者应该随意尝试的。对于新手来说,先把问题的根本原因找清楚,再考虑调优,这才是正确的顺序。

# 查看当前的 vm 相关内核参数(仅供了解,不建议随意修改)
sysctl vm.swappiness
sysctl vm.dirty_ratio
sysctl vm.dirty_background_ratio

多核机器上养成先看 top -1 的习惯

在 top 运行时按下 1 键,会展开每个 CPU 核心的独立使用率。这在排查某些特定问题时非常有用——比如你可能发现 Load Average 很高,但只有某一两个 CPU 核心跑满了,其他核心都很空闲,这说明可能存在单线程的瓶颈(某个进程没有充分利用多核)。

为 Load Average 告警设置合理的缓冲时间

如果你在监控系统中对 Load Average 设置了告警规则,建议使用"持续超过阈值 N 分钟才告警"的机制,而不是"任何时候超过阈值就告警"。比如要求 1 分钟负载连续超过阈值 5 分钟才发出告警,这样可以过滤掉绝大多数正常的短暂负载峰值,减少告警噪声。Prometheus + Alertmanager 的 for: 5m 配置就是做这个用的。

理解 Load Average 不是万能指标

Load Average 是一个非常粗粒度的综合指标,它反映了"系统繁忙程度"的一个侧面,但无法告诉你更细节的信息:它不能直接告诉你是哪个进程有问题,不能告诉你网络带宽是否打满,不能告诉你应用的内部性能瓶颈在哪里。把它当做一个"需要进一步排查"的信号源,而不是结论本身。

十五、扩展知识:从 Load Average 延伸出的系统调优方向

理解了 Load Average 之后,自然会引出几个相关的调优方向。这里做简单的延伸介绍,每一个方向都可以单独写一篇深度文章。

I/O 调度器

Linux 内核允许为不同的磁盘设备配置不同的 I/O 调度算法。在 Ubuntu 22.04 / 24.04 上,常见的调度器有:

# 查看当前磁盘的 I/O 调度器
cat /sys/block/sda/queue/scheduler

[mq-deadline] kyber bfq none

方括号内的是当前使用的调度器。对于普通 HDD,mq-deadline 通常是不错的选择;对于 NVMe SSD,none(不调度,直接提交)往往性能更好,因为 SSD 本身的随机访问延迟已经很低了,调度反而会增加开销。

Swap 配置与 vm.swappiness

vm.swappiness 控制内核在多大程度上倾向于将内存页面换出到 Swap。默认值是 60,表示当可用内存降低到一定程度时,内核会比较积极地使用 Swap。对于内存充足的服务器,把这个值调低(比如 10)可以让内核更倾向于保留热数据在内存中,减少因不必要的 Swap 操作导致的 Load Average 上升。

# 临时修改(重启后失效)
sudo sysctl vm.swappiness=10

# 永久修改
echo 'vm.swappiness=10' | sudo tee -a /etc/sysctl.d/99-tuning.conf
sudo sysctl -p /etc/sysctl.d/99-tuning.conf

CPU 亲和性(CPU Affinity)

对于某些特定的高性能场景,可以把某个进程绑定到特定的 CPU 核心上运行,减少跨核心调度带来的 cache miss 开销。这属于较深入的性能调优,在普通 Ubuntu 服务器运维中不常用,但在高频交易、实时音视频处理等场景下有实际意义。

# 查看进程当前绑定的 CPU 核心
taskset -p <PID>

# 将进程绑定到 CPU 0 和 1
sudo taskset -cp 0,1 <PID>

cgroups 资源限制

如果你需要限制某个进程或进程组的资源使用(防止某个失控的进程吃掉所有 CPU),可以使用 cgroups(Control Groups)。systemd 在管理服务时实际上就是通过 cgroups 实现资源隔离的:

# 查看某个 systemd 服务的资源使用情况(通过 cgroup)
systemctl status nginx

# 查看服务的详细 cgroup 资源统计
sudo systemd-cgtop

如果你想为某个服务设置 CPU 使用率上限,可以在 systemd unit 文件中配置:

# 在 /etc/systemd/system/myapp.service 中添加
[Service]
CPUQuota=50% # 最多使用 50% 的 CPU(单核等价)
MemoryMax=512M # 最多使用 512MB 内存

十六、完整排查流程回顾

用一张流程图来总结本文介绍的 Load Average 分析全流程,相关示意图绘制如下,仅供大家保存查阅:

这个流程图是本文核心内容的完整梳理。在真实的排查工作中,不一定每个步骤都需要走完——有时候 Step 3 就能找到明确答案,有时候可能需要更深入的工具和分析。但这个思路框架是稳定的:从整体到局部,从表象到根因,每一步缩小范围。

十七、总结

Load Average 是 Linux 系统监控领域里看似简单、实则内涵丰富的一个指标。用了这篇文章比较大的篇幅来讲它,核心原因只有一个:很多人天天看这个数字,但真正理解它的人并不多。

让我们回顾一下本文覆盖的核心知识:

第一,Load Average 的本质是系统中处于"可运行"和"不可中断睡眠"状态的进程数量的指数加权移动平均值。它包含了 CPU 排队和 I/O 等待两部分,不等于 CPU 使用率。

第二,判断 Load Average 高不高,必须以 CPU 核心数为基准。单独看绝对值毫无意义,load / nproc 的比值才是判断依据。

第三,wa(iowait)是区分 CPU 密集型和 I/O 密集型负载的关键指标。高 iowait + 低 CPU idle 通常指向磁盘或内存不足导致的 Swap 风暴。

第四,三个 Load Average 值的相对关系告诉你负载是突然发生的、持续积累的,还是正在恢复中的。这比任何一个绝对值都更有判断价值。

第五,完整的排查工具链是:uptime → top → ps(D 状态)→ iostat(磁盘)→ pidstat / iotop(进程 I/O)→ free(内存)。每个工具有它的侧重点,组合使用才能覆盖所有常见场景。

第六,sar 的历史数据收集在生产环境中是不可或缺的。告警往往在你不在场时触发,有历史数据才能事后复盘。

本章到这里,你已经掌握了理解和分析 Linux 系统负载的核心方法。在下一节(第9节:僵尸进程与孤儿进程)里,我们会深入讲解你在本文 top 输出里见到的那个 zombie 进程——它是什么、为什么存在、有没有危害、以及如何处理。

…

ok,同学们,本节课就上到这儿,下课~

🧧 学习福利 · 限时开放 🧧

当然,无论你是计算机专业在读学生,还是刚开始接触 Linux 的入门者,亦或是希望提升开发环境搭建、服务器管理、系统运维能力的开发者,都强烈建议系统学习 Ubuntu 全体系专栏:👉 「滚雪球学 Ubuntu」;涵盖 Ubuntu 从入门到进阶的完整学习内容。

该专栏以“循序渐进 + 实战驱动 + 场景落地”为核心理念,从基础认知到系统安装,从桌面操作到命令行实践,从系统管理到网络配置,再到安全加固、开发环境搭建、性能优化、故障排查、服务器部署与云平台应用,逐层展开,帮助你快速建立完整的 Ubuntu / Linux 技术体系,真正把 Ubuntu 用明白、用熟练、用稳定。

📌 学习承诺: 通过该专栏,你将能够:

  • 快速掌握 Ubuntu 系统安装、配置与日常使用能力
  • 熟练使用 Linux 常用命令、终端工具与系统管理技巧
  • 搭建稳定可复用的开发环境、测试环境与服务器环境
  • 掌握网络配置、SSH 远程访问、防火墙、安全加固与备份恢复
  • 建立从“入门使用”到“独立运维”的完整 Ubuntu 实战能力

就像“滚雪球”一样,先打牢基础,再持续叠加系统管理、开发环境、网络安全、性能优化与服务器部署能力,让知识不断积累、经验持续放大,最终形成属于自己的 Linux 技术护城河 🚀

最后,如果这篇文章对你有所帮助,帮忙给作者来个一键三连,关注、点赞、收藏,您的支持就是我坚持写作最大的动力。

同时欢迎大家关注技术号:「猿圈奇妙屋」 ,以便学习更多同类型的技术文章,免费白嫖最新 BAT 互联网公司面试题、4000G PDF 编程电子书、简历模板、技术文章 Markdown 文档等海量资料。

ps:本文涉及的 Ubuntu 常用命令、系统配置、环境搭建步骤、服务部署思路与排障方法,均已在文章中结合实战场景进行整理,同学们可以直接对照学习、边看边练。原创整理不易,如果觉得内容有帮助,欢迎点赞、收藏、评论支持一波,非常感谢❗

🫵 Who am I?

我是 bug菌,一名长期深耕后端开发、Linux 系统实践与服务器运维领域的一线技术创作者,曾担任独角兽企业后端技术经理、研发架构师等职位,长期专注于 Java 后端、Linux / Ubuntu 系统管理、服务器部署、分布式架构、微服务治理、高并发系统、工程效能与研发管理等方向。

目前活跃于多个主流技术社区,包括:

CSDN|稀土掘金|InfoQ|51CTO|华为云开发者社区|阿里云开发者社区|腾讯云开发者社区|开源中国|博客园|墨天轮 等平台。

曾获得:

  • CSDN 博客之星 Top30
  • 华为云多年度十佳博主 & 卓越贡献奖
  • 掘金多年度人气作者 Top40
  • CSDN、掘金、InfoQ、51CTO 等平台签约作者 / 优质作者

截至目前,全网技术内容累计影响读者众多,全网粉丝已超过 30w+。

如果你也关注 Linux、Ubuntu、Java 后端、服务器运维、架构设计、技术成长、职场进阶与研发管理,欢迎关注我的技术内容合集入口:👉 点击查看 👈️

硬核技术号 「猿圈奇妙屋」 期待你的加入。

这里不仅分享技术干货,也记录一线研发人的成长、踩坑、思考与进阶路径。

愿我们一起打怪升级,把 Ubuntu 用成生产力工具,把 Linux 练成核心竞争力,在技术路上持续进阶。

– End –

赞(0)
未经允许不得转载:网硕互联帮助中心 » Ubuntu零基础入门到精通【10.8讲】:Load Average 深度解析 - 从“系统负载“到真正读懂服务器压力!
分享到: 更多 (0)

评论 抢沙发

评论前必须登录!