服务端 tcp 丢失SYN/ACK 问题排查

[toc]

总览

与某公司对接, 发现有 10% 的超时情况. tcp在我们服务器发现, 有大量 SYN 包重传的情况, 而且只有 SYN包才会重传, 很多包重传失败, 有一些包重传也会成功(注意 Retransmission):

163	2017-12-20 13:27:41.125680	xxx.xxx.xxx.xxx	xxx.xxx.xxx.xxx	TCP	74	[TCP Retransmission] 60671 → 80 [SYN] Seq=0 Win=14600 Len=0 MSS=1460 SACK_PERM=1 TSval=2897178400 TSecr=0 WS=128

最终通过在对方服务端 nginx 和 后台服务器关闭net.ipv4.tcp_tw_recycle功能解决.

排查过程

因以前没抓过包, 被同事笑话了一番. 周末买了一本看完<Wireshark网络分析就这么简单()>, 抓住这个机会实战一下.

让对方分别在 nginx 和 后端服务器上抓了包. 显示, nginx 上请求包和我们机器上抓包现象相同. 但是 nginx 到 后端服务器的包都正常. 也就是说, nginx 没有及时处理TCP连接请求.

排查了一下nginx机器负载, 以及基本配置都没有问题. 既然只有 SYN 类型包重传, 现象很明显, 就Google了一下. 找到这个帖子: 为什么服务端不回复 SYN/ACK. 问题和我们的一模一样. 但是题主给出的解决方法存疑. 而且没有给出为什么. 我注意到了帖子中lav的答案, 可能和net.ipv4.tcp_tw_recycle参数相关. 经过查看, 对方果然开启了这个参数.

度娘了一下这个参数, 发现这么一段话(链接:tcp_tw_reuse、tcp_tw_recycle 使用场景及注意事项):

对于服务端
1. 打开tw_reuse无效

2. 线上环境 tw_recycle 不要打开

   服务器处于NAT 负载后,或者客户端处于NAT后(这是一定的事情,基本公司家庭网络都走NAT);

 公网服务打开就可能造成部分连接失败,内网的话到时可以视情况打开;

   像我所在公司对外服务都放在负载后面,负载会把timestamp 都给清空,好吧,就算你打开也不起作用
4. recycle

    对于服务端,同一个src ip,可能会是NAT后很多机器,这些机器timestamp递增性无可保证,服务器会拒绝非递增请求连接。

结论

因对方开启了net.ipv4.tcp_tw_recycle参数, 这个参数会对同一个请求 IP 按照时间戳增续处理, 凡是小于上次时间戳的链接请求, 都被认为是重传包而丢弃. 我们后台服务器经过同一个 NAT 访问对方 nginx, 出口IP是一个, 后台服务器访问对方nginx, 请求包里面的 timestamp 可能会有差异. 导致 timestamp 落后的包被对方丢弃.

解决方法

在对方服务端 nginx 和 后端服务器 把net.ipv4.tcp_tw_recycle参数关闭即可.

猜你喜欢

转载自my.oschina.net/u/1169457/blog/1594969