180808-tcp-tw-recycle参数引发的系统问题

tcp_tw_recycle参数引发的系统问题

问题背景

前段时间为了应对苹果的ATS策略,完成了全站服务端的HTTPS部署。为了减少负载均衡设备的开销,我们开启的是F5的四层模式Perfomance(Layer4),即只处理四层TCP连接,过来后直接做NAT转发到后端Web Server。
然而诡异的问题发生了,完成这次升级后,部分用户直接无法打开网页,我们立刻组织分析。

无法访问此网站

从客户端来看,TCP建连失败
客户端访问失败

负载均衡器抓包分析
在负载均衡上抓包分析,syn包已经发到Web Server,但没返回syn ack
wireshark抓包分析

Web Server抓包分析
Web Server上抓包,确定有收到syn包,但被拒绝。同时,发现只有客户端带时间戳的包才会被拒绝。
reject

时间戳分析

我们发现,只要为客户端的TCP带上时间戳,就会导致问题发生,关闭客户端时间戳,问题恢复。这就解释了为什么只有部分用户有问题,其他用户正常。

内核控制参数
内核控制参数

问题定位

通过参考网上的资料,我们定位到问题发生的原因:我们的Web Server的Linux内做过调整,开启了net.ipv4.tcp_tw_recycle,在负载均衡只做NAT的情况下,触发了大量的TCP建连失败。

ipv4-tcp

tcp_tw_recycle
Enable fast recycling of TIME-WAIT sockets. Enabling this option is not recommended since this causes
problems when working with NAT (Network Address Translation).

启用TIME-WAIT状态sockets的快速回收,这个选项不推荐启用。在NAT(Network Address Translation)网络下,会导致大量的TCP连接建立错误。

下面我们来具体说下,首先解释下TCP的TIME_WAIT状态:

  1. 通信双方建立TCP连接后,主动关闭连接的一方就会进入TIME_WAIT状态。
  2. 比如,客户端主动关闭连接时,会发送最后一个ack后,然后会进入TIME_WAIT状态,再停留2个MSL时间,进入CLOSED状态。
  3. TIME_WAIT状态的作用是为了保证连接正常关闭,且不影响其他新建的链接。

tcp端口连接

开启net.ipv4.tcp_tw_recycle的目的,就是希望能够加快TIME_WAIT状态的回收,当然这个选项的生效也依赖于net.ipv4.tcp_timestamps的开启(缺省就是开启的)。

当开启了tcp_tw_recycle选项后,当连接进入TIME_WAIT状态后,会记录对应远端主机最后到达分节的时间戳。如果同样的主机有新的分节到达,且时间戳小于之前记录的时间戳,即视为无效,相应的数据包会被丢弃

当负载均衡启用NAT模式时,客户端TCP请求到达负载均衡,修改目的地址(IP+端口号)后便转发给后端服务器,而客户端时间戳数据没有变化。对于后端Web Server,请求的源地址是负载均衡,所以从后端服务器的角度看,原本不同客户端的请求经过LVS的转发,就可能会被认为是同一个连接,加之不同客户端的时间可能不一致,所以就会出现时间戳错乱的现象,于是后面的数据包就被丢弃了。

问题解决

解决办法是Linux内核引入 tcp_fin_timeout 开关,该开关可以动态设置TIME_WAIT 时间,加速回收TIME_WAIT 状态,从而可以关闭tcp_tw_recycle ,避免上述问题。

名词解释

MSL(最大分节生命期)
MSL就是maximum segment lifetime(最大分节生命期),这是一个IP数据包能在互联网上生存的最长时间,超过这个时间IP数据包将在网络中消失。

参考资料

tcp_tw_recycle参数引发的系统问题

#
Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×