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 = 60max_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 restart6、有时候也可能是自己修改过下面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:9000php 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重启 cron
service crond restart脚本将会每隔2分钟运行一次得到状态码502的时候将自动重启 php-fpm.
写在最后
最近因为502的问题伤神,查看日志 -> 推测可能造成问题的原因 -> 修改与测试 ->反复失败。并且502错误出现的时间非常有规律每隔30分钟报错一次。并且都是在半点和整点的时间出现。(通过脚本检测网页状态返回503打印一条日志得到的结果)
最后博主使用排除法,移除 eAccelerator,502错误不再复现。推测初始化安装的 eAccelerator 版本与PHP版本不兼容导致。






