我们的一个web项目,由于新上城市增多,导致访问量增大,DB压力增大,作为提供接口的业务方,最近被下游反馈大量请求“502”。
502,bad gateway,一般都是upstream(这里就是php)出错,对于php,造成502的原因常见的就是脚本执行超过timeout设置时间,或者timeout设置过大,导致php进程长时间不能被释放,没有空闲worker进程来接客。
我们的项目就是php执行时间设置过短导致的,对于这种情况,可以先适当增大php的执行时间,先保证清除502,优化的事情毕竟要花更多的时间。
控制php执行时间的选项有两个,在php.ini中 max_execution_time 和php-fpm中 request_terminate_timeout,其中 request_terminate_timeout 可以覆盖 max_execution_time,所以如果不想改全局的php.ini,那只改php-fpm的配置就可以了。
下边我就来详细的分析一下为什么php脚本执行超出设置时间会导致nginx返回502。
先来布景,让问题复现:
nginx和php分别只启动一个worker,方便追踪。
php-fpm的request_terminate_timeout设置为3S。
测试脚本test.php
sleep(20);echo 'ok';
go go go:
在浏览器访问www.v.com/test.php,3S后如期出现...404???what???
出师不利啊,赶紧看看nginx的配置文件
这个location配置是当发生5xx错误时跳转到一个好看点的界面,但是我在/usr/share/nginx/html下并没有50x.html这个文件。所以搞了个404出来。这不是很影响我判断问题的准确性?直接注释掉!再次访问,等待3S,终于'正常'的界面出来了。
环境好了,下边就上套路,按照web问题的排查套路走一遍,先看看错误日志吧:
nginx:
报错都是 recv() failed (104: Connection reset by peer。
recv时失败了,连接被重置了。为啥连接被重置了?难道一言不合。
我们在看看php-fpm的错误日志:
(注意php-fpm中php_admin_value[error_log]选项指定php的错误日志,会覆盖php.ini中的。但是这里不是看php的错误,而是看php-fpm的错误。php-fpm的错误日志由php-fpm.conf中的error_log选项指定。)
每一次请求都是产生2个WARNING和1个NOTICE:
WARNING:脚本执行超时了,终止了。
WARNING:子进程收到SIGTERM信号退出了。
NOTICE:启了一个新的子进程(因为我设置的pm.min_spare_servers = 1)
新闻热点
疑难解答