理解平均负载
每当系统变慢时,我们进入机器的第一件事,就是用top
或者uptime
命令,来了解系统的负载情况;比如我在终端里面输入uptime
命令,系统也随即给出了结果。
实际上我们未必能清楚里面每列输出的含义?
我们对前面几列比较熟悉,它们分别是当前时间、系统运行时间以及正在登录的用户数;
而后面的三个数字,依次则是过去1分钟、5分钟、15分钟的平均负载(Load Average);
平均负载?听起来既熟悉又陌生,我们每天的工作中,都会用到这个词,但未必真正理解它背后的含义;假设一个场景,我们能给公司的新人解释清楚什么是平均负载吗?
对于基础问题,我们要多问自己几个”为什么“, 以求能够彻底理解现象背后的本质原理,使用起来才能够更灵活,更有底气;
我们这就来观测和理解这个最常见,也是最重要的系统指标;
有人会说,平均负载不就是单位时间内的cpu的利用率吗?上面的0.53, 就是代表CPU的使用率是53%。
实则不然,我们可以通过man uptime命令来了解下平均负载的详细解释;
|
|
简单来说,平均负载就是指单位时间内,系统处于可运行状态和不可中断状态的平均进程数,也即是平均活跃进程数,它和CPU使用率并没有直接关系;
可运行状态的进程,是指正在使用CPU或者正在等待CPU的进程,也就是我们常用ps命令看到的,处于R状态(Running或Runable)的进程;
不可中断的进程则是正处于内核态关键流程中的进程,并且这些流程是不可打断的。比如说最常见的是等待硬件设备的I/O响应,也就是我们在ps命令中看到的D状态(Uninterruptible Sleep, 也称为Disk Sleep)的进程。
比如,当一个进程向磁盘读写数据时,为了保证数据的一致性,在得到磁盘回复前,它是不能被其他进程或中断打断的,这个时候的进程就处于不可中断状态。如果此时的进程被打断了,就容易出现磁盘数据和进程数据不一致的问题;
所以,不可中断状态实际上是系统对进程和硬件设备的一种保护机制;
因此,可以理解为,平均负载其实就是平均活跃进程数。平均活跃进程数,直观上的理解就是单位时间内的活跃进程数,但它实际上是
活跃进程数的指数衰减平均值。
既然平均的是活跃进程数,那么最理想的,就是每个CPU上都刚好运行着一个进程,这样每个CPU都得到了充分利用。比如当平均负载为2时,这意味着什么意思呢?
- 在只有2个CPU的系统上,意味着所有的CPU都刚好被完全占用;
- 在4个CPU的系统上,意味着CPU有50%的空闲;
- 在只有1个CPU的系统中,则意味着有一半的进程竞争不到CPU;
平均负载为多少时合理
我们解释了一下什么是平均负载,回到最开始的uptime的命令结果中,那三个时间段的平均负载数,多大时候能说明系统负载搞?或是多小的时候就能说明系统负载很低呢?
我们知道,平均负载最理想的情况是等于CPU的个数。所以在评判平均负载时,首先需要知道系统有几个CPU, 这可以通过top命令或者从文件/proc/cpuinfo
中读取,例如:
grep "model name" /proc/cpuinfo | wc -l
有了CPU个数,可以判断出,当平均负载比CPU个数还大的时候,系统已经出现了过载;
但是平均负载里面有三个数值,到底该参考哪一个呢?
实际上,都需要看。三个不同时间间隔的平均值,其实给我们提供了,分析系统负载趋势的数据来源,可以让我们能更全面、更立体地理解目前的负载情况;
就像我们去观察初秋北京的天气一样,如果只看中午的温度,你还认为是7月份的大夏天呢。但是结合早上,中午,晚上三个时间点的温度来看,基本就可以全方位的了解这一天的天气情况了;同样的,前面说到的CPU的三个负载时间段也是这个道理;
- 如果1分钟、5分钟、15分钟的三个值基本相同,或者相差不大,那就说明系统负载很平稳;
- 但如果1分钟的值远小于15分钟的值,就说明系统最近1分钟的负载在减少,而过去15分钟内却有很大的负载;
- 反过来,如果1分钟的值远大于15分钟的值,就说明最近1分钟的负载在增加,这种增加可能只是临时性的,也有可能还会持续增加下去,所以就需要持续观察;一旦1分钟的平均负载接近或者超过了CPU的个数,就意味着系统正在发生过载的问题,这时候就得分析调查是哪里导致的问题,并且想办法优化了;
那么,实际在生产环境中,平均负载多高时,需要我们重点关注呢?
一般说来,当平均负载高于CPU数量的70%的时候,就应该去排查负载高的问题了;一旦负载过高,就可能导致进程响应变慢,进而影响服务的正常功能;但实际上70%的数字并不是绝对的,最推荐的方法还是把系统的平均负载监控起来,然后根据更多的历史数据,判断负载的变化趋势;当发现负载有明显升高的趋势时,需要再去分析和调查;
平均负载和CPU使用率
现实工作中,我们经常容易把平均负载和CPU利用率混淆,我们需要做一个区分,
可能你会疑惑,既然平均负载代表的是活跃进程数,那么平均负载搞了,不就意味着CPU的使用率变高嘛?
听起来好像是这样,但我们最终还是要回到平均负载的含义上,平均负载就是指单位时间内,系统处于可运行状态和不可中断状态的平均进程数。所以,它不仅包括了正在使用CPU的进程,还包括等待CPU和等待I/O的进程;
而CPU使用率,是单位时间内CPU繁忙情况的统计,跟平均负载并不一定完全对应;比如,
- CPU密集型进程,使用大量CPU会导致平均负载升高,此时这两者是一致的;
- I/O密集型进程,等待I/O也会导致平均负载升高,但CPU使用率不一定很高;
- 大量等待CPU的进程调度也会导致平均负载升高,此时的CPI使用率 也会比较高;
平均负载案例分析
下面用三个示例分别来看这三种情况,并用iostat、mpstat、pidstat
等工具,找出平均负载升高的根源;
我的准备
实验环境基于Ubuntu18.04, 当然其他的Linux系统也是可以的。实验环境配置如下:
- 机器配置:4CPU, 8GB内存;
- 预先安装了
stress
和sysstat
包;
stress
是一个 Linux 系统压力测试工具。这里我们来用作异常进程模拟平均负载升高的场景;
sysstat
包含了常用的 Linux 性能工具,用来监控和分析系统的性能。我们的案例中会用到 mpstat
和 pidstat
。
mpstat
是一个常用的多核 CPU 性能分析工具,用来实时查看 CPU 的性能指标及所有 CPU 的平均指标。pidstat
是一个常用的进程性能分析工具,用来实时查看进程的 CPU、内存、I/O 及上下文切换等性能指标。
我们这里打开三个终端,登录到同一台Linux机器,以方便观察监控机器负载的变化;
先用uptime来看一下测试前的平均负载情况:
场景一:CPU密集型进程
首先我们在终端一运行stress命令,模拟一个CPU使用率100%的场景:
stress --cpu 1 --timeout 600
接着,在第二个终端运行uptime查看平均负载的变化情况:
|
|
最后,在第三个终端运行mpstat
查看CPU使用率的变化情况:
|
|
从终端二可以看到,1分钟的平均负载会慢慢增加到1.00,而从终端三中可以看到有一个CPU的使用率为100%, 但它的iowait
只有0;
这说明,平均负载的升高正是由于CPU使用率为100%;
那么,到底是哪个进程导致了CPU使用率为100%呢?我们可以使用pidstat
来查询;
从这里可以明显看到,stress进程的CPU使用率为100%;
场景二:I/O密集型进程
首先还是运行stress命令,但这次模拟I/O压力,即不停地执行sync:
stress -i 1 --timeout 600
stress-ng -i 1 --hdd 1 --timeout 600
还是在第二个终端运行uptime来查看平均负载的变化情况:
watch -d uptime
然后终端三运行mpstat
来查看CPU使用率的变化情况:
mpstat -P ALL 5
从这里可以看到,1分钟的平均负载会慢慢增加到1.24, 但是我这里并没有模拟出iowait占用率高的情形;但是仍然可以观察到CPU的使用率很高。
那么,到底是哪个进程导致了CPU使用率很高呢?我们可以使用pidstat
来查询;
可以发现,这里还是stress进程导致的;
场景三:大量进程的场景
当系统中运行进程超出CPU运行能力时,就会出现等待CPU的进程;
比如,我们还是使用stress, 但这次模拟的是16个进程:
stress -c 16 --timeout 600
由于系统只有4个cpu,明显比16个进程要少的多,因而,系统的CPU处于严重过载状态,平均负载高达7.82;
接着再运行pidstat来看一下进程的情况:
可以看出,16个进程在争抢4个CPU, 每个进程等待CPU的时间(也就是pidstat
输出中的%wait列)高达74.70。这些超出CPU计算能力的进程,最终导致CPU过载;
学习小结
通过实验上面3个案例,来归纳一下对平均负载的理解:
平均负载提供了一个快速查看系统整体性能的手段,反映了整体的负载情况。但只看平均负载本身,我们并不能直接发现,到底是哪里出现了瓶颈。所以,在理解平均负载时,也要注意:
- 平均负载高有可能是CPU密集型进程导致的;
- 平均负载高并不一定代表CPU使用率高,还有可能是I/O更加繁忙了;
- 当发现负载高的时候,可以使用
mpstat, pidstat
等工具,辅助分析负载的来源;