对于生产环境下php响应缓慢的问题,一般我们可以把分析流程拆分为如下几步操作:

1.分析开发环境下执行是否会慢;

如果是代码问题,在开发环境下就能检测出来;

2.分析测试机器执行是否会慢;

如果是数据库或者第三方扩展问题,在测试阶段就能检查出来。

3.从生产环境下线一台机器,分析代码执行慢的原因;

如果是机器的问题,在这一步才能检查出来。

1,2,3步骤都需要去分析代码,看哪部分执行时间长。如果迫不得已在生产环境下调试代码,不但要耗费大量时间还可能导致用户流失。

大多时候我们会使用第三方的分析工具xhprof来快速发现问题。‌‌xhprof是由facebook开发的一款非侵入式php性能分析框架。但是官方已经不在维护,也没有跟进php7,只能在php5上运行,tideways则是一直由商业公司在xhprof停止维护后fork出的版本,开源在Github上(托管服务需付费,自行搭建免费),支持PHP7。‌‌显而易见,tideways是我们的选择。

tideways扩展能把每条请求生成详细的执行日志,通过对日志做简单的分析就能看到程序哪部分耗时最长,这里可以使用xhprof的UI程序(xhprof生成的日志和tideways生成的日志格式通用),交互虽然不大友好但是够用了。‌‌当然,也可按照本文介绍使用xhgui来进行可视化的分析。

先决条件

本文部署所用环境为Ubuntu 18.04 LTS,其它环境请自行研究类似的配置。

安装Tideways

由于部署环境php采用编译安装,故Tideways也采用编译安装。‌‌如果采用apt安装,也可以直接使用apt安装php-tideways。‌‌还可以使用pecl安装,具体方法不详细讲了。

‌                              git clone https://github.com/tideways/php-xhprof-extension  cd php-xhprof-extension phpize ./configure make make install //sudo make install if not root

配置php.ini,加入

‌                              extension=tideways_xhprof.so tideways.auto_prepend_library=0 //optional

注意最好加上后面那行,因为如果不加,tideways会调试所有经过php-fpm的请求,包括xhgui的请求,而这些请求不是我们想看的。

安装xhgui

其实xhgui就是一个网站程序,建过站的同学都知道大概怎么回事,只不过数据库换用了mongodb而已。

安装mongodb

因为xhgui需要储存由tideways传入的信息,所以需要安装mongodb。‌‌另有人维护了一个mysql版本的xhgui,如果不喜欢mongodb可以换用。‌‌部署环境使用了oneinstack安装lnmp栈,所以也使用oneinstack安装mongodb

‌                              wget http://mirrors.linuxeye.com/oneinstack.tar.gz tar zxf oneinstack.tar.gz cd oneinstack ./install.sh // sudo install.sh if not root

按照提示交互式安装mongodb就行了。‌‌如果你不想这么麻烦或者非生产环境部署,也可以直接使用apt安装:apt install mongodb

如果没有在php中加入mongodb扩展,则需继续安装mongodb扩展。git clone https://github.com/mongodb/mongo-php-driver.git cd mongo-php-driver git submodule update --init phpize ./configure make make install // add sudo if not root

同样地,在php.ini中添加extension=mongodb.so

官方基于性能建议我们为mongodb添加索引

$ mongo > use xhprof > db.results.ensureIndex( { 'meta.SERVER.REQUEST_TIME' : -1 } ) > db.results.ensureIndex( { 'profile.main().wt' : -1 } ) > db.results.ensureIndex( { 'profile.main().mu' : -1 } ) > db.results.ensureIndex( { 'profile.main().cpu' : -1 } ) > db.results.ensureIndex( { 'meta.url' : 1 } ) > db.results.ensureIndex( { 'meta.simple_url' : 1 } )

至此mongodb算是安装完毕。‌‌注意生产环境安装还需要为mongodb配置访问权限,此处不详细讨论了。

下载xhgui

‌                              git clone https://github.com/perftools/xhgui

代码下载完以后上传到网站目录,具体操作因环境而异,若不熟悉请先熟悉lnmp架构。‌‌上传完后执行

‌                              php <wwwroot>/install.php

配置Nginx

假设我们需要调试的网站位于dev.fqdn‌‌而xhgui位于xhgui.fqdn

则需要在dev.fqdn配置文件的location段加入

‌                              fastcgi_param PHP_VALUE "auto_prepend_file=/<wwwroot of xhfui.fqdn>/xhgui/external/header.php";

此配置的作用是在dev.fqdn下的每个php经过fastcgi的时候自动在开头加入这个xhgui/external/header.php‌‌而这个文件的作用是运行你的代码前调用tideways开启调试‌‌你的代码运行完毕后结束调试并把结果传入mongodb等待查看。

xhgui.fqdn配置则是正常php网站的配置,不赘述了。‌‌注意需有这一行

‌                              location / {     try_files $uri $uri/ /index.php?$args; }

配置tideways

tideways的配置文件位于/config/config.php‌‌安装时这个文件不存在,故需要把默认配置复制到这个文件

‌                              cp <wwwroot>/config/config.default.php <wwwroot>/config/config.php

除了mongodb链接配置(一般无需调整)‌‌主要关注这一个回调函数

‌                              // In config/config.php return array(     // Other config     'profiler.enable' => function() {         return rand(1, 100) === 42;     } );

默认配置的此函数仅仅做了节流,截取1%的流量进行分析。这是基于生产环境的性能考虑,如果我们仅仅是在开发环境中使用,就不需要管这么多了。‌‌例如

‌                              // In config/config.php return array(     // Other config     'profiler.enable' => function() {         return true;     } );

这个配置就会把所有流量全部截取分析。‌‌令人哭笑不得的是,这所有流量包括了xhgui.fqdn的流量,这显然不是我们想要分析的。‌‌还有的时候我们也不想看到dev.fqdn中管理界面的流量,这就需要一些进阶配置了。‌‌例如

‌                              'profiler.enable' => function() {         $url = $_SERVER['SERVER_NAME'].$_SERVER['REQUEST_URI'];         if (strpos($url, 'dev.fqdn/admin') === 0) {             return false;         } elseif (strpos($url, 'dev.kucloud.win') === 0) {             return true;         }         return false;     },

这样一来就只会看到我们希望分析的请求了。

参考:‌‌

phperzh‌‌

Xhgui

Readme