您的位置:首页 > 其它

记录一次lnmp故障报告

2017-04-20 15:35 274 查看
业务架构图:



nginx 状态监控图:



本次故障的表现为:前端php页面无法打开,空白页或者502错误。

nginx中php配置如下:

location ~ \.php$ {
root                /xxx/xxx;
fastcgi_pass        unix:/dev/shm/php-cgi.sock;
fastcgi_index       index.php;
include             fastcgi.conf;
access_log          logs/fastcgi.log ngx_Web_log;
}


首先查看 logs/fastcgi.log 如下:

统计nginx和php交互状态码如下:

总数    状态码
233694    499
55891    200
34029    302
100    500


可以发现日志里大量的出现了499的状态码,百度说明:

nginx源码:

/*
* HTTP does notdefine the code for the case when a client closed
* the connectionwhile we are processing its request so we introduce
* own code to logsuch situation when a client has closed the connection
* before we even tryto send the HTTP header to it
*/
#define NGX_HTTP_CLIENT_CLOSED_REQUEST 499


这是nginx定义的一个状态码,用于表示这样的错误:服务器返回http头之前,客户端就提前关闭了http连接

简单来说,由于后端服务处理时间过长而导致前端nginx等待超时断开。

查看nginx状态监控图发现active在这个时间段,活动连接一直保持在3000左右,根据经验,日常活动连接数一般在900左右,这次突然上了3000,有可能是攻击所致。

1. 查看网络连接数:netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'
2. 过滤fastcgi.log访问连接ip数量,通过nginx deny禁止掉可疑ip。

经过上面的处理后,活动连接数的变化不是很明显。于是在程序中添加info.php来测试php响应情况。

测试结果:
重启php-fpm 大概10秒后,就无法再次访问info.php ,大致估计是因为php accept queue 被占满所致。查看一下内核参数是否正常:

# ulimit -n     # 文件最大描述符

# sysctl -a | egrep "tw|backlog|cookies|synack|soconnmax"

net.core.netdev_max_backlog = 262144         # 程序accept queue队列长度
net.ipv4.tcp_max_syn_backlog = 262144         # syn queue 队列长度
net.ipv4.tcp_max_tw_buckets = 6000             # 保持 TIME_WAIT 最大值
net.ipv4.tcp_synack_retries = 1             # 服务端发送syn + ack 包次数限制
net.ipv4.tcp_syncookies = 1                 # 启用syn cookies,当syn等待队列出现溢出时,启用cookies来处理,可以防范少量的syn攻击
net.ipv4.tcp_tw_recycle = 1                 # TIME_WAIT 状态快速回收
net.ipv4.tcp_tw_reuse = 1                     # TIME_WAIT 状态快速重用


一些常用的内核参数都是没有问题的。

问题总汇下:
1. nginx fastcgi.log 大量返回499
2. nginx 活动连接数远远高于正常业务并发
3. php 重启很快就失去响应。

这时候发现问题排查起来有点困难了,于是和开发、数据库沟通下。

沟通下来的结果就是:
早上数据库被DBA调整过。出现过停止服务的状态,而开发人员通过java开发的api是要去连接数据库的。
请求从nginx进来,通过php去调用java接口,而java接口无法连接上数据库无法将数据返回给php,所以nginx等待超时返回499

沟通后思路清晰了,早上DBA动MySQL没有通知到大家,造成了这一系列连锁反应。可见,通知和沟通是很重要的。

重启java程序,php正常返回结果,业务恢复正常。

最后,做技术不能只是关注技术本身,熟悉业务流程和沟通也是作为运维人员必备的技能。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: