打开tcp_tw_recycle引起的一次投诉分析

本文分析了一次因TCP_TW_RECYCLE配置不当导致的20%连接失败率的问题,详细解释了该机制在负载均衡场景下的潜在风险,并提供了关闭此设置后的解决方案。

转自https://www.cnblogs.com/jdonson/p/4760166.html

打开tcp_tw_recycle引起的一次投诉分析

背景:

我们有个基于oauth2.0协议给第三方授权以及信息的业务,年前对接入层、业务层做了次迁移。业务架构简单介绍下:

lvs接入---> nginx ---> tomcat

 

问题:

迁移完第1天,接到好几个合作商的投诉,其中有家说在他们业务集群中,有20%左右的失败率,日志显示连接被拒绝。

 

定位:

和开发商调试,telnet我方端口正常。curl发测试请求也正常。没办法,请开发商的运维同学tcpdump抓了几分钟的数据,
发过来分析。如下图

打开一看全是灰色...怪吓人的。从抓包看被server端rst的数据包也不少,这个就是为啥有20%左右连接被拒绝了。看这些
请求基本就是发出syn后server没回包。看到这个就有点怀疑server端是不是开启了tcp_tw_recycle和tcp_timestamps,马
上登录RS nginx机器查看,果然是打开的。把tcp_tw_recycle关闭,再联系开发商观察日志。ok了!

原因:
在TCPIP的标准RFC 1323里有这样的定义:
  An additional mechanism could be added to the TCP, a per-host
  cache of the last timestamp received from any connection.
  This value could then be used in the PAWS mechanism to reject
  old duplicate segments from earlier incarnations of the
  connection, if the timestamp clock can be guaranteed to have
  ticked at least once since the old connection was open.  This
  would require that the TIME-WAIT delay plus the RTT together
  must be at least one tick of the sender's timestamp clock.
  Such an extension is not part of the proposal of this RFC.
大概的中文意思就是:TCP协议中有一种机制,缓存了每个主机(即ip)过来的连接最新的timestamp值。这个缓存的值
可以用于PAWS(Protect Against Wrapped Sequence numbers,是一个简单的防止重复报文的机制)中,来丢弃当前连
接中可能的旧的重复报文。而Linux实现这个机制的方法就是同时启用net.ipv4.tcp_timestamps和net.ipv4.tcp_tw_recycle 
这两个选项。

这种机制在 客户端-服务器 一对一的时候,没有任何问题,但是当服务器在负载均衡器后面时,由于负载均衡器不会修改
包内部的timestamp值,而互联网上的机器又不可能保持时间的一致性,再加上负载均衡是会重复多次使用同一个tcp端口
向内部服务器发起连接的,就会导致什么情况呢:

负载均衡通过某个端口向内部的某台服务器发起连接,源地址为负载均衡的内部地址——同一ip
假如恰巧先后两次连接源端口相同,这台服务器先后收到两个包,第一个包的timestamp被服务器保存着,第二个包又来了,
一对比,发现第二个包的timestamp比第一个还老——客户端时间不一致。服务器基于PAWS,判断第二个包是重复报文,
丢弃之
反映出来的情况就是在服务器上抓包,发现有SYN包,但服务器就是不回ACK包,因为SYN包已经被丢弃了。为了验证这
一结果,可以执行netstat -s | grep timestamp 命令,看输出里面passive connections rejected by timestamp 一项的数字变化。


参考:
1. http://saview.wordpress.com/2011/09/27/tcp_tw_recycle%E5%92%8Cnat%E9%80%A0%E6%88%90syn_ack%E9%97%AE%E9%A2%98/

### tcp_tw_recycle 的作用 `tcp_tw_recycle` 是 Linux 系统中用于优化 TCP 连接管理的参数之一。该参数控制是否启用快速回收处于 `TIME_WAIT` 状态的连接。在 TCP 协议中,当一个连接关闭后,两端会进入 `TIME_WAIT` 状态,通常持续时间为 2 倍的最大报文生存时间(MSL),默认为 60 秒,总计 120 秒。这种机制是为了确保网络中所有旧的重复数据包都被丢弃,从而避免它们干扰新的连接。 启用 `tcp_tw_recycle` 后,系统会利用 TCP 时间戳选项(`tcp_timestamps`)来判断某个 `TIME_WAIT` 连接是否可以被提前释放[^2]。具体来说,系统会记录最近一次从某个 IP 地址收到的时间戳值,并与当前连接的时间戳进行比较。如果当前的时间戳更小,则说明这是一个旧的数据包,可以直接丢弃,而无需等待完整的 `TIME_WAIT` 时间结束。这样可以在一定程度上减少系统中处于 `TIME_WAIT` 状态的连接数量,提升资源利用率。 需要注意的是,`tcp_tw_recycle` 不适用于存在 NAT(网络地址转换)的环境。因为多个客户端可能共享同一个公网 IP 地址,这会导致时间戳冲突,进而引发连接异常[^1]。 --- ### 使用场景 - **内部服务调用**:当服务器仅作为客户端频繁请求其他 IP 地址时,例如微服务架构中的服务间通信。 - **可控性强的环境**:对上下游应用有较强的控制能力,可以协调调整参数以适配当前服务器配置。 - **无对外服务需求**:服务器不作为服务端接收外部连接,仅作为客户端主动发起请求[^1]。 --- ### 配置方法 可以通过修改 `/proc/sys/net/ipv4/tcp_tw_recycle` 文件来临时开启或关闭此功能: ```bash # 开启 tcp_tw_recycle sudo bash -c 'echo 1 > /proc/sys/net/ipv4/tcp_tw_recycle' # 关闭 tcp_tw_recycle sudo bash -c 'echo 0 > /proc/sys/net/ipv4/tcp_tw_recycle' ``` 若希望永久生效,可将以下内容添加到 `/etc/sysctl.conf` 文件中: ```conf net.ipv4.tcp_tw_recycle = 1 ``` 然后执行命令使其立即生效: ```bash sudo sysctl -p ``` --- ### 注意事项 - 必须同时启用 `tcp_timestamps` 才能使用 `tcp_tw_recycle` 功能[^2]。 - 在 NAT 环境下启用此参数可能导致连接失败,建议谨慎使用。 - 如果系统中存在大量短连接且客户端频繁重连,可考虑使用 `tcp_tw_reuse` 来复用处于 `TIME_WAIT` 的连接[^5]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值