Skip to content

tcpTIMEWAIT

  • 回顾 TCP 四次挥手:正常情况下服务端收到了 ACK 消息并关闭当前 TCP 连接,客户端等待

     msl 查看
     cat /proc/sys/net/ipv4/tcp_fin_timeout
  • 2msl(Maximum Segment Lifetime) 进入 CLOSED。tcp四次挥手

从上述过程中,我们会发现 TIME_WAIT 仅在主动断开连接的一方出现,被动断开连接的一方会直接进入 CLOSED 状态,进入 TIME_WAIT 的客户端需要等待 2 MSL 才可以真正关闭连接。

一、没有 TIME_WAIT、或 TIME_WAIT 时间过短的问题

  • 防止延迟的数据段被其他使用相同源地址、源端口、目的地址以及目的端口的 TCP 连接收到;

    • 场景1:由于丢包(客户端发送的 ACK 丢失),服务端没有收到 ACK 消息,服务器重新发送 FIN 关闭连接并等待新的 ACK 消息。如果没有 TIME_WAIT、或 TIME_WAIT 时间过短客户端无法收到重传的 FIN 包导致四次挥手服务优雅的完成。

      TIME_WAIT_ACK丢失

    • 场景2:假设刚好客户端以相同端口发送 SYN,那么服务器端就会返回 RST

      TIME_WAIT_RST

    • 场景3:由于 TIME_WAIT 过短,客户端用之前的端口新建 session。客户端收到了上个会话服务端延时的数据包。

      TIME_WAIT_服务器延时数据包

三、解决 TIME_WAIT 过多新会话无法建立

  1. 使用 SO_LINGER 选项并设置暂存时间 l_linger 为 0,在这时如果我们关闭 TCP 连接,内核就会直接丢弃缓冲区中的全部数据并向服务端发送 RST 消息直接终止当前的连接。
  2. 使用 net.ipv4.tcp_tw_reuse 选项,通过 TCP 的时间戳选项允许内核重用处于 TIME_WAIT 状态的 TCP 连接。
  3. 修改 net.ipv4.ip_local_port_range 选项中的可用端口范围,增加可同时存在的 TCP 连接数上限
  4. TCP 配置项 net.ipv4.tcp_tw_recycle 已经在 Linux 4.12 中移除,所以我们不能再通过该配置解决 TIME_WAIT 设计带来的问题。