linux之平均负载(学习笔记非原创)

什么是平均负载

[root@111 ~]# uptime
11:03:33 up 149 days, 17:34, 1 user, load average: 0.08, 0.05, 0.01

最后三个数字,依次则是过去1分钟、5分钟、15分钟的平均负载(Load Average),常用的top工具也能展示

平均负载作为极其重要的系统指标,是指单位时间内,系统处于可运行状态和不可中断状态的平均进程数,也就是平均活跃进程数,它和CPU使用率并没有直接关系。

可运行状态的进程,是指正在使用CPU或者正在等待CPU的进程,也就是我们常用ps命令看到的,处于R状态(Running 或 Runnable)的进程。

不可中断状态的进程则是正处于内核态关键流程中的进程,并且这些流程是不可打断的,比如最常见的是等待硬件设备的I/O响应,也就是我们在ps命令中看到的D状态(Uninterruptible Sleep)的进程。

比如,当一个进程向磁盘读写数据时,为了保证数据的一致性,在得到磁盘回复前,它是不能被其他进程或者中断打断的,这个时候的进程就处于不可中断状态。如果此时的进程被打断了,就容易出现磁盘数据与进程数据不一致的问题。

所以,不可中断状态实际上是系统对进程和硬件设备的一种保护机制。

综上所述,平均负载其实就是平均活跃进程数,即单位时间内的活跃进程数。

平均负载为多少时合理

最理想的状态,是每个CPU上都刚好跑着一个进程,这样每个CPU都得到了充分利用。比如当平均负载为2时,意味着什么呢?

  • 在只有2个CPU的系统上,意味着所有的CPU都刚好被完全占用。

  • 在4个CPU的系统上,意味着CPU有50%的空闲。

  • 而在只有1个CPU的系统中,则意味着有一半的进程竞争不到CPU。

所以,平均负载最理想的情况是等于 CPU个数。在评判平均负载时,首先要知道系统有几个 CPU,可以通过 top 命令或者从文件 /proc/cpuinfo 中读取,比如:

逻辑cpu个数:
[root@111 ~]# grep processor /proc/cpuinfo |wc -l
4

一般来说,实际生产环境中,当平均负载为 CPU 数量的70-80%的时候,就应该分析排查负载高的问题了。

另一方面,我们需要关注平均负载三个数值的变化:

  • 如果1分钟、5分钟、15分钟的三个值基本相同,或者相差不大,那就说明系统负载很平稳。

  • 但如果1分钟的值远小于15 分钟的值,就说明系统最近1分钟的负载在减少,而过去15分钟内却有很大的负载。

  • 反过来,如果1分钟的值远大于 15 分钟的值,就说明最近1分钟的负载在增加,这种增加有可能只是临时性的,也有可能还会持续增加下去,所以就需要持续观察。一旦1分钟的平均负载接近或超过了CPU的个数,就意味着系统正在发生过载的问题,这时就得分析调查是哪里导致的问题,并要想办法优化了。

举个栗子,4核的机子,平均负载为 3.23,1.60,6.98:

  • 在过去的15分钟,平均负载超过cpu个数,说明负载很高,可能是cpu使用率很高,也可能是I/O的压力等等原因。
  • 过去1分钟和过去5分钟,平均负载都小于cpu个数,说明负载正常,从整体趋势来看,系统的负载在降低,但是过去1分钟的值大于过去5分钟的值,说明平均负载又在升高。

70-80%这个数字并不是绝对的,毕竟最长的15分钟的数据也只是短期的表现,最推荐的方法,是把系统的平均负载监控起来,然后根据更多的历史数据,判断负载的整体变化趋势。

平均负载与CPU使用率

现实工作中,我们经常容易把平均负载和 CPU 使用率混淆,其实两者还是有区别的。

可能你会疑惑,既然平均负载代表的是活跃进程数,那平均负载高了,不就意味着 CPU 使用率高吗?

我们还是要回到平均负载的含义上来,平均负载是指单位时间内,处于可运行状态和不可中断状态的进程数。所以,它不仅包括了正在使用 CPU 的进程,还包括等待 CPU 和等待 I/O 的进程。

CPU 使用率,是单位时间内 CPU 繁忙情况的统计,跟平均负载并不一定完全对应。比如:

  • CPU 密集型进程,使用大量 CPU 会导致平均负载升高,此时这两者是一致的;

  • I/O 密集型进程,等待 I/O 也会导致平均负载升高,但 CPU 使用率不一定很高;

  • 大量等待 CPU 的进程调度也会导致平均负载升高,此时的CPU使用率也会比较高。

平均负载案例模拟分析

模拟三个场景分别来看以上三种情况,使用iostat、mpstat、pidstat 等工具,找出平均负载升高的根源。

  • 机器配置:4cpu,16G内存,centos
  • 安装 stress 和 sysstat 工具包,yum install stress sysstat -y

stress 是一个 Linux 系统压力测试工具

stress语法格式:
stress <options> 常用选项:
-c, --cpu N 产生 N 个进程,每个进程都反复不停的计算随机数的平方根
-i, --io N 产生 N 个进程,每个进程反复调用 sync() 将内存上的内容写到硬盘上
-m, --vm N 产生 N 个进程,每个进程不断分配和释放内存
--vm-bytes B 指定分配内存的大小
--vm-stride B 不断的给部分内存赋值,让 COW(Copy On Write)发生
--vm-hang N 指示每个消耗内存的进程在分配到内存后转入睡眠状态 N 秒,然后释放内存,一直重复执行这个过程
--vm-keep 一直占用内存,区别于不断的释放和重新分配(默认是不断释放并重新分配内存)
-d, --hadd N 产生 N 个不断执行 write 和 unlink 函数的进程(创建文件,写入内容,删除文件)
--hadd-bytes B 指定文件大小
-t, --timeout N 在 N 秒后结束程序
--backoff N 等待N微妙后开始运行
-q, --quiet 程序在运行的过程中不输出信息
-n, --dry-run 输出程序会做什么而并不实际执行相关的操作
--version 显示版本号
-v, --verbose 显示详细的信息

sysstat 包含了常用的 Linux 性能工具,用来监控和分析系统的性能,主要包括:

iostat 工具提供CPU使用率及硬盘吞吐效率的数据;  #比较核心的工具
mpstat 工具提供单个处理器或多个处理器相关数据;
pidstat: 关于运行中的进程/任务、CPU、内存等的统计信息
sar 工具负责收集、报告并存储系统活跃的信息; #统计数据的核心工具
sa1 工具负责收集并存储每天系统动态信息到一个二进制的文件中。它是通过计划任务工具cron来运行,是为sadc所设计的程序前端程序;
sa2工具负责把每天的系统活跃性息写入总结性的报告中。它是为sar所设计的前端 ,要通过cron来调用
sadc 是系统动态数据收集工具,收集的数据被写一个二进制的文件中,它被用作sar工具的后端;
sadf 显示被sar通过多种格式收集的数据;
nfsiostat: NFS(Network File System)的I/O统计信息。
cifsiostat: CIFS(Common Internet File System)的统计信息。

每个场景都需要开三个终端,登录到同一台 Linux 机器中,使用uptime看一下测试前的平均负载:

[root@123~]# uptime
16:11:04 up 150 days, 22:42, 3 users, load average: 0.06, 0.03, 0.00

场景一:CPU 密集型进程

首先,在第一个终端运行 stress 命令,模拟一个 CPU 使用率 100% 的场景:

#产生1个进程反复不停的计算随机数的平方根,300秒后停止
[root@123 ~]# stress -c 1 -t 300

接着,在第二个终端运行watch -d uptime查看平均负载的变化情况:

# -d 参数表示高亮显示变化的区域
Every 2.0s: uptime 
16:26:55 up 150 days, 22:58, 3 users, load average: 1.05, 0.76, 0.40

可以看到,1 分钟的平均负载会慢慢增加到 1.00出头

最后,在第三个终端运行mpstat查看 CPU 使用率的变化情况:

mpstat --help
用法: mpstat [ 选项 ] [ <时间间隔> [ <次数> ] ]
选项:
[ -I { SUM | CPU | SCPU | ALL } ] [ -N { <node_list> | ALL } ]
[ --dec={ 0 | 1 | 2 } ] [ -o JSON ] [ -P { <CPU_列表> | ALL } ] #-P ALL 表示监控所有CPU,间隔5秒后输出一组数据,总计5组
[root@123~]# mpstat -P ALL 5 5 04:25:28 PM CPU %usr %nice %sys %iowait %irq %soft %steal %guest %idle
04:25:33 PM all 25.11 0.00 0.20 0.35 0.00 0.00 0.00 0.00 74.34
04:25:33 PM 0 0.40 0.00 0.20 0.00 0.00 0.00 0.00 0.00 99.40
04:25:33 PM 1 100.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
04:25:33 PM 2 0.00 0.00 0.60 1.60 0.00 0.00 0.00 0.00 97.80
04:25:33 PM 3 0.00 0.00 0.20 0.00 0.00 0.00 0.00 0.00 99.80 04:25:33 PM CPU %usr %nice %sys %iowait %irq %soft %steal %guest %idle
04:25:38 PM all 25.13 0.00 0.15 0.40 0.00 0.00 0.00 0.00 74.32
04:25:38 PM 0 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 100.00
04:25:38 PM 1 100.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
04:25:38 PM 2 0.20 0.00 0.40 1.41 0.00 0.00 0.00 0.00 97.99
04:25:38 PM 3 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 100.00

可以看到,正好有一个 CPU 的使用率为 100%,但它的 iowait 只有 0。这说明,平均负载的升高正是由于 CPU 使用率为 100%

那么,到底是哪个进程导致了 CPU 使用率为 100% 呢?可以使用 pidstat 来查询:

pidstat --help
用法:pidstat [ 选项 ] [ <时间间隔> [ <计数> ] ] [ -e <程序> <参数> ]
选项:
[ -d ] [ -H ] [ -h ] [ -I ] [ -l ] [ -R ] [ -r ] [ -s ] [ -t ] [ -U [ <用户名> ] ]
[ -u ] [ -V ] [ -v ] [ -w ] [ -C <命令> ] [ -G <进程名> ]
[ -p { <pid> [,...] | SELF | ALL } ] [ -T { TASK | CHILD | ALL } ]
[ --dec={ 0 | 1 | 2 } ] [ --human ]
常用选项解释:
-u:默认的参数,显示各个进程的cpu使用统计
-r:显示各个进程的内存使用统计
-d:显示各个进程的IO使用情况
-p:指定进程号
-w:显示每个进程的上下文切换情况 #间隔5秒输出一组数据,总计5组
[root@123 ~]# pidstat -u 5 5 04:26:17 PM PID %usr %system %guest %CPU CPU Command
04:26:22 PM 2464 0.20 0.00 0.00 0.20 3 netdata
04:26:22 PM 2677 0.20 0.00 0.00 0.20 0 python
04:26:22 PM 26629 0.00 0.40 0.00 0.40 2 apps.plugin
04:26:22 PM 28735 100.00 0.00 0.00 100.00 3 stress 04:26:22 PM PID %usr %system %guest %CPU CPU Command
04:26:27 PM 2464 0.20 0.00 0.00 0.20 3 netdata
04:26:27 PM 26629 0.20 0.20 0.00 0.40 2 apps.plugin
04:26:27 PM 28735 100.00 0.00 0.00 100.00 3 stress

从这里可以明显看到,stress进程的CPU使用率为100%。

场景二:I/O 密集型进程

首先还是运行 stress 命令,但这次模拟 I/O 压力,即不停地执行 sync:

# 产生1个进程,反复调用 sync() 将内存上的内容写到硬盘上,300秒后结束
[root@123~]# stress -i 1 -t 300

还是在第二个终端运行watch -d uptime查看平均负载的变化情况:

17:14:02 up 150 days, 23:45,  4 users,  load average: 1.52, 1.68, 0.80

可以看到,平均负载再次上升

然后,第三个终端运行mpstat查看 CPU 使用率的变化情况:

#显示所有CPU的指标,间隔5秒输出一组数据,持续输出
[root@123 ~]# mpstat -P ALL 5
05:08:10 PM CPU %usr %nice %sys %iowait %irq %soft %steal %guest %idle
05:08:15 PM all 0.15 0.00 0.15 0.20 0.00 0.00 0.00 0.00 99.50
05:08:15 PM 0 0.20 0.00 0.20 0.00 0.00 0.00 0.00 0.00 99.60
05:08:15 PM 1 0.20 0.00 0.40 0.00 0.00 0.00 0.00 0.00 99.40
05:08:15 PM 2 0.20 0.00 0.00 1.00 0.00 0.00 0.00 0.00 98.80
05:08:15 PM 3 0.20 0.00 0.20 0.00 0.00 0.00 0.00 0.00 99.60 05:08:15 PM CPU %usr %nice %sys %iowait %irq %soft %steal %guest %idle
05:08:20 PM all 0.15 0.00 0.20 10.67 0.00 0.00 0.00 0.00 88.98
05:08:20 PM 0 0.20 0.00 0.00 14.63 0.00 0.00 0.00 0.00 85.17
05:08:20 PM 1 0.00 0.00 0.40 0.00 0.00 0.00 0.00 0.00 99.60
05:08:20 PM 2 0.00 0.00 0.20 28.11 0.00 0.00 0.00 0.00 71.69
05:08:20 PM 3 0.20 0.00 0.00 0.00 0.00 0.00 0.00 0.00 99.80 05:08:20 PM CPU %usr %nice %sys %iowait %irq %soft %steal %guest %idle
05:08:25 PM all 0.15 0.00 0.20 22.19 0.00 0.00 0.00 0.00 77.45
05:08:25 PM 0 0.20 0.00 0.20 29.46 0.00 0.00 0.00 0.00 70.14
05:08:25 PM 1 0.20 0.00 0.40 0.00 0.00 0.00 0.00 0.00 99.40
05:08:25 PM 2 0.20 0.00 0.20 59.44 0.00 0.00 0.00 0.00 40.16
05:08:25 PM 3 0.20 0.00 0.20 0.00 0.00 0.00 0.00 0.00 99.60

可以发现,系统CPU使用率很低,而 iowait很高,其中一个高达 59.44%,这说明平均负载的升高是由于 iowait 的升高。

是哪个进程导致iowait这么高?

#pidstat -d:显示各个进程的IO使用情况
[root@123 ~]# pidstat -d 3 3

05:12:56 PM       PID   kB_rd/s   kB_wr/s kB_ccwr/s  Command
05:12:59 PM 701 0.00 68.00 0.00 jbd2/dm-0-8
05:12:59 PM 1518 0.00 292.00 0.00 flush-253:0
05:12:59 PM 1968 0.00 28.00 0.00 java 05:12:59 PM PID kB_rd/s kB_wr/s kB_ccwr/s Command
05:13:02 PM 701 0.00 80.00 0.00 jbd2/dm-0-8
05:13:02 PM 1518 0.00 268.00 0.00 flush-253:0
05:13:02 PM 1968 0.00 30.67 0.00 java 05:13:02 PM PID kB_rd/s kB_wr/s kB_ccwr/s Command
05:13:05 PM 701 0.00 80.00 0.00 jbd2/dm-0-8
05:13:05 PM 1518 0.00 286.67 0.00 flush-253:0
05:13:05 PM 1968 0.00 36.00 0.00 java

jbd2/dm-0-8和flush-253:0都是操作系统针对磁盘和文件系统的进程,本质上是stress 进程导致的,因为300秒后当stress结束了,这两个进程也结束了。

场景三:大量进程的场景

当系统中运行进程超出 CPU 运行能力时,就会出现等待 CPU 的进程。

比如,我们还是使用 stress,但这次模拟的是 8 个进程:

[root@123 ~]# stress -c 8 -t 300

由于系统只有 4 个CPU,比 8 个进程要少一半,因而,系统的 CPU 处于严重过载状态,平均负载高达7.90:

11:35:53 up 155 days, 18:07,  4 users,  load average: 7.90, 5.51, 3.00

使用mpstat查看cpu使用率

[root@123~]# mpstat -P ALL 3 10

11:30:17 AM  CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest   %idle
11:30:20 AM all 99.83 0.00 0.17 0.00 0.00 0.00 0.00 0.00 0.00
11:30:20 AM 0 100.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
11:30:20 AM 1 100.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
11:30:20 AM 2 100.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
11:30:20 AM 3 99.67 0.00 0.33 0.00 0.00 0.00 0.00 0.00 0.00 11:30:20 AM CPU %usr %nice %sys %iowait %irq %soft %steal %guest %idle
11:30:23 AM all 99.92 0.00 0.08 0.00 0.00 0.00 0.00 0.00 0.00
11:30:23 AM 0 100.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
11:30:23 AM 1 99.67 0.00 0.33 0.00 0.00 0.00 0.00 0.00 0.00
11:30:23 AM 2 99.67 0.00 0.33 0.00 0.00 0.00 0.00 0.00 0.00
11:30:23 AM 3 100.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00

可见4个cpu都被打满,再用pidstat看一下进程使用cpu的情况:

[root@123 ~]# pidstat 3 10

11:30:20 AM       PID    %usr %system  %guest    %CPU   CPU  Command
11:30:23 AM 2385 0.33 0.00 0.00 0.33 2 java
11:30:23 AM 2464 0.33 0.33 0.00 0.66 0 netdata
11:30:23 AM 26384 49.67 0.00 0.00 49.67 1 stress
11:30:23 AM 26385 49.67 0.00 0.00 49.67 0 stress
11:30:23 AM 26386 49.01 0.00 0.00 49.01 3 stress
11:30:23 AM 26387 49.67 0.00 0.00 49.67 2 stress
11:30:23 AM 26388 50.66 0.00 0.00 50.66 3 stress
11:30:23 AM 26389 49.67 0.00 0.00 49.67 0 stress
11:30:23 AM 26390 49.67 0.00 0.00 49.67 1 stress
11:30:23 AM 26391 49.67 0.00 0.00 49.67 2 stress 11:30:23 AM PID %usr %system %guest %CPU CPU Command
11:30:26 AM 26223 0.33 0.00 0.00 0.33 3 watch
11:30:26 AM 26384 49.67 0.00 0.00 49.67 1 stress
11:30:26 AM 26385 50.00 0.00 0.00 50.00 0 stress
11:30:26 AM 26386 50.00 0.00 0.00 50.00 3 stress
11:30:26 AM 26387 50.00 0.00 0.00 50.00 2 stress
11:30:26 AM 26388 49.67 0.00 0.00 49.67 3 stress
11:30:26 AM 26389 50.00 0.00 0.00 50.00 0 stress
11:30:26 AM 26390 50.00 0.00 0.00 50.00 1 stress
11:30:26 AM 26391 50.00 0.00 0.00 50.00 2 stress
11:30:26 AM 26524 0.00 0.33 0.00 0.33 2 pidstat

可以看出,8 个stress进程在争抢 4 个 CPU,每个进程都占据着0.5个cpu,同时等待 CPU 的时间也是 50%。这些超出 CPU 计算能力的进程,最终导致 CPU 过载。

小结

分析完这三个案例,归纳一下平均负载的理解。

平均负载提供了一个快速查看系统整体性能的手段,反映了整体的负载情况。但只看平均负载本身,我们并不能直接发现,到底是哪里出现了瓶颈。所以,在理解平均负载时,也要注意:

  • 平均负载高有可能是 CPU 密集型进程导致的;

  • 平均负载高并不一定代表 CPU 使用率高,还有可能是 I/O 更繁忙了;

  • 当发现负载高的时候,你可以使用 mpstat、pidstat 等工具,辅助分析负载的来源。

上一篇:linux系统的负载详解


下一篇:Linux系统的负载与CPU、内存、硬盘、用户数监控的shell脚本