nginx+php-fpm.sock时504,502错误解决办法
环境:
CentOS 7.1 x64
nginx-1.8.0
php-5.6.17
nginx和php通信采用的是unix socket机制
小记:
http://nginx.org/en/docs/stream/ngx_stream_core_module.html
nginx-1.9.0开始支持tcp的反向代理,编译时需要加上--with-stream参数
504
出现错误的前因
在phpMyAdmin中执行了一段非常耗时的查询语句,不一会功夫,phpMyAdmin就报如下错误
nginx日志
2016/04/02 22:28:56 [error] 15308#0: *53 upstream timed out (110: Connection timed out) while reading response header from upstream, client: 192.168.130.1, server: ssl.example.com, request: "POST /phpMyAdmin/import.php HTTP/1.1", upstream: "fastcgi://unix:/dev/shm/php-fpm.sock", host: "192.168.130.254", referrer: "https://192.168.130.254/phpMyAdmin/db_sql.php?db=isfdb&token=b9cf017794df498e0cb52518b8021c82"
2016/04/02 22:33:00 [error] 15305#0: *71 upstream timed out (110: Connection timed out) while reading response header from upstream, client: 192.168.130.1, server: ssl.example.com, request: "GET /phpMyAdmin/
注意:重启nginx无效),但只治得了一时,于时开始查找解决方案
解决办法
location ~ \.php$ {
fastcgi_connect_timeout
fastcgi_read_timeout
fastcgi_send_timeout
}
调高上面标红的3个值后,主要是read和send两项(默认Nginx超时为60),完美地解决了504错误。
并且可以配置在http,server级别,也可以配置在location级别。
factcgi_connect_{read|send|timeout}是对fastcgi_pass生效
proxy_connect_{read|send|timeout|是对proxy_pass生效
502
的确,504是解决了,但运行一段时间后,又报了502错误
nginx日志
2016/04/02 23:24:55
[error] 18748#0: *35 recv() failed (104:
Connection reset by peer) while reading response header
from upstream, client: 192.168.130.1, server: ssl.example.com,
request: "POST /phpMyAdmin/import.php HTTP/1.1", upstream:
"fastcgi://unix:/dev/shm/php-fpm.sock:", host: "192.168.130.254",
referrer:
"https://192.168.130.254/phpMyAdmin/db_sql.php?db=isfdb&token=231148330c40cfa09b03d52ccf49f38a"
php-fpm日志
[02-Apr-2016
23:24:55] WARNING: [pool www] child 18822, script
'/usr/local/nginx/html/phpMyAdmin/import.php' (request: "POST
/phpMyAdmin/import.php") execution timed
out (340.677871 sec), terminating
[02-Apr-2016
23:24:55] WARNING: [pool www] child 18822 exited on signal 15
(SIGTERM) after 396.757450 seconds from start
[02-Apr-2016
23:24:55] NOTICE: [pool www] child 19164 started
从日志上可以看到, 23:24:55的时,php-fpm的子进程18822因为等待了340.677871秒后被强行终止了并重新生成了一个新的子进程19164
但因为自动生成了新子进程,php网页还是可以正常访问的,只是该查询任务被终止了。
解决办法
max_execution_time值
php-fpm.conf中的request_terminate_timeout值
还会终止执行脚本的Worker进程。
如上,php-fpm child 18822被terminate后重新生成了新的Worker进程19164,所以nginx发现与自己通信的连接断了,就自然会返回502错误给客户端。客户端需再次发起请求重新建立新的连接,表象是刷新下浏览器即重新发起请求
所以只需将这两项的值适当调大,让PHP脚本不会因为执行时间长而被终止从而与nginx激活连接丢失。
不想改全局的php.ini,只改php-fpm的配置就可以了。这里暂且调到600秒
request_terminate_timeout = 600
补充:
nginx也要注意upstream模块中max_fail和fail_timeout。有时nginx与后端服务器(Tomcat、FastCGI)的通信只是偶然断掉,但max_fail设置太小,那么在接下来的fail_timeout时间内,nginx都会认为后端服务器无响应,都会返回502错误。
所以可以将max_fail调大一些,将fail_timeout调小一些