nginx 50x故障分析

近期经历了一系列的nginx 50x错误,在此总结一下如何处理错误,以及各个错误可能根源。

错误处理提前需要了解

1 代码发布时间

2 php error log

3 nginx access log

4 nginx error log

5 每个接口访问时间log

错误处理流程

1. 确认是否有人刚发过代码。根据故障时间线&代码发布时间线,如果能找到精确对应关系,基本上可以判定这次事故的原因为代码发布事故,回滚代码往往是解决问题最直接有效的方式。

2. 线上测试服务器,测试接口。线上测试服务器访问量较小,不存在nginx访问压力过大造成的其他隐患,可以直接测试后端的存储服务器是否有故障。

3. 从日志挖掘有效信息。

3.1 php日志,检查是否有大量的php报错信息。

3.2 nginx日志,确定接口开始出现大量50x错误的时间点

3.3 接口请求时间日志(自行记录),查看接口请求时间是否有异常。

3.4 配合xhprof等工具,分析耗时请求的时间分布。

50x原因分析:

分析前需要了解

1. php.ini

2. php-fpm.conf (访问<?php phpinfo(); 查找"Loaded Configuration File"可以找到php-fpm.conf的位置 php -i | grep PATH | grep php; cd ../etc # 找到php-fpm.conf存储位置)

3. nginx.conf

504:

1. 在nginx.conf keepalive_timeout时间内php-fpm没有返回结果

2. php-fpm设置的过少,请求过多达到php-fpm.conf pm.max_children

pm = dynamic
; The number of child processes to be created when pm is set to 'static' and the 
; maximum number of child processes to be created when pm is set to 'dynamic'.
; This value sets the limit on the number of simultaneous requests that will be
; served. Equivalent to the ApacheMaxClients directive with mpm_prefork.
; Equivalent to the PHP_FCGI_CHILDREN environment variable in the original PHP 
; CGI.
; Note: Used when pm is set to either 'static' or 'dynamic'
; Note: This value is mandatory.
pm.max_children = 4096

; The number of child processes created on startup.
; Note: Used only when pm is set to 'dynamic'
; Default Value: min_spare_servers + (max_spare_servers - min_spare_servers) / 2 
pm.start_servers = 768 

; The desired minimum number of idle server processes.
; Note: Used only when pm is set to 'dynamic'
; Note: Mandatory when pm is set to 'dynamic'
pm.min_spare_servers = 512 

这里面我觉得最重要的参数是max_children: 代表了dynamic状态下,fpm的最大数量。

3. nginx请求排队超时

fpm到达上限,nginx会将fpm放入请求队列,如果在keepalive_timeout时间内始终没有空闲fpm,返回504

504的access&error log

2013/08/14 20:48:31 [error] 20370#0: *1948283 upstream timed out (110: Connection timed out) while reading response header from upstream, client: 127.0.0.1, server: lv.com.cn, request: "GET /a.php HTTP/1.1", upstream: "fastcgi://127.0.0.1:9000", host: "lv.com"
127.0.0.1 - - [14/Aug/2013:20:48:31 +0800] "GET /a.php HTTP/1.1" 504 183 "-" "curl/7.15.5 (x86_64-redhat-linux-gnu) libcurl/7.15.5 OpenSSL/0.9.8b zlib/1.2.3 libidn/0.6.5"

502原因分析,502错误出现的原因一般都不是nginx的问题。

1. php-fpm request_terminate_timeout超时

request_terminate_timeout用于设置当某个php脚本运行最长时间,若超出php-fpm进程管理器强行中止当前程序,并关闭fastcgi和nginx的网络连接,然后nginx中就会出现Connection reset by peer的错误了。

warning: php.ini中的max_execution_time在fpm中一般是不生效的,因为max_execution_time不计入网络请求,系统请求,对于网络请求,大部分都是访问数据库,很少有纯粹的计算,因此很难超时。

盲目的延长request_terminate_timeout并不能解决问题,一般对于线上请求1s就已经非常长了,所以如果超时,更应该去查找哪个步骤耗时,并优化。

2. php-fpm进程出错

想写一个将php-fpm出现段错误,意外退出也是一件比较难的事情。大部分情况都是因为某些扩展的某些bug。(redis->pconnect遇到过, 如下)

PHP Notice:  Redis::setex(): send of 869 bytes failed with errno=32 Broken pipe in /data/home/xxx.php on line 43

3. php.ini的memory_limit过小

4. nginx.conf client head buffer,fastcgi buffer size过小

nginx错误日志: pstream sent too big header while reading response header from upstream

502的access&error log

2013/08/23 17:14:26 [error] 20370#0: *2529767 recv() failed (104: Connection reset by peer) while reading response header from upstream, client: 10.18.128.37, server: lv.com.cn, request: "GET /a.php HTTP/1.1", upstream: "fastcgi://127.0.0.1:9000", host: "lv.com"
10.18.128.37 - - [23/Aug/2013:17:14:26 +0800] "GET /a.php HTTP/1.1" 502 575 "-" "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.17 (KHTML, like Gecko) Chrome/24.0.1312.57 Safari/537.17"

参考文献
http://blog.xiuwz.com/2012/09/25/php-max-execution-time-internal/

http://www.cnblogs.com/zhengyun_ustc/archive/2013/06/06/3120967.html

原文地址:https://www.cnblogs.com/codesay/p/3278717.html