性能分析小案例系列,可以通过下面链接查看哦

https://www.cnblogs.com/poloyy/category/1814570.html

 

系统架构背景

  • VM1:用作 Web 服务器,来模拟性能问题
  • VM2:用作 Web 服务器的客户端,来给 Web 服务增加压力请求
  • 使用两台虚拟机(均是 Ubuntu 18.04)是为了相互隔离,避免交叉感染

 

VM2 运行 ab 命令,初步观察 Nginx 性能

简单介绍 ab 命令

  • ab(apache bench)是一个常用的 HTTP 服务性能测试工具
  • 可以向目标服务器并发发送请求

 

运行 ab 命令

并发 10 个请求测试 VM1 的 Nginx 性能,总共测试 100 个请求

ab -c 10 -n 10 http://172.20.72.58:10000/

从 ab 的输出结果可以看到,Nginx 能承受的每秒平均请求数只有 14.73(这也太辣鸡了吧)

 

那到底是哪里出了问题呢

接下来,我们将通过一系列的命令来观察哪里出问题了

 

深入分析

VM2 长时间运行 ab 命令

并发 10 个请求测试 VM1 的 Nginx 性能,总共测试 10000 个请求

ab -c 10 -n 10000 http://172.20.72.58:10000/

 

VM1 终端运行 top 命令

输入后,按1,查看每个 CPU 的使用率

结果分析

  • 系统中有几个 php-fpm 进程的 CPU 使用率加起来接近 200%
  • 而每个 CPU 的用户使用率(us)也已经超过了 96%,接近饱和
  • 结论:正是用户空间的 php-fpm 进程,导致 CPU 使用率骤升

 

分析 php-fpm 进程到底是因为哪个函数导致了 CPU 使用率升高

在 VM1 终端运行 perf 命令

perf record -g -p 84408
  • record:录制的意思
  • -g:开启调用关系分析
  • -p:指定 php-fpm 的进程号84408

 

录制约 30s 后,ctrl+c 终止进程,然后可以在当前目录下看到 perf.data 文件

 

然后执行下面命令,分析报告(perf.data)

perf report

 

按方向键可上下切换,有+的按回车键可以展开

结果分析

最终是关系到 sqrtadd_function 这两个函数

 

查看 Nginx 应用的源码,找到问题根源

找到 sqrt 函数

grep sqrt -r app/

原来只有 sqrt 函数在 app/index.php 文件中调用了

 

找到 add_function 函数

grep add_function -r app/

会发现找不到,因为 add_function 是 PHP 内置函数

 

查看 index.php 源码

<?php
// test only.
$x = 0.0001;
for ($i = 0; $i <= 1000000; $i++) {
  $x += sqrt($x);
}

echo "It works!"

可以看到,这里有一个循环很多次的代码段

 

解决方法

找到问题的根源,就可以快速解决了,删除循环代码块

<?php

echo "It works!"

 

perf 拓展

其实有一条命令更方便查看函数

perf top -g -p 84408

那为啥我要用 perf record 然后再用 perf report 呢

因为如果没有 perf 源码的话,是无法读取到 php 的函数,只会显示一堆十六进制码

 

修复问题后,验证 Nginx 性能是否有所变化

VM2 终端再次运行 ab 命令

ab -c 10 -n 10000 http://172.20.72.58:10000/

结果分析

每秒请求数突飞猛进的升到 2500,比之前的 14 好多了

 

分析整体思路

  1. 使用 ab 短时间压测,发现服务器性能低下,TPS 比较低
  2. 使用 ab 长时间压测,让服务器保持一个高负载的状态,方便排查问题
  3. 通过 top 命令监控系统资源情况,发现用户态的 CPU 使用率(us)很高,且进程列表中发现几个进程的 CPU 使用率特别高,都是同一个 php 进程
  4. 通过 perf record 命令录制进程一段时间
  5. 通过 perf report 查看录制进程的结果数据,可以分析 php-fpm 进程到底是哪个函数导致 CPU 使用率高
  6. 找到 add_function、sqrt 函数
  7. 通过 grep 命令确认函数是在 index.php 代码文件中
  8. 查看 index.php 文件的源码,确认问题代码块
  9. 删除问题代码块,重新压测,每秒平均请求数有了质的飞升,成功解决问题