重新认识CPU飙高

只要是玩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的确成了瓶颈,那就该考虑扩容了

上一篇:pm.inc


下一篇:4组-Beta冲刺-2/5