基于 Nginx, PHP-FPM 的网站,有时候会发现出现以下错误:
The page you are looking for is temporarily unavailable.Please try again later.
排查服务器发现 Nginx 正常,PHP-FPM 也有进程,但是网页就是无法正常打开,重启 PHP-FPM 后网站就正常打开了。
找到 PHP-FPM 的错误日志文件,并查阅:
$ tail /usr/local/php/var/log/php-fpm.log -n 100
PHP-FPM 错误日志文件路径可以在
/usr/local/php/etc/php-fpm.conf
配置文件找到,默认是放到 PHP 安装目录的var/log/php-fpm.log
里。
如果你发现一下错误信息:
[19-Dec-2012 11:41:13] WARNING: [pool www] server reached pm.max_children setting (5), consider raising it
那么基本可以判断是 PHP-FPM 没有优化到位。
编辑 PHP-FPM 配置文件:
$ vim /usr/local/php/etc/php-fpm.conf
在上面的配置文件里有两个至关重要的参数:一个是pm.max_children
,另一个是 pm.request_terminate_timeout
。
我的两个设置的分别是 40
和 900
,但是这个值不是通用的,而是需要自己计算的。
如果你的服务器性能足够好,且宽带资源足够充足,PHP 脚本没有死循环或 BUG 的话你可以直接将 pm.request_terminate_timeout
设置成 0s
。
0s
的含义是让PHP-CGI一直执行下去而没有时间限制。
而如果你做不到这一点,也就是说你的 PHP-CGI 可能出现某个 BUG,或者你的宽 带不够充足或者其他的原因导致你的 PHP-CGI 能够假死那么就建议你给 request_terminate_timeout
赋一个值,这个值可以根 据你服务器的性能进行设定。一般来说性能越好你可以设置越高,20-30 分钟都可以。
由于我的服务器 PHP脚本 需要长时间运行,有的可能会超过 10 分 钟因此我设置了 900 秒,这样不会导致 PHP-CGI 死掉而出现 502 Bad gateway
这个错误。
而 pm.max_children
这个值又是怎么计算出来的呢?这个值原则上是越大越好,PHP-CGI 的进程多了就会处理的很快,排队的请求就会很少。
设置 pm.max_children
也需要根据服务器的性能进行设定,一般来说一台服务器正常情况下每一个 PHP-CGI 所耗费的内存在 20M 左右,因此我的 pm.max_children
我设置成 40 个(20M*40 = 800M)。
也就是说在峰值的时候所有 PHP-CGI 所耗内存在 800M 以内,低于我的有效内存 1GB。而如果我 的 pm.max_children
设置的较小,比如 5-10 个,那么 PHP-CGI 就会“很累”,处理速度也很慢,等待的时间也较长。如果长时间没有得到处理的请求就会出现 504 Gateway Time-out
这个错误,而正在处理的“很累”的那几个 PHP-CGI 如果遇到了问题就会出现 502 Bad gateway
这个错误。
pm.max_children
基本就是进程数,跟 Nginx 的进程没有想象中的那么大,因为 PHP-FPM 会自己管理进程(有待考证,起码我简单浏览了一下源码,认为是这个意思)。参数不宜设置过大,很占内存,进程的消耗就不用我多说了.
pm.max_children
较好的设置方式根据 req/s
来设置,若程序是 100 req/s
的处理能力,最大并发是 10K
,那么就设置 100 比较好,这是动态来调整的.
很简单,具体看配置文件,这样的设置之后,在高负载和复杂的 PHP 程序会省事一点,毕竟测试 req/s
是可恶的体力活。
req/s
表示 每秒请求量
pm.max_requests
即是说每个进程若超过这个数目(跟 PHP 进程有一点点关系,关系不大),就自动杀死。我这里应该设置 512 的,不过懒得压力测试。
其他参数说明:
错误日志的位置. 默认安装路径:#INSTALL_PREFIX#/log/php-fpm.log
。
错误级别. 可用级别为:
如果子进程在 emergency_restart_interval
设定的时间内收到该参数设定次数的 SIGSEGV
或者 SIGBUS
退出信息号,则FPM会重新启动。
默认值: 0(表示关闭该功能)
emergency_restart_interval
用于设定平滑重启的间隔时间. 这么做有助于解决加速器中共享内存的使用问题. 可用单位: s(秒), m(分), h(小时), 或者 d(天)。
默认单位:s(秒)
设置子进程接受主进程复用信号的超时时间. 可用单位:s(秒), m(分), h(小时), 或者 d(天)。
默认单位:s(秒)
设置 FPM 在后台运行. 设置 no
将 FPM 保持在前台运行用于调试。
默认值:yes
设置接受 FastCGI 请求的地址。
可用格式为:'ip:port', 'port', '/path/to/unix/socket'
。
每个进程池都需要设置。
设置 listen(2) 的半连接队列长度。
默认值: -1(表示无限制)
设置允许连接到 FastCGI 的服务器 IPV4 地址。等同于 PHP FastCGI (5.2.2+) 中的 FCGI_WEB_SERVER_ADDRS
环境变量。
仅对 TCP 监听起作用,每个地址是用逗号分隔。如果没有设置或者为空,则允许任何服务器请求连接。
默认值: any
如果使用,表示设置 Unix 套接字的权限。
在 Linux 中,读写权限必须设置,以便用于WEB服务器连接。
在很多BSD派生的系统中可以忽略权限允许自由连接。
默认值:运行所使用的用户合租, 权限为0666。
参见 listen.owner
参见 listen.owner
FPM 进程运行的 Unix 用户(必须设置)。
FPM 进程运行的 Unix 用户组。如果没有设置,则默认用户的组被使用。
设置进程管理器如何管理子进程。
可用值:static
或 dynamic
(必须设置)
static:子进程的数量是固定的 (pm.max_children).
dynamic:子进程的数量在下面配置的基础上动态设置: pm.max_children
, pm.start_servers
, pm.min_spare_servers
, pm.max_spare_servers
。
子进程的数量,pm 设置为 static
时表示创建的,pm 设置为 dynamic
时表示最大可创建的。必须设置。
该选项设置可以同时提供服务的请求数限制. 类似 Apache 的 mpm_prefork
中 MaxClients
的设置和 普通 PHP FastCGI 中的 PHP_FCGI_CHILDREN
环境变量.
设置启动时创建的子进程数目。仅在 pm 设置为 dynamic
时使用。
默认值: min_spare_servers
+ (max_spare_servers
– min_spare_servers
) / 2
设置空闲服务进程的最低数目。仅在 pm 设置为 dynamic
时使用(必须设置)。
设置空闲服务进程的最大数目。仅在 pm 设置为 dynamic
时使用(必须设置)。
设置每个子进程重生之前服务的请求数。
对于可能存在内存泄漏的第三方模块来说是非常有用的. 如果设置为 0 则一直接受请求. 等同于 PHP_FCGI_MAX_REQUESTS
环境变量。
默认值: 0
FPM 状态页面的网址。如果没有设置, 则无法访问状态页面。
默认值: none
FPM监控页面的ping网址. 如果没有设置, 则无法访问ping页面. 该页面用于外部检测FPM是否存活并且可以响应请求。
请注意必须以斜线开头(/)
用于定义 ping 请求的返回相应。返回为 HTTP 200 的 text/plain
格式文本。
默认值:pong
设置单个请求的超时中止时间。 该选项可能会对 php.ini 设置中的 max_execution_time
因为某些特殊原因没有中止运行的脚本有用。
默认值:0(表示无限制)
可用单位:s(秒,默认), m(分), h(时), d(天)
当一个请求该设置的超时时间后,就会将对应的 PHP 调用堆栈信息完整写入到慢日志中。
默认值:0(表示无限制)
可用单位:s(秒,默认), m(分), h(时), d(天)
慢请求的记录日志。
默认值:#INSTALL_PREFIX#/log/php-fpm.log.slow
设置文件打开描述符的 rlimit
限制。
默认值:系统定义值
设置核心rlimit最大限制值。
可用值:‘unlimited’、0或者正整数。
默认值:系统定义值
启动时的Chroot目录,所定义的目录需要是绝对路径。如果没有设置,则chroot不被使用。
设置启动目录,启动时会自动 Chdir 到该目录,所定义的目录需要是绝对路径。
默认值: 当前目录 或者 /目录 (chroot时)
重定向运行过程中的 stdout
和 stderr
到主要的错误日志文件中。如果没有设置, stdout
和 stderr
将会根据 FastCGI 的规则被重定向到 /dev/null
。
默认值: 空