
TIME_WAIT 状态?TIME_WAIT,俗称2MSL等待状态,是TCP连接主动关闭一方(通常是客户端,但也可能是服务端)在发送最后一次ACK确认报文后,会进入的一个状态。它需要等待2倍的最大报文段生存时间后,才会最终进入CLOSED状态,释放连接资源。
设计TIME_WAIT状态主要有两个核心原因,它们是确保TCP协议可靠性的基石:
这是最主要的原因。让我们回顾一下TCP四次挥手的正常流程:
FIN报文,进入FIN_WAIT_1状态。FIN后,回复ACK,进入CLOSE_WAIT状态。A收到这个ACK后,进入FIN_WAIT_2状态。FIN报文,进入LAST_ACK状态。FIN后,回复最后一个ACK报文,并进入TIME_WAIT状态。现在,想象一下如果没有TIME_WAIT,A在发送完最后一个ACK后,就立即关闭连接。那么:
FIN报文A没有收到,所以B会超时重传这个FIN报文。CLOSED状态。当A收到B重传的FIN时,它已经“不认识”这个连接了,因为它已经忘记了过去的事情。RST(重置)报文给B。RST后,会将其解释为一个错误,认为连接异常终止,而不是优雅地关闭。TIME_WAIT的作用:
当A进入TIME_WAIT状态并等待2MSL时间,这足以:
FIN。A在TIME_WAIT状态下,能够识别出这个FIN是来自旧连接的,于是会重新发送一次ACK,确保B能正确收到并正常关闭。FIN)都因生存时间到期而消失。这样就避免了它们干扰后续使用相同四元组的新连接。这个原因同样至关重要。TCP连接是通过一个四元组来唯一标识的:(源IP,源端口,目的IP,目的端口)。
假设一个TCP连接关闭后,我们立即使用相同的四元组建立一个新的连接。
TIME_WAIT的作用:
让主动关闭方在TIME_WAIT状态等待2MSL时间。
TIME_WAIT 状态过多是什么原因?在传统的客户端-服务器模型中,通常是客户端主动发起关闭,所以TIME_WAIT状态多出现在客户端。但服务端也可能成为主动关闭方,从而积累大量TIME_WAIT。
简单来说,服务端TIME_WAIT过多,是因为服务端主动发起了大量连接的关闭,并且这些连接已经完成了四次挥手,正在等待2MSL超时。
具体原因主要有以下几种:
这是最常见的原因。比如一些服务端程序(如传统的HTTP/1.0服务器)在处理完客户端的请求后,会主动关闭连接。
FIN挥手,进入TIME_WAIT状态。TIME_WAIT状态,并在系统参数(如net.ipv4.tcp_fin_timeout,它控制着TIME_WAIT的超时时间,默认为60秒)规定的时间内等待。在高峰期,积压的TIME_WAIT数量就可能变得非常庞大。有时候,问题并非由服务端自身引起,而是客户端的异常行为导致的。
TIME_WAIT。在使用负载均衡器(如Nginx、LVS、F5等)的环境中,负载均衡器会定期向后端真实服务器发送健康检查请求(例如TCP连接探测)。
TIME_WAIT(取决于哪一方主动关闭)。如果健康检查频率很高(比如每秒一次),并且后端服务器数量众多,那么TIME_WAIT的数量就会非常可观。所以,服务端 TIME_WAIT 过多,本质上是它作为通信的主动关闭方,在高并发短连接场景下的一个自然且正常的结果。它本身不是错误,只是TCP协议为了保证可靠性而必须付出的代价。但在极端情况下,过多的TIME_WAIT可能会耗尽系统资源(主要是内存和本地端口),导致新的连接无法建立。
解决或缓解这个问题的方法包括:
tcp_fin_timeout的值,缩短TIME_WAIT的等待时间;或开启tcp_tw_reuse(需要谨慎)和tcp_tw_recycle(Linux 4.12后已移除,不推荐使用)等。首先,TIME_WAIT 是 TCP 连接主动关闭方(通常是客户端,但也可能是服务端)最后停留的一个状态。它在发送完最后一次 ACK 确认报文后,会等待2MSL(两倍的最大报文段生存期)的时间才会完全关闭连接。
至于为什么要有这个状态,主要是为了解决两个核心的网络可靠性问题:
第一,为了保证最后一个 ACK 能让对方收到,实现可靠的连接终止。 如果服务端没收到客户端发起的最后一次 ACK,服务端会以为自己的 FIN 包丢了,就会超时重发 FIN 包。如果客户端直接关闭了,收到这个重发的 FIN 包就会回一个 RST(复位包),导致服务端报错。有了 TIME_WAIT,客户端就能在等待期内重新发送 ACK,确保对方正常关闭。
第二,为了让旧连接的数据包在网络中消失,防止干扰新连接。 网络环境很复杂,数据包可能会延迟。如果没有 TIME_WAIT,刚关闭一个连接,立马又用同样的四元组(IP 和端口)建立新连接。这时,如果网络中还有一个延迟的老数据包到达,新连接就会收到脏数据,导致数据错乱。等待 2MSL 时间,足以让老包在网络里消失,保证新连接的安全。
通常主动关闭连接的是客户端,但如果服务端出现了大量 TIME_WAIT,那说明服务端自己在主动关闭连接。常见的原因有这么几个:
大量的 TIME_WAIT 本身不会导致系统崩溃,但它会占用内存和有限的端口资源。如果端口被占满,服务端就无法对外发起新连接了针对这个问题,常见的优化手段有:
net.ipv4.tcp_tw_reuse 和 net.ipv4.tcp_timestamps,允许内核将 TIME_WAIT 状态的连接复用到新的连接上。net.ipv4.tcp_max_tw_buckets,限制 TIME_WAIT 的最大数量,超过的会被系统直接释放——但这是一个防御手段,不建议设得太低。原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。