TCP连接出现大量TIME_WAIT?


在网络编程中,TIME_WAIT 是 TCP 协议的一个正常状态,用于确保数据能够可靠地传输到对方。然而,在高并发场景下,大量的 TIME_WAIT 连接可能会对服务器性能产生影响,甚至导致新的连接无法建立。本文将深入分析 TIME_WAIT 状态的成因,并提供相应的解决策略。

一、TIME_WAIT 状态概述

TIME_WAIT,也称为 2MSL 等待状态,是 TCP 连接终止过程中的一个阶段。当一方主动关闭连接后,会进入 TIME_WAIT 状态,并保持该状态 2 倍的最大报文段生命周期(MSL)。默认情况下,MSL 为 2 分钟,因此 TIME_WAIT 通常持续 4 分钟。这个状态的目的是确保:

  1. 对方收到连接终止的确认(ACK)。
  2. 延迟到达的任何数据包被丢弃,而不是被后续连接错误地接收。
    附:MSL 时间
    MSL,Maximum Segment Lifetime,“报文最大生存时间”
  3. 任何报文在网络上存在的最长时间,超过这个时间报文将被丢弃。(IP 报文)
  4. TCP报文 (segment)是ip数据报(datagram)的数据部分。
  5. RFC 793中规定MSL为2分钟,实际应用中常用的是30秒,1分钟和2分钟等。
  6. 2MSL,TCP 的 TIME_WAIT 状态,也称为2MSL等待状态:
  7. 当TCP的一端发起主动关闭(收到 FIN 请求),在发出最后一个ACK 响应后,即第3次握手完成后,发送了第四次握手的ACK包后,就进入了TIME_WAIT状态。
  8. 必须在此状态上停留两倍的MSL时间,等待2MSL时间主要目的是怕最后一个 ACK包对方没收到,那么对方在超时后将重发第三次握手的FIN包,主动关闭端接到重发的FIN包后,可以再发一个ACK应答包。
  9. 在 TIME_WAIT 状态时,两端的端口不能使用,要等到2MSL时间结束,才可继续使用。(IP 层)
  10. 当连接处于2MSL等待阶段时,任何迟到的报文段都将被丢弃
    不过在实际应用中,可以通过设置 「SO_REUSEADDR选项」,达到不必等待2MSL时间结束,即可使用被占用的端口

二、TIME_WAIT 状态的成因

  1. 短连接:应用程序频繁地开启和关闭连接,而不是使用持久连接。
  2. HTTP 请求:HTTP 请求中 Connection 头部被设置为 close,导致服务端主动关闭连接。
  3. TCP 四次挥手:TCP 的正常关闭流程需要进入 TIME_WAIT 状态,以完成数据传输和确保可靠性
    在这里插入图片描述

三、TIME_WAIT 状态的影响

  1. 端口耗尽:由于每个 TIME_WAIT 状态的连接都会占用一个本地端口,大量的 TIME_WAIT 连接可能导致端口耗尽,进而无法建立新的连接,上限为 65535(16 bit,2 Byte)
    tips:TCP 本地端口数量,上限为 65535(6.5w),这是因为 TCP 头部使用 16 bit,存储「端口号」,因此约束上限为 65535
  2. 资源占用:TIME_WAIT 状态的连接虽然不会消耗大量资源,但在大规模系统中,累积起来的影响也不容忽视

四、分析

出现大量的 TIME_WAIT 状态的 TCP 连接时,可以通过以下几个步骤进行分析:

  1. 确认现象:首先确认是否真的存在大量的 TIME_WAIT 连接。可以通过网络监控工具或命令(如 netstat -n)来查看当前的 TCP 连接状态。
// 统计:各种连接的数量
$ netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'
ESTABLISHED 1154
TIME_WAIT 1645
  1. 分析连接模式:分析应用程序的连接模式,是否存在大量的短连接。例如,HTTP 请求中如果 Connection 头部被设置为 close,则服务端会主动关闭连接,导致 TIME_WAIT 状态
  2. 查看端口使用情况:检查本地端口的使用情况,确认是否因为 TIME_WAIT 状态的连接过多导致端口耗尽,从而无法创建新的连接
  3. 考虑网络配置:检查网络配置,如 tcp_max_tw_buckets 参数控制系统整体可用 TIME_WAIT 数量,ip_local_port_range 影响源端口的范围
  4. 检查应用程序行为:检查应用程序是否正确地管理了连接。例如,HTTP 客户端是否使用了持久连接(Connection: keep-alive),服务器端是否在适当的时候重用了 TIME_WAIT 状态的连接
  5. 考虑使用解决方案:如果 TIME_WAIT 状态的连接确实对系统造成了影响,可以考虑以下解决方案:
  • 客户端使用持久连接。
  • 服务器端调整 tcp_tw_reuse 和 tcp_tw_recycle 参数,允许重用处于 TIME_WAIT 状态的 socket
  • 调整 net.ipv4.tcp_timestamps 参数,以利用 TCP 时间戳选项来减少 TIME_WAIT 状态的时间
  1. 监控和优化:持续监控 TCP 连接的状态,并根据实际业务需求对应用程序或系统配置进行优化。

五、大量的 TIME_WAIT 状态 TCP 连接存在,其本质原因是什么?

1.大量的短连接存在
2.特别是 HTTP 请求中,如果 connection 头部取值被设置为 close 时,基本都由「服务端」发起主动关闭连接
3.而,TCP 四次挥手关闭连接机制中,为了保证 ACK 重发和丢弃延迟数据,设置 time_wait 为 2 倍的 MSL(报文最大存活时间)

六、解决办法

解决上述 time_wait 状态大量存在,导致新连接创建失败的问题,一般解决办法:1.客户端,HTTP 请求的头部,connection 设置为 keep-alive,保持存活一段时间:现在的浏览器,一般都这么进行了2.服务器端允许 time_wait 状态的 socket 被重用缩减 time_wait 时间,设置为 1 MSL(即,2 mins)

结论:几个核心要点
1.time_wait 状态的影响:
TCP 连接中,「主动发起关闭连接」的一端,会进入 time_wait 状态
time_wait 状态,默认会持续 2 MSL(报文的最大生存时间),一般是 2x2 mins
time_wait 状态下,TCP 连接占用的端口,无法被再次使用
TCP 端口数量,上限是 6.5w(65535,16 bit)
大量 time_wait 状态存在,会导致新建 TCP 连接会出错,address already in use : connect 异常
2.现实场景:
服务器端,一般设置:不允许「主动关闭连接」
但 HTTP 请求中,http 头部 connection 参数,可能设置为 close,则,服务端处理完请求会主动关闭 TCP 连接
现在浏览器中, HTTP 请求 connection 参数,一般都设置为 keep-alive
Nginx 反向代理场景中,可能出现大量短链接,服务器端,可能存在
3.解决办法:
服务器端允许 time_wait 状态的 socket 被重用
缩减 time_wait 时间,设置为 1 MSL(即,2 mins)

几个核心疑问

1.time_wait 是「服务器端」的状态?or 「客户端」的状态?
time_wait 是「主动关闭 TCP 连接」一方的状态,可能是「客服端」的,也可能是「服务器端」的
一般情况下,都是「客户端」所处的状态;「服务器端」一般设置「不主动关闭连接」
2.服务器在对外服务时,是「客户端」发起的断开连接?还是「服务器」发起的断开连接?
正常情况下,都是「客户端」发起的断开连接
「服务器」一般设置为「不主动关闭连接」,服务器通常执行「被动关闭」
但 HTTP 请求中,http 头部 connection 参数,可能设置为 close,则,服务端处理完请求会主动关闭 TCP 连接
3、关于 HTTP 请求中,设置的主动关闭 TCP 连接的机制:TIME_WAIT的是主动断开方才会出现的,所以主动断开方是服务端?
1.答案是是的。在HTTP1.1协议中,有个 Connection 头,Connection有两个值,close和keep-alive,这个头就相当于客户端告诉服务端,服务端你执行完成请求之后,是关闭连接还是保持连接,保持连接就意味着在保持连接期间,只能由客户端主动断开连接。还有一个keep-alive的头,设置的值就代表了服务端保持连接保持多久。
2.HTTP默认的Connection值为close,那么就意味着关闭请求的一方几乎都会是由服务端这边发起的。那么这个服务端产生TIME_WAIT过多的情况就很正常了。
3.虽然HTTP默认Connection值为close,但是,现在的浏览器发送请求的时候一般都会设置Connection为keep-alive了。所以,也有人说,现在没有必要通过调整参数来使TIME_WAIT降低了。
关于 time_wait:
1.TCP 连接建立后,「主动关闭连接」的一端,收到对方的 FIN 请求后,发送 ACK 响应,会处于 time_wait 状态;
2.time_wait 状态,存在的必要性:a、可靠的实现 TCP 全双工连接的终止:四次挥手关闭 TCP 连接过程中,最后的 ACK 是由「主动关闭连接」的一端发出的,如果这个 ACK 丢失,则,对方会重发 FIN 请求,因此,在「主动关闭连接」的一段,需要维护一个 time_wait 状态,处理对方重发的 FIN 请求;b、处理延迟到达的报文:由于路由器可能抖动,TCP 报文会延迟到达,为了避免「延迟到达的 TCP 报文」被误认为是「新 TCP 连接」的数据,则,需要在允许新创建 TCP 连接之前,保持一个不可用的状态,等待所有延迟报文的消失,一般设置为 2 倍的 MSL(报文的最大生存时间),解决「延迟达到的 TCP 报文」问题

  • 21
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
服务器出现大量time_wait是指在TCP连接断开后,服务器端口仍处于等待状态的情况。这可能会导致服务器资源的浪费,影响服务器的性能和可用性。以下是理解并解决这个问题的步骤: 首先,需要理解time_wait的原因:TCP连接的断开是一个多步骤的过程,在最后一个ACK报文发送后,服务器端口会进入time_wait状态一段时间,以确保在这段时间内没有延迟的报文重新出现。这是网络协议设计的一部分,用于确保数据传输的可靠性。 为了解决服务器出现大量time_wait的问题,可以采取以下措施: 1. 调整服务器参数:可以通过修改服务器操作系统的参数来调整time_wait状态的时间。例如,可以减少time_wait状态的持续时间,以释放服务器资源。具体的操作方法可以参考操作系统的文档或相关文档。 2. 加大服务器资源:如果服务器出现大量time_wait的问题,可能是服务器的资源(例如端口号)不足造成的。此时,可以考虑增加服务器的资源,例如扩大服务器的端口范围等。 3. 优化应用程序代码:服务器出现大量time_wait可能是应用程序代码设计不佳造成的。在应用程序,可以优化代码,以减少TCP连接的数量和时间。例如,可以使用连接池来重用连接,或者调整连接关闭的时机。 4. 负载均衡和故障转移:如果服务器经常出现大量time_wait,可能是由于服务器负载过高或单点故障引起的。此时,可以考虑使用负载均衡和故障转移技术来分散流量和提高服务器的可用性,从而减少time_wait的数量。 总之,彻底理解并解决服务器出现大量time_wait的问题需要对网络协议、服务器参数和应用程序代码等方面有一定的了解。通过调整参数、加大服务器资源、优化代码以及使用负载均衡和故障转移等技术,可以有效地减少time_wait的数量,提高服务器的性能和可靠性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值