应该如何理解“平均负载”

本文是通过学习倪朋飞老师的《Linux性能优化实战》 :到底应该怎么理解“平均负载”

平均负载?对很多人来说,可能既熟悉又陌生,我们每天的工作中,也都会提到这个词,但是我们真正理解它背后的含义吗?如果有人问我们什么是平均负载,我们能给他讲清楚什么是平均负载吗?

我曾做过总结,发现自己对平均负载的理解并不是很深刻,只知道只言片语,很是奇怪,随后我又和我们公司的运维讨论过,发现彼此都是一样,平时发现系统变慢了在命令行里输入top或者uptime命令进行查看,明明总能看到也总会用到,但是就是说不明白,其实还是自己的功底不够,理解的不够深刻。

[root@service home]# uptime 
 10:20:27 up 93 days, 14:52,  3 users,  load average: 0.38, 0.40, 0.37
 #10:20:27 当前时间
 # up 93 days, 14:52 系统运行时间
 # 3 users 正在登录用户数
 # load average: 0.18, 0.27, 0.32  依次则是过去 1 分钟、5 分钟、15 分钟的平均负载(Load Average)

于是,近几年,遇到问题,特别是基础问题,都会多查,多看,以理解现象背后的本质原理,用起来更灵活,也更有底气。

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

  1. 可运行进程
    所谓可运行状态的进程,是指正在使用 CPU 或者正在等待 CPU 的进程,也就是我们常用 ps 命令看到的,处于 R 状态(Running 或 Runnable)的进程。
  2. 不可中断状态的进程
    不可中断状态的进程则是正处于内核态关键流程中的进程,并且这些流程是不可打断的, 比如最常见的是等待硬件设备的 I/O 响应,也就是我们在 ps 命令中看到的 D 状态 (Uninterruptible Sleep,也称为 Disk Sleep)的进程。
    比如,当一个进程向MySql写数据时,为了保证数据的一致性,在得到MySql回复前,它是不能被其他进程中断打断的,这个时候的进程就处于不可中断状态。如果此时的进程被打断了,就容易出现MySql数据与进程数据不一致的问题。
    所以,不可中断状态实际上是系统对进程和硬件设备的一种保护机制

因此,可以简单理解为,平均负载其实就是平均活跃进程数。平均活跃进程数,直观上的理解就是单位时间内的活跃进程数,但它实际上是活跃进程数的指数衰减平均值。

既然平均的是活跃进程数,那么最理想的,就是每个 CPU 上都刚好运行着一个进程,这样每个CPU都得到了充分利用。比如当平均负载为 2 时,意味着什么呢?

  • 在只有 2 个 CPU 的系统上,意味着所有的 CPU 都刚好被完全占用。
  • 在 4 个 CPU 的系统上,意味着 CPU 有 50% 的空闲。
  • 而在只有 1 个 CPU 的系统中,则意味着有一半的进程竞争不到 CPU。

平均负载为多少时合理

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

[root@service ~]# cat /proc/cpuinfo |grep "model name"|wc -l
4

有了 CPU 个数,我们就可以判断出,当平均负载比 CPU 个数还大的时候,系统已经出现了过载。不过这个观察也是要评估多个指标的,我们要同时用1分钟5分钟15分钟的值来大概的估算这个设备的负载是呈现上升或者下降的趋势,其实最好的方式是通过监控的手段,采集足够多的load值,这样可以更精准的知道自己设备的负载情况。

当平均负载高于 CPU 数量 70% 的时候,你就应该分析排查负载高的问题了。 一旦负载过高,就可能导致进程响应变慢,进而影响服务的正常功能。

但 70% 这个数字并不是绝对的,最推荐的方法,还是把系统的平均负载监控起来,然后 根据更多的历史数据,判断负载的变化趋势。当发现负载有明显升高趋势时,比如说负载翻倍了,再去做分析和调查。

平均负载与 CPU 使用率

在日常工作中,我们经常容易把平均负载和CPU使用率混淆,这里我们做下区分:
可能我们会疑惑,既然平均负载代表的是活跃进程数,那平均负载高了,不就意味着 CPU 使用率高吗?
我们还是要回到平均负载的含义上来,平均负载是指单位时间内,处于可运行状态不可中断状态的进程数。所以,它不仅包括了正在使用 CPU 的进程,还包括等待 CPU 和等待 I/O 的进程。
而 CPU 使用率,是单位时间内 CPU 繁忙情况的统计,跟平均负载并不一定完全对应。比如:

  • CPU 密集型进程,使用大量 CPU 会导致平均负载升高,此时这两者是一致的;
  • I/O 密集型进程,等待 I/O 也会导致平均负载升高,但 CPU 使用率不一定很高;
  • 大量等待 CPU 的进程调度也会导致平均负载升高,此时的 CPU 使用率也会比较高。

平均负载案例分析

这里会用到2个工具,stress和sysstat
stress是一个Linux系统压力测试工具,这里我们用作异常进程模拟平均负载升高的场景。

sysstat是一个linux性能工具,用来监控和分析系统的性能,以下案例中会用到这个包的2个命令mpstat和pidstat。

  • mpstat 是一个常用的多核CPU性能分析工具用来实时查看每个CPU的性能指标,一级所有CPI的平均指标。
参数释义
CPU处理器ID
%usr在internal时间段里,用户态的CPU时间(%),不包含 nice值为负进程 sr/total*100
%nice在internal时间段里,nice值为负进程的CPU时间(%) nice/total*100
%sys在internal时间段里,CPU时间(%) system/total*100
%iowait在internal时间段里,硬盘IO等待(%) iowait/total*100
%irq在internal时间段里,硬中断时间(%) irq/total*100
%soft在internal时间段里,软中断时间(%) softirq/total*100
%steal显示虚拟机管理器在服务另一个虚拟处理器时虚拟CPU处在非自愿等待下花费时间的百分比 steal/total*100
%guest显示运行虚拟处理器时CPU花费时间的百分比 guest/total*100
%gnicegnice/total*100
%idle在internal时间段里,CPU除去等待磁盘IO操作外的因为任何原因而空闲的时间闲置时间(%) idle/total*100
  • pidstat 是一个常用的进程性能分析工具,用来实时查看进程的CPU、内存、I/O以及上下文切换等性能指标。
参数释义
UID用户id
PID进程ID
%usr进程在用户空间占用cpu的百分比
%system进程在内核空间占用cpu的百分比
%guest进程在虚拟机占用cpu的百分比
%wait进程在等待CPU的时间百分比
%CPU进程占用cpu的百分比
CPU处理进程的cpu编号
%Command当前进程对应的命令

此外,每个场景都需要你开三个终端,登录到同一台 Linux 机器中。

场景一:CPU 密集型进程

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

 stress --cpu 2 --timeout 600

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

# -d 参数表示高亮显示变化的区域
watch -d uptime
11:01:49 up 93 days, 15:33,   2 users,  load average: 1.90, 1.14, 0.66

# 在使用top看一下负载
top
top - 11:02:13 up 93 days, 15:34,  4 users,  load average: 2.18, 1.66, 1.21
Tasks: 190 total,   4 running, 186 sleeping,   0 stopped,   0 zombie
%Cpu0  :  8.4 us, 16.1 sy,  0.0 ni, 74.6 id,  0.0 wa,  0.7 hi,  0.3 si,  0.0 st
%Cpu1  : 99.7 us,  0.0 sy,  0.0 ni,  0.0 id,  0.0 wa,  0.3 hi,  0.0 si,  0.0 st
%Cpu2  :  2.8 us,  7.3 sy,  0.0 ni, 77.1 id,  0.0 wa,  3.5 hi,  9.4 si,  0.0 st
%Cpu3  : 99.0 us,  0.0 sy,  0.0 ni,  0.0 id,  0.0 wa,  0.7 hi,  0.3 si,  0.0 st
MiB Mem :   3780.5 total,    144.2 free,   1227.9 used,   2408.4 buff/cache
MiB Swap:   4096.0 total,   4089.7 free,      6.3 used.   2290.5 avail Mem 

  PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND                                                                                                
 2181 root      20   0    7948    100      0 R 100.0   0.0   3:19.39 stress                                                                                                 
 2180 root      20   0    7948    100      0 R  99.7   0.0   3:19.23 stress       

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

# -P ALL 表示监控所有 CPU,后面数字 5 表示间隔 5 秒后输出一组数据
 mpstat -P ALL 5
Linux 4.18.0-147.5.1.el8_1.x86_64 (service) 	2021年06月17日 	_x86_64_	(4 CPU)

11时02分41秒  CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest  %gnice   %idle
11时02分46秒  all   3.34    0.00    1.41   69.68    0.10    0.05    0.00    0.00    0.00   25.42
11时02分46秒    0    8.54    0.00    7.72   31.30    0.00    0.00    0.00    0.00    0.00   52.44
11时02分46秒    1   0.20    0.00    0.40   31.06    0.20    0.00    0.00    0.00    0.00   68.14
11时02分46秒    2    1.61    0.00    0.81   71.57    0.20    0.00    0.00    0.00    0.00   25.81
11时02分46秒    3   1.81    0.00    2.62   90.14    0.00    0.20    0.00    0.00    0.00    5.23

从终端二中可以看到,1 分钟的平均负载会慢慢增加到 2.08,而从终端三中还可以看到, 正好有2个 CPU 的使用率为 7.72%,而 iowait 高达 90.14%。这说明,平均负载的升高是由于 iowait 的升高 。

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

# 间隔 5 秒后输出一组数据
pidstat -u 5 1
Linux 4.18.0-147.5.1.el8_1.x86_64 (webim-service-mq) 	2021年06月17日 	_x86_64_	(4 CPU)

11时03分29秒   UID       PID    %usr %system  %guest   %wait    %CPU   CPU  Command
11时03分34秒     0      2180   99.40    0.00    0.00    0.00   99.40     3  stress
11时03分34秒     0      2181   99.60    0.00    0.00    0.00   99.60     1  stress

平均时间:   UID       PID    %usr %system  %guest   %wait    %CPU   CPU  Command
平均时间:     0      2180   99.40    0.00    0.00    0.00   99.40     -  stress
平均时间:     0      2181   99.60    0.00    0.00    0.00   99.60     -  stress

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

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

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

#产生 1 个进程,每个进程都反复调用 sync 函数将内存上的内容写到硬盘上:
stress -i 1 --hdd 1 --timeout 3600 
#--hdd表示读写临时文件 

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

watch -d uptime
15:35:35 up 93 days, 20:07,  5 users,  load average: 158.98, 269.72, 140.74

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

[root@webim-service-mq ~]# mpstat -P ALL 5 1
Linux 4.18.0-147.5.1.el8_1.x86_64 (webim-service-mq) 	2021年06月17日 	_x86_64_	(4 CPU)
15时35分46秒  CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest  %gnice   %idle
15时35分51秒  all    2.85    0.00    6.84   43.32    1.04    2.18    0.00    0.00    0.00   43.78
15时35分51秒    0    2.52    0.00    5.67   50.21    0.63    0.00    0.00    0.00    0.00   40.97
15时35分51秒    1    4.12    0.00    8.25   22.89    0.82    0.21    0.00    0.00    0.00   63.71
15时35分51秒    2    1.67    0.00    4.60   70.92    1.67    8.58    0.00    0.00    0.00   12.55
15时35分51秒    3    3.05    0.00    8.76   29.94    1.02    0.00    0.00    0.00    0.00   57.23

从这里可以看到,1 分钟的平均负载会慢慢增加到 14.92,其中2个 CPU 的系统 CPU 使用率升高到了 10%以上,而 iowait 高达70%以上,这就说明,平均负载的升高是由于iowait的升高、。
那么到底是哪个进程,导致 iowait 升高呢?我们还是用 pidstat 来查询:

pidstat -u 5 1
11时48分27秒   UID       PID    %usr %system  %guest   %wait    %CPU   CPU  Command
11时48分32秒     0      3598    0.20    0.00    0.00    0.40    0.20     1  watch
11时48分32秒     0     14161    0.00    2.00    0.00    0.00    2.00     1  stress
11时48分32秒     0     14162    0.00    7.20    0.00    0.20    7.20     2  stress

可以发现,还是 stress 进程导致的。

场景三:大量进程的场景

当系统中运行进程超出 CPU 运行能力时,就会出现等待 CPU 的进程
我们还是使用 stress,但这次模拟的是 80 个进程:

stress -c 80 --timeout 3600 

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

watch -d uptime
14:56:21 up 93 days, 19:28,  5 users,  load average: 70.75, 82.49, 61.12

使用 pidstat 来看一下进程的情况

pidstat -u 5 1
14时55分01秒     0      9657    4.58    0.00    0.00   94.62    4.58     1  stress
14时55分01秒     0      9658    4.78    0.00    0.00   95.22    4.78     3  stress
14时55分01秒     0      9659    4.78    0.20    0.00   95.82    4.98     2  stress
14时55分01秒     0      9660    4.78    0.00    0.00   92.83    4.78     2  stress
14时55分01秒     0      9661    4.78    0.00    0.00   97.21    4.78     1  stress
14时55分01秒     0      9662    4.58    0.00    0.00   92.63    4.58     0  stress
14时55分01秒     0      9663    4.78    0.00    0.00   93.23    4.78     1  stress
14时55分01秒     0      9664    5.18    0.00    0.00   98.01    5.18     2  stress
14时55分01秒     0      9665    4.98    0.00    0.00   97.41    4.98     2  stress
14时55分01秒     0      9666    4.78    0.00    0.00   96.02    4.78     3  stress
14时55分01秒     0      9667    4.78    0.00    0.00   96.41    4.78     3  stress
14时55分01秒     0      9668    4.78    0.20    0.00   92.43    4.98     2  stress
14时55分01秒     0      9669    4.78    0.00    0.00   91.24    4.78     2  stress
14时55分01秒     0      9670    4.78    0.00    0.00   96.22    4.78     3  stress
14时55分01秒     0      9671    4.78    0.20    0.00   95.42    4.98     2  stress
14时55分01秒     0      9672    4.78    0.00    0.00   92.43    4.78     2  stress
14时55分01秒     0      9673    4.58    0.00    0.00   93.82    4.58     1  stress
14时55分01秒     0      9674    4.78    0.00    0.00   94.82    4.78     3  stress
14时55分01秒     0      9675    4.58    0.00    0.00   91.63    4.58     1  stress
14时55分01秒     0      9676    4.78    0.00    0.00  102.59    4.78     3  stress
14时55分01秒     0      9677    4.58    0.00    0.00   97.41    4.58     1  stress
14时55分01秒     0      9678    4.58    0.00    0.00   91.83    4.58     2  stress
14时55分01秒     0      9679    4.78    0.00    0.00   96.61    4.78     1  stress

可以看出,80个进程在争抢 4个 CPU,每个进程等待 CPU 的时间(也就是代码块中的 %wait 列)高达 90%以上。这些超出 CPU 计算能力的进程,最终导致 CPU 过载。

总结:

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

  1. 平均负载高有可能是 CPU 密集型进程导致的;
  2. 平均负载高并不一定代表 CPU 使用率高,还有可能是 I/O 更繁忙了;
  3. 当发现负载高的时候,你可以使用 mpstat、pidstat 等工具,辅助分析负载的来源。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值