背景

Profiling 是指在代码级测量应用程序相关性能。Profiling 会捕捉 CPU 使用率,内存使用率,每个函数被调用的次数和时间,调用关系图等。需要知道的是,做 Profiling 会影响性能。

对比 Benchmarking,两者区别在于 Benchmarking 是在应用程序外部进行,并且测量的是实际性能:即你的终端用户会看到的结果。

在做 Profiling 之前,我们需要问两个问题:

  1. 我的应用是否有性能问题?如果有性能问题,那么你需要量化这个问题,然后再问自己
  2. 这个问题到底有多大?

如果不问这两个问题就做性能优化,那么就是盲目优化,除了浪费时间外没有任何意义。

为了判断应用是否有性能问题,我们需要明确对于应用的性能期望是什么样的。例如:100个并发访问的时候,响应时间小于1s。接下来我们需要做 Benchmarking,来确认应用程序是否满足我们的期望。对于 Benchmarking,常见的错误做法是在开发环境做测试,正确的做法应该是在和生产环境一样的硬件和软件环境下做。能用于 Benchmarking的工具很多,例如ab,siege,Jmeter,推荐使用 Jmeter。

一旦确定了我们的程序存在性能问题,那么就应该开始对代码做 Profiling,修复问题,重新再做 Benchmark,确定性能是否达到要求。

对代码的改动,每次应该只修改一处,然后做 Benchmark,因为代码改动有可能修复问题,但也有可能导致问题更严重,如果积累多处修改后再做测试,就无法定位到底是哪一处改动导致的。

对于 PHP 程序有 New Relic,Blackfire 这样的商用程序来做 Profiling,也有开源的方案,那就是 Facebook 开源的Xhprof,但目前 Facebook 已经停止更新。因此,另一家公司,Tideways 在 Xhprof fork 出来,继续开发,支持PHP 7,Tideways 是商业开源,其有自己炫酷UI,但是收费。不收费的 UI 也有,就是 Xhgui,本文就是讲如何利用 Tideways 和Xhgui 来给 PHP 程序做 Profiling。

在这里抛出一个问题:安装Tideways、Xhprof等扩展后代码改动会不会很大?

答:tideways.so扩展提供的监控方式是非侵入式的监控,不会对当前项目有任何的影响。

我们只需要在 Nginx 配置文件中加上一行配置即可:
fastcgi_param PHP_VALUE "auto_prepend_file=/etc/xhgui-branch/external/header.php";
代码的含义:在执行主程序前都运行我们指定的PHP脚本,这个地址是xhgui安装的路径

具体如何安装这个服务,我在文章的下半部分会详细说明。现在仅需要知道『非侵入式的监控』不用改动一行项目代码。

这个时候又会有一个问题:每个请求都生成日志会不会影响服务性能?

答:用户的每次请求都生成执行日志对服务性能会有轻微的影响。虽然tideways.so扩展提供的监控方式是非侵入式的,但对CPU和内存的消耗是不可忽略的。为了减少对内存和CPU的消耗,我们可以控制生成日志的频率,还能编写生成日志的规则。默认频率为1%(每100个请求生成1条日志,这里的概率非绝对)。
如果有多台服务器,只需要对一台进行监控,机器比较多的话可以每个机房一台。


搭建非侵入式性能监控分析环境

安装PHP mongodb扩展

pecl 是 PHP 的自带命令,全局如果找不到,请到 PHP 的安装目录bin下查看。如果你的 PHP 是集成安装的,没有 pecl 的话,请先安装 pecl(yum install php-devel php-pear),已安装的可直接运行命令:sudo pecl install mongodb

安装PHP tideaways扩展

tideaways 的文档写的非常详细,安装tideaways扩展(官方文档),这里我用Centos举例。

echo "[tideways]
name = Tideways
baseurl = https://s3-eu-west-1.amazonaws.com/qafoo-profiler/rpm" > /etc/yum.repos.d/tideways.repo
rpm --import https://s3-eu-west-1.amazonaws.com/qafoo-profiler/packages/EEB5E8F4.gpg
yum makecache --disablerepo=* --enablerepo=tideways
yum install tideways-php tideways-cli tideways-daemon

修改PHP.ini文件

我们需要在php.ini文件中引入扩展

[mongodb]
extension=mongodb.so
[tideways]
extension=tideways.so
;不需要自动加载,在程序中控制就行
tideways.auto_prepend_library=0
;频率设置为100,在程序调用时能改
tideways.sample_rate=100

下载安装xhgui

没安装 git 的先安装git(yum install git),已安装的可以直接下载 xhgui 包并安装

git clone https://github.com/laynefyc/xhgui-branch.git
#下载PHP composer,将xhgui的composer源改为中国镜像,因为国外的composer实在连不上
wget https://getcomposer.org/download/1.4.1/composer.phar
php composer.phar config repo.packagist composer https://packagist.phpcomposer.com
#然后进入git下来的xhgui目录进行安装
cd xhgui-branch
chmod -R 777 cache
php install.php

修改配置文件,如果你的 MongoDB 安装在当前机器可以不用修改 xhgui 的配置文件,否则你需要在配置文件中修改 MongoDB的连接ip和域名,路径如下(以你安装路径为准):xhgui-branch/config/config.default.php

return array(
    'debug' => false,
    'mode' => 'development',
   /*
    * support extension: uprofiler, tideways_xhprof, tideways, xhprof
    * default: xhprof
    */
    'extension' => 'xhprof',

    // Can be either mongodb or file.
    /*
    'save.handler' => 'file',
    'save.handler.filename' => dirname(__DIR__) . '/cache/' . 'xhgui.data.' . microtime(true) . '_' . substr(md5($url), 0, 6),
    */
    'save.handler' => 'mongodb',

    // Needed for file save handler. Beware of file locking. You can adujst this file path
    // to reduce locking problems (eg uniqid, time ...)
    //'save.handler.filename' => __DIR__.'/../data/xhgui_'.date('Ymd').'.dat',
    'db.host' => 'mongodb://127.0.0.1:27017',
    'db.db' => 'xhprof',

【可选,但建议做】

修改 mongodb 配置,加入index,可以提高性能,当前机器安装过 mongo 客户端才能调用 mongo 命令

$ 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 } )

配置Nginx

Nginx 需要加入两处配置,一是添加 PHP_VALUE,告诉 PHP 程序在执行前要调用服务(划重点):
fastcgi_param PHP_VALUE "auto_prepend_file=/etc/xhgui-branch/external/header.php";

另一个是需要配置一个路径指向安装的 xhgui 的 webroot 目录,如下配置是通过单独的域名来访问:

server {
    listen       80;
    server_name  192.168.100.2;
    root  /etc/xhgui-branch/webroot;
    location / {
        index  index.php;
        if (!-e $request_filename) {
            rewrite . /index.php last;
        }
    }
    location ~ \.php$ {
        fastcgi_pass   127.0.0.1:9001;
        fastcgi_index  index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include        fastcgi_params;
    }
}

好了,至此安装差不多告一段落。开始访问站点看看效果如何,结果报错,非常简单直接的报错了
错误信息:The Process class relies on proc_open, which is not available on your PHP installation.
是 proc_open 函数被禁止了,在 php.ini 中,找到 disable_functions 选项,看看后面是否有 proc_open 函数被禁用了,如果有的话,去掉即可。

其实如果php的文档熟悉的话,你应该马上就能知道 proc_open 实际上是一个函数,是php用来和shell交互的函数,一般这种可以直接作用于操作系统的函数是非常不安全的,对于这种不安全的函数,总是要做一些措施来进行保护

在 php.ini 的配置中,找到 disable_functions 选项,这个选项就是专门用来禁止某些不安全函数的,尤其在命令行运行时,很可能对操作系统带来安全隐患

好了,折腾了这么久,最最最最后一步,重启nginx,php-fpm,mongodb。

访问

xhgui

最后修改:2020 年 02 月 05 日 01 : 29 PM
如果觉得我的文章对你有用,请随意赞赏