之前我讲了cpu使用率的问题,cpu使用率是我们监控中非常关注的指标。
但是工作中,我们经常遇到业务应用已经很慢了,但是cpu利用率显示很低。
这种时候,你会发现top中load很高。
在top中,load average后面有3个数字。分别代表1分钟,5分钟和15分钟的平均负载。
是对过去一段时间的负载情况的反应。
对load average的正确理解
假设一台只有1个cpu的服务器,如果此时cpu在运行一个进程,并且没有其他等待运行的进程。那么现在的load就是1。
如果此时还有2个进程在等待运行,那么load就是3
也就是说load = 正在运行的进程数 + 等待运行的进程数
对于一个24C的服务器,如果只有10个进程在运行,那么load就是10
不管cpu的使用率是多少。所以我们通常建议说最好的情况是load 大致等于cpu数。这样表示cpu都在工作,没有浪费。又不至于太忙导致任务等待。
这是理想的情况。
实际上,我们经常遇到cpu利用率几乎是0,但是load非常高的情况。
这是因为我们假设了服务器其他模块全部都非常给力,没有拖后腿。但是在实际的业务中,磁盘或者网络总是会出问题的。
比如同样的业务应用场景,服务器配置一样,将高速磁盘换成低速磁盘,会明显感受到应用性能的降低。
但是如果按照前面的公式,load是不会变大的。就是说load没有真实反应服务器的性能
然后linux的一位开发者给内核打了个补丁,增加了对 TASK_UNINTERRUPTIBLE 状态进程的计数。将 TASK_UNINTERRUPTIBLE 状态的进程也计算在了load中。
在前面的文章里,我提到过TASK_UNINTERRUPTIBLE 状态。
7dbd023628f5f4165abc23c1d67aca99还是看这张图,在进行磁盘io操作的时候,进程就会进入这个状态。
TASK_UNINTERRUPTIBLE 根据名字就能猜到这个状态是不能被打断的。这对于保证某些关键操作的原子性和完整性是必要的。
比如write()操作可不能执行一半被打断。
TASK_UNINTERRUPTIBLE状态的进程,在系统里显示位D状态。
进程状态 "D" 代表 "Uninterruptible Sleep" 或 "Disk Sleep"。这通常意味着进程正在等待 I/O 操作,如从磁盘读取数据,而这个操作目前无法完成,可能是因为物理设备(如硬盘)正在忙碌,或者数据尚未准备好。
可以查询一下系统里是否有D进程
ps -eo pid,stat | grep -w 'D'有D进程不是啥好事,如果D进程太多,一定要分析出根因。因为D进程会显著拖慢整个系统,使load上升。
可以 cat /proc/<pid>/stack, 看到进程停在内核中的哪个函数上,结合内核的代码,猜一下到底是卡在哪里。
总结,
load = 可运行的进程数 + D状态的进程数
对于load可以做一个比方,每个cpu是一条道路,进程就是路上的车。单位时间通过的车辆数就是load值。
可以想象load值不会等于车的数量,因为有红绿灯的存在。绿灯就是进程在等待的资源。