记一次TCP 连接超时
背景
用户反馈 >> 有出现支付超时、页面问题 (部分情况会出现)
分析
检查最近是否有上线导致 (并没有上线) 排除
对接第三方平台 API接口是否有上线 (没有) 排除
是否网络延迟导致 (从前端 到后端 内网检测没问题ICMP包),检查从外网到第三方接口(ICMP没有问题) 排除网络问题导致
-
没有办法只能上tcpdump 抓包 (抓取双方服务器 网络通讯数据包)
发现 ICMP,http协议均无问题,只有TCP 出现问题,如图所示:
难道是TCP连接跑满了?
检查本机机房并没有,检查对方服务器也没有。
我擦 一头雾水 怎么搞。。。。。。
冷静分析一波。。。。。。。抽个烟想想。。。
从TCP 抓包上看吧 问题描述:TCP Retransmission
SYN
重传,第三次握手被重传了,没有收到服务器放的ACK
确认
在服务器上抓包能捕获SYN
的请求,那就说明服务器端接收到了请求但是没有回应ACK
包,于是想起了以前nat
环境下tw_recyle``的坑,当多个客户端使用同一个外网IP通过NAT访问内网服务器的时候,服务器如果在内核参数中打开了
net.ipv4.tcp_tw_recycle = 1`
就有可能导致服务器收到SYN但是不会向客户端发送SYN+ACK包。因为打开recyle参数后会识别这些包的时间戳(net.ipv4.tcp_timestamps = 1
),但是nat过来的数据包又因为时间戳有可能不是顺序的,导致服务器认为包不可信而丢弃。
故当我们在使用阿里云的VPC虚拟专网的时候,使用弹性IP接入,一定要注意NAT的问题,在服务器参数上关闭net.ipv4.tcp_tw_recycle
。 否则从一个ip来的不同客户端请求很有可能导致大量请求失败
测试验证是否是这问题。
修改 linux /etc/sysctl.conf
sysctl -p
验证一波,然并卵的感觉
Timestamp value
成功的值都比较小
改/etc/sysctl.conf文件里面得
net.ipv4.tcp_timestamps=0
再次 抓包测试 TCP 连接没有再出现 超时
搞定收工
timestamp扩展:
同时开启timestamp
(时间戳)和tw_recycle
(快速回收),会导致在一个MSL时间内只响应timestamp递增的请求,对于时间戳较小的请求都抛弃了(不响应ack)
MSL
扩展: RFC793中规定MSL为2分钟,也就是说2分钟内同一个ip的请求的时间戳要求递增,不是递增的话服务器不予响应。