tcp/ip-常见的TIME_WAIT和CLOSE_WAIT问题
参考:https://mp.weixin.qq.com/s?__biz=MzAxOTg2NDUyOA==&mid=2657554876&idx=1&sn=05990e85c366e45415d77593b0d3bda1&mpshare=1&scene=1&srcid=0928LA06I6JCzy2vKKkaPt9f#rd
1 TIME_WAIT
因为TCP连接是双向的,所以在关闭连接的时候,两个方向各自都需要关闭。先发FIN包的一方执行的是主动关闭;后发FIN包的一方执行的是被动关闭。主动关闭的一方会进入TIME_WAIT状态,并且在此状态停留两倍的MSL时长。MSL指的是报文段的最大生存时间,关于MSL的大小,RFC 793协议中给出的建议是两分钟,但是Linux通常是半分钟,并且这个数值是硬编码在内核中的,也就是说除非你重新编译内核,否则没法修改它
TIME_WAIT状态存在的必要性。
为什么主动关闭的一端不直接进入closed状态,而是要先进入time_wait并且停留两倍的MSL时长呢?这是因为TCP是建立在不可靠网络上的可靠协议。如果主动关闭的一端收到被动关闭一端的发出的FIN包后,返回ACK包,同时进入TIME_WAIT,但是由于网络的原因,主动关闭一端发送的ACK包可能会延迟,从而触发被动关闭一方重传FIN包,这样一来一回极端情况正好是2MSL。如果主动关闭的一端直接close或者不到两倍MSL时间就关闭,那么被动关闭发出重传FIN包到达,可能出现的问题是:旧的连接不存在,系统只能返回RST包;新的TCP连接已经建立,延迟包可能会干扰新连接。这都可能导致TCP不可靠。
TIME_WAIT过多的危害
在生产过程中,如果服务器使用短连接,那么完成一次请求后会主动断开连接,就会造成大量time_wait状态。因此我们常常在系统中会采用长连接,减少建立连接的消耗,同时也减少TIME_WAIT的产生,但实际上即使使用长连接配置不当时,当TIME_WAIT的生产速度远大于其消耗速度时,系统仍然会累计大量的TIME_WAIT状态的连接。TIME_WAIT状态连接过多就会造成一些问题。如果客户端的TIME_WAIT连接过多,同时它还在不断产生,将会导致客户端端口耗尽,新的端口分配不出来,出现错误。如果服务器端的TIME_WAIT连接过多,可能会导致客户端的请求连接失败,
上图中标红的部分是外部访问nginx的连接,我们可以看到状态都是ESTABLISHED,表明是长连接。
标绿的部分是nginx访问tomcat的连接,存在大量的TIME_WAIT,默认nginx访问tomcat的连接是短连接,请求完毕立即中断连接,所以我们会在nginx服务所在节点看到大量的TIME_WAIT,就是这个原因。默认情况下TIME_WAIT状态会维持2MSL(linux为60秒)。但是如果请求并发数比较大,TIME_WAIT会耗尽端口号,新的连接建立不起来,会出现问题。