1. 平均负载介绍

以centos7为例,通过uptime可以看到平均系统的平均负载。

  1. [root@localhost ~]# uptime
  2. 15:56:22 up 5 days, 16:45, 1 user, load average: 1.73, 0.60, 7.98
  3. # 15:56:22 代表系统当前时间
  4. # up 5 days, 16:45 代表系统运行时间
  5. # 1 user 代表正在登录用户数
  6. # load average 代表过去1分钟,5分钟,15分钟的平均负载

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

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

因此可以简单理解为平均负载就是平均活跃进程数。既然平均的是活跃进程数,那么最理想的就是刚好每个CPU上都刚好运行着一个进程。这样每个CPU都得到了充分的利用。
比如当平均负载为2时,意味着在2核CPU(逻辑总核数,非物理CPU)的系统上所有的CPU都刚好被完全占用。
在4核CPU(逻辑总核数,非物理CPU)的系统上,有50%的CPU是空闲的。

2.平均负载为多少时合理

首先需要获取当前系统中的CPU核数

  1. [root@localhost ~]# grep "model name" /proc/cpuinfo | wc -l
  2. 2

举例说明:load average: 1.73, 0.60, 7.98
表明过去一分钟内系统有73%的超载,而在15分钟内,有698%的超载。
经验总结:当平均负载高于CPU数量的70%的时候,就应该开始排查负载高的问题了。当然此数据并非是绝对的,最推荐的方法是:把平均负载监控起来,然后根据更多的历史数据,判断负载的变化趋势,比如负载翻倍了,再去做分析和调查。

3.平均负载与CPU使用率

  1. 平均负载和CPU使用率是有区别的,回到平均负载的含义,平均负载是指单位时间内,处于可运行状态和不可中断状态的进程数。所以,它不仅包含了正在使用CPU的进程,还包括等待CPU和等待I/O的进程。<br />而CPU使用率,是单位时间内CPU繁忙情况的统计,跟平均负载并不一定完全对应。比如:<br />CPU密集型进程,使用大量CPU会导致平均负载升高,此时这两者是一致的。<br />I/O密集型进程,等待I/O也会导致平均负载升高,但CPU使用率不一定很高。<br />大量等待CPU的进程调度也会导致平均负载升高,此时CPU的使用率也会比较高。

4.平均负载案例分析

4.1 CPU使用率密集型场景

机器:2cpu,1G内存
工具:iostat(磁盘性能分析工具)、mpstat(多核CPU性能分析工具)、pidstat(进程性能分析工具)、stress(Linux系统的压力测试工具)、stress-ng

  1. [root@localhost ~]# yum install stress -y
  2. [root@localhost ~]# yum install stress-ng -y

打开三个终端,在第一个终端使用stress命令,模拟2CPU使用率100%的场景:

  1. [root@localhost ~]# stress --cpu 2 --timeout 600
  2. stress: info: [31679] dispatching hogs: 2 cpu, 0 io, 0 vm, 0 hdd

在第二个终端实时查看负载的变化:

  1. [root@localhost ~]# watch -d uptime
  2. Every 2.0s: uptime Fri May 7 15:08:55 2021
  3. 15:08:55 up 6 days, 15:57, 3 users, load average: 2.18, 1.04, 0.44

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

  1. [root@localhost ~]# mpstat -P ALL 5
  2. Average: CPU %usr %nice %sys %iowait %irq %soft %steal %guest %gnice %idle
  3. Average: all 99.56 0.00 0.41 0.00 0.00 0.03 0.00 0.00 0.00 0.00
  4. Average: 0 99.55 0.00 0.40 0.00 0.00 0.04 0.00 0.00 0.00 0.00
  5. Average: 1 99.56 0.00 0.41 0.00 0.00 0.03 0.00 0.00 0.00 0.00

从终端2可以看到平均负载已经升到2.18,在第三个终端上可以看到2个CPU的使用率均接近100%,但是此时%iowait只有0%。这说明,平均负载的升高正是由于CPU使用率为100%。
那么,到底是哪个进程导致了CPU使用率为100%呢,此时可以使用pidstat来查询:

  1. [root@localhost ~]# pidstat -u 5 1
  2. Linux 3.10.0-1160.15.2.el7.x86_64 (localhost.localdomain) 05/07/2021 _x86_64_ (2 CPU)
  3. 03:17:56 PM UID PID %usr %system %guest %CPU CPU Command
  4. 03:18:01 PM 0 32348 99.20 0.20 0.00 99.40 1 stress
  5. 03:18:01 PM 0 32349 99.20 0.00 0.00 99.20 0 stress
  6. 03:18:01 PM 0 32405 0.00 0.20 0.00 0.20 1 pidstat

4.2 I/O密集型进程场景

首先在第一个终端运行stress命令,但这次模拟I/O压力,即不停地执行sync:

  1. [root@localhost ~]# stress -i 1 --timeout 600
  2. stress: info: [32446] dispatching hogs: 0 cpu, 1 io, 0 vm, 0 hdd

在第二个终端运行uptime命令,监控负载的实时变化:

  1. [root@localhost ~]# watch -d uptime
  2. Every 2.0s: uptime Fri May 7 15:25:30 2021
  3. 15:25:30 up 6 days, 16:14, 3 users, load average: 1.17, 0.99, 1.01

在第三个终端上运行mpstat,查看CPU的使用情况,可以看到,此时CPU使用率不高,但iowait的使用率高。

  1. [root@localhost ~]# mpstat -P ALL 5
  2. Linux 3.10.0-1160.15.2.el7.x86_64 (localhost.localdomain) 05/07/2021 _x86_64_ (2 CPU)
  3. 04:04:36 PM CPU %usr %nice %sys %iowait %irq %soft %steal %guest %gnice %idle
  4. 04:04:41 PM all 0.10 0.00 2.83 53.88 0.00 0.10 0.00 0.00 0.00 43.09
  5. 04:04:41 PM 0 0.20 0.00 2.02 96.96 0.00 0.00 0.00 0.00 0.00 0.81
  6. 04:04:41 PM 1 0.20 0.00 3.43 11.09 0.00 0.00 0.00 0.00 0.00 85.28

使用iotop命令查看io读写高的进程:

  1. [root@localhost ~]# iotop
  2. Total DISK READ : 0.00 B/s | Total DISK WRITE : 11.07 M/s
  3. Actual DISK READ: 0.00 B/s | Actual DISK WRITE: 0.00 B/s
  4. TID PRIO USER DISK READ DISK WRITE SWAPIN IO> COMMAND
  5. 34781 be/4 root 0.00 B/s 11.07 M/s 0.00 % 99.99 % stress-ng -i 1 --hdd 1 --timeout 600

使用lsof查看进程中io读写高的文件

  1. [root@localhost ~]# lsof -p 34781
  2. COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
  3. stress-ng 34781 root cwd DIR 8,3 4096 33574977 /root
  4. stress-ng 34781 root rtd DIR 8,3 255 64 /
  5. stress-ng 34781 root txt REG 8,3 5040792 52147222 /usr/bin/stress-ng
  6. stress-ng 34781 root DEL REG 0,4 1131334 /dev/zero
  7. stress-ng 34781 root mem REG 8,3 19248 1273 /usr/lib64/libdl-2.17.so
  8. stress-ng 34781 root mem REG 8,3 11400 973 /usr/lib64/libfreebl3.so
  9. stress-ng 34781 root mem REG 8,3 88720 3579797 /usr/lib64/libgcc_s-4.8.5-20150702.so.1
  10. stress-ng 34781 root mem REG 8,3 2156344 984 /usr/lib64/libc-2.17.so
  11. stress-ng 34781 root mem REG 8,3 6264 1949 /usr/lib64/libaio.so.1.0.1
  12. stress-ng 34781 root mem REG 8,3 11336 149056 /usr/lib64/libsctp.so.1.0.17
  13. stress-ng 34781 root mem REG 8,3 142144 48045 /usr/lib64/libpthread-2.17.so
  14. stress-ng 34781 root mem REG 8,3 43712 48049 /usr/lib64/librt-2.17.so
  15. stress-ng 34781 root mem REG 8,3 40600 1268 /usr/lib64/libcrypt-2.17.so
  16. stress-ng 34781 root mem REG 8,3 90176 3579834 /usr/lib64/libz.so.1.2.7
  17. stress-ng 34781 root mem REG 8,3 87464 149059 /usr/lib64/libbsd.so.0.8.3
  18. stress-ng 34781 root mem REG 8,3 1136944 48020 /usr/lib64/libm-2.17.so
  19. stress-ng 34781 root mem REG 8,3 163312 3579799 /usr/lib64/ld-2.17.so
  20. stress-ng 34781 root 0u CHR 136,0 0t0 3 /dev/pts/0
  21. stress-ng 34781 root 1u CHR 136,0 0t0 3 /dev/pts/0
  22. stress-ng 34781 root 2u CHR 136,0 0t0 3 /dev/pts/0
  23. stress-ng 34781 root 3u unix 0xffff98eab31b0cc0 0t0 1131331 socket
  24. stress-ng 34781 root 4u REG 8,3 481923072 33983612 /root/tmp-stress-ng-hdd-34781-0/stress-ng-hdd-34781-0-917808322 (deleted)

查看对应进程的文件读写的大小。

  1. [root@localhost ~]# cat /proc/34781/io
  2. rchar: 9663676416
  3. wchar: 10223157257
  4. syscr: 147456
  5. syscw: 155995
  6. read_bytes: 0
  7. write_bytes: 10223173632
  8. cancelled_write_bytes: 1112530944

4.3 大量进程的场景

当系统中运行的进程超出CPU运行能力时,就会出现等待CPU的进程。
比如在2CPU的系统中模拟8个进程。

  1. [root@localhost ~]# stress -c 8 --timeout 600
  2. stress: info: [44328] dispatching hogs: 8 cpu, 0 io, 0 vm, 0 hdd

监控负载使用情况:

  1. [root@localhost ~]# watch -d uptime
  2. Every 2.0s: uptime Mon May 10 16:02:27 2021
  3. 16:02:27 up 9 days, 16:51, 7 users, load average: 9.17, 6.90, 3.36

查看CPU使用率:

  1. [root@localhost ~]# mpstat -P ALL 5
  2. 04:03:20 PM CPU %usr %nice %sys %iowait %irq %soft %steal %guest %gnice %idle
  3. 04:03:25 PM all 99.29 0.00 0.61 0.00 0.00 0.10 0.00 0.00 0.00 0.00
  4. 04:03:25 PM 0 99.59 0.00 0.41 0.00 0.00 0.00 0.00 0.00 0.00 0.00
  5. 04:03:25 PM 1 99.19 0.00 0.81 0.00 0.00 0.00 0.00 0.00 0.00 0.00

查看进程:

  1. [root@localhost ~]# pidstat -u 5 1
  2. Linux 3.10.0-1160.15.2.el7.x86_64 (localhost.localdomain) 05/10/2021 _x86_64_ (2 CPU)
  3. 04:03:47 PM UID PID %usr %system %guest %CPU CPU Command
  4. 04:03:52 PM 0 44329 24.85 0.00 0.00 24.85 1 stress
  5. 04:03:52 PM 0 44330 24.46 0.00 0.00 24.46 1 stress
  6. 04:03:52 PM 0 44331 24.65 0.00 0.00 24.65 1 stress
  7. 04:03:52 PM 0 44332 24.46 0.00 0.00 24.46 0 stress
  8. 04:03:52 PM 0 44333 24.26 0.00 0.00 24.26 0 stress
  9. 04:03:52 PM 0 44334 24.46 0.00 0.00 24.46 0 stress
  10. 04:03:52 PM 0 44335 24.65 0.00 0.00 24.65 1 stress
  11. 04:03:52 PM 0 44336 24.46 0.20 0.00 24.65 0 stress
  12. 04:03:52 PM 0 44353 0.20 0.20 0.00 0.39 1 watch
  13. 04:03:52 PM 0 45382 0.00 0.20 0.00 0.20 0 pidstat