美文网首页
对linux系统中“平均负载”的理解

对linux系统中“平均负载”的理解

作者: 冬天里的懒喵 | 来源:发表于2021-07-13 19:52 被阅读0次

    最近在极客时间学习了倪朋飞老师的《Linux性能优化实战》专题,里面讲到了linux的平均负载这个概念。也就是load average。现在谈谈对平均负载的理解,并整理为笔记。

    1.概念

    1.1 如何查看系统的平均负载?

    当我们通过ssh进入linux系统之后,通常来说,有两种方式可以查看这个load average.

    • uptime

    执行uptime

    [root@m162p201 ~]# uptime
     15:26:21 up 621 days,  8:06,  1 user,  load average: 0.00, 0.01, 0.05
    
    • top

    执行top

    [root@m162p201 ~]# top
    top - 15:26:59 up 621 days,  8:07,  1 user,  load average: 0.00, 0.01, 0.05
    Tasks: 106 total,   1 running, 105 sleeping,   0 stopped,   0 zombie
    %Cpu(s):  0.5 us,  0.5 sy,  0.0 ni, 98.8 id,  0.0 wa,  0.0 hi,  0.0 si,  0.2 st
    KiB Mem :  8175664 total,  2006684 free,  4863032 used,  1305948 buff/cache
    KiB Swap:  4063228 total,  4063228 free,        0 used.  2626032 avail Mem 
    

    通过上述两种方法,都可以得到load average。
    我们看到这个load average的值由3个分隔的数字构成。
    分别代表过去1分钟、5分钟、15分钟三个时间段系统的平均负载。

    1.2 平均负载概念

    让我们看看平均负载的解释,man uptime中的描述如下:

        uptime  gives a one line display of the following information.  The current time, how long the system has been running, how many users are currently logged on, and the system load averages for the
           past 1, 5, and 15 minutes.
    
           This is the same information contained in the header line displayed by w(1).
    
           System load averages is the average number of processes that are either in a runnable or uninterruptable state.  A process in a runnable state is either using the CPU or waiting to use the CPU.  A
           process  in  uninterruptable  state  is waiting for some I/O access, eg waiting for disk.  The averages are taken over the three time intervals.  Load averages are not normalized for the number of
           CPUs in a system, so a load average of 1 means a single CPU system is loaded all the time while on a 4 CPU system it means it was idle 75% of the time.
    
    

    这个定义为:系统的平均负载(load averages)是处于Runnable(运行)状态和Uninterruptable(不可中断)状态的两种状态下的进程在单位时间内的平均数。对,没有看错,这里说的是平均的进程数量,与CPU本身的使用率没有直接关系。这个load averages实际上表示的是系统中的平均活跃进程数

    对于进程的这两种状态

    • Runnable

    在前面学过jvm的线程模型,线程的状态也与进程的状态类似,实际上这个状态指正在使用或者正在等待使用的CPU进程。通过PS中看到的R状态的进程。

    • Uninterruptable

    不可中断的进程,指的是该进程处于内核态关键流程中的状态,这些流程是不能被中断的。比如在等待硬件设备或者是I/O响应,这也是我们在PS过程中看到的D状态进程。这些进程如果被中断,将会造成数据不一致问题或者故障。

    因此,我们可以讲系统的平均负载理解为单位时间内的平均的活跃进程数。
    那么我们如果需要知道一个服务器上负载究竟是多少合适呢?既然是单位时间内的平均活跃进程数,那么最理想的状态就是,一个CPU运行一个进程,这样每个CPU都将充分被利用。假如我们得到的平均负载为2的话,那么在只有1个CPU的系统中,将会形成系统过载,意味着其中一半的进程竞争不到资源。而2个CPU的系统中,则意味着CPU刚好被利用。在4个CPU的系统中,则CPU可能存在50%的空闲。

    1.3 扩展

    1.3.1 ps中的进程状态

    通过ps命令我们可以查看linux中的进程状态,通常的如 ps -aux。

    [root@m162p201 ~]# ps -aux
    USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
    root         1  0.0  0.0  51720  3484 ?        Ss    2019 203:55 /usr/lib/systemd/systemd --system --deserialize 22
    root         2  0.0  0.0      0     0 ?        S     2019   0:04 [kthreadd]
    root         3  0.0  0.0      0     0 ?        S     2019   9:45 [ksoftirqd/0]
    root         7  0.0  0.0      0     0 ?        S     2019   0:07 [migration/0]
    root         8  0.0  0.0      0     0 ?        S     2019   0:00 [rcu_bh]
    root         9  0.0  0.0      0     0 ?        S     2019 262:40 [rcu_sched]
    root        10  0.0  0.0      0     0 ?        S     2019   4:27 [watchdog/0]
    root        11  0.0  0.0      0     0 ?        S     2019   4:04 [watchdog/1]
    root        12  0.0  0.0      0     0 ?        S     2019   0:06 [migration/1]
    root        13  0.0  0.0      0     0 ?        S     2019  26:33 [ksoftirqd/1]
    root        17  0.0  0.0      0     0 ?        S<    2019   0:00 [khelper]
    root        18  0.0  0.0      0     0 ?        S     2019   0:00 [kdevtmpfs]
    root        19  0.0  0.0      0     0 ?        S<    2019   0:00 [netns]
    root        20  0.0  0.0      0     0 ?        S     2019   0:36 [khungtaskd]
    root        21  0.0  0.0      0     0 ?        S<    2019   0:00 [writeback]
    root        22  0.0  0.0      0     0 ?        S<    2019   0:00 [kintegrityd]
    root        23  0.0  0.0      0     0 ?        S<    2019   0:00 [bioset]
    root        24  0.0  0.0      0     0 ?        S<    2019   0:00 [kblockd]
    

    上述表中的列分别为:

    列名 说明
    USER 进程所有者用户名。
    PID 用来唯一标识的进程ID(进程号)
    %CPU 进程占用CPU的百分比。
    %MEM 进程占用内存的百分比。
    VSZ 进程使用的虚拟内存的大小,单位KB
    RSS 进程使用物理内存的总page数,这是内存管理的最小单位,每个page为4k
    TTY 进程所在的终端ID
    STAT 进程的状态,后面详细介绍。
    START 进程启动时间
    TIME 进程占用总CPU的时间
    COMMAND 进程执行的命令和参数

    对于STAT的常用状态如下表:

    状态 说明
    R 可运行状态,此时进程处于正在运行或者正在运行的队列中准备运行
    S 可中断状态。处于可中断的某一状态的进程可以被中断信号中断。
    D 不可中断状态。处于不可中断的等待状态的进程不可被中断信号中断,将一直等待事件发生或者直到某种系统资源完成。
    T 暂停状态,处于暂停状态的进程被暂停运行
    Z 僵死状态,每个进程在运行结束之后都会处于僵死状态,等待父进程的调用而释放资源,处于该状态的进程已经运行结束,但是其父进程并没有释放其资源,或者父进程已经死亡

    进程的附加状态说明:

    附加状态 说明
    < 高优先级进程。
    N 低优先级进程。
    L 存在某些页面被锁在内存中
    s 主进程
    l 开启了多线程的进程
    + 前台进程

    1.3.2 如何查看CPU数量

    可以通过grep获取/proc/cpuinfo来得到。

    [root@m162p201 ~]# grep 'model name' /proc/cpuinfo |wc -l
    2
    

    2.平均负载的合理数值

    在得到系统的CPU个数之后,我们就很容易来判断系统的平均负载了,当平均负载大于CPU个数,说明系统肯定是过载了,如果当平均负载低于CPU个数,貌似这种情况是可以接受的。
    但是现在问题是,load averages存在3个值,我们应该参考哪个值呢?

    实际上,这三个平均负载,我们在系统中都要进行参考。必须结合才能反应系统的负载情况。这三个值分别代表了1分钟、5分钟、15分钟内的平均负载。

    结合这三个值,我们可以做出如下预测:
    如果1分钟、5分钟、15分钟三个值基本相同,或者相差不大,那么说明系统负载平稳。
    如果1分钟的值远小于15分钟的值,那么说明系统最近1分钟内负载降低,而过去15分钟内存在很高的负载。
    如果1分钟的值,远大于15分钟,说明1分钟的负载在增加,但是这种增加,也可能是临时增加,需要持续观察。
    一旦1分钟内的值接近或者超过了CPU个数,由于这个值记录的是系统已经发生的,所以要想办法进行优化,分析问题产生的原因。

    参考课程中的例子:
    如果在一个单核CPU的系统中平均负载为:1.75,0.80,8.75
    那么说明在过去1分钟内,系统存在75%的超载,过去5分钟,系统没有超载,而过去的15分钟,系统存在775%的超载。
    从这个趋势来看,系统的整体负载在降低。
    按照课程的经验值,通常情况下,当平均负载高于CPU数量70%的时候,就应该对负载进行排查了,一旦系统负载过高,可能对整体服务的性能造成影响。
    当然,这也不是绝对值,因为对于不同类型的服务,其系统负载不同,因此还是要根据系统监控,根据历史数据来进行判断。

    3.平均负载与CPU使用率的关系

    平均负载是指单位时间内,处于可运行状态和不可中断状态的进程数。因此,它不仅包括了正在使用CPU的进程,还包括等待CPU和等待I/O的进程以及处于等待中的一切不可中断的进程,而CPU使用率,是单位时间内CPU繁忙情况的统计,跟平均负载并不一定完全对应。

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

    4.测试案例

    现在对平均负载的案例进行测试,环境准备:


    系统环境htop

    硬件情况如上图。2CPU,8G内存。
    操作系统Centos7.7

    [root@m162p201 ~]# lsb_release -a
    LSB Version:    :core-4.1-amd64:core-4.1-noarch:cxx-4.1-amd64:cxx-4.1-noarch:desktop-4.1-amd64:desktop-4.1-noarch:languages-4.1-amd64:languages-4.1-noarch:printing-4.1-amd64:printing-4.1-noarch
    Distributor ID: CentOS
    Description:    CentOS Linux release 7.7.1908 (Core)
    Release:    7.7.1908
    Codename:   Core
    

    需要安装软件:

    yum install -y stress sysstat
    

    stress是一个Linux压力测试工具,存在于epel包中。sysstat包含了常用的linux性能工具。用于监控和分析系统性能。这个包括两个命令,mpstat和pidstat,其中mpstat是一个多核的CPU性能分析工具,用来查看CPU的实时性能指标和平均性能指标。而pidstat则是一个性能分析的工具。可以实时查看PU、内存、I/O 以及上下文切换等性能指标。
    在测试过程中,需要打开三个终端,需要注意的是终端类型不能为Xterm。

    4.1 CPU密集型进程

    第一个终端中运行:

    [root@m162p201 ~]# stress --cpu 1 --timeout 600
    stress: info: [11708] dispatching hogs: 1 cpu, 0 io, 0 vm, 0 hdd
    

    第二个终端,采用watch运行uptime

    watch -d uptime
    
    uptime截图

    第三个终端,通过mpstat查看CPU的变化情况。

    [root@m162p201 ~]# mpstat -P ALL 5 1
    Linux 3.10.0-514.el7.x86_64 (m162p201)  07/13/2021  _x86_64_    (2 CPU)
    
    06:44:39 PM  CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest  %gnice   %idle
    06:44:44 PM  all   50.96    0.00    0.61    0.00    0.00    0.00    0.00    0.00    0.00   48.43
    06:44:44 PM    0    4.49    0.00    1.22    0.00    0.00    0.00    0.00    0.00    0.00   94.29
    06:44:44 PM    1   96.59    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00    3.41
    
    Average:     CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest  %gnice   %idle
    Average:     all   50.96    0.00    0.61    0.00    0.00    0.00    0.00    0.00    0.00   48.43
    Average:       0    4.49    0.00    1.22    0.00    0.00    0.00    0.00    0.00    0.00   94.29
    Average:       1   96.59    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00    3.41
    

    通过上述三个案例可以发现,1分钟的负载逐渐上升到1.2,而此时,1号CPU的负载高达96.5%,但是这个CPU的iowait以及其他指标都为0,只有3.41%的idle。
    这说明,系统的平均负载正是由于CPU的高使用率造成。
    那么,究竟是哪个进程导致的呢,我们通过pidstat来查看:

    [root@m162p201 ~]# pidstat -u 5 1
    Linux 3.10.0-514.el7.x86_64 (m162p201)  07/13/2021  _x86_64_    (2 CPU)
    
    06:49:57 PM   UID       PID    %usr %system  %guest    %CPU   CPU  Command
    06:50:02 PM     0         1    0.00    0.20    0.00    0.20     0  systemd
    06:50:02 PM     0         9    0.00    0.20    0.00    0.20     0  rcu_sched
    06:50:02 PM  1008      5244    0.20    0.80    0.00    1.00     0  java
    06:50:02 PM  1008      8031    6.60    5.20    0.00   11.80     1  java
    06:50:02 PM  1007     10589    0.00    0.80    0.00    0.80     1  java
    06:50:02 PM     0     11709   99.80    0.20    0.00  100.00     1  stress
    06:50:02 PM     0     11785    0.20    0.00    0.00    0.20     0  watch
    06:50:02 PM     0     18040    0.40    0.60    0.00    1.00     0  etcd
    06:50:02 PM   998     18737    0.00    0.20    0.00    0.20     0  polkitd
    06:50:02 PM  1001     32703    0.00    0.20    0.00    0.20     1  java
    
    Average:      UID       PID    %usr %system  %guest    %CPU   CPU  Command
    Average:        0         1    0.00    0.20    0.00    0.20     -  systemd
    Average:        0         9    0.00    0.20    0.00    0.20     -  rcu_sched
    Average:     1008      5244    0.20    0.80    0.00    1.00     -  java
    Average:     1008      8031    6.60    5.20    0.00   11.80     -  java
    Average:     1007     10589    0.00    0.80    0.00    0.80     -  java
    Average:        0     11709   99.80    0.20    0.00  100.00     -  stress
    Average:        0     11785    0.20    0.00    0.00    0.20     -  watch
    Average:        0     18040    0.40    0.60    0.00    1.00     -  etcd
    Average:      998     18737    0.00    0.20    0.00    0.20     -  polkitd
    Average:     1001     32703    0.00    0.20    0.00    0.20     -  java
    

    可以发现,这正是由于stress的CPU达到100%所致。

    4.2 I/O密集型

    我们在终端1中执行:

    [root@m162p201 ~]# stress -i 1 --timeout 600
    stress: info: [12898] dispatching hogs: 0 cpu, 1 io, 0 vm, 0 hdd
    

    由于测试io,实际上就是调用sync不断的同步磁盘数据。
    在终端2中,通过watch查看:


    uptime截图

    在终端3中通过mpstat查看:

    [root@m162p201 ~]# mpstat -P ALL 5 1
    Linux 3.10.0-514.el7.x86_64 (m162p201)  07/13/2021  _x86_64_    (2 CPU)
    
    06:54:14 PM  CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest  %gnice   %idle
    06:54:19 PM  all    0.62    0.00   46.15    1.13    0.00    0.00    0.10    0.00    0.00   52.00
    06:54:19 PM    0    1.42    0.00    1.22    0.00    0.00    0.00    0.00    0.00    0.00   97.36
    06:54:19 PM    1    0.00    0.00   92.28    2.30    0.00    0.00    0.00    0.00    0.00    5.43
    
    Average:     CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest  %gnice   %idle
    Average:     all    0.62    0.00   46.15    1.13    0.00    0.00    0.10    0.00    0.00   52.00
    Average:       0    1.42    0.00    1.22    0.00    0.00    0.00    0.00    0.00    0.00   97.36
    Average:       1    0.00    0.00   92.28    2.30    0.00    0.00    0.00    0.00    0.00    5.43
    

    可以看到1分钟内,系统负载上升到, 1.22而1号CPU的sys状态为92.8,这说明load的上升是由于IO造成的。
    执行pidstat:

    [root@m162p201 ~]# pidstat -u 5 1
    Linux 3.10.0-514.el7.x86_64 (m162p201)  07/13/2021  _x86_64_    (2 CPU)
    
    06:57:49 PM   UID       PID    %usr %system  %guest    %CPU   CPU  Command
    06:57:54 PM  1008      5244    0.20    0.80    0.00    1.00     0  java
    06:57:54 PM     0      6533    0.00    0.20    0.00    0.20     0  kworker/u4:2
    06:57:54 PM  1008      8031    0.00    0.40    0.00    0.40     1  java
    06:57:54 PM     0      8985    0.00    0.20    0.00    0.20     1  kworker/1:2H
    06:57:54 PM  1002      9636    0.00    0.20    0.00    0.20     1  java
    06:57:54 PM  1007     10589    0.20    0.80    0.00    1.00     1  java
    06:57:54 PM     0     12899    0.00   93.00    0.00   93.00     0  stress
    06:57:54 PM     0     12907    0.20    0.20    0.00    0.40     1  watch
    06:57:54 PM     0     12921    0.00    0.20    0.00    0.20     0  kworker/u4:0
    06:57:54 PM     0     13490    0.00    0.20    0.00    0.20     1  pidstat
    06:57:54 PM     0     13497    0.00    0.20    0.00    0.20     0  kworker/u4:1
    06:57:54 PM     0     18691    0.20    0.00    0.00    0.20     0  irqbalance
    06:57:54 PM     0     18778    0.00    0.20    0.00    0.20     1  kworker/1:2
    06:57:54 PM  1001     32703    0.00    0.20    0.00    0.20     1  java
    
    Average:      UID       PID    %usr %system  %guest    %CPU   CPU  Command
    Average:     1008      5244    0.20    0.80    0.00    1.00     -  java
    Average:        0      6533    0.00    0.20    0.00    0.20     -  kworker/u4:2
    Average:     1008      8031    0.00    0.40    0.00    0.40     -  java
    Average:        0      8985    0.00    0.20    0.00    0.20     -  kworker/1:2H
    Average:     1002      9636    0.00    0.20    0.00    0.20     -  java
    Average:     1007     10589    0.20    0.80    0.00    1.00     -  java
    Average:        0     12899    0.00   93.00    0.00   93.00     -  stress
    Average:        0     12907    0.20    0.20    0.00    0.40     -  watch
    Average:        0     12921    0.00    0.20    0.00    0.20     -  kworker/u4:0
    Average:        0     13490    0.00    0.20    0.00    0.20     -  pidstat
    Average:        0     13497    0.00    0.20    0.00    0.20     -  kworker/u4:1
    Average:        0     18691    0.20    0.00    0.00    0.20     -  irqbalance
    Average:        0     18778    0.00    0.20    0.00    0.20     -  kworker/1:2
    Average:     1001     32703    0.00    0.20    0.00    0.20     -  java
    

    可以看到,stress进程导致了cpu升高。

    4.3 多进程场景

    还有一种场景就是进程数量过多。现在通过stress模拟。
    终端1中:

    [root@m162p201 ~]# stress -c 8 --timeout 600
    stress: info: [15557] dispatching hogs: 8 cpu, 0 io, 0 vm, 0 hdd
    

    现在由于只有2个CPU,而进程数量大于2,显然会导致系统负载上升。
    终端2中:


    uptime截图

    可以看到1分钟的负载变成了7.62
    我们再通过pidstat来分析。
    终端3中:
    mpstat

    [root@m162p201 ~]# mpstat -P ALL 5 1
    Linux 3.10.0-514.el7.x86_64 (m162p201)  07/13/2021  _x86_64_    (2 CPU)
    
    07:38:44 PM  CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest  %gnice   %idle
    07:38:49 PM  all   99.70    0.00    0.20    0.00    0.00    0.10    0.00    0.00    0.00    0.00
    07:38:49 PM    0  100.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00
    07:38:49 PM    1   99.80    0.00    0.20    0.00    0.00    0.00    0.00    0.00    0.00    0.00
    
    Average:     CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest  %gnice   %idle
    Average:     all   99.70    0.00    0.20    0.00    0.00    0.10    0.00    0.00    0.00    0.00
    Average:       0  100.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00
    Average:       1   99.80    0.00    0.20    0.00    0.00    0.00    0.00    0.00    0.00    0.00
    [root@m162p201 ~]# 
    
    

    pidstat

    [root@m162p201 ~]# pidstat -u 5 1
    Linux 3.10.0-514.el7.x86_64 (m162p201)  07/13/2021  _x86_64_    (2 CPU)
    
    07:37:54 PM   UID       PID    %usr %system  %guest    %CPU   CPU  Command
    07:37:59 PM  1008      8031    0.20    0.00    0.00    0.20     1  java
    07:37:59 PM  1007     10589    0.20    0.20    0.00    0.40     1  java
    07:37:59 PM     0     15558   24.60    0.00    0.00   24.60     0  stress
    07:37:59 PM     0     15559   24.40    0.00    0.00   24.40     0  stress
    07:37:59 PM     0     15560   24.60    0.00    0.00   24.60     0  stress
    07:37:59 PM     0     15561   24.60    0.00    0.00   24.60     1  stress
    07:37:59 PM     0     15562   24.60    0.00    0.00   24.60     1  stress
    07:37:59 PM     0     15563   25.00    0.00    0.00   25.00     1  stress
    07:37:59 PM     0     15564   25.00    0.00    0.00   25.00     0  stress
    07:37:59 PM     0     15565   24.60    0.00    0.00   24.60     1  stress
    07:37:59 PM     0     15571    0.00    0.20    0.00    0.20     1  watch
    07:37:59 PM     0     18040    0.40    0.20    0.00    0.60     0  etcd
    07:37:59 PM     0     18778    0.00    0.20    0.00    0.20     1  kworker/1:2
    07:37:59 PM  1001     32703    0.20    0.00    0.00    0.20     1  java
    
    Average:      UID       PID    %usr %system  %guest    %CPU   CPU  Command
    Average:     1008      8031    0.20    0.00    0.00    0.20     -  java
    Average:     1007     10589    0.20    0.20    0.00    0.40     -  java
    Average:        0     15558   24.60    0.00    0.00   24.60     -  stress
    Average:        0     15559   24.40    0.00    0.00   24.40     -  stress
    Average:        0     15560   24.60    0.00    0.00   24.60     -  stress
    Average:        0     15561   24.60    0.00    0.00   24.60     -  stress
    Average:        0     15562   24.60    0.00    0.00   24.60     -  stress
    Average:        0     15563   25.00    0.00    0.00   25.00     -  stress
    Average:        0     15564   25.00    0.00    0.00   25.00     -  stress
    Average:        0     15565   24.60    0.00    0.00   24.60     -  stress
    Average:        0     15571    0.00    0.20    0.00    0.20     -  watch
    Average:        0     18040    0.40    0.20    0.00    0.60     -  etcd
    Average:        0     18778    0.00    0.20    0.00    0.20     -  kworker/1:2
    Average:     1001     32703    0.20    0.00    0.00    0.20     -  java
    

    可以看出,user的cpu上升,而这些cpu的上升都是stress进程过多所致。这超出了当前系统的计算能力。

    5 总结

    通过本文学习,我们需要知道,平均负载是一个快速查看系统整体性能的手段。但是只通过这一个参数,我们很难发现系统的问题,我们需要结合cpu数量,以及其他的系统监控指标共同做出判断。
    CPU密集型和IO密集型都可能导致平均负载升高。而系统的平均负载升高,则需要结合相关的工具如mpstat和pidstat来综合判断。
    最后,再总结一下平均负载的概念,表示单位时间内系统的活跃进程数量(包括R状态和D状态的进程)

    相关文章

      网友评论

          本文标题:对linux系统中“平均负载”的理解

          本文链接:https://www.haomeiwen.com/subject/usispltx.html