应用偶发性访问异常深度分析

团队介绍

Guide reading

我们是光大科技有限公司智能云计算部运维服务团队系统运维项目组,致力保障和服务集团各业务系统操作系统、中间件和数据库的稳定、安全、高效的运转,降低集团各业务系统以及业务运行的风险,为集体信息化建设保驾护航。我们的团队拥有经验丰富的操作系统、中间件和数据库领域的专家,将不定期分享运维领域的原创技术文章和实践经验,共同探索金融科技领域IT运维的最佳实践和发展趋势。

应用偶发性访问异常

深度分析

Part

01

问题描述

近段时间监控平台时常会出现监控系统页面状态的告警,奇怪的是告警持续时间很短,不用干预也可以自动恢复,告警发生时互联网客户端访问有时正常,有时会显示错误提示页面。

应用偶发性访问异常深度分析

图 1 监控平台告警截图

Part

02

排查步骤

1

排查告警系统  

首先排查告警的系统有无问题,系统架构如下:

应用偶发性访问异常深度分析

图 2 系统架构

登录后台服务器/监控平台,查看系统资源情况:

应用偶发性访问异常深度分析

图 3 服务器性能指标

如上图所示排查结果:

  • 业务服务器CPU、内存、磁盘、I/O、网络带宽等正常,整体资源利用率不高。

  • 查看服务器系统日志无集中报错信息。

  • 查看业务系统日志无报错信息。

初步怀疑故障时上层服务没有将请求连接发送给业务系统,期间咨询基础资源组网络情况,故障时间段内排查后无异常,下一步排查上层nginx反向代理服务。

2

排查上层服务  

  1. 登录其中一台nginx节点,top命令查看系统资源,如图4所示,资源利用不高。

  2. 查看nginx error日志,无特殊报错。

  3. 查看access日志,统计下有无异常状态请求,如图5所示,其中分析日志后404状态请求均为找不到favicon.ico图标报错,并无其他异常。

应用偶发性访问异常深度分析

图 4 nginx服务器资源情况

应用偶发性访问异常深度分析

图 5 统计access日志结果

考虑到nginx服务上也代理了其他系统应用,查看nginx连接情况如下:

应用偶发性访问异常深度分析

图 6 nginx服务tcp连接情况

如图6所示,nginx单台平均在1850的并发量,对于复用的nginx代理服务器来说并发量太小,怀疑并发配置太小导致连接被丢弃,查看TCP连接队列统计数据。

执行命令:

netstat -s |grep -i listen

结果如下:

1698257 times the listen queue of a socket overflowed

2176095 SYNs to LISTEN sockets dropped

反复查看几次之后发现overflowed 一直在增加,可以明确服务器上全连接队列一定发生了溢出。

接着查看溢出后,OS怎么处理:

# cat /proc/sys/net/ipv4/tcp_abort_on_overflow

0

tcp_abort_on_overflow 为0,表示如果三次握手第三步的时候,全连接队列满了,那么server扔掉client 发过来的ack(在server端认为连接还没建立起来),client端最终认为连接异常断开连接,和间歇性的访问不通现象比较匹配。

应用偶发性访问异常深度分析

Part

03

问题分析

1

TCP建立连接过程介绍  

应用偶发性访问异常深度分析

图 7 tcp建立连接过程(图片来源于网络)

第一步:client 发送 syn 到server 发起握手;

第二步:server 收到 syn后回复syn+ack给client;

第三步:client 收到syn+ack后,回复server一个ack表示收到了server的syn+ack,此时client的连接已经是established,server收到ack后也进入了established数据传输状态。

2

半连接队列及全连接队列介绍  

如图7所示,这里有两个队列:syns queue(半连接队列)和accept queue(全连接队列)。三次握手中,在第一步server收到client的syn后,把这个连接信息放到半连接队列中,同时回复syn+ack给client(第二步);第三步server收到client的ack,如果这时全连接队列没满,那么从半连接队列拿出这个连接的信息放入到全连接队列中,否则按tcp_abort_on_overflow指示的执行。

这时如果全连接队列满了并且tcp_abort_on_overflow是0,server会扔掉三次握手中第三步收到的ack(假装没有收到一样),过一段时间再次发送syn+ack给client(也就是重新走握手的第二步),如果client超时等待比较短,就很容易异常了。其实此时client认为连接已经建立了,可以发数据可以断开,而实际server上连接还没建立好。

3

排查命令  

服务器上可以用ss命令查看队列大小:

[root@server ~]# ss -lnt

Recv-Q Send-Q Local Address:Port  Peer Address:Port 

0        128               *:18080             *:* 

上面看到的第二列Send-Q 值是128,表示第三列的listen端口上的全连接队列最大为128,第一列Recv-Q为全连接队列当前使用了多少。

4

关键参数  

全连接队列的大小取决于:min(backlog, somaxconn) somaxconn 是 Linux 内核的参数,是一个os级别的系统参数,默认值是 128,可以通过/proc/sys/net/core/somaxconn 来设置其值。

backlog 是 listen(int sockfd, int backlog) 函数中的 backlog 大小,是在socket创建的时候传入的,Nginx 默认值是 511,可以通过修改配置文件设置其长度。

半连接队列的大小取决于max(64, /proc/sys/net/ipv4/ tcp_max_syn_backlog),系统一般默认tcp_max_syn_backlog值为128,可以增大其参数。

应用偶发性访问异常深度分析

Part

04

解决方案

1

优化nginx并发配置  

优化并发配置包括两方面:

1. 内核参数配置中增加以下配置:

net.ipv4.tcp_syncookies = 1

##表示开启SYN Cookies。当出现SYN等待队列溢出时,启用cookie来处理

net.ipv4.tcp_max_syn_backlog = 1024

##表示SYN队列的长度,可以容纳更多等待连接的网络连接数。

net.core.somaxconn = 1024

##定义了系统中每一个端口最大的监听队列的长度,这是个全局的参数,默认值为128

net.ipv4.tcp_tw_reuse = 1

##表示开启重用。允许将TIME-WAIT套接字重新用于新的TCP连接。

net.ipv4.tcp_tw_recycle = 1

##表示开启TCP连接中TIME-WAIT套接字的快速回收。

net.ipv4.tcp_fin_timeout = 30

##表示如果套接字由本端要求关闭,这个参数决定了它保持在FIN-WAIT-2状态的时间。

net.ipv4.tcp_timestamps = 0 

##开启TCP时间戳,默认开启,这里关闭,NAT环境影响tcp_tw_reuse

net.ipv4.ip_local_port_range = 22768 65500

##表示向外连接的端口范围。默认值很小:32768~61000

2. Nginx并发优化:

# vi /nginx/conf/nginx.conf

修改参数worker_connections 20480;

2

优化结果  

优化后的并发量(单台):

应用偶发性访问异常深度分析

图 8 nginx服务器tcp连接情况

观察tcp队列溢出及丢弃值不再增长,问题解决。

应用偶发性访问异常深度分析

—— E N D ——

作者/宗鑫

原创文章,作者:EBCloud,如若转载,请注明出处:https://www.sudun.com/ask/32400.html

(0)
EBCloud's avatarEBCloud
上一篇 2024年4月2日 下午3:28
下一篇 2024年4月2日 下午3:28

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注