业务背景
框架及相应环境
-
laravel5.7, mysql5.7, redis5, nginx1.15
-
ce*本文来源gaodai#ma#com搞@代~码^网+搞代gaodaima码ntos 7.5 bbr
-
docker, docker-compose
-
阿里云 4C和8G
问题背景
php已经开启opcache, laravel也运行了optimize命令进行优化, composer也进行过dump-autoload命令.
首先需要声明的是, 系统的环境中是一定有小问题的(没有问题也不可能能够提升如此大的性能), 但是这些问题, 如果不通过使用合适的工具, 可能一辈子也发现不出来.
本文关注的就是如何发现这些问题, 以及发现问题的思路.
我们首先找到系统中一个合适的API或函数, 用来放大问题.
这个api设计之初是给nginx负载均衡做健康检查的.使用ab -n 100000 -c 1000 进行压测, 发现qps只能到140个每秒.
我们知道Laravel的性能是出了名的不好, 但是也不至于到这个程度, 从api的编写来看不应该这么低. 所以决定一探究竟.
public function getActivateStatus() { try { $result = \DB::select('select 1'); $key = 1; if ($result[0]->$key !== 1) { throw new \Exception("mysql 检查失败"); } } catch (\Exception $exception) { \Log::critical("数据库连接失败: {$exception->getMessage()}", $exception->getTrace()); return \response(null, 500); } try { Cache::getRedis()->connection()->exists("1"); } catch (\Exception $exception) { \Log::critical("缓存连接失败: {$exception->getMessage()}", $exception->getTrace()); return \response(null, 500); } return \response(null, 204); }
问题表现以及排查思路
top
top命令发现系统CPU占用100%其中用户态占80%, 内核态占20%, 看起来没什么大问题. 有一个地方看起来很奇怪,top命令的运行结果
就是有一部分php-fpm进程处在Sleep状态, 但CPU占用还是达到了近30%.当一个进程处于Sleep状态的时候, 任然占用了不少CPU, 先不要怀疑是不是进程的问题, 我们看一下Ttop命令的man page.
%CPU -- CPU usageThe task's share of the elapsed CPU time since the last screen update, expressed as a percentage of total CPU time.
大致意思是这个占用是最后一次屏幕刷新的时候, 进程CPU的占用. 由于top命令收集信息的时候, 可能linux把这个进程强制调度了 ( 比如用于top收集进程信息 ), 所以在这一瞬间(屏幕刷新的这一瞬间)某些php-fpm进程处于sleep状态, 可以理解, 所以应该不是php-fpm的问题.
pidstat
首先选出一个php-fpm进程, 然后使用pidstat查看进程详细的运行情况
过程中也没发现什么异样, 并且和top命令的运行结果也基本一致.
vmstat
保持压测压力, 运行vmstate查看, 除了context switch (上下文切换)有点高之外, 并没有看到太多异常.由于我们使用的docker, redis, mysql都运行在同一台机器上, 7000左右的CS还是一个合理的范围, 但是这个IN(中断)就有点太高了, 达到了1.4万左右. 一定有什么东西触发了中断.