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过载。

posted @ 2019-04-15 22:42  博小园  阅读(283)  评论(0编辑  收藏  举报
回到顶部