CPU负载与CPU占用率
uptime
, m
, top
几个命令查看load average
cat /proc/cpuinfo
查看CPU相关信息,核心数等等
[root@VM_0_11_centos ~]# uptime
11:10:26 up 762 days, 20:29, 1 user, load average: 0.19, 0.18, 0.22
CPU平均负载指的是一段时间内处于可运行状态和不可中断状态的平均进程数(R状态和D状态),比如上面的uptime命令输出结果就是1分钟、5分钟、15分钟分别有平均0.19, 0.18, 0.22个进程处于可运行状态或不可中断状态的进程。
不可中断是进程处于内核态的关键流程阶段,比如正向磁盘写数据,这时候中断会出现数据不一致的问题。
如果负载超过核数,那么进程就会排队执行了。
平均负载超过cpu核数70%的话就要注意过载的风险了。
而CPU使用率就是当前CPU的使用占比了,被运行中的进程占用的情况。
1、负载高、使用率低
因为负载体现的是进程处于可运行或不可中断状态,所以这里出了运行中的进程体现在CPU使用率上之外,还有Runnable等待运行状态,以及不可中断状态。
所以负载高,使用率不一定高。出现这种情况需要去排查一下iostat,看看哪些进程。
2、负载低、使用率高
负载低说明这时候同时执行的进程不多,使用率高说明这少数的几个进程中可能有1个进程一直占着CPU用,通常发生在所谓CPU密集型应用里,大量的计算型任务。服务没问题的话一般会降下去的。
Linux进程状态
ps -aux
, ps -axjf
都是可以查看进程的状态的,Linux进程状态比较常见的是如下几个:
R状态 ,可执行状态 TASK_RUNNING ,进程的task_struct已经进入某个cpu的可执行队列了、等待进程调度并执行。 R状态包括Running和Runnable两种情况。
S状态 , 可中断的睡眠状态TASK_INTERRUPTIBLE,task_struct已经进入某事件的等待队列被挂起,当事件发生则会被中断或其他进程唤醒。比如等待socket事件、等待信号量等等。
D状态 , 不可中断的睡眠状态TASK_UNINTERRUPTIBLE,内核的某些处理阶段不可以被打断,比如等待硬件设备的 I/O 响应,read设备文件的通过驱动读取硬件的阶段,如果被打断会引发数据不一致的问题。处于这个状态的进程是不响应异步信号的(但响应硬件中断),所以kill -9是无效的。
-
T状态 , 进程处于暂停或被跟踪状态,TASK_STOPPED和TASK_TRACED,向进程发送SIGSTOP信号会使得其进入TASK_STOPPED,然后发送SIGCONT则可以使进程从TASK_STOPPED恢复为TASK_RUNNING状态。
笔者曾经遇到过线上jmap -heap导致进程状态变T了,最后用kill -CONT恢复了进程)
Z状态 , 僵尸进程,进程退出时资源被回收,但会保留task_struct等待父进程回收,这时候就是Z状态。
如何排查CPU 100%问题
top -Hp pid
找到cpu占用高的进程中哪个线程cpu占用最高,
printf "0x%x\n" 线程ID
,得到线程ID的16进制,
然后 jstack pid | grep 线程ID的16进制 -C5 --color
,就可以找到线程栈信息并据此进行分析了。
笔者之前用这个办法定位了一个问题,测试环境的一个tomcat(jdk7)响应非常慢,CPU 100%,最后找到jstack中CPU忙于执行的是一个GC线程,然后查看JVM内存使用情况,最后发现是perm space永久代占用已经99%,通过调整catalina.sh中的配置调大了永久代解决。
平均负载与CPU使用率的关联
平均负载是指单位时间内,处于可运行状态和不可中断状态的进程数。所以,它不仅包括了正在使用 CPU 的进程,还包括等待 CPU 和等待 I/O 的进程。
CPU 密集型进程,使用大量 CPU 会导致平均负载升高,此时这两者是一致的;
I/O 密集型进程,等待 I/O 也会导致平均负载升高,但 CPU 使用率不一定很高;
大量等待 CPU 的进程调度也会导致平均负载升高,此时的 CPU 使用率也会比较高。
案例模拟
stress -c 4 --timeout 600
使用stress压测工具模拟4个进程并行的情况,笔者这台虚机只有1个cpu,所以将处于严重过载状态:
watch -d uptime #每隔2秒更新输出uptime结果
可以看到平均负载已经快上天了。。。
再top看看详细情况:
负载高,CPU使用率也高,然后可以看到是4个stress进程争用CPU。
再用pidstat看看进程性能:
pidstat -u 5 1
可以看出,4 个stress进程在争抢 1 个 CPU,每个进程等待 CPU 的时间( %wait 列)高达 75%。这些超出 CPU 计算能力的进程,最终导致 CPU 过载。
注:如果sysstat的版本比较低,推荐升级到最新版本
[root@VM_0_11_centos ~]# pidstat -V
sysstat version 10.1.5
升级一下,下载sysstat源码之后
cd sysstat
./configure
make
sudu make install
环境变量要添加一下,不然这时候相关命令默认还是会去用原来的旧版本
vi /etc/profile
export PATH=/root/sysstat/:$PATH #把sysstat的安装目录追加到PATH
source /etc/profile #使环境变量生效
[root@VM_0_11_centos sysstat]# pidstat -V
sysstat version 12.5.1
(C) Sebastien Godard (sysstat <at> orange.fr)
升级成功。