Linux性能优化实践----到底应该怎么理解"平均负载"
在遇到系统变慢时,我们通常使用top或者uptime命令来了解负载情况,比如输入uptime命令 :
1 $ uptime 2 up 2 days, 20:14, 1 user, load average: 0.63, 0.83, 0.88
其中
1 02:34:03 # 表示当前时间 2 up 2 days,20:14 # 表示系统运行的时间 3 1 user # 正在登陆的用户数
而最后的三个数字表示过去1min,5min,15min的平均负载。
什么是平均负载呢,简单来说,平均负载是指在单位时间内,系统处于可运行状态和不可中断状态的平均进程数,也就是平均活跃进程数,可理解为单位时间内的活跃进程数,它和CPU使用率并没有直接关系。
所谓可运行状态的进程,是指正在使用CPU或者正在等待CPU的进程,也就是使用ps(ps aux中stat列,R表示正在运行或者在队列中的进程,D表示不可中断)命令看到的处于R状态的进程;不可中断状态的进程是指正处于内核态关键流程中的进程,并且这些流程是不可打断的,比如ps命令中看到的D状态(等待硬件设备的I/O响应)的进程,如当一个进程向磁盘读写操作时,为了保证数据的一致性,在得到磁盘回复前,它是不能被其他进程或者中断打断的,这个时候的进程就是出于不可中断状态,因为如果此时的进程被打断了,就容易出现磁盘与进程数据不一致的问题,因此,不可中断状态实际上是系统对进程和硬件设备的一种保护机制。
既然平均负载平均的是活跃进程数,那么理想情况下,就是每个CPU上刚好运行着一个进程,这样每个CPU都能得到充分利用,比如平均负载为2,意味着:
- 在只有2个CPU的系统上,意味着所有的CPU都刚好完全占用。
- 在4个CPU的系统上,意味着CPU的50%未空闲。
- 在只有1个CPU的系统上,意味着有一半的进程竞争不到CPU。
一.平均负载多少合理
现在回到刚开始的例子中去,在uptime命令的结果里,三个时间段的平均负载,多大的时候说明系统负载高,多小的时候说明系统负载很低?
平均负载最理想的情况就是等于CPU个数,所以在评判平均负载时,需要知道CPU的个数,这个可以通过top(在top基本视图中,按数字1)或者从/proc/cpuinfo文件中读取:
1 $ grep 'model name' /proc/cpuinfo | wc -l 2 2
有了CPU个数,我们就可以判断出,当均负载比CPU个数大的时候,说明系统已经过载。
uptime命令结果的三个值都是需要看的,三个不同时间间隔的平均值,提供了分析系统负载趋势的数据来源,让我们可以更全面,更立体的理解目前的负载状况。
- 如果1min,5min,15min的三个值基本相同,或者相差不大,则说明系统平均负载很平稳。
- 如果1min的值远远小于15min的值,则说明最近1min的负载在减少,过去15min内有很大的负载。
- 如果1min的值远远大于15min的值,则说明最近1min的负载在增大,这种增大可能是临时的,也可能会持续增加下去,需要持续观察,一旦1min的平均负载接近或者超过CPU个数,就说明系统正在发生过载,就需要分析问题的原因了。
当平均负载高于CPU数量的70%时,就需要分析负载高的问题了,但是70%也不是绝对的,还是需要把系统的平均负载监控起来,然后根据更多历史数据,判断负载的变化趋势。
二.平均负载与CPU使用率
平均负载是指单位时间内,处于可运行状态和不可中断状态的进程数,它包括正在使用CPU的进程和等待CPU和等待I/O的进程。
CPU使用率是指单位时间内CPU繁忙情况的统计,跟平均负载并不一定完全对应,比如:
- CPU密集型进程,使用大量CPU会导致平均负载升高,此时两者一致;
- I/O密集型进程,等待I/O会导致平均负载升高,但是CPU使用率不一定很高;
- 大量等待CPU的进程调度也会导致平均负载升高,此时的CPU使用率也会比较高。
三.平均负载案例分析
接下来,以三个示例来演示这三种情况,并使用iostat,mpstat,pidstat等工具,来找出平均负载升高的根源。
首先准备一台linux机器(2核,8G内存),然后在这台linux机器中安装stress-ng和sysstat包,然后每个场景都需要打开三个终端。
stress是linux系统中的压力测试工具,这里用做异常进程来模拟平均负载升高的场景;sysstat则包含了常用的linux性能工具,用来监控和分析系统的性能,我们这个案例使用到了这个包的mpstat和pidstat。
Ubuntu中安装stress-ng和stress:
apt install stress-ng sysstat。
stress-up选项说明
-t, --timeout N 指定运行N秒后停止 -c, --cpu N 产生n个进程,每个进程都反复不停的计算随机数的平方根 -i, --io N 产生n个进程,每个进程反复调用sync(),sync()用于将内存上的内容写到硬盘上 -m, --vm N 产生n个进程,每个进程不断调用内存分配malloc和内存释放free函数
- mpstat是一个常用的多核cpu性能分析工具,用来实时查看每个CPU的性能指标,以及所有CPU的平均指标;
- pidstat是一个常用的进程性能分析工具,用来实时查看进程的CPU,内存,I/O以及上下文切换等性能指标。
root@boxiaoyaun:~# uptime 14:14:52 up 11 min, 2 users, load average: 0.08, 0.20, 0.26
场景一:CPU密集型进程
首先,在第一个终端运行stress命令,模拟一个CPU使用率为100%的场景:
root@boxiaoyaun:~# stress --cpu 1 --timeout 600 stress: info: [2474] dispatching hogs: 1 cpu, 0 io, 0 vm, 0 hdd
然后,在第二个终端运行uptime查看平均负载的变化情况:
# -d参数可以高亮显示变化的区域
root@boxiaoyaun:~# watch -d uptime
Every 2.0s: uptime Fri May 3 19:18:23 2019 19:18:23 up 39 min, 4 users, load average: 1.00, 0.72, 0.40
最后,在第三个终端运行mpstat,查看CPU使用率的变化情况:
# -P ALL表示监控所有CPU,后面的5表示每隔5s输出一组数据 boxiaoyuan@boxiaoyaun:~$ mpstat -P ALL 5 Linux 4.15.0-124-generic (boxiaoyaun) 11/20/2020 _x86_64_ (2 CPU) 02:19:55 PM CPU %usr %nice %sys %iowait %irq %soft %steal %guest %gnice %idle 02:20:00 PM all 50.00 0.00 0.20 0.00 0.00 0.10 0.00 0.00 0.00 49.70 02:20:00 PM 0 0.40 0.00 0.40 0.00 0.00 0.20 0.00 0.00 0.00 99.00 02:20:00 PM 1 100.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
从终端二可以看到,1分钟的平均负载会慢慢增加到1.00,从终端三中可以看到,正好有一个CPU的使用率为100%,但是它的iowait为0,这说明,平均负载的升高是由于CPU的使用率为100%所致。
如果想要查看哪个进程导致CPU使用率为100%,可以使用pidstat查看:
# 间隔5s输出一组数据
boxiaoyuan@boxiaoyaun:~$ pidstat -u 5 1
Linux 4.15.0-124-generic (boxiaoyaun) 11/20/2020 _x86_64_ (2 CPU)
02:26:04 PM UID PID %usr %system %guest %wait %CPU CPU Command 02:26:09 PM 0 876 0.00 0.20 0.00 0.00 0.20 0 vmtoolsd 02:26:09 PM 0 2475 100.00 0.00 0.00 0.00 100.00 1 stress 02:26:09 PM 1000 2548 0.00 0.20 0.00 0.00 0.20 0 sshd 02:26:09 PM 1000 3440 0.20 0.20 0.00 0.00 0.40 0 pidstat
可以看到,stress进程的CPU使用率为100%。
场景二:I/O密集型进程
首先使用stress命令模拟I/O压力,--hdd表示读写临时文件。
root@boxiaoyaun:~# stress-ng -i 1 --hdd 1 --timeout 600 stress-ng: info: [3736] dispatching hogs: 1 io, 1 hdd
然后在第二个终端运行uptime查看平均负载的变化:
root@boxiaoyuan:~# watch -d uptime Every 2.0s: uptime boxiaoyaun: Sat Nov 21 07:28:08 2020 07:28:08 up 9 min, 3 users, load average: 1.00, 0.44, 0.27
接着在第三个终端运行mpstat查看CPU使用率:
# 显示所有 CPU 的指标,并在间隔 5 秒输出一组数据 root@boxiaoyaun:~# mpstat -P ALL 5 1 Linux 4.15.0-124-generic (boxiaoyaun) 11/21/2020 _x86_64_ (2 CPU) 07:36:58 AM CPU %usr %nice %sys %iowait %irq %soft %steal %guest %gnice %idle 07:37:03 AM all 0.12 0.00 0.71 83.12 0.00 1.53 0.00 0.00 0.00 14.52 07:37:03 AM 0 0.00 0.00 0.23 71.53 0.00 0.23 0.00 0.00 0.00 28.02 07:37:03 AM 1 0.00 0.00 0.99 95.81 0.00 3.20 0.00 0.00 0.00 0.00
可以看出,1分钟的平均负载会慢慢增加到1.00,CPU的系统CPU使用率很低,而iowait均很高,这说明,平均负载的升高是由于iowait的升高所致。
最后使用pidstat查看iowait升高的原因:
# 间隔 5 秒后输出一组数据,-u 表示 CPU 指标 root@boxiaoyaun:~# pidstat -u 5 1 Linux 4.15.0-124-generic (boxiaoyaun) 11/21/2020 _x86_64_ (2 CPU) 07:42:05 AM UID PID %usr %system %guest %wait %CPU CPU Command 07:42:10 AM 0 7 0.00 0.40 0.00 0.00 0.40 0 ksoftirqd/0 07:42:10 AM 0 306 0.00 0.20 0.00 0.00 0.20 0 kworker/0:1H 07:42:10 AM 0 309 0.00 0.20 0.00 0.40 0.20 1 kworker/1:1H 07:42:10 AM 0 2594 0.20 0.00 0.00 0.00 0.20 1 watch 07:42:10 AM 0 3737 0.00 0.20 0.00 0.20 0.20 0 stress-ng-io 07:42:10 AM 0 3738 0.40 17.10 0.00 0.40 17.50 0 stress-ng-hdd 07:42:10 AM 0 3779 0.00 3.18 0.00 0.40 3.18 1 kworker/u256:1 07:42:10 AM 0 4207 0.00 0.20 0.00 0.00 0.20 1 pidstat
场景三:大量进程的场景
当系统中运行的进程超过CPU运行能力时,会出现等待CPU的进程。
首先我们使用stress命令,模拟8个进程:
root@boxiaoyaun:~# stress -c 8 --timeout 600 stress: info: [4720] dispatching hogs: 8 cpu, 0 io, 0 vm, 0 hdd
由于系统中只有2个CPU,明显比8个进程少的多,因此系统的CPU此时处于严重的过载状态,平均负载高达:8.46。
[root@boxiaoyuan ~]# uptime Every 2.0s: uptime Fri May 3 19:36:56 2019 19:36:56 up 58 min, 4 users, load average: 8.46, 4.20, 2.22
然后使用pidstat命令来查看进程:
root@boxiaoyaun:~# pidstat -u 5 1 Linux 4.15.0-124-generic (boxiaoyaun) 11/21/2020 _x86_64_ (2 CPU) 07:51:56 AM UID PID %usr %system %guest %wait %CPU CPU Command 07:52:01 AM 0 862 0.00 0.20 0.00 0.20 0.20 0 vmtoolsd 07:52:01 AM 0 3634 0.00 0.20 0.00 0.00 0.20 1 kworker/1:0 07:52:01 AM 0 4721 24.65 0.00 0.00 74.55 24.65 1 stress 07:52:01 AM 0 4722 24.65 0.20 0.00 74.95 24.85 0 stress 07:52:01 AM 0 4723 25.05 0.00 0.00 74.55 25.05 1 stress 07:52:01 AM 0 4724 25.05 0.00 0.00 74.35 25.05 1 stress 07:52:01 AM 0 4725 24.85 0.00 0.00 74.16 24.85 1 stress 07:52:01 AM 0 4726 24.65 0.20 0.00 74.75 24.85 0 stress 07:52:01 AM 0 4727 24.85 0.00 0.00 74.55 24.85 0 stress 07:52:01 AM 0 4728 24.65 0.00 0.00 74.55 24.65 0 stress 07:52:01 AM 0 4825 0.20 0.00 0.00 0.00 0.20 1 pidstat
可以看出,8个进程在争抢2个CPU,每个进程等待CPU的时间(即%wait列)高达75%,这些超出了CPU计算能力的进程,最终导致CPU过载。