Socket中的TIME_WAIT状态

本文深入解析了TCP/IP协议中TIME_WAIT状态的原理及其对服务器的影响,指出长时间维持该状态可能导致的资源消耗问题,并提出通过调整内核参数来优化TIME_WAIT状态的回收机制,从而减轻服务器负担,提升整体性能。


从上面的示意图可以看得出来,TIME_WAIT是主动关闭连接的一方保持的状态,在客户端完成数据传输之后,它就会发起主动关闭连接close(),从而进入TIME_WAIT的状态,然后在保持这个状态2MSL(max segment lifetime)时间之后,彻底关闭回收资源。为什么要这么做?明明就已经主动关闭连接了为啥还要保持资源一段时间呢?这个是TCP/IP的设计者规定的,主要出于以下两个方面的考虑:

1)防止上一次连接中的包,迷路后重新出现,影响新连接(经过2MSL,上一次连接中所有的重复包都会消失)
2)可靠的关闭TCP连接。在主动关闭方发送的最后一个 ack(fin) ,有可能丢失,这时被动方会重新发fin, 如果这时主动方处于 CLOSED 状态 ,就会响应 rst 而不是 ack。所以主动方要处于 TIME_WAIT 状态,而不能是 CLOSED 。另外这么设计TIME_WAIT 会定时的回收资源,并不会占用很大资源的,除非短时间内接受大量请求或者受到攻击。

值得一说的是,对于基于TCP的HTTP协议,关闭TCP连接的是Server端,这样,Server端会进入TIME_WAIT状态,可 想而知,对于访问量大的Web Server,会存在大量的TIME_WAIT状态,假如server一秒钟接收1000个请求,那么就会积压240*1000=240,000个 TIME_WAIT的记录,维护这些状态给Server带来负担。当然现代操作系统都会用快速的查找算法来管理这些TIME_WAIT,所以对于新的 TCP连接请求,判断是否hit中一个TIME_WAIT不会太费时间,但是有这么多状态要维护总是不好。  


HTTP协议1.1版规定default行为是Keep-Alive,也就是会重用TCP连接传输多个 request/response,一个主要原因就是发现了这个问题。  


HTTP的交互中关闭连接的不是客户端,而是服务器,所以WEB服务器会出现大量的TIME_WAIT的情况。
解决思路是让服务器能够快速回收和重用那些TIME_WAIT的资源。


主要修改/etc/sysctl.conf的以下参数:
net.ipv4.tcp_tw_reuse和net.ipv4.tcp_tw_recycle的开启都是为了回收处于TIME_WAIT状态的资源。
net.ipv4.tcp_fin_timeout这个时间可以减少在异常情况下服务器从FIN-WAIT-2转到TIME_WAIT的时间。
net.ipv4.tcp_keepalive_*一系列参数,是用来设置服务器检测连接存活的相关配置。

参考:

再谈应用环境下的TIME_WAIT和CLOSE_WAIT:http://shootyou.iteye.com/blog/1129507

TCP 的 TIME_WAIT 状态是连接关闭过程中的关键环节,对网络稳定性和资源管理至关重要。 ### 本质与产生原因 当连接主动关闭方(先发送 FIN 的一端)收到对端的 FIN + ACK 后,进入 TIME_WAIT 状态状态持续时间为 2 × MSL(Maximum Segment Lifetime,报文最大生存时间)。RFC 793 [Postel 1981c] 指出 MSL 为 2 分钟,不过实现中的常用值是 30 秒、1 分钟或 2 分钟 [^1][^2]。 ### 核心作用 虽然引用中未明确提及核心作用,但从 TCP 机制原理来说,TIME_WAIT 状态有两个重要作用。一是确保最后一个 ACK 报文能到达对端,防止对端因未收到 ACK 而重发 FIN 报文。若没有 TIME_WAIT 状态主动关闭关闭连接后,对端重发的 FIN 报文会让主动关闭方回复 RST 报文,使对端产生错误。二是避免新旧连接混淆,在 2MSL 时间内,旧连接的所有报文都会消失,新连接不会受到旧连接延迟报文的影响。 ### 发生场景 主动发起关闭连接的一方会进入 TIME_WAIT 状态,需要注意的是,并非只有客户端才能主动关闭连接,服务器也可能主动断开很多 TCP 连接,从而出现大量的 TIME_WAIT 状态的 TCP 连接 [^3]。 ### TCP状态中的位置 在 TCP 状态机中,各状态如下:CLOSED 表示无连接是活动的或正在进行;LISTEN 是服务器在等待进入呼叫;SYN_RECV 意味着一个连接请求已经到达,等待确认;SYN_SENT 表示应用已经开始打开一个连接;ESTABLISHED 是正常数据传输状态;FIN_WAIT1 表示应用说它已经完成;FIN_WAIT2 表示另一边已同意释放;ITMED_WAIT 表示等待所有分组死掉;CLOSING 表示两边同时尝试关闭TIME_WAIT 表示另一边已初始化一个释放;LAST_ACK 表示等待最后一个 ACK 信号就关闭 [^4]。 ### 代码示例(Python 简单模拟 TCP 连接关闭) ```python import socket # 创建一个 TCP 套接字 server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server_socket.bind(('localhost', 8888)) server_socket.listen(1) print('等待客户端连接...') conn, addr = server_socket.accept() print(f'连接来自: {addr}') # 模拟数据传输 data = conn.recv(1024) print(f'收到数据: {data.decode()}') # 模拟主动关闭连接 conn.sendall(b'Goodbye!') conn.close() # 这里可能会进入 TIME_WAIT 状态(如果是主动关闭方) server_socket.close() ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值