TIMEWAIT状态

版权声明:guojawee https://blog.csdn.net/weixin_36750623/article/details/84949809

在这里插入图片描述
图中可以看到:主动关闭方将进入TIME_WAIT状态;被动关闭方将进入CLOSE_WAIT状态

该计时器就是TIME_WAIT计时器,即当主动方A发送FIN给对方B后,被动方B回复ACK后,主动方A将进入TIME_WAIT状态(用来等待B发送FIN+ACK)。如果在计时器时间内没有接收到B发来的FIN+ACK,A将会重启TIME_WAIT计时器继续等待B发来的FIN+ACK。保证全双工管道的安全断开。

TIMEWAIT是友好的

Note1:什么是TIME_WAIT状态?
客户端在接收到服务器发送的FIN段后,没有立即进入CLOSED状态,而是进入TIME_WAIT状态;在TIME_WAIT状态,客户端连接要等待一段长为2MSL的时间才能完全关闭。

Note2:TIME_WAIT状态存在的2个原因
(1)可靠的终止TCP连接
假如报文段7(ACK)丢失:那么服务器将会重发报文段6(FIN),客户端需要停留在TIME_WAIT状态以处理重复收到的报文段6(FIN),(补充说明:假如没有2MSL的延时等待,客户端只能以RST段回应服务器,异常终止连接
(2)保证让迟来的TCP报文段有足够的时间被识别并丢弃
在Linux系统上,一个TCP端口不能被同时打开多次。当一个TCP连接处于TIME_WAIT状态是,无法立即使用该连接占用着的端口来建立一个新连接。

Note3:假如没有TIME_WAIT状态,会有哪些危害?
① 如果不存在TIME_WAIT状态,则应用程序能够建立一个和刚关闭的连接相似的连接(相似指它们具有相同的IP和PORT)。这个新的、和原来相似的连接称为原来连接的化身。新的化身可能接收到属于原来连接的TCP报文段,这显然是不应该发生的。 因此,一个连接的新的化身可以在2MSL时间之后安全的建立,而绝对不会收到属于原来连接的应用程序数据,这就是TIME_WAIT状态要持续2MSL时间的原因。
②另外,因为TCP报文段的最大生存时间是MSL,所以坚持2MSL时间的TIME_WAIT状态能确保网络上两个传输方向上尚未被接收到、迟到的TCP报文段都已经消失。

大量TIMEWAIT在某些场景中导致的令人头疼的业务问题

在高并发短连接的TCP服务器上,当服务器处理完请求后立刻按照主动正常关闭连接。这个场景下,会出现大量socket处于TIMEWAIT状态。如果客户端的并发量持续很高,此时部分客户端就会显示连接不上。
来解释下这个场景。主动正常关闭TCP连接,都会出现TIMEWAIT。为什么我们要关注这个高并发短连接呢?有两个方面需要注意:

  1. 高并发可以让服务器在短时间范围内同时占用大量端口,而端口有个0~65535的范围,并不是很多,刨除系统和其他服务要用的,剩下的就更少了。
  2. 在这个场景中,短连接表示“业务处理+传输数据的时间 远远小于 TIMEWAIT超时的时间”的连接。这里有个相对长短的概念,比如,取一个web页面,1秒钟的http短连接处理完业务,在关闭连接之后,这个业务用过的端口会停留在TIMEWAIT状态几分钟,而这几分钟,其他HTTP请求来临的时候是无法占用此端口的。单用这个业务计算服务器的利用率会发现,服务器干正经事的时间和端口(资源)被挂着无法被使用的时间的比例是 1:几百,服务器资源严重浪费。(说个题外话,从这个意义出发来考虑服务器性能调优的话,长连接业务的服务就不需要考虑TIMEWAIT状态。同时,假如你对服务器业务场景非常熟悉,你会发现,在实际业务场景中,一般长连接对应的业务的并发量并不会很高)

综合这两个方面,持续的到达一定量的高并发短连接,会使服务器因端口资源不足而拒绝为一部分客户服务。同时,这些端口都是服务器临时分配,无法用SO_REUSEADDR选项解决这个问题:(

一对矛盾:TIMEWAIT既友好,又令人头疼。但是我们还是要抱着一个友好的态度来看待它,因为它尽它的能力保证了服务器的健壮性。

可行而且必须存在,但是不符合原则的解决方式

  1. linux没有在sysctl或者proc文件系统暴露修改这个TIMEWAIT超时时间的接口,可以修改内核协议栈代码中关于这个TIMEWAIT的超时时间参数,重编内核,让它缩短超时时间,加快回收;
  2. 利用SO_LINGER选项的强制关闭方式,发RST而不是FIN,来越过TIMEWAIT状态,直接进入CLOSED状态。(详细请看socket套接字选项详解的SO_LINGER

为什么说上述两种解决方式我觉得可行,但是不符合原则?
首先认为,要依靠TIMEWAIT状态来保证我的服务器程序健壮,网络上发生的乱七八糟的问题太多了,先要服务功能正常。
那是不是就不要性能了呢?并不是。如果服务器上跑的短连接业务量到了我真的必须处理这个TIMEWAIT状态过多的问题的时候,解决原则是尽量处理,而不是跟TIMEWAIT干上,非先除之而后快:)如果尽量处理了,还是解决不了问题,仍然拒绝服务部分请求,那我会采取分机器的方法,让多台机器来抗这些高并发的短请求。持续十万并发的短连接请求,两台机器,每台5万个,应该够用了吧。一般的业务量以及国内大部分网站其实并不需要关注这个问题,一句话,达不到需要关注这个问题的访问量。
真正地必须使用上述我认为不合理的方式来解决这个问题的场景有没有呢?答案是有,像淘宝、百度、新浪、京东商城这样的站点,由于有很多静态小图片业务,如果过度分服会导致需要上线大量机器,多买机器多花钱,得多配机房,多配备运维工程师来守护这些机器,成本增长非常严重。这个时候就要尽一切可能去优化。

如何尽量并合理地处理TIMEWAIT过多

  1. sysctl改两个内核参数就行了,如下:
    net.ipv4.tcp_tw_reuse = 1
    net.ipv4.tcp_tw_recycle = 1
    简单来说,就是打开系统的TIMEWAIT重用和快速回收,至于怎么重用和快速回收,这个问题我没有深究,实际场景中这么做确实有效果。用netstat或者ss观察就能得出结论。
  2. 还有些朋友同时也会打开syncookies这个功能,如下:
    net.ipv4.tcp_syncookies = 1
    打开这个syncookies的目的实际上是:“在服务器资源(并非单指端口资源,拒绝服务有很多种资源不足的情况)不足的情况下,尽量不要拒绝TCP的 syn(连接)请求,尽量把syn请求缓存起来,留着过会儿有能力的时候处理这些TCP的连接请求”。
    如果并发量真的非常非常高,打开这个其实用处不大。

猜你喜欢

转载自blog.csdn.net/weixin_36750623/article/details/84949809