nginx fpm 常见错误对比分析

fastcgi_read_timeout 8; // nginx.conf
request_terminate_timeout=0 // php-fpm.conf

sleep(10);

浏览器 8 秒后返回 504 Gateway Time-out

nginx-error.log
upstream timed out (110: Connection timed out) while reading response header from upstream

 

fastcgi_read_timeout 8; // nginx.conf
request_terminate_timeout=5 // php-fpm.conf

sleep(10);

浏览器 5 秒后返回 502 Bad Gateway

nginx-error.log
recv() failed (104: Connection reset by peer) while reading response header from upstream
fpm-error.log
[pool www] child 5378, script ‘/usr/share/nginx/html/sleep.php’ (request: “GET /sleep.php”) execution timed out (5.793874 sec), terminating

 

fastcgi_read_timeout 8; // nginx.conf
request_terminate_timeout=5 // php-fpm.conf

set_time_limit(1);
while(true){}

浏览器返回 500 Internal Server Error
php-error.log
[08-Apr-2017 23:39:44 Asia/Shanghai] PHP Fatal error: Maximum execution time of 1 second exceeded in /usr/share/nginx/html/while_true.php on line 3

Opcache 开启前后性能对比

测试环境介绍

机器是一台基于 vmware 的虚拟机

CPU: cat /proc/cpuinfo 看到为 8 核 CPU,
    型号是 Intel(R) Xeon(R) CPU E5-2430 v2 @ 2.50GHz
MEM: free 命令看到内存大小为 16G
nginx 版本为 1.11.5, worker_processes 8
php 版本为 7.0.12, fpm 进程 100 个

程序是 yii2-app-basic , HelloController.php 文件内容如下:

<?php
namespace app\controllers;

class HelloController extends \yii\web\Controller
{
    public function actionWorld()
    {
        return 'Hello, world!';
    }
}

测试命令: ab -n10000 -c100 ‘http://yii2.app.com:8090/index.php?r=/hello/world’

测试结果:

 Opcache CPU占用 Requests per second(吞吐率)
未开启 99% 520
开启 99% 5480

用 strace 追踪 php-fpm 的系统调用(strace 会严重影响性能,追踪系统调用时用的测试命令是:ab -n1000 -c100 ‘http://yii2.app.com:8090/index.php?r=/hello/world’,总请求减少为之前的10%),结果如下:

未开启 Opcache php-fpm的系统调用
% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
29.99    0.512695           3    174053           fstat
18.60    0.318016           5     59611           munmap
13.98    0.238919           4     58059         3 open
13.56    0.231822           4     59235           mmap
9.70    0.165759           3     59559           close
4.83    0.082623           8     11010         4 lstat
3.46    0.059209           2     28014           read
1.14    0.019432           4      5102       100 stat
0.76    0.012930          13      1000           accept
0.66    0.011317           6      2000           chdir
0.50    0.008500           8      1005           write
0.50    0.008488           8      1001           getcwd
0.44    0.007527           8      1000           shutdown
0.41    0.006957           2      3000           setitimer
0.40    0.006795           7      1000           poll
0.37    0.006369           4      1610           rt_sigaction
0.31    0.005215           3      2000           times
0.19    0.003238           2      2000           recvfrom
0.11    0.001857           2      1001           rt_sigprocmask

开启 Opcache php-fpm的系统调用
% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
26.92    0.041058           1     28015           read
15.73    0.023990           5      5160       100 stat
8.44    0.012872           6      2000           chdir
6.78    0.010336           3      3000           setitimer
6.04    0.009209           4      2132           fcntl
5.49    0.008373           8      1000           accept
5.29    0.008068          13       615         4 lstat
3.63    0.005544           3      1618           close
3.48    0.005308           3      2000           times
3.01    0.004586           5      1001           rt_sigprocmask
2.90    0.004427           4      1005           write
2.65    0.004042           4      1001           getcwd
2.39    0.003651           2      1610           rt_sigaction
2.29    0.003491           2      2000           recvfrom
1.93    0.002950           3      1000           shutdown
1.65    0.002516           3      1000           poll
0.81    0.001241           3       397           mmap
0.38    0.000582           6       100           clone

测试结果分析:

Opcache 开启前后 cpu 使用率都达到了 100% 说明系统瓶颈在 cpu。开启 Opcache 后系统调用少了很多,特别是 fstat,mumap,open,mmap,开启后,这几个系统调用可以忽略不计。Opcache 省去了每次加载和解析 PHP 脚本的开销,一次加载解析后后续请求不用去读源码,因此少了这么多系统调用。

结论:提高PHP程序的性能,最重要也最有效的方法就是开启 Opcache。

其它:  最初 fpm 配置是监听端口,吞吐率在开启Opcache前只有340左右;开启Opcache后在900左右,cpu占有80%,无法达到100%;如果请求过多,则会出现超时错误。后来改 fpm 监听 unix sock,性能一下子上来了。Yii2 开启  debug 模式后,吞吐率为 1200  左右。

nginx php-fpm 捕获记录 php 的错误日志

请确认 php-fpm.conf 的如下配置为:

catch_workers_output = yes # 捕获进程的输出,这个值默认为 no
error_log = log/php-fpm.log # 这个是默认值,指定 php-fpm 输出 log 的文件路径

确认 php.ini 的如下配置为:

log_errors = On # 开启记录错误日志,这个值默认为 Off
error_reporting=E_ALL&~E_NOTICE # 默认就是这个值,php 的 error_reporting 级别

参考网址:http://www.nginx.cn/666.html

NetBeans Xdebug 调试老是等待链接

如果你确认你的 NetBeans 及 Xdebug 配置无误,但 NetBeans 就是显示等待链接,那么请接着往下看。

默认 NetBeans 的设置,PHP 调试器端口是 9000,默认 xdebug.remote_port 是 9000,这个配置是没有任何问题的。而 PHP-FPM 的默认监听端口也是 9000,所以,问题就是因为 9000 端口已经被 PHP-FPM 占用,NetBeans 链接 Xdebug 调试器端口显然就链接不上了。

解决办法:要么更改 xdebug.remote_port 和 NetBeans 的端口,要么更改 PHP-FPM 的监听端口(建议使用 Unix Sock)。

参考网址:http://www.cnblogs.com/azev/archive/2009/08/09/1542227.html

nginx + php-fpm 开启 PATH_INFO 模式

很多框架默认路由都是 PATH_INFO 模式,比如默认在 Apache 并且没有 rewrite 时,CodeIgniter 一般可以这样访问 /index.php/controller/action ,那么 nginx 和 php-fpm 如何设置支持 PATH_INFO 模式呢?

php.ini 中一个与 PATH_INFO 有关的设置是 cgi.fix_path 默认为 1,我们将其设置为 0。

php.ini 设置:

cgi.fix_path = 0

接下来是 nginx 配置:

location ~ \.php($|/) {
# 下面这一行设置 $fastcgi_script_name 和 $fastcgi_path_info 的值,具体请看 nginx 文档
    fastcgi_split_path_info ^(.+\.php)(/.+)$;
# 下面这行也可以为 fastcgi_pass unix:/var/run/php-fpm.sock 看你的 fpm 设置了
    fastcgi_pass   127.0.0.1:9000;
    fastcgi_index  index.php;
    include        fastcgi_params;
# 下面这行不能少默认 fastcgi_params 里面并没有 SCRIPT_FILENAME 
    fastcgi_param  SCRIPT_FILENAME    $document_root$fastcgi_script_name;
    fastcgi_param  PATH_INFO          $fastcgi_path_info;
}

看官如有疑问,请在下面留言,希望对您有帮助。

相关链接:

nginx php5-fpm 出现 Access denied

今天我想让 phps 后缀的文件显示其源代码。网上搜索之,按照这里的修改:

location ~ \.phps$ {
    fastcgi_pass backend;
    fastcgi_param  DOCUMENT_ROOT    $document_root;
    fastcgi_param  SCRIPT_NAME      $uri;
    fastcgi_param  SCRIPT_FILENAME  /path/to/hightlight_source.php;
}

结果访问 phps 文件出现 Access denied.

查看错误日志,发现是 security.limit_extensions 配置的问题。

修改 /etc/php5/fpm/pool.d/www.conf ,修改配置为以下即可:

security.limit_extensions = .php .phps

同理,如果你想让 php5-fpm 处理后缀文件,在该行配置下添加相应后缀名即可。
感悟:看错误日志对于排错帮助很大,找到错误之处后再在网上找相应内容一般都能解决问题。