写点什么

TCP-SYN 超时重传问题排查

作者:Kevin Wu
  • 2022-12-27
    江苏
  • 本文字数:1138 字

    阅读完需:约 4 分钟

TCP-SYN超时重传问题排查

前言

XProxy 是基于 Node.js 研发的七层负载网关,承担着全公司所有互联网和私有云的流量入口,高峰期 QPS 达 20W,日志量每天达数十亿条,部署架构为两地三中心,网关机器集群接近三百台机器。


访问链路图


存在问题


地市业务方通过四层 ELB(只负责转发)访问网关时,偶发出现超时的情况。通过网关日志分析,初步分析排除是应用层超时引起的,因此只能通过抓包分析,由于白天流量过大,使用 tcpdump(tcpdump原理) 抓包时对系统可能造成影响,即使 tcpdump 的底层逻辑是在内核态实现,但高峰期接近千兆的带宽会对内存和 CPU 有一定的占用,为了避免对业务造成影响,因此选择在晚上进行抓包。


排查过程

同步在省 ELB 和网关用 tcpdump 进行抓包,从省 ELB 的抓包情况可以看到:

客户端有不断的 SYN 包(ISN生成规则)重传,并且 WireShark 也提示 reuse port,说明端口被复用了:


仔细分析 TCP 报文,看到服务端响应的 ACK 包 ACK Number 都是相同的:



继续往下看报文,发现在一段时间之前该连接已经发生了四次挥手,并且由网关发起的主动挥手,我们知道,主动发起四次挥手的一方会进入 time_wait 的状态,并且等待 2msl(默认 120s)后才会释放连接,由此可以分析重传的 SYN 包在网关侧被认为是历史包,因此每次 ACK 包都是以第四次挥手时 ACK 包进行响应,因为网络抖动之类的原因也有可能会出现这种情况,这也符合 TCP 的设计:


通过上述的综合分析,可以排除是网关应用或者网关服务器的问题,那么最有可能存在的问题就是 NAT 网络。由于地市的不同业务系统通过地市防火墙访问省 ELB 时,地市防火墙会统一进行 NAT 映射后才到省 ELB。这种方式带来的问题就是假设 A 业务系统建立 TCP 连接的时候,端口 NAT 成 12345,当没有数据交换时网关会断开连接,此时在 120s 内 B 业务系统也建立 TCP 连接,同时端口也被 NAT 成 12345,并且 SYN 包的 SEQ Number 是倒序的(倒序的原因是由于 SYN 包来自于不同的客户端),那么对于网关服务器来说,认为对方是同一个客户端发起的请求,倒叙的 Seq Number 是历史包,那么就会响应第四次挥手的 ACK 包。


解决方案

首先考虑的是从网络侧入手,看看是否能根据不同的地市 NAT 成不同的 IP,咨询网络组的同事后得知目前实现不了。

既然网络侧解决不了,那只能从应用侧解决这个问题。当时在想,如果能够让客户端主动断开连接,让客户端进入 time_wait 状态,这样的话客户端就不会出现 reuse port 的情况,此时查看网关与客户端连接的超时配置。

网关与客户端的连接在空闲时会保持 30s,当 30s 没有进行数据交换时,网关会主动发送 FIN 包请求断开连接,经过四次挥手后,该连接在网关侧的状态已经进入 time_wait 状态。那么这样的话如果由客户端主动断开连接,进入 time_wait 状态的是客户端而不是网关侧。

把思路提供给业务系统,建议业务方把 socket timeout 设置为小于 30s,当前的设置是 900s,改完配置重启后,问题就解决了。


用户头像

Kevin Wu

关注

To Be A Elegant Programmer 2018-01-29 加入

Golang、Node.js、中间件,目标是深入Rust

评论

发布
暂无评论
TCP-SYN超时重传问题排查_高并发_Kevin Wu_InfoQ写作社区