主动关闭连接的一方在最后会进入TIME-WAIT状态,这个TIME-WAIT状态通常会保持在2分钟左右,也就是有2分钟的时间对这个端口是占用的,这对于同时处理大量TCP连接的服务器来说是一个非常大的负担,所以我们总是去试图减少TIME-WAIT状态所持续的时间。
下面介绍如何去优化TIME-WAIT状态端口的数量。
右边图发送3个报文,1 2 3都被接收到了,但是3丢掉了,如果右边这端主动发送了FIN包,进入了FIN-WAIT-1,然后客户端也发送了FIN+ACK,正常的关闭。
如果没有TIME-WAIT状态或者TIME-WAIT状态非常短,就有可能发生下面的事情,比如第三个报文其实不是丢失了,它只是在网络当中被延迟了,现在它突然收到了,就会对接收方造成数据错乱的影响,所以time-wait是有保护效果的,它保持不让延迟发过来的数据来扰乱我的新连接。
time-wait通常保持报文往返时间内端口都是不可复用的。
在Linux上面由于处理了大量的连接,所以time-wait作用对其影响比较大,tcp_tw_reuse开启这个功能之后,它意味着当作为客户端的时候建立新的连接的时候,仍然可以使用处于time-wait状态的端口。
之前介绍了tcp的timestamp这样一个功能,由于有这样的option选项的存在,所以我们就可以拒绝迟到的报文,因为迟到的报文有timestamp,所以知道其隶属于上一个连接,不是我当前的连接,我就可以将其拒绝掉,当然启用的时候要将net.ipv4.tcp_timestamps置为1。
当然对Linux下面的优化还有一些功能,net.ipv4.tcp_tw_recycle = 0是关闭的,同时作为客户端,服务器都可以使用time-wait状态下的端口,上面tcp_tw_reuse只是作为客户端可以使用,这个时候风险是比较小的,作为服务器端也可以使用time-wait状态的端口,就一定会被延迟的报文还有重复的报文影响新的连接,造成数据的混乱,所以通常是不开启的。
还有处于time-wait状态连接的数量也是可以控制的,net.ipv4.tcp_max_tw_buckets来控制最大time-wait连接的数量,当达到最大连接数量之后,如果还需要进入time-wait状态,那我们要直接关闭连接,直接进入close状态。