Appearance
tcpTIMEWAIT
回顾 TCP 四次挥手:正常情况下服务端收到了
ACK
消息并关闭当前 TCP 连接,客户端等待msl 查看 cat /proc/sys/net/ipv4/tcp_fin_timeout
2msl(Maximum Segment Lifetime) 进入 CLOSED。
从上述过程中,我们会发现 TIME_WAIT
仅在主动断开连接的一方出现,被动断开连接的一方会直接进入 CLOSED
状态,进入 TIME_WAIT
的客户端需要等待 2 MSL 才可以真正关闭连接。
一、没有 TIME_WAIT、或 TIME_WAIT 时间过短的问题
防止延迟的数据段被其他使用相同源地址、源端口、目的地址以及目的端口的 TCP 连接收到;
场景1:由于丢包(客户端发送的
ACK
丢失),服务端没有收到ACK
消息,服务器重新发送FIN
关闭连接并等待新的ACK
消息。如果没有 TIME_WAIT、或 TIME_WAIT 时间过短客户端无法收到重传的FIN
包导致四次挥手服务优雅的完成。场景2:假设刚好客户端以相同端口发送
SYN
,那么服务器端就会返回RST
。场景3:由于 TIME_WAIT 过短,客户端用之前的端口新建 session。客户端收到了上个会话服务端延时的数据包。
三、解决 TIME_WAIT 过多新会话无法建立
- 使用
SO_LINGER
选项并设置暂存时间l_linger
为 0,在这时如果我们关闭 TCP 连接,内核就会直接丢弃缓冲区中的全部数据并向服务端发送RST
消息直接终止当前的连接。 - 使用
net.ipv4.tcp_tw_reuse
选项,通过 TCP 的时间戳选项允许内核重用处于TIME_WAIT
状态的 TCP 连接。 - 修改
net.ipv4.ip_local_port_range
选项中的可用端口范围,增加可同时存在的 TCP 连接数上限 - TCP 配置项
net.ipv4.tcp_tw_recycle
已经在 Linux 4.12 中移除,所以我们不能再通过该配置解决TIME_WAIT
设计带来的问题。