本文原创作者:Cloud Chou. 欢迎转载,请注明出处和本文链接
有时候我们觉得linux系统特别卡顿,这时候可以通过查看系统的平均负载情况来定位卡顿问题的原因。本篇会介绍linux平均负载的概念,如何查看系统负载,如何定位系统负载过高的原因,以及如何解决负载过高的问题
什么是系统平均负载
系统平均负载对应的英文概念是: Load Average,它是指一段时间内正在执行或等待执行的进程的总数的平均值。
简单假设: 假设系统每隔5s统计一下正在执行或者等待执行的进程数,那么1分钟的系统平均负载是指这1分钟内20次统计得到的数量的平均值。 但实际上计算系统平均负载时,是对这些观察数据使用指数加权移动平均(Exponentially Weighted Moving Average)的方式来处理这些数据得到这1分钟内的平均负载,这种方式比简单平均更能反应真实情况。我们通常所说的过去1分钟的平均负载,实际上过去1分钟的平均负载情况只占了63%,而从开机到过去1分钟之前的平均负载情况会占到37%。另外系统也不会是按照5s一次统计的频率,而是根据cpu的频率来决定的。不过通常我们并不需要关注这些细节
大部分Unix系统只统计进程状态为正在执行或者等待cpu资源来执行的进程,但是linux还会统计进程状态为不可中断休眠(uninterruptible sleep)状态的进程,这种状态的进程通常在等待磁盘数据
linux进程状态:
- R(TASK_RUNNING) 可执行状态 会被平均负载统计 处于该状态的进程可能正在CPU上执行,也可能处在CPU的可执行队列中,进程调度器可从CPU的可执行队列中选择一个进程在该 CPU上执行。 教科书将等待CPU执行的状态称之为就绪状态,但是在linux上都称为可执行状态(TASK_RUNNING)
- S(TASK_INTERRUTILBE) 可中断的睡眠状态 不会被平均负载统计 处于该状态的进程一般都在等待某事件的发生(比如等待socket连接,等待信号量),这些进程会被内核放在对应事件的等待队列,如果事件发生,则等待队列的一个或者多个进程就被唤醒,变为可执行状态 linux大部分进程会处于这个状态
- D(TASK_UNINTERRUPTIBLE) 不可中断的睡眠状态 会被平均负载统计 进程处于这个状态,其实还是睡眠状态,它将不会响应异步信号(比如使用kill -9杀不死这个进程),但是还会响应硬件中断。 一般由同步IO操作引起,同步IO在做读或写操作时,cpu不能做其它事情,只能等待,这个时候进程还是会霸占这个cpu,不会调度其它进程执行。 如果程序采用异步IO,这种状态就很少会看到 不可中断的睡眠状态很短暂,用ps命令一般捕捉不到
- T(TASK_STOPPED or TASK_TRACED) 暂停状态或跟踪状态 不会平均负载统计 向进程发送一个SIGSTOP信号,它会响应该信号而进入TASK_STOPPED状态,SIGSTOP与SIGKILL信号一样,非常强制,不允许用户进程通过signal系列系统调用重新设置对应的信号处理函数。若向进程发送SIGCONT信号,可以让进程从TASK_STOPPED状态恢复到TASK_RUNNING状态 通过ptrace系统调用来调试进程时,会让进程进入TASK_TRACED状态
- Z(EXIT_ZOMBIE) 僵尸状态 不会被平均负载统计 进程退出过程中进程占有的所有资源都会被回收,内核中只会保留task_struct结构,如果父进程通过wait系列的调用来等待子进程退出,子进程退出后,父进程可以通过wait调用返回的数据来得到子进程的退出信息。但是如果父进程没有通过wait系列调用来等待子进程退出,那么子进程的退出信息将不被父进程获得,内核会一直保留子进程的task_struct信息,因此子进程会进入僵尸状态。进程的task_struct结构信息里有退出状态信息
- X(EXIT_DEAD) 退出状态 不会被平均负载统计 进程退出过程中进程占有的所有资源都会被回收,包括它的task_struct结构。进程即将被销毁时会处于这个状态,这个状态是非常短暂的,几乎不可能通过ps命令捕捉
操作系统描述的进程状态:
- 就绪
- 执行
- 阻塞 就绪能切换到执行状态,执行状态可能切换到就绪状态或者阻塞状态,阻塞状态只能切换到执行状态
对于单个cpu且单核的机器来说,如果是CPU密集型应用,我们可以用系统平均负载来衡量系统利用率。如果是多个CPU或者多核的情况下,我们必须拿平均负载除以所有的核心数,才能用来衡量系统利用率。
举例来说,如果单cpu系统的系统平均负载的数值是1.73 0.60 7.98
:
- 过去1分钟 系统平均负载超负荷73%(1.73个可执行进程,那么有0.73个进程需要等待这个cpu资源才可以运行)
- 过去5分钟 cpu有40%是空闲的
- 过去15分钟 系统平均负载超负荷698%(7.98个可执行进程,那么6.98个进程需要等待cpu资源才可以运行)
上述的例子以为着这台机器(CPU,磁盘,内存等资源)如果能快1.73倍,那么它能处理过去1分钟内的所有任务,也可以看出来过去15分钟到过去5分钟这一段时间内的任务都被系统处理完了,所以过去5分钟的负载还有40%的空闲
如果一台机型有4个cpu,3.73的平均负载意味着有3.73个进程可以运行,这样每个进程都可以占用一个cpu来运行,如果只1个4核的cpu,每个进程也都可以占用一个核来运行
一般认为单核cpu平均负载小于等于0.7是一个理想状态,如果超过则想办法降低负载
系统平均负载 VS CPU利用率
CPU利用率: 表示程序在运行期间实时占用的CPU百分比
CPU利用率高,并不意味着负载一定大
举例来说:如果我有一个程序它需要一直使用CPU的运算功能,那么此时CPU的利用用率可能达到100%,但是CPU的工作负载则是趋近于“1”,因为CPU仅负责一个工作嘛!如果同时执行这样的程序两个呢?CPU的使用率还是100%,但是工作负载则变成2了。所以也就是说,当CPU的工作负载越大,代表CPU必须要在不同的工作之间进行频繁的工作切换
系统平均负载 比 CPU利用率 能更好的评估系统的压力
但是容器内通常只会跑一个应用服务,所以看系统平均负载并没有太大的意义,一般看CPU利用率
如何查看系统平均负载情况
1. w
命令
1
2
3
4
5
ubuntu@xxx-container1:~$ w
23:02:26 up 9 days, 6:35, 2 users, load average: 0.71, 0.75, 0.63
USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
ubuntu pts/0 10.0.0.6 21:17 1:44m 0.06s 0.06s -bash
ubuntu pts/1 10.0.0.6 23:01 1.00s 0.06s 0.00s w
w
命令用于显示有哪些用户登录了,并显示他们正在干什么。
首行显示了当前时间 系统开机多长时间了,以及有多少用户已经登录了,还有系统平均负载,分别是1分钟内 5分钟内 15分钟内的系统平均负载
接下来的表格每行显示的是登录用户的名字,使用的终端名字,从哪个ip登录,登录时间,空闲的时间,JCPU, PCPU,已经他们当前进程的命令行
The JCPU time is the time used by all processes attached to the tty. It does not include past background jobs, but does include currently running background jobs.
The PCPU time is the time used by the current process, named in the “what” field.
2. uptime
命令
1
2
ubuntu@Xxx-container1:~$ uptime
23:15:50 up 9 days, 6:48, 2 users, load average: 0.62, 0.53, 0.56
uptime
命令显示了当前时间,开机了多长时间有多少登录的用户,系统平均负载,分别是1分钟内 5分钟内 15分钟的系统平均负载
3. top
命令
1
2
3
4
5
6
7
8
9
ubuntu@studybird-container1:~$ top -n 1
top - 23:20:38 up 9 days, 6:53, 2 users, load average: 0.50, 0.60, 0.59
Tasks: 207 total, 1 running, 206 sleeping, 0 stopped, 0 zombie
%Cpu(s): 1.7 us, 0.8 sy, 0.0 ni, 97.1 id, 0.2 wa, 0.0 hi, 0.2 si, 0.0 st
KiB Mem : 8043944 total, 857808 free, 888232 used, 6297904 buff/cache
KiB Swap: 0 total, 0 free, 0 used. 6360040 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
1740 root 20 0 680936 80428 23784 S 26.7 1.0 296:52.01 kubelet
第1行: 当前时间,开机多长时间,登录用户数量,系统平均负载: 1分钟,5分钟, 15分钟
第2行: 进程总数量, 正在运行或者等待运行的进程数, 休眠的进程数, 停止运行的进程数, 僵尸进程数
第3行:
us(user cpu time):用户态使用的cpu时间比
sy(system cpu time):系统态使用的cpu时间比,其实就是内核态占的cpu时间比
ni(user nice cpu time):用做nice加权的进程分配的用户态cpu时间比
id(idle cpu time):空闲的cpu时间比
wa(io wait cpu time):cpu等待磁盘写入完成时间
hi(hardware irq):硬中断消耗时间
si(software irq):软中断消耗时间
st(steal time):虚拟机偷取时间
以上解释的这些参数的值加起来是100%
4. vmstat
命令
1
2
3
4
ubuntu@Xxxxx-container1:~$ vmstat
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
0 0 0 851348 2360012 3943904 0 0 9 145 2 11 2 1 97 0 0
procs部分的解释 r: The number of runnable processes (running or waiting for run time). 如果长期大于1,说明cpu不足,需要增加cpu。 b: The number of processes in uninterruptible sleep. 比如正在等待I/O(同步IO操作才会有这种情况)、或者内存交换等
cpu部分的解释 us 列显示了用户方式下所花费 CPU 时间的百分比。us的值比较高时,说明用户进程消耗的cpu时间多,但是如果长期大于50%,需要考虑优化用户的程序。 sy 列显示了内核进程所花费的cpu时间的百分比。这里us + sy的参考值为80%,如果us+sy 大于 80%说明可能存在CPU不足。 wa 列显示了IO等待所占用的CPU时间的百分比。这里wa的参考值为30%,如果wa超过30%,说明IO等待严重,这可能是磁盘大量随机访问造成的,也可能磁盘或者磁盘访问控制器的带宽瓶颈造成的(主要是块操作)。 id 列显示了cpu处在空闲状态的时间百分比
system部分的解释 in 列表示在某一时间间隔中观测到的每秒设备中断数。 cs 列表示每秒产生的上下文切换次数,如当 cs 比磁盘 I/O 和网络信息包速率高得多,都应进行进一步调查。
memory部分的解释 swpd the amount of virtual memory used free the amount of idle memory buff the amount of memory used as buffers。 cache: the amount of memory used as cache inact: the amount of inactive memory. (-a option) active: the amount of active memory. (-a option)
swap部分的解释 si: Amount of memory swapped in from disk (/s). so: Amount of memory swapped to disk (/s).
IO部分的解释 bi: Blocks received from a block device (blocks/s). bo: Blocks sent to a block device (blocks/s).
5. dstat
命令
dstat也可以看cpu的信息
1
2
3
4
5
6
7
ubuntu@studybird-container1:~$ dstat
You did not select any stats, using -cdngy by default.
----total-cpu-usage---- -dsk/total- -net/total- ---paging-- ---system--
usr sys idl wai hiq siq| read writ| recv send| in out | int csw
2 1 97 0 0 0| 37k 721k| 0 0 | 0 0 |2330 3628
1 3 96 0 0 0| 0 0 | 64k 62k| 0 0 |2153 2682
1 1 98 0 0 0| 0 0 | 34k 33k| 0 0 |1230 1471
6. iostat
命令
可以使用iostat查看IO负载
1
2
3
4
5
6
7
8
[root@localhost ~]# iostat 1 1
Linux 2.6.32-696.16.1.el6.x86_64 (nc-ftp01.kevin.cn) 2017年12月29日 _x86_64_ (4 CPU)
avg-cpu: %user %nice %system %iowait %steal %idle
19.32 0.00 45.44 0.06 0.26 34.93
Device: tps Blk_read/s Blk_wrtn/s Blk_read Blk_wrtn
xvda 14.17 29.94 265.17 63120486 558975100
解释说明: avg-cpu: 总体cpu使用情况统计信息,对于多核cpu,这里为所有cpu的平均值 %user: 在用户级别运行所使用的CPU的百分比. %nice: nice操作所使用的CPU的百分比. %sys: 在系统级别(kernel)运行所使用CPU的百分比. %iowait: CPU等待硬件I/O时,所占用CPU百分比. %idle: CPU空闲时间的百分比.
Device段:各磁盘设备的IO统计信息 tps: 每秒钟发送到的I/O请求数. Blk_read /s: 每秒读取的block数. Blk_wrtn/s: 每秒写入的block数. Blk_read: 读入的block总数. Blk_wrtn: 写入的block总数.
1
2
3
4
5
6
7
8
9
[root@localhost ~]# iostat -x -k -d 1
Linux 2.6.32-696.el6.x86_64 (centos6-vm02) 01/04/2018 _x86_64_ (4 CPU)
Device: rrqm/s wrqm/s r/s w/s rkB/s wkB/s avgrq-sz avgqu-sz await r_await w_await svctm %util
scd0 0.00 0.00 0.00 0.00 0.00 0.00 8.00 0.00 0.36 0.36 0.00 0.36 0.00
vda 0.01 0.13 0.04 0.13 0.60 0.89 18.12 0.00 2.78 0.19 3.53 2.55 0.04
dm-0 0.00 0.00 0.04 0.22 0.58 0.88 11.25 0.00 3.27 0.25 3.82 1.61 0.04
dm-1 0.00 0.00 0.00 0.00 0.00 0.00 8.00 0.00 0.13 0.13 0.00 0.04 0.00
dm-2 0.00 0.00 0.00 0.00 0.00 0.00 7.91 0.00 0.19 0.10 5.00 0.16 0.00
解释说明: rrqm/s: 每秒对该设备的读请求被合并次数,文件系统会对读取同块(block)的请求进行合并 wrqm/s: 每秒对该设备的写请求被合并次数 r/s: 每秒完成的读次数 w/s: 每秒完成的写次数 rkB/s: 每秒读数据量(kB为单位) wkB/s: 每秒写数据量(kB为单位) avgrq-sz:平均每次IO操作的数据量(扇区数为单位) avgqu-sz: 平均等待处理的IO请求队列长度 await: 平均每次IO请求等待时间(包括等待时间和处理时间,毫秒为单位) svctm: 平均每次IO请求的处理时间(毫秒为单位) %util: 采用周期内用于IO操作的时间比率,即IO队列非空的时间比率
如果 %util 接近 100%,说明产生的I/O请求太多,I/O系统已经满负荷,该磁盘可能存在瓶颈。 idle小于70% IO压力就较大了,一般读取速度有较多的wait。 同时可以结合vmstat 查看查看b参数(等待资源的进程数)和wa参数(IO等待所占用的CPU时间的百分比,高过30%时IO压力高)
如何定位系统平均负载过高的问题原因并解决
Linux的负载高,主要是由于CPU使用、内存使用、IO消耗三部分引起,任意一项使用过量,都将导致服务器负载的急剧攀升
-
排查是否是cpu利用率过高 或者内存占用过高导致的负载过高
首先排查是否是cpu利用率过高 或者 内存占用太高, 这时候通过
top
命令就可以看出来cpu利用率以及内存剩余情况,或者内存是否有频繁swap in 或者swap out,也可以使用free
命令查看内存使用情况,通过free命令也可以查看剩余的内存以及交换区的工作情况如果发现cpu利用率过高,则使用
top
命令查看占用cpu最多的进程,再分析进程为啥需要这么多资源,然后看是否有优化空间,如果没有优化空间,则添加更多的cpu核如果发现内存利用率过高,或者剩余内存较少,或者频繁将物理内存的内容交换到交换区,则使用
top
命令查看占用内存最多的进程,再分析该进程为啥需要这么多内存,然后看是否有优化空间,如果没有优化空间则添加更多的cpu核 -
排查是否是io问题
可以使用命令
iostat -x 1 10
来看io开销,可以直接看“util”的百分比,until就是io利用率,如果until达到100%,则说明磁盘的负载特别大, 这时候再分析是哪个进程造成磁盘的负载特别大(可以使用ps
命令),然后再看是否有优化空间,没有优化空间则换更高效的硬盘
参考资料
Load(computing) EWMA(Exponentially Weighted Moving Average)指数加权移动平均 Linux进程状态解析之R、S、D、T、Z、X 进程状态 linux系统调用之-fork、wait、waitpid Linux中fork,vfork和clone详解(区别与联系 Linux系统下CPU使用(load average)梳理 linux负载过高 排查方法及说明