/ 中存储网

Nginx 502 Bad Gateway 错误和解决方案

2013-12-13 15:32:01 来源:ITJS.CN

Nginx 502 Bad Gateway 是因为nginx因为内存不足,PHP反应缓慢,php进程不足等引起的一类服务器错误。

发送问题的原因:

1、PHP FastCGI进程数不够用 

当网站并发访问巨大时,php fastcgi的进程数不有一定的保障,因为cgi是单线程多进程工作的,也就是说cgi需要处理完一个页面后再继续下一个页面。如果进程数不够,当访问巨大的时候,cgi按排队处理之前的请求,之后的请求只有被放弃。这个时候nginx就会不时的出现502错误。

2、PHP FastCGI的内存不够用

当nginx返回静态页面时,这个问题一般不会出现,因为nginx不需要php cgi的处理而直接返回静态页面。但是当网页需要处理大量的php复杂操作的时候,例如执行api采集,或者采集页面的时候,那对php的要求是相当高的,如果配置给他的内存太少,那很容易就会导致php崩溃。

解决方法:

1、请检查你的FastCGI进程是否启动

2、FastCGI进程不够使用

请通过执行 netstat -anpo | grep "php-cgi" | wc -l 判断,是否接近你启动的FastCGI进程,接近你的设置,表示进程不够。

3、执行超时

可以把 nginx.conf 这几项的值调大一些:

fastcgi_connect_timeout 300; fastcgi_send_timeout 300; fastcgi_read_timeout 300;

4、FastCGI缓冲不够

nginx和apache一样,有前端缓冲限制,可以把 nginx.conf 这几项的值调大一些:

fastcgi_buffer_size 32k; fastcgi_buffers 8 32k;

5、Proxy缓冲不够

如果你使用了Proxying,可以把 nginx.conf 这几项的值调大一些:

proxy_buffer_size 16k; proxy_buffers 4 16k;

6、https转发配置错误

正确的配置方法

server_name www.server110.com;  location /myproj/repos {  set $fixed_destination $http_destination; if ( $http_destination ~* ^https(.*)$ ) { set $fixed_destination http$1; }  proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header Destination $fixed_destination; proxy_pass http://subversion_hosts; }

7、php脚本执行时间过长

将 php-fpm.conf 的 <value name="request_terminate_timeout">0s</value> 的 0s 改成一个时间。

监控脚本

当发生 Nginx 502 Bad Gateway 错误问题时候重启 PHP-FPM进程,并发送邮件通知管理员:

#!/bin/bash  STATE=`curl --head http://www.server110.com | awk 'NR==1' | awk '{print $2}'`  if [ "$STATE" -eq "502" ]; then     /bin/bash /usr/local/webserver/php/sbin/php-fpm reload     /bin/bash /usr/local/webserver/nginx/sbin/nginx -s reload      echo "[报警]" "http error 502" $(date +"%y-%m-%d %H:%M:%S") "Reload php-fpm And Nginx" | mail -s "ERROR" [email protected] elif [ "$STATE" -ne "502" ] && [ "$STATE" -ne "200" ]; then     echo "[报警]" "Web Server Stop Working" $(date +"%y-%m-%d %H:%M:%S") | mail -s "ERROR" [email protected] fi

定时执行脚本,这里是30分钟执行一次,可以根据情况而定

vim /etc/crontab

  */30 * * * * root /root/satools/reload_php-fpm_error.sh

php-fpm.conf两个至关重要的参数,事关502 Bad gateway 和504 Gateway Time-out错误

这里规定了PHP-CGI的连接、发送和读取的时间,300秒足够用了,因此我的服务器很少出现504 Gateway Time-out这个错误。最关键的是php-fpm.conf的设置,这个会直接导致502 Bad Gateway和504 Gateway Time-out。

下面我们来仔细分析一下php-fpm.conf几个重要的参数:

php-fpm.conf有两个至关重要的参数,一个是”max_children”,另一个是”request_terminate_timeout”

我的两个设置的值一个是”40″,一个是”900″,但是这个值不是通用的,而是需要自己计算的。

计算的方式如下:

如果你的服务器性能足够好,且宽带资源足够充足,PHP脚本没 有系循环或BUG的话你可以直接将”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这个错误。

而”max_children”这个值又是怎么计算出来的呢?这个值原则上是越大越好,php-cgi的进程多 了就会处理的很快,排队的请求就会很少。设置”max_children”也需要根据服务器的性能进行设定,一般来说一台服务器正常情况下每一个php- cgi所耗费的内存在20M左右,因此我的”max_children”我设置成40个,20M*40=800M也就是说在峰值的时候所有PHP-CGI 所耗内存在800M以内,低于我的有效内存1Gb。而如果我的”max_children”设置的较小,比如5-10个,那么php-cgi就会“很 累”,处理速度也很慢,等待的时间也较长。如果长时间没有得到处理的请求就会出现504 Gateway Time-out这个错误,而正在处理的很累的那几个php-cgi如果遇到了问题就会出现502 Bad gateway这个错误。