网络中的TIME-WAIT和CLOSE-WAIT

TCP连接在关闭过程中,TIME_WAIT和CLOSE_WAIT状态可能导致服务器资源占用过高。TIME_WAIT确保数据包不会混淆,防止旧连接干扰新连接,并允许正确关闭连接。服务器异常时,大量TIME_WAIT可通过调整系统参数如tcp_tw_reuse和tcp_tw_recycle优化。CLOSE_WAIT则通常由未及时关闭的连接造成,需检查代码。解决方案包括设置合理的TCP超时时间和资源回收策略。


在这里插入图片描述

1、主动关闭方发送FIN包,进入FIN-WAIT1状态

2.1、被动关闭方收到FIN包后,回复ACK包,进入CLOSE_WAIT状态

2.2、主动关闭方收到ACK包后,等待对方关闭,进入FIN_WAIT2状态

3、被动关闭方在完成所有数据发送后,调用close()操作;此时,协议层发送FIN包给主动关闭方,等待对方的ACK,被动关闭的一方进入LAST_ACK状态;

4、主动关闭方收到FIN包,协议层回复ACK;此时,主动关闭方,进入TIME_WAIT状态;而被动关闭方收到ACK后,进入CLOSED状态 ;

5、主动关闭方等待2MSL(max segment lifetime)时间后,结束TIME_WAIT,进入CLOSED状态 ;

这里有个问题,就是主动关闭方发送最后一个ACK包后,为什么要进入TIME-WAIT等待2MSL而不是进入CLOSED状态,2MSL是一个发送加一个回复的最大时间,如果直到2MSL后主动关闭方没有再次收到FIN,那么可以推断出ACK已被成功接收,结束TCP连接。

而主动关闭方为什么会在发出ACK后又收到FIN包,这是因为被动关闭方在发出最后一个ACK包后也会等待2MSL的时间,如果在这个时间内没有收到主动关闭方回复的ACK后,可能是由于被动关闭方发送的FIN包没有被收到,也可能是主动关闭方回复的ACK包由于网络等原因没有发送成功,此时被动关闭方会再次发送一个FIN包给主动关闭方。

TIME_WAIT有什么用?

TIME_WAIT的出现,是为了解决网络的丢包和网络不稳定所带来的其他问题

1)**防止前一个连接上延迟的数据包或者丢失重传的数据包,被后面复用的连接错误地接收。**如果没有TIME_WAIT,或者TIME_WAIT时间非常端,那么连接关闭后源端口可能马上被服用,此时,前面一个连接上的数据被后面的一个连接错误的接收。

2)确保连接方能在时间范围内,关闭自己的连接。 如果主动关闭的一方回复的最后一个ACK丢失,而被动关闭的一方还继续停留在LAST_ACK状态,如果没有TIME_WAIT的存在,或者说,停留在TIME_WAIT上的时间很短,则主动关闭的一方很快就进入了CLOSED状态,也即是说,如果此时新建一个连接,源随机端口如果被复用,在新连接上发送SYN包后,由于被动方仍认为这条原先的连接还在等待ACK,但是却收到了SYN,则被动方会回复RST,造成新建立的连接无法成功。

服务器异常解决方案

如果服务器出了异常,百分之八九十都是下面两种情况:

1.服务器保持了大量TIME_WAIT状态

基于TCP的HTTP协议,关闭连接的不是客户端,而是服务器,所以web服务器也是会出现大量的TIME_WAIT的情况的。解决思路就是让服务器能够快速回收和重用那些TIME_WAIT的资源,可以修改对应的配置文件。

/etc/sysctl.conf

  1. #对于一个新建连接,内核要发送多少个 SYN 连接请求才决定放弃,不应该大于255,默认值是5,对应于180秒左右时间
  2. net.ipv4.tcp_syn_retries=2
  3. #net.ipv4.tcp_synack_retries=2
  4. #表示当keepalive起用的时候,TCP发送keepalive消息的频度。缺省是2小时,改为300秒
  5. net.ipv4.tcp_keepalive_time=1200
  6. net.ipv4.tcp_orphan_retries=3
  7. #表示如果套接字由本端要求关闭,这个参数决定了它保持在FIN-WAIT-2状态的时间
  8. net.ipv4.tcp_fin_timeout=30
  9. #表示SYN队列的长度,默认为1024,加大队列长度为8192,可以容纳更多等待连接的网络连接数。
  10. net.ipv4.tcp_max_syn_backlog = 4096
  11. #表示开启SYN Cookies。当出现SYN等待队列溢出时,启用cookies来处理,可防范少量SYN攻击,默认为0,表示关闭
  12. net.ipv4.tcp_syncookies = 1
  13. #表示开启重用。允许将TIME-WAIT sockets重新用于新的TCP连接,默认为0,表示关闭
  14. net.ipv4.tcp_tw_reuse = 1
  15. #表示开启TCP连接中TIME-WAIT sockets的快速回收,默认为0,表示关闭
  16. net.ipv4.tcp_tw_recycle = 1
  17. ##减少超时前的探测次数
  18. net.ipv4.tcp_keepalive_probes=5
  19. ##优化网络设备接收队列
  20. net.core.netdev_max_backlog=3000
2.服务器保持了大量CLOSE_WAIT状态

TIME_WAIT状态可以通过优化服务器参数得到解决,因为发生TIME_WAIT的情况是服务器自己可控的,要么就是对方连接的异常,要么就是自己没有迅速回收资源,总之不是由于自己程序错误导致的。

但 是CLOSE_WAIT就不一样了,如果一直保持在CLOSE_WAIT状态,那么只有一种情况,就是在对方连接关闭之后,程序里没有检测到,或者程序压根就忘记了这个时候需要关闭连接,于是这个资源就一直被程序占着。所以解决方法只能是检查代码

### TIME_WAIT 状态概述 TIME_WAIT 是 TCP 协议中的一个正常状态,用于确保数据能够可靠地传输到对方。当 TCP 连接关闭时,主动关闭连接的一方会进入 TIME_WAIT 状态。该状态的持续时间为 2 倍的 MSL(Maximum Segment Lifetime),即报文的最大生存时间。这一机制确保了两个目的:一是防止旧连接的报文干扰新连接;二是确保最后一个确认报文能够被正确接收,避免连接关闭失败[^3]。 ### TIME_WAIT 状态的成因 TIME_WAIT 状态的出现是 TCP 协议设计的一部分,主要目的是保证数据的可靠传输连接的正确关闭。在 TCP 连接关闭过程中,主动关闭连接的一方在发送 FIN 报文后,会等待对方的 FIN-ACK 回复。在收到对方的 FIN 报文并发送 ACK 回复后,主动关闭方进入 TIME_WAIT 状态,以确保网络中可能存在的旧连接报文已经失效。这一状态的持续时间通常为 2MSL,即 2 倍的报文最大生存时间[^3]。 此外,某些应用程序在使用完网络连接后,没有及时关闭连接,或者没有正确处理连接关闭的逻辑,导致连接不能正常释放,进而进入 TIME_WAIT 状态。如果应用程序中存在大量短时间内频繁创建销毁连接的操作,也会导致系统中 TIME_WAIT 状态的连接增多[^1]。 ### TIME_WAIT 状态的影响 在高并发场景下,大量的 TIME_WAIT 连接可能会对服务器性能产生影响。由于每个 TCP 连接都有唯一的五元组(源 IP、源端口、目标 IP、目标端口、协议),当系统中存在大量处于 TIME_WAIT 状态的连接时,可能导致端口资源耗尽,进而导致新的连接无法建立。此外,大量的 TIME_WAIT 连接也会占用系统内存资源,影响服务器的整体性能[^2]。 ### TIME_WAIT 状态的优化 针对 TIME_WAIT 状态的优化,核心思路是尽量缩小等待时长,而不是暴力地直接关闭连接(可能会引起新连接收到旧连接数据的风险),也不建议直接发送 RST 复位连接(可能会引起发送、接收缓冲区中的数据丢失)。因此,最保险的方式是通过修改内核参数 `tcp_tw_reuse` 来优化 TIME_WAIT 状态。通过根据实际网络情况应用场景适当调节 `tcp_timestamp` 的值,可以达到缩小 TIME_WAIT 等待时长,进而减少系统中同一时刻处于 TIME_WAIT 状态的连接数量的目的[^4]。 以下是一些常见的内核参数调整建议: ```bash # 开启 TIME_WAIT 重用 net.ipv4.tcp_tw_reuse = 1 # 开启 TCP 时间戳(用于支持 tcp_tw_reuse) net.ipv4.tcp_timestamps = 1 # 减少 TIME_WAIT 的超时时间(默认为 60 秒,可以适当减少) net.ipv4.tcp_fin_timeout = 15 ``` 这些参数可以通过修改 `/etc/sysctl.conf` 文件并执行 `sysctl -p` 命令来生效。 ### 相关问题 1. 如何查看系统中处于 TIME_WAIT 状态的连接数量? 2. TIME_WAIT 状态与 CLOSE_WAIT 状态的区别是什么? 3. 在高并发场景下,如何进一步优化 TCP 连接管理? 4. `tcp_tw_reuse` `tcp_tw_recycle` 之间有什么区别? 5. 如果不调整内核参数,是否有其他方法可以减少 TIME_WAIT 状态的连接数量?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值