服务器出现大量TIME_WAIT,如何解决

原创
小哥 2年前 (2023-05-28) 阅读数 53 #大杂烩

我经常发现服务器上出现一些连接 TIME_WAIT 地位,那为什么会有 TIME_WAIT状态是如何生成的?大量 TIME_WAIT 有哪些危害?如何排除故障?如何优化?用这些问题逐渐分析:

1. TCP 连接回顾

TCP 创建连接(三次握手)

① 客户端发送连接请求 SYN 报文。

② 接受连接后回复服务器 ACK 为此连接发送消息并分配资源。

③ 收到的客户 ACK 消息后,将其发送到服务器 ACK 消息,分配资源,TCP 连接已建立。

(图片来自网络)

TCP 紧密连接(四波)

① 客户端发送 FIN关闭客户端到服务器的数据传输,客户端进入 FIN_WAIT_1 状态。

② 由服务器接收 FIN 之后,发送一个 ACK 对于客户端,服务器输入 CLOSE_WAIT 状态。

③ 服务器发送 FIN关闭从服务器到客户端的数据传输,服务器进入 LAST_ACK 状态。

④ 收到的客户 FIN 后进入 TIME_WAIT 状态, 发送 ACK 到服务器,服务器进入CLOSED 状态,从而完成四次握手。

(图片来自网络)

注意:TCP 连接的任何一方都可以呼叫 close() 启动主动关机。以上 TCP 建立/释放连接的过程忽略了协议细节,例如由各种原因引起的重传和拥塞控制。

根据上面的分析,TIME_WAIT 状态显示在 TCP 四波后主动关闭连接,发送最后一波(ACK 信号结束后,主动关闭连接方的状态。

2. 为什么有 TIME_WAIT

① 可以 保证 可靠的端接 TCP 连接 如果在 TIME_WAIT 如果客户端向服务器发送确认消息,指出该分段丢失,则服务器将重新发送该消息 FIN 消息段,因此客户端必须处于可接受的状态 TIME_WAIT 而不是 CLOSED 状态。

② 可以 保证迟到 TCP 消息段有足够的时间被识别和丢弃 在某些情况下,TCP 消息可能会迟到以避免迟到 TCP 该消息被错误地视为新消息 TCP 需要为新创建启用连接的数据 TCP 在连接之前,请保持不可用状态并等待处理所有延迟的消息。

3. 如何确定 TIME_WAIT 时间

TIME_WAIT 通常也称为 2MSL 切换到 TIME_WAIT 状态的 socket 会保持 2 乘以最大段生命周期(MSL)的延迟时间。

MSL (Maximum Segment Lifetime)是 TCP 协议数据报中的任何数据段在被丢弃到网络上之前保持可用的最长时间,不同的实现是 MSL 设置了不同的值。

为什么是 2MSL 有多长?等效于允许消息至少丢失一次。例如,如果 A CK 在一个 MSL 内部损耗,使被动端可以重新发送 FIN 会在第 2 个 MSL 内到达,TIME_WAIT 状态的连接可以处理它。

4. 如何调整 TIME_WAIT 时间

① Windows 可以修改注册表 TIME_WAIT (注册表项,TcpTimedWaitDelay)。

② 在 Linux 默认的 TIME_WAIT 持续时间一般为 60 秒,在内核中定义 include/net/tcp.h 如果要修改文件,则需要修改内核宏定义并重新编译。

#define TCP_TIMEWAIT_LEN (60*HZ) /* how long to wait to destroy TIME-WAIT
                  * state, about 60 seconds */
#define TCP_FIN_TIMEOUT   TCP_TIMEWAIT_LEN/* BSD style FIN_WAIT2 deadlock breaker.
                  * It used to be 3min, new value is 60sec,
                  * to combine FIN-WAIT-2 timeout with
                  * TIME-WAIT timer.
                  */

HZ 它用于定义每秒发生的次数 timer interrupts,HZ 可以在核心编译期间设置。

注意:/proc/sys/net/ipv4/tcp_fin_timeout 并不是 TIME_WAIT 时间,但是 Fin-WAIT-2 状态超时时间。 TIME_WAITFIN_WAIT2 状态的最长持续时间为 2 MSL,由于在 Linux,MSL 的值固定为 30 秒,所以都是 60 秒。

5. TIME_WAIT 有什么影响

之前介绍 TIME_WAIT 状态的必要性,但毕竟会消耗系统资源并产生影响。

① 客户端受端口资源限制 如果客户端 TIME_WAIT 如果太多,会导致端口资源被占用,因为端口 65536 被完全占用将导致无法创建新连接。

② 服务器受系统资源限制 理论上,服务器可以建立许多连接。虽然只需要监听一个端口,但会抛出对处理线程的连接,所以当服务器上出现大量连接时 TIME_WAIT 当系统资源被充分利用时,可能会导致无法处理新连接。

6.  如何排查 TIME_WAIT

① 查看状态为 TIME_WAIT 的 TCP 连接

netstat -tan |grep TIME_WAIT

② 统计 TCP 处于各种状态的连接数

netstat -n | awk /^tcp/ {++S[$NF]} END {for(i in S) print i, S[i]}

7.  常见 TIME_WAIT 出现场景

例如, 在 HTTP/1.0 默认情况下,协议中使用短连接。浏览器需要为每个请求与服务器建立连接 TCP 服务器完成处理后立即连接和断开连接 TCP 连接。

例如,如果 HTTP 请求中,connection 被设置成 close这相当于通知 Server 执行请求后,主动关闭连接。

8.  如何优化

将短链接调整为长链接

长连接从根本上减少了连接关闭的次数,并且 TIME_WAIT 优化效果显著,在高并发系统中。使用时 nginx 作为反向代理,为了支持长连接,应注意:

从 Client 到 nginx 连接是长连接, 默认 nginx 它已被激活 Client 连接的 keepalive 支持、调整相关参数:

http {

    keepalive_timeout 120s;    # 客户端连接的超时期限。由 0 禁用长连接时。

    keepalive_requests 10000;  # 长连接上的最大请求数。

}

从 nginx 到 Server 连接是长连接: 要配置与上游服务器的长连接,必须 upstream 模块中的配置 keepalive

http {
upstream backend{
  server 10.10.0.1:8080 weight=1;
  server 10.10.0.2:8080 weight=1;
  keepalive 300; #关键配置
 }   

server {
...
location / {
  proxy_pass http://backend;
  proxy_http_version 1.1;         #设置 HTTP 版本为 1.1
  proxy_set_header Connection ""; #设置 Connection 对于长连接(默认为no)
  }
 }
}

调整服务器内核参数

① Linux 提供了 tcp_max_tw_buckets 参数,当 TIME_WAIT 当连接数超过此参数时,新关闭的连接将不再体验 TIME_WAIT 并直接关闭:

[root@kvm-10-115-88-47 ~]# cat /proc/sys/net/ipv4/tcp_max_tw_buckets
32768

② 另外 Linux  提供了 tcp_tw_reuse 参数,允许 TIME_WAIT  sockets 重用新的 TCP 连接,多路复用连接。但是,应该注意的是,此参数仅用于客户端(建立连接的发起方)。

net.ipv4.tcp_timestamps = 1

net.ipv4.tcp_tw_reuse = 1

③ Linux 4.12 以前提供 tcp_tw_recycle 参数,指示TCP连接中TIME-WAIT sockets快速回收。

请注意,当它启用时,例如使用 NAT,LVS 当不能保证时间戳会单调增加时,某些数据包可能会被服务器拒绝。此参数在内核中 4.12 之后,它被删除,不建议启动生产环境。

版权声明

所有资源都来源于爬虫采集,如有侵权请联系我们,我们将立即删除

热门