/ 中存储网

解决Nginx轮询PHP服务池经常出现502错误的方法

2013-12-31 13:56:02 来源:kejihao

网站架构采用的就是linux nginx php(php-fpm模式) mysql

网站经常会出现502错误,可以从一下几个方面着手查:

检查下php-fpm的进程数使用情况:

netstat -napo |grep "php-cgi" | wc -l

如果这个查询出来的数量超过了php-fpm.conf里设置的数量,说明是进程数量不够用,可以适当增加。

也可能是php程序执行时间过长造成超时,如果是这个问题,可以通过修改nginx.conf和php-fpm.conf里面相关的超时设置来解决

nginx.conf里面主要是如下

fastcgi_connect_timeout 300;

fastcgi_send_timeout 300;

fastcgi_read_timeout 300;

php-fpm.conf里如要是如下

request_terminate_timeout 设置为0s或者比目前时间更长,0s表示无限制,一直执行下去。

还可能是fastcgi缓存不够,主要是在nginx.conf配置里修改如下参数:

fastcgi_buffer_size 128

fastcgi_buffers 8 128k;

fastcgi_busy_buffers_size 256k

另外还有注意系统各方面的限制ulimit -a查看一下。

一般上面几个地方做合适的优化,会有较明显的效果。

最后的解决方法:nginx轮询php服务池避免502

既然上面的常规办法不能解决,那就得想其他办法了。502引起肯定是因为php-fpm引发的,也就是nginx将正确的客户端请求发给了后端的php-fpm进程,但是因为php-fpm进程的问题导致不能正确解析php代码。最终返回给了客户端502错误。nginx既然upstream可以支持多组后端服务器轮询实现简单的负责均衡,并且可以做简单的健康检查,因为有了健康检查机制,这样就可以在错误到达客户端前换另外一个php-fpm进程重新解析了。那就用这个办法开多组php-fpm服务来实现一个php-fpm池,让nginx在这个php-fpm资源里通过stream轮询。

使用不同端口或php-fpm.sock启动多个php-fpm主进程的方法:

先修改php-fpm.conf来开启多组php-fpm进程

以/usr/local/php/etc/php-fpm.conf为样板,复制另外3个文件出来,假设为php-fpm_fcbucom1.conf,php-fpm_fcbucom2.conf,php-fpm_fcbucom3.conf;原有的php-fpm.conf不动,作为备份吧。

三个配置文件中,需要修改的两个地方是pid文件名和sock文件名,假设为/tmp/php-cgi_fcbucom1.sock , /tmp/php-cgi_fcbucom2.sock , /tmp/php-cgi_fcbucom3.sock (也可以设置不同的pool名字,默认是default)

执行命令使用不同的配置文件启动3个创建sock监听的PHP-FPM主进程。

/usr/local/php/bin/php-cgi --fpm --fpm-config /usr/local/php/etc/php-fpm_fcbucom1.conf

/usr/local/php/bin/php-cgi --fpm --fpm-config /usr/local/php/etc/php-fpm_fcbucom2.conf

/usr/local/php/bin/php-cgi --fpm --fpm-config /usr/local/php/etc/php-fpm_fcbucom3.conf

启动之后,就在相应目录(一般是/tmp/)出现php-cgi_fcbucom1.sock , php-cgi_fcbucom2.sock , php-cgi_fcbucom3.sock这3个sock文件。

接下来修改nginx.conf配置

主要在http {} 的配置块内,加入我们要使用的轮询配置:

upstream FCBUcom_php_servers{

  server unix:/tmp/php-cgi_fcbucom1.sock;

  server unix:/tmp/php-cgi_fcbucom2.sock;

  server unix:/tmp/php-cgi_fcbucom3.sock;

}

fastcgi_next_upstream error timeout invalid_header http_500 http_503;

#注:fastcgi_next_upstream 不需要加http_502,也加不上去的,不支持。

这样我们就建立了一个可以根据健康状况轮询并可以重试的资源池。

接着修改我们网站server配置,原来处理php代码的fastcgi配置

location ~ .*.(php|php5)?$

   {

fastcgi_pass  unix:/tmp/php-cgi.sock;

fastcgi_index index.php;

include fastcgi.conf;

   }

或原来这样

location ~ .*.(php|php5)?$

   {

fastcgi_pass  127.0.0.1:9000;

fastcgi_index index.php;

include fastcgi.conf;

   }

将其中的fastcgi_pass由原来的php-cgi.sock.sock单独的php-fpm进程或127.0.0.1:9000修改为刚刚创建的FCBUcom_php_servers轮询池,如:

location ~ .*.(php|php5)?$

   {

fastcgi_pass FCBUcom_php_servers;

fastcgi_index index.php;

include fastcgi.conf;

   }

原有配置文件的每段类似这种location ~ .*.(php|php5)?$ {代码都需要对fastcgi_pass这行修改。

通过这样的配置,可以肯定的是php-fpm因为采用3个资源池来轮询工作,并且有fastcgi_next_upstream进程简单的健康检查,可以最大程度的避免502错误发生了。

最后重启php-cgi和nginx。