只要是玩Linux的,只要CPU变高了,想到的第一个Linux性能排查工具大多数是TOP,然后即使使用TOP,很多运维同学看的也永远是那几行,server load, mem 使用率,CPU使用率等,然后看看哪个进程高了,然后看看是不是core了之类的,在这个过程中,有些很基础但是很容易被大家忽略的问题,load多少算高?有啥评判标准?万一每个进程CPU使用率都很高/很低,那我该杀哪个呢?CPU使用率有些进程已经超过100%了,这个100%怎么来的呢?
首先我觉得要先理解啥是load 和 cpu usage
LOAD 和 CPU 使用率
在实际工作中,我们经常会把load和CPU 使用率混淆,但其实这两者根本不是一回事。
- load,或者说average load,即单位时间内系统上所有处于Running 或 Runnable状态以及Uninterruptible Sleep 状态的进程的平均值。有点绕口,简单套个公式就是ps -eo pid,stat | grep -E “R|D” | wc -l / 单位时间,所以在看到load的时候,并没有单位,因为他就是个平均进程数而已。
补充一下PS的几个进程状态:
D 不可中断 R 正在运行,或在队列中的进程 S 处于休眠状态 T 停止或被追踪 Z 僵尸进程 W 进入内存交换(从内核2.6开始无效) X 死掉的进程< 高优先级 N 低优先级 L 有些页被锁进内存 s 包含子进程 + 位于后台的进程组 l 多线程,克隆线程
- cpu使用率,就是除了空闲时间外的其他时间占总CPU时间的百分比,时间片即CPU分配给各个程序的时间,每个线程被分配一个时间段,称作它的时间片,而Linux 作为一个多任务操作系统,将每个CPU的时间划分为很短的时间片,所以TOP 上看到经常超过100%的CPU 这种情况也就解答了,因为比如有4个CPU,假定程序绑定了多个CORE,则每个CORE原则上都会有该进程的时间片,所以这个进程可以承载的CPU可用时间就是4倍,所以CPU使用率最大当然可以到400%。
所以可以看出,CPU 和 LOAD 虽然都是在计算CPU的使用性能,但维度是不一样的,不可混为一谈。
上下文切换
其实日常TS经常有一些套路,然而套路用多了,大家也就不爱去看为啥这些套路为什么是套路了,举个例子,以前刚入行有个前辈和我说,CPU 一高看TOP,IOWAT高看磁盘,USER高看进程,SYS高看上下文切换。就很简单粗暴,当时只觉得前辈真牛逼,干个运维都能整出几句顺口溜,那为啥SYS 高了就是上下文切换的问题呢?可以先看下啥是上下文切换。
我们知道CPU 内部其实有个很小的寄存器,这个寄存器的作用说白了就是让CPU知道任务从哪里加载,又从哪里开始运行,而上下文切换就是不停的刷新这个寄存器,难道sys变高是服务器的寄存器坏了?其实不一定,因为上面提到的寄存器刷新操作忽略了一个不速之客,即硬件触发信号,也可以理解为系统调用(内核态对硬件的调用),由于系统调用的优先级非常高,所以会导致服务的用户态进程中断,然且这个情况往往是非常高的,举个简单的例子,我有一个简单的服务,从配置文件内拉取配置,然后执行程序,最后写入到日志里去,在这个过程中,一旦涉及到磁盘了,其实就是一个硬件触发信息,既系统调用。所以可以看到在这个过程中,CPU寄存器里的值经过了进程上下文保存->系统调用->恢复进程上下文->进程上下文保存->系统调用->恢复进程上下文,这就造成了频繁的上下文切换。
除此之外,进程太多也可能导致上下文切换,假设我们在一台服务器上跑了100个服务,每个服务又有100个线程,然而分给每个服务的CPU时间切片是一定的,那么在这种情况,一旦有进程耗尽了他所在的CPU时间切片,该进程就会被挂起,而CPU则会切换到其他进程继续执行。
排错思路
最后回顾问题,简单的CPU 飙高,大家一般只要TOP 一下即可看出个7788,但万一发现没啥进程CPU使用率高,iowait也不高,但就是sys奇高的情况下,可以按照以下方法套路一番:
- vmstat 一下
[root@192 ~]# vmstat 1procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu----- r b swpd free buff cache si so bi bo in cs us sy id wa st 2 0 0 726560 2108 134040 0 0 2 0 40 41 0 0 100 0 0 0 0 0 726560 2108 134040 0 0 0 0 49 45 0 0 100 0 0 0 0 0 726560 2108 134040 0 0 0 0 48 40 0 0 100 0 0 0 0 0 726560 2108 134040 0 0 0 0 53 54 0 0 100 0 0
- 按照套路套一下:
proc 的r 高表示CPU队列长,一般比CPU 核数多可能是进程抢资源导致
cpu 的sys 高表示cpu主要被内核占住了,结合上面的,大概率是系统调用太多 - 然后找异常进程:
[root@192 ~]# pidstat -wt -u 1Linux 3.10.0-862.el7.x86_64 (192.168.118.163) 10/27/2020 _x86_64_ (1 CPU)11:44:36 PM UID TGID TID %usr %system %guest %CPU CPU Command 11:44:37 PM 0 6563 - 0.00 0.98 0.00 0.98 0 pidstat 11:44:37 PM 0 - 6563 0.00 0.98 0.00 0.98 0 |__pidstat 11:44:36 PM UID TGID TID cswch/s nvcswch/s Command 11:44:37 PM 0 3 - 1.96 0.00 ksoftirqd/0 11:44:37 PM 0 - 3 1.96 0.00 |__ksoftirqd/0 11:44:37 PM 0 9 - 4.90 0.00 rcu_sched 11:44:37 PM 0 - 9 4.90 0.00 |__rcu_sched 11:44:37 PM 0 287 - 0.98 0.00 kworker/u256:3 11:44:37 PM 0 - 287 0.98 0.00 |__kworker/u256:3 11:44:37 PM 0 3348 - 9.80 0.00 vmtoolsd 11:44:37 PM 0 - 3348 9.80 0.00 |__vmtoolsd 11:44:37 PM 0 - 3923 0.98 0.00 |__gmain 11:44:37 PM 0 - 4551 0.98 0.00 |__tuned 11:44:37 PM 0 - 4361 0.98 0.00 |__in:imjournal 11:44:37 PM 0 6505 - 1.96 0.00 kworker/0:1 11:44:37 PM 0 - 6505 1.96 0.00 |__kworker/0:1 11:44:37 PM 0 6563 - 0.98 0.98 pidstat 11:44:37 PM 0 - 6563 0.98 0.98 |__pidstat
这时候只要找到哪个进程的cswch(自愿中断)和nvcswch(非自愿中断)比较高即可
如果cswch变多,说明进程都在等待自愿,可以往硬件,比如磁盘IO这里查一下
如果nvcswch变多, 说明进程都在被强制调动,也就是在争抢CPU,说明CPU的确成了瓶颈,那就该考虑扩容了