某个应用的CPU使用率居然达到100%,我该怎么办?[size=; font-size: 1.059em,1.059em]分析过程
- 使用观察系统CPU使用情况(并按下数字 1 ,切换到每个 CPU 的使用率)
$ top...%Cpu0 : 98.7 us, 1.3 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st%Cpu1 : 99.3 us, 0.7 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st...PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND21514 daemon 20 0 336696 16384 8712 R 41.9 0.2 0:06.00 php-fpm21513 daemon 20 0 336696 13244 5572 R 40.2 0.2 0:06.08 php-fpm21515 daemon 20 0 336696 16384 8712 R 40.2 0.2 0:05.67 php-fpm21512 daemon 20 0 336696 13244 5572 R 39.9 0.2 0:05.87 php-fpm21516 daemon 20 0 336696 16384 8712 R 35.9 0.2 0:05.61 php-fpm这里可以看到,系统中有几个 php-fpm 进程的 CPU 使用率加起来接近 200%;而每个 CPU 的用户使用率(us)也已经超过了 98%,接近饱和。这样,我们就可以确认,正是用户空间的 php-fpm 进程,导致 CPU 使用率骤升# -g开启调用关系分析,-p指定php-fpm的进程号21515$ perf top -g -p
21515按方向键切换到 php-fpm,再按下回车键展开 php-fpm 的调用关系,你会发现,调用关系最终到了 sqrt 和 add_function
[size=; font-size: 1.059em,1.059em]总结
CPU 使用率是最直观和最常用的系统性能指标,更是我们在排查性能问题时,更要熟悉它每个指标的的含义,尤其要弄清楚用户(%user)、Nice(%nice)、系统(%system) 、等待 I/O(%iowait) 、中断(%irq)以及软中断(%softirq)这几种不同 CPU 的使用率。比如说:- 用户 CPU 和 Nice CPU 高,说明用户态进程占用了较多的 CPU,所以应该着重排查进程的性能问题。
- 系统 CPU 高,说明内核态占用了较多的 CPU,所以应该着重排查内核线程或者系统调用的性能问题。
- I/O 等待 CPU 高,说明等待 I/O 的时间比较长,所以应该着重排查系统存储是不是出现了 I/O 问题。
- 软中断和硬中断高,说明软中断或硬中断的处理程序占用了较多的 CPU,所以应该着重排查内核中的中断服务程序。
碰到 CPU 使用率升高的问题,你可以借助 top、pidstat 等工具,确认引发 CPU 性能问题的来源;再使用 perf 等工具,排查出引起性能问题的具体函数。系统的 CPU 使用率很高,但为啥却找不到高 CPU 的应用?[size=; font-size: 1.059em,1.059em]分析过程
$ top...%Cpu(s): 80.8 us, 15.1 sy, 0.0 ni, 2.8 id, 0.0 wa, 0.0 hi, 1.3 si, 0.0 st...PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND6882 root 20 0 8456 5052 3884 S 2.7 0.1 0:04.78 docker-containe6947 systemd+ 20 0 33104 3716 2340 S 2.7 0.0 0:04.92 nginx7494 daemon 20 0 336696 15012 7332 S 2.0 0.2 0:03.55 php-fpm7495 daemon 20 0 336696 15160 7480 S 2.0 0.2 0:03.55 php-fpm10547 daemon 20 0 336696 16200 8520 S 2.0 0.2 0:03.13 php-fpm10155 daemon 20 0 336696 16200 8520 S 1.7 0.2 0:03.12 php-fpm10552 daemon 20 0 336696 16200 8520 S 1.7 0.2 0:03.12 php-fpm15006 root 20 0 1168608 66264 37536 S 1.0 0.8 9:39.51 dockerd4323 root 20 0 0 0 0 I 0.3 0.0 0:00.87 kworker/u4:1通过以上输出分析
- 系统的整体 CPU 使用率是比较高的: 用户CPU到了80%,系统CPU为15.1%,空闲CPU只有2.8%。(用户CPU使用率高,肯定是有用户进程占用CPU导致)
- CPU 使用率最高的进程也只不过才 2.7%,并不高
- 观察进程状态发现:Nginx 和所有的 php-fpm 都处于 Sleep(S)状态,而真正处于 Running(R)状态的,却是几个 stress 进程
# 使用 -p 选项指定stress进程的 PID$ pidstat -p
2434416:
14:
55 UID PID %usr %system %guest %wait %CPU CPU Command
没有任何输出。
现在终于发现问题,原来这个进程已经不存在了,所以 pidstat 就没有任何输出,而且从top的输出我们看到stress的PID一直在变化,出现这种情况的无非就两个原因:- 第一个原因,进程在不停地崩溃重启,比如因为段错误、配置错误等等,这时,进程在退出后可能又被监控系统自动重启了。
- 第二个原因,这些进程都是短时进程,也就是在其他应用内部通过 exec 调用的外面命令。这些命令一般都只运行很短的时间就会结束,你很难用 top 这种间隔时间比较长的工具发现(上面的案例,我们碰巧发现了)。
$ pstree | grep stress|-docker-containe-+-php-fpm-+-php-fpm---sh---stress| |-
3*[php-fpm---sh---stress---stress]
从这里可以看到,stress 是被 php-fpm 调用的子进程,并且进程数量不止一个(这里是 3 个),接下来就是去看php-fpm的内部代码逻辑了,不在展开- 使用perf继续分析下stress的cpu占用函数
# 记录性能事件,等待大约15秒后按 Ctrl+C 退出$ perf record -g
# 查看报告$ perf report

perf输出分析:
- stress 占了所有 CPU 时钟事件的 77%,而 stress 调用调用栈中比例最高的,是随机数生成函数 random(),看来它的确就是 CPU 使用率升高的元凶了。
[size=; font-size: 1.059em,1.059em]总结
碰到常规问题无法解释的 CPU 使用率情况时,首先要想到有可能是短时应用导致的问题,比如有可能是下面这两种情况。- 第一,应用里直接调用了其他二进制程序,这些程序通常运行时间比较短,通过 top 等工具也不容易发现。
- 第二,应用本身在不停地崩溃重启,而启动过程的资源初始化,很可能会占用相当多的 CPU。
对于短时进程,我们可以通过pstree命令
找到它们的父进程,再从父进程所在的应用入手,排查问题的根源