06 | 系统的 CPU 使用率很高,但为啥却找不到高 CPU 的应用?

134 阅读2分钟

1. 案例

环境准备:

  • 机器配置:2 CPU,8GB 内存
  • 预先安装 docker、sysstat、perf、ab 等工具,如 apt install docker.io sysstat linux-tools-common apache2-utils

这个案例要用到两台虚拟机,如下图所示:

VM 1执行

docker stop nginx
docker rm nginx
docker stop phpfpm
docker rm phpfpm

$ docker run --name nginx -p 10000:80 -itd feisky/nginx:sp
$ docker run --name phpfpm -itd --network container:nginx feisky/php-fpm:sp

VM 2执行

# 172.23.28.83是第一台虚拟机的IP地址
$ curl http://172.23.28.83:10000/
It works!

VM 2执行

# 并发100个请求测试Nginx性能,总共测试1000个请求
$ ab -c 100 -n 1000 http://172.23.28.83:10000/
This is ApacheBench, Version 2.3 <$Revision: 1706008 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, 
...
Requests per second:    87.86 [#/sec] (mean)
Time per request:       1138.229 [ms] (mean)
...

Nginx 能承受的每秒平均请求数,只有 170+。

继续VM 2执行、且把并行改为5,执行持续时间改成10分钟

$ ab -c 5 -t 600 http://172.23.28.83:10000/

VM 1执行

$ top
top - 12:27:22 up 11:24,  4 users,  load average: 0.95, 0.21, 0.07
Tasks: 141 total,   6 running,  87 sleeping,   0 stopped,   0 zombie
%Cpu0  : 73.2 us, 19.9 sy,  0.0 ni,  5.3 id,  0.0 wa,  0.0 hi,  1.7 si,  0.0 st
%Cpu1  : 73.2 us, 20.1 sy,  0.0 ni,  5.0 id,  0.0 wa,  0.0 hi,  1.7 si,  0.0 st
KiB Mem :  8070116 total,   381384 free,  6343008 used,  1345724 buff/cache
KiB Swap:  4194300 total,  4170224 free,    24076 used.  1435776 avail Mem

  PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND
20943 systemd+  20   0   33104   3864   2440 R   4.0  0.0   0:00.75 nginx
24187 daemon    20   0  336696  15932   8260 S   3.3  0.2   0:00.43 php-fpm
24177 daemon    20   0  336696  15800   8128 S   3.0  0.2   0:00.43 php-fpm
24178 daemon    20   0  336696  15780   8108 S   2.7  0.2   0:00.42 php-fpm
24188 daemon    20   0  336696  15932   8260 S   2.7  0.2   0:00.41 php-fpm
20877 root      20   0  712488  10052   7792 S   2.3  0.1   0:00.63 containerd-shim
24200 daemon    20   0  336696  15932   8260 S   2.3  0.2   0:00.41 php-fpm
20020 root      20   0 1563880  72992  49920 S   1.7  0.9   0:15.22 dockerd
   16 root      20   0       0      0      0 S   0.3  0.0   0:00.20 ksoftirqd/1
21099 root      20   0  336312  47524  40128 S   0.3  0.6   0:00.21 php-fpm
31639 daemon    20   0    8192   1636    556 R   0.3  0.0   0:00.01 stress
 .....

user CPU使用率非常高

# 间隔1秒输出一组数据(按Ctrl+C结束)
$ pidstat 1
...
04:36:24      UID       PID    %usr %system  %guest   %wait    %CPU   CPU  Command
04:36:25        0      6882    1.00    3.00    0.00    0.00    4.00     0  docker-containe
04:36:25      101      6947    1.00    2.00    0.00    1.00    3.00     1  nginx
04:36:25        1     14834    1.00    1.00    0.00    1.00    2.00     0  php-fpm
04:36:25        1     14835    1.00    1.00    0.00    1.00    2.00     0  php-fpm
04:36:25        1     14845    0.00    2.00    0.00    2.00    2.00     1  php-fpm
04:36:25        1     14855    0.00    1.00    0.00    1.00    1.00     1  php-fpm
04:36:25        1     14857    1.00    2.00    0.00    1.00    3.00     0  php-fpm
04:36:25        0     15006    0.00    1.00    0.00    0.00    1.00     0  dockerd
04:36:25        0     15801    0.00    1.00    0.00    0.00    1.00     1  pidstat
04:36:25        1     17084    1.00    0.00    0.00    2.00    1.00     0  stress
04:36:25        0     31116    0.00    1.00    0.00    0.00    1.00     0  atopacctd
...

pidstat命令没有发现异常,CPU使用率非常低。

回头分析TOP命令,发现task为running状态的进程有6个,但是在下方我们又可以看到大部分的进程状态都是S(Sleep)。

继续使用pidstat分析

pidstat -p 24178

继续观察top命令的IPD会发现,PID一直在变化。

进程ID不断变化,一般有两种情况

  • 短时进程
  • 进程在不断地崩溃重启

用 pstree 就可以用树状形式显示所有进程之间的关系

$ pstree | grep stress
        |-docker-containe-+-php-fpm-+-php-fpm---sh---stress
        |         |-3*[php-fpm---sh---stress---stress]

# 记录性能事件,等待大约15秒后按 Ctrl+C 退出
$ perf record -g

# 查看报告
$ perf report

# 一起执行
perf record -ag -- sleep 10;perf report

stress确实是元凶。具体原因需要进一步分析代码。

清理实验环境

$ docker rm -f nginx phpfpm

目前为止,我们使用了top、pidstat、pstree等工具比较复杂的分析了整个过程,那么对于短时进程其实有专门的分析工具,execsnoop