ThinkChat🤖让你学习和工作更高效,注册即送10W Token,即刻开启你的AI之旅 广告
## 参考来源: https://www.cnblogs.com/qq78292959/p/4034359.html php-fpm的安装很简单,参见[PHP(PHP-FPM)手动编译安装](http://blog.csdn.net/dc_726/article/details/9519619)。下面主要讨论下如何提高Nginx+Php-fpm的性能。 **1.Unix域Socket通信** 之前简单介绍过Unix Domain Socket这种通信方式,参见:[Nginx+PHP-FPM的域Socket配置方法](http://blog.csdn.net/dc_726/article/details/9336193) Unix域Socket因为不走网络,的确可以提高Nginx和php-fpm通信的性能,但在高并发时会不稳定。 Nginx会频繁报错:      connect() to unix:/dev/shm/php-fcgi.sock failed (11: Resource temporarily unavailable) while connecting to upstream 可以通过下面两种方式提高稳定性: 1)调高nginx和php-fpm中的backlog      配置方法为:在nginx配置文件中这个域名的server下,在listen 80后面添加default backlog=1024。      同时配置php-fpm.conf中的listen.backlog为1024,默认为128。 2)增加sock文件和php-fpm实例数      再新建一个sock文件,在Nginx中通过upstream模块将请求负载均衡到两个sock文件背后的两套php-fpm实例上。 * * * **2.php-fpm参数调优** **2.1进程数** php-fpm初始/空闲/最大worker进程数      pm.max\_children = 300      pm.start\_servers = 20      pm.min\_spare\_servers = 5      pm.max\_spare\_servers = 35 **2.2最大处理请求数** 最大处理请求数是指一个php-fpm的worker进程在处理多少个请求后就终止掉,master进程会重新respawn一个新的。 这个配置的主要目的是避免php解释器或程序引用的第三方库造成的内存泄露。      pm.max\_requests = 10240 **2.3最长执行时间** 最大执行时间在php.ini和php-fpm.conf里都可以配置,配置项分别为max\_execution\_time和request\_terminate\_timeout。 其作用及其影响参见:[Nginx中502和504错误详解](http://blog.csdn.net/dc_726/article/details/11950189) * * * **3.php-fpm的高CPU使用率排查方法** **3.1CPU使用率监控方法** 1)top命令 直接执行top命令后,输入1就可以看到各个核心的CPU使用率。而且通过top -d 0.1可以缩短采样时间。 下面的sar貌似最短只能是1秒。 2)sar命令 sar和iostat命令的安装:      sysstat.x86\_64 : The sar and iostat system monitoring commands      yum install -y sysstat.x86\_64 执行sar -P ALL 1 100。-P ALL表示监控所有核心,1表示每1秒采集,100表示采集100次。 输出结果如下: `CPU     %user     %nice   %system   %iowait    %steal     %idle` `all     85.54      0.00      5.69      0.00      0.00      8.76` `0     74.75      0.00     25.25      0.00      0.00      0.00` `1     98.00      0.00      2.00      0.00      0.00      0.00` `2     89.22      0.00      3.92      0.00      0.00      6.86` `3     91.00      0.00      2.00      0.00      0.00      7.00` `4     75.00      0.00      9.00      0.00      0.00     16.00` `5     94.95      0.00      5.05      0.00      0.00      0.00` `6     95.00      0.00      4.00      0.00      0.00      1.00` `7     87.88      0.00      4.04      0.00      0.00      8.08` `8     93.94      0.00      3.03      0.00      0.00      3.03` `9     88.00      0.00      3.00      0.00      0.00      9.00` `10     89.11      0.00      2.97      0.00      0.00      7.92` `11     82.35      0.00      3.92      0.00      0.00     13.73` `12     73.27      0.00      7.92      0.00      0.00     18.81` `13     81.44      0.00      4.12      0.00      0.00     14.43` `14     77.23      0.00      6.93      0.00      0.00     15.84` `15     78.79      0.00      4.04      0.00      0.00     17.17` **3.2开启慢日志** 配置输出php-fpm慢日志,阀值为2秒: > request\_slowlog\_timeout = 2 > slowlog = log/$pool.log.slow 利用sort/uniq命令分析汇总php-fpm慢日志: `[root@b28-12 log]# grep -v "^$" www.log.slow.tmp | cut -d " " -f 3,2 | sort | uniq -c | sort -k1,1nr | head -n 50` `5181 run() /www/test.net/framework/web/filters/CFilter.php:41` `5156 filter() /www/test.net/framework/web/filters/CFilterChain.php:131` `2670 = /www/test.net/index.php` `2636 run() /www/test.net/application/controllers/survey/index.php:665` `2630 action() /www/test.net/application/controllers/survey/index.php:18` `2625 run() /www/test.net/framework/web/actions/CAction.php:75` `2605 runWithParams() /www/test.net/framework/web/CController.php:309` `2604 runAction() /www/test.net/framework/web/filters/CFilterChain.php:134` `2538 run() /www/test.net/framework/web/CController.php:292` `2484 runActionWithFilters() /www/test.net/framework/web/CController.php:266` `2251 run() /www/test.net/framework/web/CWebApplication.php:276` `1799 translate() /www/test.net/application/libraries/Limesurvey_lang.php:118` `1786 load_tables() /www/test.net/application/third_party/php-gettext/gettext.php:254` `1447 runController() /www/test.net/framework/web/CWebApplication.php:135` 参数解释:      sort:  对单词进行排序      uniq -c:  显示唯一的行,并在每行行首加上本行在文件中出现的次数      sort -k1,1nr:  按照第一个字段,数值排序,且为逆序      head -10:  取前10行数据 **3.3用strace跟踪进程** 1)利用nohup将strace转为后台执行,直到attach上的php-fpm进程死掉为止: > nohup strace -T -p 13167 > 13167-strace.log & 参数说明: > **\-c 统计每一系统调用的所执行的时间,次数和出错的次数等.** > > \-d 输出strace关于标准错误的调试信息. > > **\-f 跟踪由fork调用所产生的子进程.** > > \-o filename,则所有进程的跟踪结果输出到相应的filename > > \-F 尝试跟踪vfork调用.在-f时,vfork不被跟踪. > > \-h 输出简要的帮助信息. > > \-i 输出系统调用的入口指针. > > \-q 禁止输出关于脱离的消息. > > \-r 打印出相对时间关于,,每一个系统调用. > > \-t 在输出中的每一行前加上时间信息. > > \-tt 在输出中的每一行前加上时间信息,微秒级. > > \-ttt 微秒级输出,以秒了表示时间. > > **\-T 显示每一调用所耗的时间.** > > \-v 输出所有的系统调用.一些调用关于环境变量,状态,输入输出等调用由于使用频繁,默认不输出. > > \-V 输出strace的版本信息. > > \-x 以十六进制形式输出非标准字符串 > > \-xx 所有字符串以十六进制形式输出. > > \-a column > > 设置返回值的输出位置.默认为40. > > \-e execve 只记录 execve 这类系统调用 > > **\-p 主进程号** 2)也可以用利用-c参数让strace帮助汇总,非常方便非常强大! `[root@b28-12 log]# strace -cp 9907` `Process 9907 attached - interrupt to quit` `Process 9907 detached` `% time     seconds  usecs/call     calls    errors syscall` `------ ----------- ----------- --------- --------- ----------------` `56.61    0.016612           5      3121           read` `11.11    0.003259           1      2517       715 stat` `8.04    0.002358           7       349           brk` `6.02    0.001767           1      1315           poll` `4.28    0.001255           6       228           recvfrom` `2.71    0.000796           1       671           open` `2.54    0.000745           0      2453           fcntl` `2.37    0.000696           1      1141           write` `1.69    0.000497           1       593        13 access` `1.37    0.000403           0      1816           lseek` `0.89    0.000262           1       451        22 sendto` `0.56    0.000163           1       276       208 lstat` `0.49    0.000145           0       384           getcwd` `0.31    0.000090           0      1222           fstat` `0.28    0.000082           0       173           munmap` `0.26    0.000077           0       174           mmap` `0.24    0.000069           2        41           socket` `0.23    0.000068           0       725           close` `0.00    0.000000           0        13           rt_sigaction` `0.00    0.000000           0        13           rt_sigprocmask` `0.00    0.000000           0         1           rt_sigreturn` `0.00    0.000000           0        78           setitimer` `0.00    0.000000           0        26        26 connect` `0.00    0.000000           0        15         2 accept` `0.00    0.000000           0        39           recvmsg` `0.00    0.000000           0        26           shutdown` `0.00    0.000000           0        13           bind` `0.00    0.000000           0        13           getsockname` `0.00    0.000000           0        65           setsockopt` `0.00    0.000000           0        13           getsockopt` `0.00    0.000000           0         8           getdents` `0.00    0.000000           0        26           chdir` `0.00    0.000000           0         1           futex` `------ ----------- ----------- --------- --------- ----------------` `100.00    0.029344                 18000       986 total` ps:可以使用strace学习php解释器的解释执行过程 **3.4加速PHP解释执行** 如果自己的程序的确没有问题,只是执行了太多操作,没法再做优化了。则考虑使用APC或xcache等PHP加速器来减少CPU解释php文件的耗时。 这些PHP加速器在php文件第一次解释时会生成中间代码opcode,所以之后的执行会快很多,并且减少了一些CPU的运算。下面以xcache为例, 看下如何安装和配置。 安装xcache命令如下,./configure的参数好多不知道是做什么用的,官网上也没说明,所以只开启--enable-xcache了:      tar zxvf xcache-3.0.3.tar.gz      /usr/local/php/bin/phpize      ./configure --with-php-config=/usr/local/php/bin/php-config --enable-xcache      make      make install php.ini中配置如下,最重要的是标红的两个参数,一般推荐xcache.size根据php文件多少来定,xcache.count与CPU核心数相同: > \[xcache.admin\] > > xcache.admin.enable\_auth = Off > > xcache.admin.user = "xcache" > > xcache.admin.pass = "" > > \[xcache\] > > xcache.shm\_scheme ="mmap" > > **xcache.size=1024M** > > **xcache.count =16** > > xcache.slots =8K > > xcache.ttl=0 > > xcache.gc\_interval =0 > > xcache.var\_size=16M > > xcache.var\_count =1 > > xcache.var\_slots =8K > > xcache.var\_ttl=0 > > xcache.var\_maxttl=0 > > xcache.var\_gc\_interval =300 > > xcache.test =Off > > xcache.readonly\_protection = Off > > ;xcache.readonly\_protection = On > > xcache.mmap\_path ="/dev/zero" > > ;xcache.mmap\_path ="/tmp/xcache" > > xcache.coredump\_directory ="" > > xcache.cacher =On > > xcache.stat=On > > xcache.optimizer =Off > > \[xcache.coverager\] > > ;;xcache.coverager =On > > ;;xcache.coveragedump\_directory ="" 常见问题是启动php-fpm时会报错:      Cannot open or create file set by xcache.mmap\_path, check the path permission or check xcache.size/var\_size against system limitation 这是因为/tmp/xcache是一个文件,而不能创建成目录。 重启php-fpm服务后,用top命令观察会发现每个worker进程的VIRT(包含了swap区)都是xcache.size大小,但REQ变得很小了。 使用上面的配置在使CPU使用率的峰值时间变短了,但峰值时还是所有核心都会达到90%以上,不知道是不是哪里没有配置对。 另外高并发时,/dev/zero这种配置方式经常会导致Nginx 502错误。/tmp/xcache和开启readonly\_protection则很稳定。 * * * **4.php程序性能监控** 常用的方法就是开启xdebug的性能监控功能,将xdebug输出结果通过WinCacheGrind软件分析。 xdebug的安装和配合IDE调试的方法参见:[Vim+XDebug调试PHP](http://blog.csdn.net/dc_726/article/details/8809696) php.ini中配置的这几项是输出性能信息的: > xdebug.auto\_trace = on > xdebug.auto\_profile = on > xdebug.collect\_params = on > xdebug.collect\_return = on > xdebug.profiler\_enable = on > xdebug.trace\_output\_dir = "/tmp" > xdebug.profiler\_output\_dir ="/tmp" 这样XDebug会输出所有执行php函数的性能数据,但产生的文件也会比较大。可以关闭一些选项如collect\_params、collect\_return, 来减少输出的数据量。或者关闭自动输出,通过在想要监控的函数首尾调用xdebug函数来监控指定的函数。 输出的文件名类似cachegrind.out.1277560600和trace.3495983249.txt,可以拿到Windows平台下用WinCacheGrind进行图形化分析。 WinCacheGrind使用方法网上有很多介绍,这里就不详细说明了。