PHP-FPM,关于网站502错误的知识和解决方案


PHP-FPM,关于网站502错误的知识和解决方案

1、php-fpm介绍

1.1、CGI

CGI通用网关接口(Common Gateway Interface/CGI)描述了客户端和服务器程序之间传输数据的一种标准,可以让一个客户端,从网页浏览器向执行在网络服务器上的程序请求数据。CGI 独立于任何语言的,CGI 程序可以用任何脚本语言或者是完全独立编程语言实现,只要这个语言可以在这个系统上运行。Unix shell>

最初,CGI 是在 1993 年由美国国家超级电脑应用中心(NCSA)为 NCSA HTTPd Web 服务器开发的。这个 Web 服务器使用了 UNIX shell 环境变量 来保存从 Web 服务器传递出去的参数,然后生成一个运行 CGI 的独立的进程。cgi的处理流程如下图所示:

PHP-FPM,关于网站502错误的知识和解决方案


1.2、FastCGI

快速通用网关接口(Fast Common Gateway Interface/FastCGI)是通用网关接口(CGI)的改进,描述了客户端和服务器程序之间传输数据的一种标准。FastCGI致力于减少Web服务器与CGI程式之间互动的开销,从而使服务器可以同时处理更多的Web请求。与为每个请求创建一个新的进程不同,FastCGI使用持续的进程来处理一连串的请求。这些进程由FastCGI进程管理器管理,而不是web服务器。(http://www.dwz.cn/yFMap)

PHP-FPM,关于网站502错误的知识和解决方案

当进来一个请求时,Web 服务器把环境变量和这个页面请求通过一个unix domain socket(都位于同一物理服务器)或者一个IP Socket(FastCGI部署在其它物理服务器)传递给FastCGI进程。


PHP-FPM,关于网站502错误的知识和解决方案

l step1. Web 服务器启动时载入初始化FastCGI执行环境 。 例如IIS ISAPI、apache mod_fastcgi、nginx ngx_http_fastcgi_module、lighttpd mod_fastcgi


l step2. FastCGI进程管理器自身初始化,启动多个CGI解释器进程并等待来自Web 服务器的连接。启动FastCGI进程时,可以配置以ip和UNIX 域socket两种方式启动。

l step3. 当客户端请求到达Web 服务器时, Web 服务器将请求采用socket方式转发到 FastCGI主进程,FastCGI主进程选择并连接到一个CGI解释器。Web 服务器将CGI环境变量和标准输入发送到FastCGI子进程。

l step4. FastCGI子进程完成处理后将标准输出和错误信息从同一socket连接返回Web 服务器。当FastCGI子进程关闭连接时,请求便处理完成。


l step5. FastCGI子进程接着等待并处理来自Web 服务器的下一个连接。

由于 FastCGI 程序并不需要不断的产生新进程,可以大大降低服务器的压力并且产生较高的应用效率。它的速度效率最少要比CGI 技术提高 5 倍以上。它还支持分布式的部署, 即 FastCGI 程序可以在web 服务器以外的主机上执行。


总结:CGI 就是所谓的短生存期应用程序,FastCGI 就是所谓的长生存期应用程序。FastCGI像是一个常驻(long-live)型的CGI,它可以一直执行着,不会每次都要花费时间去fork一次(这是CGI最为人诟病的fork-and-execute 模式)。

1.3、FastCGI进程管理器:php-fpm

PHP-FPM是一个PHPFastCGI管理器,是只用于PHP的。


2、php-fpm配置优化、进程数优化

2.1、Linux 简单指令

<code>#Top
#ps aux | grep “process name”\t\t#ps –ef | grep “name”
内存管理指令:df -ht
/<code>
PHP-FPM,关于网站502错误的知识和解决方案

2.2、Top指令详解

PHP-FPM,关于网站502错误的知识和解决方案

<code>第一行:
12:26:43 当前系统时间
2:58系统已经运行时间(在这期间没有重启过)1 user 当前有1个用户登录系统
load average: 0.00, 0.01, 0.05 load average后面的三个数分别是1分钟、5分钟、15分钟的负载情况。
load average数据是每隔5秒钟检查一次活跃的进程数,然后按特定算法计算出的数值。如果这个数除以逻辑CPU的数量,结果高于5的时候就表明系统在超负荷运转了。

第二行:
Tasks 任务(进程),系统现在共有112个进程,其中处于运行中的有1个,111个在休眠(sleep),stoped状态的有0个,zombie状态(僵尸)的有0个。
第三行:cpu状态(%)
13.7 us 用户空间占用CPU的百分比。
4.8 sy 内核空间占用CPU的百分比。
80.7 id 空闲CPU百分比
第四行:内存状态(KiB)
12000044 total 物理内存总量(11.4GB)
3365720 used 使用中的内存总量(3.2GB)
8634324 free 空闲内存总量(8.2GB)
88244 buffers 缓存的内存量 (86.2M)
第五行:
swap交换分区(KiB) \t\t0 total 交换区总量(0)
0 used 使用的交换区总量(0) \t0 free 空闲交换区总量(0)
1748600 cached 缓冲的交换区总量(1.7GB)
第六行是空行
第七行以下:各进程(任务)的状态监控
PID 进程id \t\tUSER 进程所有者 \tPR 进程优先级
NI nice值。负值表示高优先级,正值表示低优先级
VIRT 进程使用的虚拟内存总量,单位kb。VIRT=SWAP+RES
RES 进程使用的、未被换出的物理内存大小,单位kb。RES=CODE+DATA
SHR 共享内存大小,单位kb
S 进程状态。D=不可中断的睡眠状态 R=运行 S=睡眠 T=跟踪/停止 Z=僵尸进程

%CPU 上次更新到现在的CPU时间占用百分比
%MEM 进程使用的物理内存百分比
TIME+ 进程使用的CPU时间总计,单位1/100秒
COMMAND 进程名称(命令名/命令行)
/<code>

//==============================================================

多U多核CPU监控

在top基本视图中,按键盘数字1,可监控每个逻辑CPU的状况

应用:使用top和kill强制结束进程

例如想要结束某一个进程:

<code>可以通过top工具动态的显示系统中的进程找到想要停止的进程对应的PID号码,然后键盘q键 退出top工具,然后通过sudo kill [PID]完成操作。
/<code>


2.3、php-fpm配置文件详解

<code>配置目录
默认:/usr/local/php/etc/php-fpm.conf
Php-fpm启动、重启、停止
命令行:#/etc/init.d/php5-fpm strat\t启动
杀死进程:\t#ps aux|grep php-fpm#kill“主进程pid”
/<code>

a、PHP-fpm.conf文件详解

php-fpm.conf文件是php-fpm主要配置文件。定义了全局变量,并包含了其他的配置定义和pool定义的配置文件。

###############################[全局变量]##################################

<code>;include=/etc/php5/fpm/*.conf可以自己新建其他的配置文件并包含进来。
pid = /var/run/php5-fpm.pidpid设置
error_log =/var/log/php5-fpm.log错误日志
/<code>
PHP-FPM,关于网站502错误的知识和解决方案

表示在emergency_restart_interval所设值内出现SIGSEGV或者SIGBUS错误的php-cgi进程数如果超过 emergency_restart_threshold个,php-fpm就会优雅重启。这两个选项一般保持默认值。

<code>;process_control_timeout = 0
/<code>

设置子进程接受主进程复用信号的超时时间. 可用单位: s(秒), m(分), h(小时), 或者 d(天) 默认单位: s(秒). 默认值: 0。

PHP-FPM,关于网站502错误的知识和解决方案

最大进程数。(看注释)

PHP-FPM,关于网站502错误的知识和解决方案

后台执行fpm。

<code>Rlimit_files ;\trlimitcore;events.mechanism = epoll;systemd_interval = 10略
/<code>

###############################[池定义]########################################

<code>include=/etc/php5/fpm/pool.d/*.conf
/<code>


b、Pool.d/www.conf文件解析

该文件是一个池定义配置文件,定义了pool的参数。这些参数也可以直接写在php-fpm.conf文件中。在FPM中,可以使用不同的设置来运行多个进程池。 这些设置可以针对每个进程池单独设置。

启动进程的账户和组: user=www-data group=www-data。

PHP-FPM,关于网站502错误的知识和解决方案

fpm监听端口,即nginx中php处理的地址,一般默认值即可。

<code>listen.mode=0660
listen.allowed_clients = 127.0.0.1
/<code>

允许访问FastCGI进程的IP,设置any为不限制IP,如果要设置其他主机的nginx也能访问这台FPM进程,listen处要设置成本地可被访问的IP。默认值是any。

PHP-FPM,关于网站502错误的知识和解决方案

pm = dynamic 非常重要的配置

如何控制子进程,选项有static和dynamic。

如果选择static,则由pm.max_children指定固定的子进程数。

如果选择dynamic,则由以下参数决定:

pm.max_children ,子进程最大数

pm.start_servers ,启动时的进程数

pm.min_spare_servers ,保证空闲进程数最小值,如果空闲进程小于此值,则创建新的子进程

pm.max_spare_servers ,保证空闲进程数最大值,如果空闲进程大于此值,此进行清理对于专用服务器,pm可以设置为static。

<code>pm.max_requests =1000
/<code>

设置每个子进程重生之前服务的请求数。对于可能存在内存泄漏的第三方模块来说是非常有用的。如果设置为 '0′ 则一直接受请求. 等同于 PHP_FCGI_MAX_REQUESTS 环境变量. 默认值: 0。

<code>pm.status_path = /status
/<code>

FPM状态页面的网址. 如果没有设置, 则无法访问状态页面. 默认值: none.

<code>ping.path = /ping
/<code>

FPM监控页面的ping网址. 如果没有设置, 则无法访问ping页面. 该页面用于外部检测FPM是否存活并且可以响应请求. 请注意必须以斜线开头 (/)。

<code>ping.response = pong
/<code>

用于定义ping请求的返回相应. 返回为 HTTP 200 的 text/plain 格式文本. 默认值: pong。

<code>slowlog = log/$pool.log.slowPhp-fpm的慢日志,设置慢日志的存放位置。
/<code>
PHP-FPM,关于网站502错误的知识和解决方案

用于debug,异常排查。

<code>request_terminate_timeout = 0
/<code>

设置单个请求的超时中止时间. 该选项可能会对php.ini设置中的'max_execution_time'因为某些特殊原因没有中止运行的脚本有用. 设置为 '0′ 表示 ‘Off'。

3、php-fpm优化方法

php-fpm的两种优化方式

<code>a、直接开启指定数量的php-fpm进程,不再增加或者减少;
即:pm=static ;
b、开始时开启一定数量的php-fpm进程,当请求量变大时,动态的增加php-fpm进程数到上限,当空闲时自动释放空闲的进程数到一个下限。
即:pm=dynamic ;
/<code>

这两种不同的执行方式,可以根据服务器的实际需求来进行调整。

那么,对于服务器,选择哪种执行方式比较好呢?

事实上,跟Apache一样,运行的PHP程序在执行完成后,或多或少会有内存泄露的问题。这也是为什么开始时一个php-fpm进程只占用3M左右内存,运行一段时间后就会上升到20-30M的原因了。

所以,动态方式因为会结束掉多余的进程,可以回收释放一些内存,所以推荐在内存较少的服务器或者VPS上使用。具体最大数量根据 内存/20M 得到。

比如说512M的VPS,建议pm.max_spare_servers设置为20(512*0.8/20)。至于pm.min_spare_servers,则建议根据服务器的负载情况来设置,比较合适的值在5~10之间。

然后对于比较大内存的服务器来说,设置为静态的话会提高效率。

因为频繁开关php-fpm进程也会有时滞,所以内存够大的情况下开静态效果会更好。数量也可以根据 内存/30M 得到。

比如说2GB内存的服务器,可以设置为50;4GB内存可以设置为100等。


4、方法可行性测试

服务器内存对比,未优化时:

PHP-FPM,关于网站502错误的知识和解决方案

Pm=static ; 50个子进程;方案优化后:

PHP-FPM,关于网站502错误的知识和解决方案


5、php-fpm--出现502错误

5.1、进程数不够

php-fpm有一个参数 max_requests,该参数指明了,每个children最多处理多少个请求后便会被关闭,默认的设置是500。因为php是把请求轮询给每个 children,在大流量下,每个childre到达max_requests所用的时间都差不多,这样就造成所有的children基本上在同一时间 被关闭。

在这期间,nginx无法将php文件转交给php-fpm处理,所以cpu会降至很低(不用处理php,更不用执行sql),而负载会升至很高(关闭和开启children、nginx等待php-fpm),网卡流量也降至很低(nginx无法生成数据传输给客户端)

解决问题很简单,增加children的数量,并且将 max_requests 设置未 0 (一直接受请求)或者一个比较大的值。


5.2、增加缓冲区容量大小

将nginx的error log打开,发现“pstream sent too big header while reading response header from upstream”这样的错误提示。查阅了一下资料,大意是nginx缓冲区有一个bug造成的,我们网站的页面消耗占用缓冲区可能过大。参考文档写的修改办法增加了缓冲区容量大小设置,502问题彻底解决。后来系统管理员又对参数做了调整只保留了2个设置参数:client head buffer,fastcgi buffer size。


5.3、request_terminate_timeout

如果主要是在一些post或者数据库操作的时候出现502这种情况,而不是在静态页面操作中常见,那么可以查看一下php-fpm.conf设置中的一项:

request_terminate_timeout

这个值是max_execution_time,就是fast-cgi的执行脚本时间:0s,0s为关闭,就是无限执行下去。优化fastcgi中,还可以改改这个值5s 看看效果。

php-cgi进程数不够用、php执行时间长、或者是php-cgi进程死掉,都会出现502错误。


5.4、Nginx轮询PHP服务

之前的优化都是在一个主进程多个子进程的基础上进行配置的。而这个轮询,就是建立多个php-fpm主进程多个子进程的基础上进行配置。

总结:多建几个www.conf文件,形成多个资源池,然后修改相应的Nginx配置文件进行socket套接字监听轮询。这里不介绍轮询方案。


参考文献

CGI/FastCGI 详解:http://www.cnblogs.com/skynet/p/4173450.html

Linux下php-fpm优化:http://www.1207.me/archives/162.html

http://www.cnblogs.com/jackluo/p/3366612.html

http://www.169it.com/blog_article/1780909218.html

基于php-fpm的配置详解:http://www.jb51.net/article/37749.htm

启用php-fpm状态:http://www.ttlsa.com/php/use-php-fpm-status-page-detail/

进程管理:http://www.tuicool.com/articles/I3qEZb

Nginx轮询php服务: http://www.ithao123.cn/content-2272084.html

http://linux.fcbu.com/nginx-php-fpm-502.htm

http://www.lc365.net/blog/b/15185/


分享到:


相關文章: