安心倒计时
忙完了今天的工作, 终于到了周五,可以好好休息下了。
睡梦惊醒
就在安心养神的时候, 同事转给了我一条nginx 502的报警, 赶紧去线上一顿排查。
首先得先找出哪台机器报出的(同时喊运维看下线上负载情况), 发现01机器的nginx日志在报警时间点的错误信息:
*272881176 recv() failed (104: Connection reset by peer) while reading response header from upstream, client: xx.xx.xx.xx, server: , request: "POST /xxx/xxx HTTP/1.1", upstream: "fastcgi://127.0.0.1:9000", host:
"xx.xx.xx.xx:8081"
recv()为接收返回数据的系统函数,基本可以先认为报错原因为
Nginx发现某服务与自己通信的连接断掉了,就会返回给客户端502错误。
那么nginx是从哪里接收数据呢,报错信息同样很明显,fastcgi://127.0.0.1:9000
思考缘由
同样思考为什么php的处理进程会中断呢?
莫非执行任务超时,fpm主动杀死?
又莫非系统资源不足,系统杀死?
又莫非?
同样针对这两种情况,排查结果:
报警的此接口并不是特别复杂的接口,执行时间也并不长,以前也并未出现过问题
通过zabbix、埋点监控、系统负载查看,cpu、内存、fpm整体进程情况也比较正常
顺便也看了下 fpm的错误日志、慢日志,也没有什么收获(此处很可能会忽略掉了重要信息)
蛛丝马迹
于是既然认为是fpm出了问题,就调研下fpm的配置文件吧
摘自 https://www.zybuluo.com/phper/note/89081
单独拿出几个重要配置项:
开始学习
以上便是我们线上的主要配置,主要还是集中在了 request_terminate_timeout 这个参数上。它和php.ini的 max_execution_time 有什么区别
set_time_limit()函数和配置指令max_execution_time只影响脚本本身执行的时间。任何发生在诸如使用system()的系统调用,流操作,数据库操作等的脚本执行的最大时间不包括其中,而 request_terminate_timeout 是包含所有时间的
php.ini配置时间同样也为30,但是相比而言,request_terminate_timeout时间会更短。
回归正题
但前文我们明明说了,这个接口并不是很复杂啊。..应该不会超时啊,当时第三方服务也没有什么异常情况,fpm错误日志也并没有这个超时错误信息。各个依赖的系统负载都还处于比较低峰期状态
在疑问中结束了今天的工作,回来打算写一下分享今天的调试经历,在搜索文档的时候又发现了这么一句话:
复制别人文章
Nginx 502 Bad Gateway错误
在php.ini和php-fpm.conf中分别有这样两个配置项:max_execution_time和request_terminate_timeout。
这两项都是用来配置一个PHP脚本的最大执行时间的。当超过这个时间时,PHP-FPM不只会终止脚本的执行,
还会终止执行脚本的Worker进程。所以Nginx会发现与自己通信的连接断掉了,就会返回给客户端502错误。
以PHP-FPM的request_terminate_timeout=30秒时为例,报502 Bad Gateway错误的具体信息如下:
1)Nginx错误访问日志:
2013/09/19 01:09:00 [error] 27600#0: *78887 recv() failed (104: Connection reset by peer) while reading response header from upstream,
client: 192.168.1.101, server: test.com, request: "POST /index.php HTTP/1.1", upstream: "fastcgi://unix:/dev/shm/php-fcgi.sock:",
host: "test.com", referrer: "http://test.com/index.php"
2)PHP-FPM报错日志:
所以只需将这两项的值调大一些就可以让PHP脚本不会因为执行时间长而被终止了。
request_terminate_timeout可以覆盖max_execution_time,所以如果不想改全局的php.ini,那只改PHP-FPM的配置就可以了。
此外要注意的是Nginx的upstream模块中的max_fail和fail_timeout两项。有时Nginx与上游服务器(如Tomcat、FastCGI)的通信只是偶然断掉了,但max_fail如果设置的比较小的话,那么在接下来的fail_timeout时间内,Nginx都会认为上游服务器挂掉了,都会返回502错误。所以可以将max_fail调大一些,将fail_timeout调小一些。
摘自: http://blog.51cto.com/nanchunle/1657410
自圆其说
对于nginx的upstream模块并不是很了解,回忆当时报错场景,确实发现日志里面前后报了几个不同接口同样的错误,也可能是其他接口影响了此接口,只是它正好被报警系统抓取到。
反思
思考问题可能过于片面,没有解决问题的一套体系、思路,容易绕弯路、甚至南辕北辙。
结论
这是一篇没有结论的文章.
后续会尝试复现此场景,希望大家持续关注。
领取专属 10元无门槛券
私享最新 技术干货