Nginx 502 Bad Gateway 的含义是请求的PHP-CGI已经执行,但是由于某种原因(一般是读取资源的问题)没有执行完毕而导致 PHP-CGI 进程终止,一般来说Nginx 502 Bad Gateway和php-fpm.conf的设置有关。
常规办法
常见的原因可能是php-cgi进程数不够用、php执行时间长(mysql慢)、或者是php-cgi进程死掉,都会出现502错误。在安装好的环境中,运行一段时间出现502问题,一般是因为默认php-cgi进程是5个,可能因为phpcgi进程不够用而造成502,需要修改/usr/local/php/etc/php-fpm.conf 将其中的max_children值适当增加。
php执行超时,修改/usr/local/php/etc/php.ini 将max_execution_time 改为300,设置为0则无限制,脚本会一直执行下去,直到执行结束。
磁盘空间不足,可以使用 # df -h命令查看磁盘使用量
php-cgi进程死掉了。
配置出错
文件打开数量限制
类eAccelerator/opcache/Xcached等PHP性能优化程序不兼容导致的,卸载之即可。 例:cd ~/lnmp1.5full && ./addons.sh uninstall eAccelerator
通常的排查方法如下:
1、查看php fastcgi的进程数(max_children值)# netstat -anop | grep php-cgi | wc -l
# netstat -anpo | grep php-fpm | wc -l
假如显示是5
2、查看当前进程# ps aux | grep php-fpm
观察fastcgi/php-fpm进程数,假如使用的进程数等于或高于5个,说明需要增加。
3、调整/usr/local/php/etc/php-fpm.conf 的相关设置pm.max_children = 5
request_terminate_timeout = 60
max_children最多5个进程,按照每个进程20MB内存,最多100MB。也就是1分钟。max_children增多,则php-cgi的进程多了就会处理的很快,排队的请求就会很少。 但是设置max_children也需要根据服务器的性能进行设定,一般来说一台服务器正常情况下每一个php-cgi所耗费的内存在20M左右。根据自己服务器购买的内存来实际决定。
request_terminate_timeout 执行的时间为60秒,request_terminate_timeout值可以根据服务器的性能进行设定。一般来说性能越好你可以设置越高,20分钟-30分钟都可以。
4、部分PHP程序的执行时间超过了Nginx的等待时间,可以适当增加nginx.conf配置文件中fastcgi的timeout时间,例如:http
{
……
fastcgi_connect_timeout 300;
fastcgi_send_timeout 300;
fastcgi_read_timeout 300;
……
}
5、减少FastCGI的请求次数,尽量维持buffers不变:vi /usr/local/nginx/conf/nginx.conf
修改为:fastcgi_buffer_size 64k;
fastcgi_buffers 2 64k;
fastcgi_busy_buffers_size 128k;
fastcgi_temp_file_write_size 50M;
然后重启Nginx:/etc/init.d/nginx restart
6、有时候也可能是自己修改过下面2处的配置,导致nginx配置文件里的设置和php-fpm上的设置不一样也会502。如果使用unix套接字,修改/usr/local/php/etc/php-fpm.conf 里设置,php 5.2为:
/tmp/php-cgi.sock
php 5.3及以上版本为listen = /tmp/php-cgi.sock ,同时/usr/local/nginx/conf/nginx.conf 及其/usr/local/nginx/conf/vhost/ 下面的虚拟主机配置里的fastcgi_pass unix:/tmp/php-cgi.sock; 不一致就必定502。有时候unix套接字模式下可能会502,可以尝试改成tcp/ip的方式 php 5.2下:/tmp/php-cgi.sock
替换为
127.0.0.1:9000
php 5.3及以上版本listen = /tmp/php-cgi.sock替换为listen = 127.0.0.1:9000,nginx配置文件及虚拟主机配置文件里fastcgi_pass unix:/tmp/php-cgi.sock;替换为fastcgi_pass 127.0.0.1:9000; 之后重启试试。
7、php打开文件数的限制可能也会导致502错误
编辑 /etc/security/limits.conf 加上:* soft nofile 65535
* hard nofile 65535
编辑/etc/sysctl.conf 底部添加fs.file-max=65535
再添加到自启动项echo "ulimit -SHn 65535" >> /etc/rc.local
打开php-fpm.conf 找到 rlimit_files 改成:65535 如果没有rlimit这项请自己加上rlimit_files = 65535
重启/etc/init.d/php-fpm restart
万不得已
如果以上方法均无法解决
替换修改CheckURL的链接地址,复制下面的代码并保存为 check502.sh (使用军哥LNMP一键脚本安装的在tools目录中可以找到)#!/bin/bash
time="$(date +"%Y%m%d-%H:%M")"
CheckURL="https://yourdomain.com"
STATUS_CODE=`curl -o /dev/null -m 10 --connect-timeout 10 -s -w %{http_code} $CheckURL`
#echo "$CheckURL Status Code:\t$STATUS_CODE"
if [ "$STATUS_CODE" = "502" ]; then
/etc/init.d/php-fpm restart
echo " $time 监测页: $CheckURL 状态码: $STATUS_CODE 行为: 异常&重启" >> /var/log/httpcode.log
fi
赋予sh文件可执行权限chmod a+x check502.sh
加入cron定时任务*/2 * * * * bash /路径/check502.sh
重启 cronservice crond restart
脚本将会每隔2分钟运行一次得到状态码502的时候将自动重启 php-fpm.
写在最后
最近因为502的问题伤神,查看日志 -> 推测可能造成问题的原因 -> 修改与测试 ->反复失败。并且502错误出现的时间非常有规律每隔30分钟报错一次。并且都是在半点和整点的时间出现。(通过脚本检测网页状态返回503打印一条日志得到的结果)
最后博主使用排除法,移除 eAccelerator,502错误不再复现。推测初始化安装的 eAccelerator 版本与PHP版本不兼容导致。