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。