见的原因可能是php-cgi进程数不够用、php执行时间长(mysql慢)、或者是php-cgi进程死掉,都会出现502错误。
1. 在安装好的环境中,运行一段时间出现502问题,一般是因为默认php-cgi进程是5个,可能因为phpcgi进程不够用而造成502,需要修改/usr/local/php/etc/php-fpm.conf 将其中的max_children值适当增加。
2. php执行超时,修改/usr/local/php/etc/php.ini 将max_execution_time 改为300
3. 磁盘空间不足,可以使用 # df -h命令查看磁盘使用量
4. php-cgi进程死掉了。
通常的排查方法如下:
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;
......
}
增加了fastcgi的相应请求时间。但是我在实际中碰到了这个问题,设置到500,还是会出现,只是比我设置120的时候要少一些。后来发现主要是在一些post或者数据库操作的时候出现这种情况,静态页面是不会出现的。
反复的查问题,调试,也加大了CGI的进程数。
128
256再加上去可能会变得很慢。占用内存大了。
在php-fpm.conf设置中还有一项,可能当时没注意到,无意中改了这个值。
request_terminate_timeout
这个值是max_execution_time,就是fast-cgi的执行脚本时间。
0s
0s为关闭,就是无限执行下去。(当时装的时候没仔细看就改了一个数字)
发现,问题解决了,执行很长时间也不会出错了
优化fastcgi中,还可以改改这个值5s 。看看效果
4、头部太大
nginx和apache一样,有前段缓冲限制,可以调整缓冲参数
fastcgi_buffer_size 32k;
fastcgi_buffers 8 32k;
如果你使用的是nginx的负载均衡Proxying,调整
proxy_buffer_size 16k;
proxy_buffers 4 16k;
5、https转发配置错误
正确的配置方法
server_name www.mydomain.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;
}
6、将nginx的error log打开,发现”pstream sent too big header while reading response header from upstream”这样的错误提示,查阅了一下资料,大意是nginx缓冲区有一个bug造成的,我们网站的页面消耗占用缓冲区可能过大。参考老外写的修 改办法增加了缓冲区容量大小设置,502问题彻底解决,后来系统管理员又对参数做了调整只保留了2个设置参数:client head buffer,fastcgi buffer size。
http://blog.rackcorp.com/?p=14
7、一台服务器上运行着nginx php(fpm) xcache,访问量日均 300W pv左右
最近经常会出现这样的情况: php页面打开很慢,cpu使用率突然降至很低,系统负载突然升至很高,查看网卡的流量,也会发现突然降到了很低。这种情况只持续数秒钟就恢复了
检查php-fpm的日志文件发现了一些线索
Sep 30 08:32:23.289973 [NOTICE] fpm_unix_init_main(), line 271: getrlimit(nofile): max:51200, cur:51200
Sep 30 08:32:23.290212 [NOTICE] fpm_sockets_init_main(), line 371: using inherited socket fd=10,
Sep 30 08:32:23.290342 [NOTICE] fpm_event_init_main(), line 109: libevent: using epoll
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,在大流量 下,每个childre到达max_requests所用的时间都差不多,这样就造成所有的children基本上在同一时间被关闭。
在这期间,nginx无法将php文件转交给php-fpm处理,所以cpu会降至很低(不用处理php,更不用执行sql),而负载会升至很高(关闭和开启children、nginx等待php-fpm),网卡流量也降至很低(nginx无法生成数据传输给客户端)
解决问题很简单,增加children的数量,并且将 max_requests 设置未 0 或者一个比较大的值,重启php-fpm
Nginx 504 Gateway Time-out的含义是所请求的网关没有请求到,简单来说就是没有请求到可以执行的PHP-CGI。
解决这两个问题其实是需要综合思考的,一般来说Nginx 502 Bad Gateway和php-fpm.conf的设置有关,而Nginx 504 Gateway Time-out则是与nginx.conf的设置有关。
而正确的设置需要考虑服务器自身的性能和访客的数量等多重因素。
fastcgi_connect_timeout 300s;
fastcgi_send_timeout 300s;
fastcgi_read_timeout 300s;
fastcgi_buffer_size 128k;
fastcgi_buffers 8 128k;#8 128
fastcgi_busy_buffers_size 256k;
fastcgi_temp_file_write_size 256k;
fastcgi_intercept_errors on;
这里最主要的设置是前三条,即
fastcgi_connect_timeout 300s;
fastcgi_send_timeout 300s;
fastcgi_read_timeout 300s;
这里规定了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这个错误