内容简介:就在安心养神的时候, 同事转给了我一条nginx 502的报警, 赶紧去线上一顿排查。首先得先找出哪台机器报出的(同时喊运维看下线上负载情况), 发现01机器的nginx日志在报警时间点的错误信息:recv()为接收返回数据的系统函数,基本可以先认为报错原因为
就在安心养神的时候, 同事转给了我一条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的配置文件吧
pid = /usr/local/var/run/php-fpm.pid #pid设置,一定要开启,上面是Mac平台的。默认在php安装目录中的var/run/php-fpm.pid。比如centos的在: /usr/local/php/var/run/php-fpm.pid error_log = /usr/local/var/log/php-fpm.log #错误日志,上面是Mac平台的,默认在php安装目录中的var/log/php-fpm.log,比如centos的在: /usr/local/php/var/log/php-fpm.log log_level = notice #错误级别. 上面的php-fpm.log纪录的登记。可用级别为: alert(必须立即处理), error(错误情况), warning(警告情况), notice(一般重要信息), debug(调试信息). 默认: notice. emergency_restart_threshold = 60 emergency_restart_interval = 60s #表示在emergency_restart_interval所设值内出现SIGSEGV或者SIGBUS错误的php-cgi进程数如果超过 emergency_restart_threshold个,php-fpm就会优雅重启。这两个选项一般保持默认值。0 表示 '关闭该功能'. 默认值: 0 (关闭). process_control_timeout = 0 #设置子进程接受主进程复用信号的超时时间. 可用单位: s(秒), m(分), h(小时), 或者 d(天) 默认单位: s(秒). 默认值: 0. daemonize = yes #后台执行fpm,默认值为yes,如果为了调试可以改为no。在FPM中,可以使用不同的设置来运行多个进程池。 这些设置可以针对每个进程池单独设置。 listen = 127.0.0.1:9000 #fpm监听端口,即nginx中php处理的地址,一般默认值即可。可用格式为: 'ip:port', 'port', '/path/to/unix/socket'. 每个进程池都需要设置。如果nginx和php在不同的机器上,分布式处理,就设置ip这里就可以了。 listen.backlog = -1 #backlog数,设置 listen 的半连接队列长度,-1表示无限制,由操作系统决定,此行注释掉就行。backlog含义参考:http://www.3gyou.cc/?p=41 listen.allowed_clients = 127.0.0.1 #允许访问FastCGI进程的IP白名单,设置any为不限制IP,如果要设置其他主机的nginx也能访问这台FPM进程,listen处要设置成本地可被访问的IP。默认值是any。每个地址是用逗号分隔. 如果没有设置或者为空,则允许任何服务器请求连接。 listen.owner = www listen.group = www listen.mode = 0666 #unix socket设置选项,如果使用tcp方式访问,这里注释即可。 user = www group = www #启动进程的用户和用户组,FPM 进程运行的Unix用户, 必须要设置。用户组,如果没有设置,则默认用户的组被使用。 pm = dynamic #php-fpm进程启动模式,pm可以设置为static和dynamic和ondemand #如果选择static,则进程数就数固定的,由pm.max_children指定固定的子进程数。 #如果选择dynamic,则进程数是动态变化的,由以下参数决定: pm.max_children = 50 #子进程最大数 pm.start_servers = 2 #启动时的进程数,默认值为: min_spare_servers + (max_spare_servers - min_spare_servers) / 2 pm.min_spare_servers = 1 #保证空闲进程数最小值,如果空闲进程小于此值,则创建新的子进程 pm.max_spare_servers = 3 #,保证空闲进程数最大值,如果空闲进程大于此值,此进行清理 pm.max_requests = 10000 #设置每个子进程重生之前服务的请求数. 对于可能存在内存泄漏的第三方模块来说是非常有用的. 如果设置为 '0' 则一直接受请求. 等同于 PHP_FCGI_MAX_REQUESTS 环境变量. 默认值: 0. pm.status_path = /status #FPM状态页面的网址. 如果没有设置, 则无法访问状态页面. 默认值: none. munin监控会使用到 ping.path = /ping #FPM监控页面的ping网址. 如果没有设置, 则无法访问ping页面. 该页面用于外部检测FPM是否存活并且可以响应请求. 请注意必须以斜线开头 (/)。 ping.response = pong #用于定义ping请求的返回相应. 返回为 HTTP 200 的 text/plain 格式文本. 默认值: pong. access.log = log/$pool.access.log #每一个请求的访问日志,默认是关闭的。 access.format = "%R - %u %t \"%m %r%Q%q\" %s %f %{mili}d %{kilo}M %C%%" #设定访问日志的格式。 slowlog = log/$pool.log.slow #慢请求的记录日志,配合request_slowlog_timeout使用,默认关闭 request_slowlog_timeout = 10s #当一个请求该设置的超时时间后,就会将对应的PHP调用堆栈信息完整写入到慢日志中. 设置为 '0' 表示 'Off' request_terminate_timeout = 0 #设置单个请求的超时中止时间. 该选项可能会对php.ini设置中的'max_execution_time'因为某些特殊原因没有中止运行的脚本有用. 设置为 '0' 表示 'Off'.当经常出现502错误时可以尝试更改此选项。 rlimit_files = 1024 #设置文件打开描述符的rlimit限制. 默认值: 系统定义值默认可打开句柄是1024,可使用 ulimit -n查看,ulimit -n 2048修改。 rlimit_core = 0 #设置核心rlimit最大限制值. 可用值: 'unlimited' 、0或者正整数. 默认值: 系统定义值. chroot = #启动时的Chroot目录. 所定义的目录需要是绝对路径. 如果没有设置, 则chroot不被使用. chdir = #设置启动目录,启动时会自动Chdir到该目录. 所定义的目录需要是绝对路径. 默认值: 当前目录,或者/目录(chroot时) catch_workers_output = yes #重定向运行过程中的stdout和stderr到主要的错误日志文件中. 如果没有设置, stdout 和 stderr 将会根据FastCGI的规则被重定向到 /dev/null . 默认值: 空. 复制代码
摘自 www.zybuluo.com/phper/note/…
单独拿出几个重要配置项:
pm = static #php-fpm进程启动模式,pm可以设置为static和dynamic和ondemand #如果选择static,则进程数就数固定的,由pm.max_children指定固定的子进程数。 pm.max_children = 500 #子进程最大数 request_terminate_timeout=30 #设置单个请求的超时中止时间. 该选项可能会对php.ini设置中的'max_execution_time'因为某些特殊原因没有中止运行的脚本有用. 设置为 '0' 表示 'Off'.当经常出现502错误时可以尝试更改此选项。 request_slowlog_timeout=3 #当一个请求该设置的超时时间后,就会将对应的PHP调用堆栈信息完整写入到慢日志中. 设置为 '0' 表示 'Off' pm.max_requests=10000 #设置每个子进程重生之前服务的请求数. 对于可能存在内存泄漏的第三方模块来说是非常有用的. 如果设置为 '0' 则一直接受请求. 等同于 PHP_FCGI_MAX_REQUESTS 环境变量. 默认值: 0. 复制代码
开始学习
以上便是我们线上的主要配置,主要还是集中在了 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: "test.com/index.php"
2)PHP-FPM报错日志:
WARNING: child 25708 exited on signal 15 (SIGTERM) after 21008.883410 seconds from start 复制代码
所以只需将这两项的值调大一些就可以让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调小一些。
摘自最棒的51cto: blog.51cto.com/nanchunle/1…
自圆其说
对于nginx的upstream模块并不是很了解,回忆当时报错场景,确实发现日志里面前后报了几个不同接口同样的错误,也可能是其他接口影响了此接口,只是它正好被报警系统抓取到。
反思
思考问题可能过于片面,没有解决问题的一套体系、思路,容易绕弯路、甚至南辕北辙。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。