1、502 Bad Gateway
官方解释:作为网关或者代理工作的服务器尝试执行请求时,从上游服务器接收到无效的响应。
上面说到nginx收到了无法理解的响应,什么是无法理解的响应呢?
nginx无法与php-fpm进行连接。
nginx在连接php-fpm一段时间后发现与php-fpm的连接被断开。
那么什么时候会出现上面的情况呢?
php-fpm没有启动,nginx无法将请求交给php-fpm
php-fpm运行脚本超时,php-fpm终止了脚本的执行和执行脚本的Worker进程,nginx发现自己与php-fpm的连接断开
php-fpm没有启动
我们关闭php-fpm,刷新页面,发现返回502错误:
php-fpm请求超时
我们首先将php-fpm.conf中的max_terminate_request改成5s:
request_terminate_timeout = 5
在php脚本中添加如下语句:
sleep(20);
2、其他502原因的检测
1、查看当前的PHP FastCGI进程数是否够用
netstat -anpo | grep "php-cgi" | wc –l
如果实际使用的【FastCGI进程数】接近预设的【FastCGI进程数】,那么,说明【FastCGI进程数】不够用,需要增大。
2、部分PHP程序的执行时间超过了Nginx的等待时间
可以适当增加nginx.conf配置文件中FastCGI的timeout时间。php.ini中memory_limit设低了会出错,修改了php.ini的memory_limit为64M,重启nginx,如果发现恢复了,那么就是PHP的内存不足的原因。
3、max-children和max-requests
主机上运行着nginx php(fpm) xcache的话,访问量日均 300W pv左右。如果是近期出现php页面打开很慢,cpu使用率突然降至很低,系统负载突然升至很高,查看网卡的流量,也会发现突然降到了很低这样的情况,而且这种情况只持续数秒钟就恢复,这时检查php-fpm的日志文件发现了一些线索:
1)Sep 30 08:32:23.289973 \[NOTICE\] fpm\_unix\_init\_main(), line 271: getrlimit(nofile): max:51200, cur:51200
2)Sep 30 08:32:23.290212 \[NOTICE\] fpm\_sockets\_init\_main(), line 371: using inherited socket fd=10, “127.0.0.1:9000″
3)Sep 30 08:32:23.290342 \[NOTICE\] fpm\_event\_init\_main(), line 109: libevent: using epoll
4)Sep 30 08:32:23.296426 \[NOTICE\] fpm\_init(), line 47: fpm is running, pid 30587
看显示的这几句的前面,是1000多行的关闭children和开启children的日志。因为php-fpm有一个参数 max_requests,该参数指明每个children最多处理多少个请求后便会被关闭,默认的设置是500。因为php是把请求轮询给每个children,在大流量下,每个children到达max_requests所用的时间都差不多,这样就造成所有的children基本上在同一时间被关闭。
在这期间,nginx无法将php文件转交给php-fpm处理,所以cpu会降至很低,不用处理php,更不用执行sql,而负载会升至很高,关闭和开启children、nginx等待php-fpm,网卡流量也降至很低,nginx无法生成数据传输给客户端。
解决方式:增加children的数量,并且将 max_requests 设置为 0 或者一个比较大的值,打开 /usr/local/php/etc/php-fpm.conf,调大以下两个参数,但是要根据主机实际情况,数值过大也不行。然后再重启php-fpm,就能恢复了。
4、增加缓冲区容量大小
将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、PHP脚本的最大执行时间
max_execution_time //php.ini
request_terminate_timeout //php.ini
这两项都是用来配置PHP脚本的最大执行时间。超时时php-fpm会终止脚本的执行,同时还会终止执行脚本的Worker进程。
如上,php-fpm child 18822被terminate后重新生成了新的Worker进程19164,所以nginx发现与自己通信的连接断了,就自然会返回502错误给客户端。客户端需再次发起请求重新建立新的连接,表象是刷新下浏览器即重新发起请求
所以只需将这两项的值适当调大,让PHP脚本不会因为执行时间长而被终止从而与nginx激活连接丢失。
request_terminate_timeout优先级高于max_execution_time,不想改全局的php.ini,只改php-fpm的配置就可以了。这里暂且调到600秒
request_terminate_timeout = 600
3、504 Bad Gateway timeout
504 即 nginx 超过了自己设置的超时时间,不等待 php-fpm 的返回结果,直接给客户端返回 504 错误。但是此时 php-fpm 依然还在处理请求(在没有超出自己的超时时间的情况下).
这里有三个相关的配置:
3、504 Bad Gateway timeout
504 即 nginx 超过了自己设置的超时时间,不等待 php-fpm 的返回结果,直接给客户端返回 504 错误。但是此时 php-fpm 依然还在处理请求(在没有超出自己的超时时间的情况下).
这里有三个相关的配置:
网关超时,客户端所发出的请求没有到达网关,在限定时间内没有得到php-fpm,或者完成php-fpm的传输数据的工作而超时 。
比方说:即nginx的worker去php-fpm进程池去处理,但是没有fpm进程可以使用了,等啊等,还是没有,返回504。
场景
nginx的fastcgi模块有一个fastcgi_read_timeout配置,它表示从FastCGI server获取数据的超时时间。
如果超过这个配置客户端就是收到504的响应。
比如执行了一段非常耗时的查询语句,nginx的相关fastcgi等待配置超时后,就会返回504,但是php-fpm还在运行。
解决办法网关超时,客户端所发出的请求没有到达网关,在限定时间内没有得到php-fpm,或者完成php-fpm的传输数据的工作而超时 。
比方说:即nginx的worker去php-fpm进程池去处理,但是没有fpm进程可以使用了,等啊等,还是没有,返回504。
场景
nginx的fastcgi模块有一个fastcgi_read_timeout配置,它表示从FastCGI server获取数据的超时时间。
如果超过这个配置客户端就是收到504的响应。
比如执行了一段非常耗时的查询语句,nginx的相关fastcgi等待配置超时后,就会返回504,但是php-fpm还在运行。
解决办法
location ~ \.php$ {
fastcgi_connect_timeout 180;//优化点
fastcgi_read_timeout 600;//优化点
fastcgi_send_timeout 600;//优化点
fastcgi\_pass unix:/tmp/php-fpm.sock;
fastcgi\_index index.php;
include fastcgi.conf;
}
调高上面标红的3个值后,主要是read和send两项(默认Nginx超时为60),完美地解决了504错误。
并且可以配置在http,server级别,也可以配置在location级别。
factcgi_connect_{read|send|timeout}是对fastcgi_pass生效
proxy_connect_{read|send|timeout|是对proxy_pass生效