面试篇:Time-wait状态存在的用处,怎么避免Time-wait?


Time-wait状态存在的用处,怎么避免Time-wait?
这道题目是面试过程中的高频题目,首先看一下什么是TIME_WAIT状态

1.什么是TIME_WAIT状态?

面试篇:Time-wait状态存在的用处,怎么避免Time-wait?

在TCP连接中四次挥手关闭连接时,主动关闭连接的一方(上图中时Client)会在发送最后一条ACK报文后维持一段时长2MSL(MSL指的是数据包在网络中的最大生存时间)的等待时间后才会真正关闭连接到CLOSED状态,该时间段内主动关闭方的状态为TIME_WAIT。即在TIME_WAIT状态时,定义这个连接的四元组(源/目的IP、源/目的端口)不能被使用。

2.为什么需要TIME_WAIT状态?

为实现TCP连接的可靠释放

  1. 若主动断开连接方(上图中Client)最后一次ACK报文丢失了,会触发被动方(上图中Server)的超时重传机制,Server再次向Client发送FIN+ACK报文,如果Client在发送完最后一次ACK后立即断开连接(没有TIME_WAIT状态),则Server会收到RST=1的报文响应,表示连接建立异常,而此时并非异常,只是正常的关闭连接过程,进而导致Server端不能正常关闭连接。因此,Client必须维护2MSL的等待时间,确保在Server端第二次发送的FIN+ACK被Client正常接收,收到后Client立即发送ACK给Server,并重新启动2MSL计时器。(因为极端情况涉及两次报文传输(Client向Server的ACK,Server向Client的FIN+ACK),所以等待时间为2MSL)RFC 793中规定MSL为2分钟,实际应用中常用的是30秒,1分钟和2分钟等。所以意味着有可能导致几分钟内该ip:port 不能再次使用。

  2. 为使旧的重复数据包在网络中因过期而消失

    可能存在一些数据包在传输过程中出现异常而导致严重推迟,而在它到来之前发送方已经重发了该报文,并完成其任务。如果在被推迟的报文未抵达前接收方断开了连接,随后又建立了一个与之前相同IP、Port的连接,而之前被推迟的报文在这时恰好到达,而此时此新连接非彼连接,从而会发生数据错乱,进而导致无法预知的情况。因此必须维持一段等待时间,使迟到的报文在网络中完全消失,并且在等待时间内,因为连接并未关闭,所以不能建立相同四元组的新连接,就不会出现数据错乱

这里可以看一个比方,关于四次挥手:
男生: 男生发消息给女生,我们分手把
女生:女生发消息说,好的,我的东西收拾完,发消息告诉你
(1个小时后)
女生: 女生发消息说,我收拾好了,分手把
男生:男生发消息说,好的。
(这个时候男生需要等待1h才可以去找下个女朋友,因为他和前任约定,一个小时内,如果女生收到了”好的“,就不再回复,如果没有收到“好的”,女生还会再次发消息告诉他我收拾好了,分手把)。

3.TIME_WAIT状态造成的危害

在高并发短连接的TCP服务器上,当服务器处理完请求后主动请求关闭连接,这样服务器上会有大量的连接处于TIME_WAIT状态,服务器维护每一个连接需要一个socket,也就是每个连接会占用一个文件描述符,而文件描述符的使用是有上限的,如果持续高并发,会导致一些连接失败。

还有一种情况,假设假设假设,今天双十一,这是一台Tmall的服务器,因为一些原因,服务器进程挂掉了,退出了,由于是服务器主动关闭连接,因此会有TIME_WAIT状态存在,也就意味着服务器进程想立即重启,但是起不来,因为端口(可能是80)还被之前处于TIME_WAIT的连接占用着,如果TIME_WAIT状态维持60秒,60秒服务器都起不来,双十一,啧啧。

4.如何避免?

可设置套接字选项为SO_REUSEADDR,该选项的意思是,告诉操作系统,如果端口忙,但占用该端口TCP连接处于TIME_WAIT状态,并且套接字选项为SO_REUSEADDR,则该端口可被重用。如果TCP连接处于其他状态,依然返回端口被占用。该选项对服务程序重启非常有用。

参考文章:

[1]https://www.cnblogs.com/dabai56/p/11201106.html
[2]https://blog.****.net/m673010624/article/details/99703200