02-基础篇:到底应该怎么理解“平均负载”





引子

每次发现系统变慢时,我们通常做的第一件事,就是执行top或者uptime命令,来了解系统的负载情况


uptime命令
[root@local_sa_192-168-1-6 ~]# uptime
15:58:04 up 3 min,  3 users,  load average: 0.20, 0.46, 0.23

输出结果解释
#15:58:04:    当前时间    
#up 3 min:    系统运行时间
#3 users:     当前登录系统的用户数
#load average: 0.20, 0.46, 0.23:  过去1分钟、5分钟、15分钟的平均负载(LoadAverage)




平均负载是什么

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


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


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

比如,当一个进程向磁盘读写数据时,为了保证数据的一致性,在得到磁盘回复前
它是不能被其他进程或者中断打断的
这个时候的进程就处于不可中断状态
如果此时的进程被打断了,就容易出现磁盘数据与进程数据不一致的问题
所以,不可中断状态实际上是系统对进程和硬件设备的一种保护机制

因此,你可以简单理解为,【平均负载其实就是平均活跃进程数】

既然平均的是活跃进程数,那么最理想的,就是每个CPU上都刚好运行着一个进程,
这样每个CPU都得到了充分利用。比如当平均负载为2时,意味着什么呢?
1.在只有2 个CPU的系统上,意味着所有的CPU都刚好被完全占用
2.在4个CPU的系统上,意味着CPU有50%的空闲
3.而在只有1个CPU的系统中,则意味着有一半的进程竞争不到CPU



平均负载为多少时合理

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

# /proc/cpuinfo
[root@local_sa_192-168-1-6 ~]# grep "model name" /proc/cpuinfo
model name	: QEMU Virtual CPU version (cpu64-rhel6)
model name	: QEMU Virtual CPU version (cpu64-rhel6)
[root@local_sa_192-168-1-6 ~]# grep "model name" /proc/cpuinfo |wc -l
2

# top --> 按数字 1
[root@local_sa_192-168-1-6 ~]# top
top - 16:21:10 up 26 min,  3 users,  load average: 0.00, 0.01, 0.05
Tasks: 179 total,   1 running, 178 sleeping,   0 stopped,   0 zombie
%Cpu0  :  0.3 us,  0.3 sy,  0.0 ni, 99.3 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
%Cpu1  :  0.0 us,  0.0 sy,  0.0 ni,100.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st


有了CPU个数,我们就可以判断出,当平均负载比CPU个数还大的时候,系统已经出现了过载

不过,且慢,我们在例子中可以看到,平均负载有三个数值,到底该参考哪一个呢?
【实际上,都要看。三个不同时间间隔的平均值,其实给我们提供了,分析系统负载趋势的数据来源,让我们能更全面、更立体地理解目前的负载状况】

1.如果1分钟、5分钟、15分钟的三个值基本相同,或者相差不大,那就说明系统负载很平稳
2.如果1分钟的值远小于15分钟的值,就说明系统最近1分钟的负载在减少,而过去15分钟内却有很大的负载
3.如果1分钟的值远大于15分钟的值,就说明最近1分钟的负载在增加
  这种增加有可能只是临时性的,也有可能还会持续增加下去,所以就需要持续观察
4.一旦1分钟的平均负载接近或超过了CPU的个数,就意味着系统正在发生过载的问题
  这时就得分析调查是哪里导致的问题,并要想办法优化了
  
  
举个例子,假设我们在一个单CPU系统上看到平均负载为1.73,0.60,7.98
那么说明在过去1分钟内,系统有73%的超载,
而在15分钟内,有698%的超载,
从整体趋势来看,系统的负载在降低(15*73=1095)


在实际生产环境中,平均负载多高时,需要我们重点关注呢?
【当平均负载高于CPU数量70%的时候】
就应该分析排查负载高的问题了,一旦负载过高,就可能导致进程响应变慢,进而影响服务的正常功能

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



平均负载与CPU使用率区别

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


CPU使用率,是单位时间内CPU繁忙情况的统计,跟平均负载并不一定完全对应
比如
1.CPU密集型进程,使用大量CPU会导致平均负载升高,此时这两者是一致的
2.I/O密集型进程,等待I/O也会导致平均负载升高,但CPU使用率不一定很高
3.大量等待CPU的进程调度也会导致平均负载升高,此时的CPU使用率也会比较高




平均负载案例分析

准备工作

以三个示例分别来看这三种情况,并用iostat、mpstat、pidstat等工具,找出平均负载升高的根源

机器配置:2CPU,4GB内存 centos7.6

预先安装 stress 和 sysstat 包
[root@local_sa_192-168-1-6 ~]# rpm -qa stress
stress-1.0.4-16.el7.x86_64
[root@local_sa_192-168-1-6 ~]# rpm -qa sysstat
sysstat-11.7.3-2.el8.x86_64

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

sysstat 包含了常用的Linux性能工具,用来监控和分析系统的性能。
案例中会用到这个包的两个命令mpstat和pidstat

mpstat 是一个常用的多核CPU性能分析工具,用来实时查看每个CPU的性能指标,以及所有CPU的平均指标
pidstat 是一个常用的进程性能分析工具,用来实时查看进程的CPU、内存、I/O以及上下文切换等性能指标


场景一:CPU 密集型进程

1.第一个终端运行 stress 命令,模拟一个CPU 使用率 100% 的场景

[root@local_sa_192-168-1-6 ~]# stress --cpu 1 --timeout 600
stress: info: [13051] dispatching hogs: 1 cpu, 0 io, 0 vm, 0 hdd

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

# watch动态显示数值变化
# -d 高亮显示变化的区域
[root@local_sa_192-168-1-6 ~]# watch -d uptime
17:07:51 up  1:13,  3 users,  load average: 1.00, 0.83, 0.46

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

# -P ALL 表示监控所有cpu,后面的数字5表示间隔5秒输出一组数据
[root@local_sa_192-168-1-6 ~]# mpstat -P ALL 5
17时08分12秒  CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest  %gnice   %idle
17时08分17秒  all   50.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00   50.00
17时08分17秒    0  100.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00
17时08分17秒    1    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00  100.00

4.查看原因

从终端二中可以看到,1分钟的平均负载会慢慢增加到1.00

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

那么,到底是哪个进程导致了CPU使用率为100%呢?
可以使用 pidstat 来查询
# pidstat 查看进程占用的系统资源
# 间隔5秒后输出一组数据
# -u 查看cpu数据
[root@local_sa_192-168-1-6 ~]# pidstat -u 5 1
Linux 3.10.0-1160.31.1.el7.x86_64 (local_sa_192-168-1-6) 	2021年11月08日 	_x86_64_	(2 CPU)

17时12分48秒   UID       PID    %usr %system  %guest   %wait    %CPU   CPU  Command
17时12分53秒     0       398    0.00    0.20    0.00    0.20    0.20     0  xfsaild/dm-0
17时12分53秒     0     13867   99.80    0.00    0.00    0.00   99.80     1  stress
17时12分53秒     0     13959    0.00    0.20    0.00    0.00    0.20     0  pidstat

平均时间:   UID       PID    %usr %system  %guest   %wait    %CPU   CPU  Command
平均时间:     0       398    0.00    0.20    0.00    0.20    0.20     -  xfsaild/dm-0
平均时间:     0     13867   99.80    0.00    0.00    0.00   99.80     -  stress
平均时间:     0     13959    0.00    0.20    0.00    0.00    0.20     -  pidstat

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


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

1.第一个终端,运行 stress命令,模拟 I/O 压力,即不停地执行sync

[root@local_sa_192-168-1-6 ~]# stress -i 1 --timeout 600
stress: info: [13986] dispatching hogs: 0 cpu, 1 io, 0 vm, 0 hdd

# 建议使用这条命令测试 centos系统
# 如果上一条命令不能模拟出I/O压力,那么使用这条命令
[root@local_sa_192-168-1-6 ~]# stress-ng -i 1 --hdd 1 --timeout 600

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

[root@local_sa_192-168-1-6 ~]# watch -d uptime
 17:18:32 up  1:24,  4 users,  load average: 2.06, 0.82, 0.58

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

[root@local_sa_192-168-1-6 ~]# mpstat -P ALL 5
[root@local_sa_192-168-1-6 ~]# mpstat -P ALL 5
Linux 3.10.0-1160.31.1.el7.x86_64 (local_sa_192-168-1-6) 	2021年11月08日 	_x86_64_	(2 CPU)

17时24分16秒  CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest  %gnice   %idle
17时24分21秒  all    0.20    0.00    0.20   99.50    0.00    0.00    0.10    0.00    0.00    0.00
17时24分21秒    0    0.20    0.00    0.20   99.60    0.00    0.00    0.00    0.00    0.00    0.00
17时24分21秒    1    0.20    0.00    0.20   99.40    0.00    0.00    0.20    0.00    0.00    0.00

4.查看

从终端二中可以看到,1分钟的平均负载会慢慢增加到2.06
从终端三中可以看到,iowait高达99%,这说明,平均负载的升高是由于iowait的升高

那么到底是哪个进程,导致iowait这么高呢?用pidstat -d 5 1来查询
# -d 查看磁盘数据
[root@local_sa_192-168-1-6 ~]# pidstat -d 5 1
Linux 3.10.0-1160.31.1.el7.x86_64 (local_sa_192-168-1-6) 	2021年11月08日 	_x86_64_	(2 CPU)

17时31分54秒   UID       PID   kB_rd/s   kB_wr/s kB_ccwr/s iodelay  Command
17时31分59秒     0      1378      0.00      0.80      0.00       0  teamviewerd
17时31分59秒     0     14012      0.00      0.00      0.00     494  kworker/u4:2
17时31分59秒     0     14521      0.00  17333.33      0.00     496  stress-ng-hdd
17时31分59秒     0     14522      0.00      0.00      0.00     500  stress-ng-io

平均时间:   UID       PID   kB_rd/s   kB_wr/s kB_ccwr/s iodelay  Command
平均时间:     0      1378      0.00      0.80      0.00       0  teamviewerd
平均时间:     0     14012      0.00      0.00      0.00     494  kworker/u4:2
平均时间:     0     14521      0.00  17333.33      0.00     496  stress-ng-hdd
平均时间:     0     14522      0.00      0.00      0.00     500  stress-ng-io


从这里可以看出 stress-ng 进程导致的


场景三:大量进程的场景

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

1.第一个终端,使用 stress,模拟的是 8 个进程

[root@local_sa_192-168-1-6 ~]# stress -c 8 --timeout 600

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

[root@local_sa_192-168-1-6 ~]# watch -d uptime
17:38:15 up  1:44,  4 users,  load average: 4.68, 1.76, 1.11

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

[root@local_sa_192-168-1-6 ~]# mpstat -P ALL 5
Linux 3.10.0-1160.31.1.el7.x86_64 (local_sa_192-168-1-6) 	2021年11月08日 	_x86_64_	(2 CPU)

17时39分01秒  CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest  %gnice   %idle
17时39分06秒  all   99.80    0.00    0.20    0.00    0.00    0.00    0.00    0.00    0.00    0.00
17时39分06秒    0   99.80    0.00    0.20    0.00    0.00    0.00    0.00    0.00    0.00    0.00
17时39分06秒    1   99.80    0.00    0.20    0.00    0.00    0.00    0.00    0.00    0.00    0.00

平均时间:  CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest  %gnice   %idle
平均时间:  all   99.87    0.00    0.13    0.00    0.00    0.00    0.00    0.00    0.00    0.00
平均时间:    0   99.89    0.00    0.11    0.00    0.00    0.00    0.00    0.00    0.00    0.00
平均时间:    1   99.86    0.00    0.14    0.00    0.00    0.00    0.00    0.00    0.00    0.00

4.查看

# 8个进程在争抢2个CPU,每个进程等待CPU的时间(也就是代码块中的%wait列)高达75%。
# 这些超出CPU计算能力的进程,最终导致CPU过载
[root@local_sa_192-168-1-6 ~]# pidstat -u 5 1
Linux 3.10.0-1160.31.1.el7.x86_64 (local_sa_192-168-1-6) 	2021年11月08日 	_x86_64_	(2 CPU)

17时40分44秒   UID       PID    %usr %system  %guest   %wait    %CPU   CPU  Command
17时40分49秒     0      1378    0.20    0.20    0.00    0.00    0.40     1  teamviewerd
17时40分49秒     0     14570   25.20    0.00    0.00   74.40   25.20     0  stress
17时40分49秒     0     14571   24.80    0.00    0.00   75.60   24.80     1  stress
17时40分49秒     0     14572   24.60    0.00    0.00   74.80   24.60     0  stress
17时40分49秒     0     14573   24.60    0.00    0.00   75.00   24.60     1  stress
17时40分49秒     0     14574   24.40    0.00    0.00   75.20   24.40     0  stress
17时40分49秒     0     14575   24.80    0.00    0.00   75.40   24.80     1  stress
17时40分49秒     0     14576   24.80    0.00    0.00   75.40   24.80     1  stress
17时40分49秒     0     14577   25.60    0.00    0.00   75.20   25.60     0  stress
17时40分49秒     0     14613    0.20    0.20    0.00    0.60    0.40     1  watch
17时40分49秒     0     14774    0.00    0.20    0.00    0.40    0.20     0  pidstat

平均时间:   UID       PID    %usr %system  %guest   %wait    %CPU   CPU  Command
平均时间:     0      1378    0.20    0.20    0.00    0.00    0.40     -  teamviewerd
平均时间:     0     14570   25.20    0.00    0.00   74.40   25.20     -  stress
平均时间:     0     14571   24.80    0.00    0.00   75.60   24.80     -  stress
平均时间:     0     14572   24.60    0.00    0.00   74.80   24.60     -  stress
平均时间:     0     14573   24.60    0.00    0.00   75.00   24.60     -  stress
平均时间:     0     14574   24.40    0.00    0.00   75.20   24.40     -  stress
平均时间:     0     14575   24.80    0.00    0.00   75.40   24.80     -  stress
平均时间:     0     14576   24.80    0.00    0.00   75.40   24.80     -  stress
平均时间:     0     14577   25.60    0.00    0.00   75.20   25.60     -  stress
平均时间:     0     14613    0.20    0.20    0.00    0.60    0.40     -  watch
平均时间:     0     14774    0.00    0.20    0.00    0.40    0.20     -  pidstat


小结

平均负载提供了一个快速查看系统整体性能的手段,反映了整体的负载情况。
但只看平均负载本身,我们并不能直接发现,到底是哪里出现了瓶颈。
所以,在理解平均负载时,也要注意:
1.平均负载高有可能是CPU密集型进程导致的
2.平均负载高并不一定代表CPU使用率高,还有可能是I/O更繁忙了
3.当发现负载高的时候,你可以使用mpstat、pidstat等工具,辅助分析负载的来源

posted @ 2021-11-08 18:05  李成果  阅读(312)  评论(0编辑  收藏  举报