基础篇:到底应该怎么理解“平均负载”
root@Test:/home/test# uptime
08:41:38 up 3 days, 5:40, 2 users, load average: 0.00, 0.03, 0.02
前⾯的⼏列分别是当前时间、系统运⾏时间以及正在登录⽤户数。⽽最后三个数字呢,依次则是过去1分钟、5分钟、15分钟的平均负载(Load Average)。
平均负载
平均负载是指单位时间内,系统处于可运⾏状态和不可中断状态的平均进程数,也就是平均活跃进程数,它和CPU使⽤率并没有直接关系。
- 可运⾏状态:是指正在使⽤CPU或者正在等待CPU的进程,也就是我们常⽤ps命令看到的,处于R状态(Running或 Runnable)的进程。
- 不可中断状态:是指正处于内核态关键流程中的进程,并且这些流程是不可打断的,⽐如最常⻅的是等待硬件设备的I/O响应,也就是我们在ps命令中看到的D状态(Uninterruptible Sleep,也称为Disk Sleep)的进程。⽐如,当⼀个进程向磁盘读写数据时,为了保证数据的⼀致性,在得到磁盘回复前,它是不能被其他进程或者中断打断的,这个时候的进程就处于不可中断状态。如果此时的进程被打断了,就容易出现磁盘数据与进程数据不⼀致的问题。所以,不可中断状态实际上是系统对进程和硬件设备的⼀种保护机制。
因此,可以简单理解为,平均负载其实就是平均活跃进程数。平均活跃进程数,直观上的理解就是单位时间内的活跃进程数,但它实际上是活跃进程数的指数衰减平均值。这个“指数衰减平均”的详细含义你不⽤计较,这只是系统的⼀种更快速的计算⽅式,你把它直接当成活跃进程数的平均值也没问题。
既然平均的是活跃进程数,那么最理想的,就是每个CPU上都刚好运⾏着⼀个进程,这样每个CPU都得到了充分利⽤。⽐如当平均负载为2时,意味着什么呢?
- 在只有2个CPU的系统上,意味着所有的CPU都刚好被完全占⽤。
- 在4个CPU的系统上,意味着CPU有50%的空闲。
- ⽽在只有1个CPU的系统中,则意味着有⼀半的进程竞争不到CPU。
平均负载为多少时合理
- 执行uptime,最后三个数字依次则是过去1分钟、5分钟、15分钟的平均负载(Load Average)
root@Test:/home/test# uptime 08:41:38 up 3 days, 5:40, 2 users, load average: 0.00, 0.03, 0.02
- 执行top/nproc查到cpu个数,当平均负载⽐ CPU 个数还⼤的时候,系统已经出现了过载
- 如果1分钟、5分钟、15分钟的三个值基本相同,或者相差不⼤,那就说明系统负载很平稳。
- 如果1分钟的值远⼩于15 分钟的值,就说明系统最近1分钟的负载在减少,⽽过去15分钟内却有很⼤的负载。
- 如果1分钟的值远⼤于 15 分钟的值,就说明最近1分钟的负载在增加,这种增加有可能只是临时性的,也有可能还会持续增加下去,所以就需要持续观察。⼀旦1分钟的平均负载接近或超过了CPU的个数,就意味着系统正在发⽣过载的问题,这时就得分析调查是哪⾥导致的问题,并要想办法优化了。
- 当平均负载⾼于 CPU 数量70%的时候,你就应该分析排查负载⾼的问题了。⼀旦负载过⾼,就可能导致进程响应变慢,进⽽影响服务的正常功能。
假设我们在⼀个单 CPU 系统上看到平均负载为 1.73,0.60,7.98,那么说明在过去 1 分钟内,系统有73% 的超载,⽽在 15 分钟内,有 698% 的超载,从整体趋势来看,系统的负载在降低。
平均负载与CPU使⽤率
平均负载不等于 CPU 使⽤率,平均负载是指单位时间内,处于可运⾏状态和不可中断状态的进程数。所以,它不仅包括了正在使⽤ CPU 的进程,还包括等待 CPU 和等待 I/O 的进程。⽽ CPU 使⽤率,是单位时间内 CPU 繁忙情况的统计,跟平均负载并不⼀定完全对应。⽐如:
- CPU 密集型进程,使⽤⼤量 CPU 会导致平均负载升⾼,此时这两者是⼀致的;
- I/O 密集型进程,等待 I/O 也会导致平均负载升⾼,但 CPU 使⽤率不⼀定很⾼;
- ⼤量等待 CPU 的进程调度也会导致平均负载升⾼,此时的CPU使⽤率也会⽐较⾼。
平均负载案例分析
用 htop,top 和 pidstat ⼯具,找出平均负载升⾼的根源。预先安装 stress 和 sysstat 包,如 apt install stress sysstat
- stress 是⼀个 Linux 系统压⼒测试⼯具,这⾥我们⽤作异常进程模拟平均负载升⾼的场景。
- sysstat 包含了常⽤的 Linux 性能⼯具,⽤来监控和分析系统的性能。我们的案例会⽤到这个包的两个命令 mpstat 和 pidstat
- mpstat 是⼀个常⽤的多核 CPU 性能分析⼯具,⽤来实时查看每个 CPU 的性能指标,以及所有CPU的平均指标。
- pidstat 是⼀个常⽤的进程性能分析⼯具,⽤来实时查看进程的 CPU、内存、I/O 以及上下⽂切换等性能指标
场景⼀:CPU 密集型进程
CPU密集型进程指的是进程数不多,但是计算量非常大,此时负载等于CPU使用率
- 在第⼀个终端运⾏ stress 命令,模拟⼀个 CPU 使⽤率 100% 的场景:
stress --cpu 1 --timeout 600
- 在第⼆个终端运⾏uptime查看平均负载的变化情况
watch -d uptime 08:00:37 up 3 days, 1:54, 8 users, load average: 1.00, 2.12, 2.41
- 在第三个终端运⾏mpstat查看 CPU 使⽤率的变化情况:-P ALL 表示监控所有CPU,后⾯数字5表示间隔5秒后输出⼀组数据
root@Test:/home/test# mpstat -P ALL 5 Linux 5.15.0-119-generic (Test) 09/14/2024 _x86_64_ (4 CPU) 08:01:32 AM CPU %usr %nice %sys %iowait %irq %soft %steal %guest %gnice %idle 08:01:37 AM all 25.08 0.00 0.10 0.00 0.00 0.05 0.00 0.00 0.00 74.77 08:01:37 AM 0 100.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 08:01:37 AM 1 0.20 0.00 0.00 0.00 0.00 0.20 0.00 0.00 0.00 99.60 08:01:37 AM 2 0.00 0.00 0.20 0.00 0.00 0.00 0.00 0.00 0.00 99.80 08:01:37 AM 3 0.00 0.00 0.20 0.00 0.00 0.00 0.00 0.00 0.00 99.80
从终端⼆中可以看到,1 分钟的平均负载为 1.00,⽽从终端三中还可以看到,正好有⼀个 CPU 的使⽤率为100%,但它的 iowait 只有 0。这说明,平均负载的升⾼正是由于 CPU 使⽤率为 100%。那么,到底是哪个进程导致了 CPU 使⽤率为 100% 呢?使⽤ pidstat 来查询:从这⾥可以明显看到,stress进程的CPU使⽤率为100%。
- 在第四个终端运⾏pidstat查看进程情况:间隔5秒后输出⼀组数据
root@Test:/home/test# pidstat -u 1 5 Linux 5.15.0-119-generic (Test) 09/14/2024 _x86_64_ (4 CPU) 08:05:06 AM UID PID %usr %system %guest %wait %CPU CPU Command 08:05:07 AM 1007 3954 0.00 0.99 0.00 0.00 0.99 3 mysqld 08:05:07 AM 0 284449 100.99 0.00 0.00 0.00 100.99 1 stress 08:05:07 AM 0 284454 0.99 0.99 0.00 0.00 1.98 3 pidstat
场景⼆:I/O 密集型进程
- 运⾏ stress 命令模拟 I/O 压⼒,即不停地执⾏ sync,此时系统负载增加
stress-ng -i 1 --hdd 1 --hdd-opts sync --timeout 600
- 第二个终端运⾏mpstat查看 CPU 使⽤率的变化情况:
root@Test:/home/test# mpstat -P ALL 5 Linux 5.15.0-119-generic (Test) 09/14/2024 _x86_64_ (4 CPU) 08:19:36 AM CPU %usr %nice %sys %iowait %irq %soft %steal %guest %gnice %idle 08:19:41 AM all 6.27 0.00 15.03 32.09 0.00 0.41 0.00 0.00 0.00 46.20 08:19:41 AM 0 2.62 0.00 10.89 20.77 0.00 0.40 0.00 0.00 0.00 65.32 08:19:41 AM 1 2.88 0.00 8.64 23.87 0.00 0.41 0.00 0.00 0.00 64.20 08:19:41 AM 2 15.48 0.00 26.88 43.99 0.00 0.61 0.00 0.00 0.00 13.03 08:19:41 AM 3 4.08 0.00 13.67 39.80 0.00 0.20 0.00 0.00 0.00 42.24
从这⾥可以看到,CPU 的iowait 非常高。这说明,平均负载的升⾼是由于 iowait 的升⾼。接着⽤ pidstat 来查询相关进程
- 在第三个终端运⾏pidstat查看进程情况:间隔5秒后输出⼀组数据,发现是由stress-ng进程导致CPU负载高
root@Test:/home/test# pidstat -d -u 5 5 Linux 5.15.0-119-generic (Test) 09/14/2024 _x86_64_ (4 CPU) 08:32:52 AM UID PID %usr %system %guest %wait %CPU CPU Command 08:32:57 AM 0 13 0.00 0.20 0.00 0.00 0.20 0 ksoftirqd/0 08:32:57 AM 0 14 0.00 0.20 0.00 0.00 0.20 0 rcu_sched 08:32:57 AM 0 28 0.00 0.20 0.00 0.00 0.20 2 ksoftirqd/2 08:32:57 AM 0 152 0.00 0.20 0.00 0.00 0.20 2 kworker/2:1H-kblockd 08:32:57 AM 0 198 0.00 0.20 0.00 0.00 0.20 3 kworker/3:1H-kblockd 08:32:57 AM 0 487 0.00 1.59 0.00 0.20 1.59 3 jbd2/dm-0-8 08:32:57 AM 0 565 0.00 0.20 0.00 0.00 0.20 0 systemd-journal 08:32:57 AM 0 810 0.40 0.20 0.00 0.00 0.60 2 falcon-sensor-b 08:32:57 AM 0 2332 0.20 0.00 0.00 0.00 0.20 1 ssm-agent-worke 08:32:57 AM 1007 3954 0.20 0.20 0.00 0.00 0.40 3 mysqld 08:32:57 AM 0 270327 0.00 3.78 0.00 0.80 3.78 1 kworker/u256:2-flush-253:0 08:32:57 AM 0 284436 0.00 3.78 0.00 0.80 3.78 2 kworker/u256:0-flush-253:0 08:32:57 AM 0 284438 0.00 0.40 0.00 0.00 0.40 0 kworker/u256:3-flush-253:0 08:32:57 AM 0 284725 0.00 4.58 0.00 0.60 4.58 1 kworker/u256:4+flush-253:0 08:32:57 AM 0 285023 0.20 0.00 0.00 0.00 0.20 0 kworker/0:0-events 08:32:57 AM 0 285052 0.60 10.56 0.00 2.39 11.16 2 stress-ng 08:32:57 AM 0 285053 27.49 31.27 0.00 1.79 58.76 0 stress-ng 08:32:57 AM 0 285058 0.20 0.00 0.00 0.00 0.20 3 pidstat
场景三:⼤量进程的场景
当系统中运⾏进程超出 CPU 运⾏能⼒时,就会出现等待 CPU 的进程。⽐如,我们使⽤ stress模拟 16 个进程,由于系统只有 4 个CPU,明显⽐ 16 个进程要少得多,因⽽,系统的 CPU 处于严重过载状态
- 运⾏ stress 命令模拟大量进程场景,此时系统负载增加
stress -c 8 --timeout 600
- 第二个终端运⾏mpstat查看 CPU 使⽤率的变化情况,此时CPU负载高,但是iowait低
08:39:13 AM CPU %usr %nice %sys %iowait %irq %soft %steal %guest %gnice %idle 08:39:18 AM all 99.95 0.00 0.05 0.00 0.00 0.00 0.00 0.00 0.00 0.00 08:39:18 AM 0 100.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 08:39:18 AM 1 99.80 0.00 0.20 0.00 0.00 0.00 0.00 0.00 0.00 0.00 08:39:18 AM 2 100.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 08:39:18 AM 3 100.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
- 在第三个终端运⾏pidstat查看进程情况。可以看出,16 个进程在争抢 4 个 CPU,每个进程等待 CPU 的时间(也就是代码块中的 %wait 列)⾼达 70%。这些超出 CPU计算能⼒的进程,最终导致 CPU 过载。
root@Test:/home/test# pidstat -u 1 5 Linux 5.15.0-119-generic (Test) 09/14/2024 _x86_64_ (4 CPU) 08:44:02 AM UID PID %usr %system %guest %wait %CPU CPU Command 08:44:03 AM 0 2332 0.93 0.00 0.00 0.00 0.93 3 ssm-agent-worke 08:44:03 AM 0 285023 0.93 0.00 0.00 0.00 0.93 0 kworker/0:0-events 08:44:03 AM 0 285092 23.15 0.00 0.00 73.15 23.15 0 stress 08:44:03 AM 0 285093 24.07 0.00 0.00 71.30 24.07 3 stress 08:44:03 AM 0 285094 24.07 0.00 0.00 72.22 24.07 0 stress 08:44:03 AM 0 285095 23.15 0.00 0.00 72.22 23.15 0 stress 08:44:03 AM 0 285096 24.07 0.00 0.00 72.22 24.07 1 stress 08:44:03 AM 0 285097 24.07 0.00 0.00 70.37 24.07 1 stress 08:44:03 AM 0 285098 24.07 0.00 0.00 72.22 24.07 3 stress 08:44:03 AM 0 285099 24.07 0.00 0.00 70.37 24.07 1 stress 08:44:03 AM 0 285100 23.15 0.00 0.00 71.30 23.15 1 stress 08:44:03 AM 0 285101 24.07 0.00 0.00 71.30 24.07 2 stress 08:44:03 AM 0 285102 24.07 0.00 0.00 71.30 24.07 3 stress 08:44:03 AM 0 285103 24.07 0.00 0.00 72.22 24.07 2 stress 08:44:03 AM 0 285104 24.07 0.00 0.00 71.30 24.07 2 stress 08:44:03 AM 0 285105 23.15 0.00 0.00 69.44 23.15 0 stress 08:44:03 AM 0 285106 24.07 0.00 0.00 72.22 24.07 2 stress 08:44:03 AM 0 285107 23.15 0.00 0.00 71.30 23.15 3 stress 08:44:03 AM 0 285109 0.00 0.93 0.00 0.93 0.93 0 pidstat
⼩结
平均负载提供了⼀个快速查看系统整体性能的⼿段,反映了整体的负载情况。但只看平均负载本身,我们并不能直接发现,到底是哪⾥出现了瓶颈。所以,在理解平均负载时,也要注意:
- 平均负载⾼有可能是 CPU 密集型进程导致的;
- 平均负载⾼并不⼀定代表 CPU 使⽤率⾼,还有可能是 I/O 更繁忙了;
- 当发现负载⾼的时候,你可以使⽤ mpstat、pidstat 等⼯具,辅助分析负载的来源。