也说说TIME_WAIT状态

也说说TIME_WAIT状态

一个朋友问到,自己用go写了一个简单的HTTP服务端程序,为什么压测的时候服务端会出现一段时间的TIME_WAIT超高的情况,导致压测的效果不好呢?
记得老王有两篇文章专门说这个,当时粗粗看了一遍,正好碰上这个问题,又翻出来细细搂了。

第一个要弄懂的,是TIME_WAIT是怎么产生的。

TIME_WAIT状态是怎么产生的

要弄懂TIME_WAIT要从TCP的四次握手的分手协议说起。

上面这个图片展示了TCP从连接建立到连接释放的过程中,客户端和服务端的状态变化图。如果只看连接释放阶段,四次握手

  • 客户端先发送FIN,进入FIN_WAIT1状态
  • 服务端收到FIN,发送ACK,进入CLOSE_WAIT状态,客户端收到这个ACK,进入FIN_WAIT2状态
  • 服务端发送FIN,进入LAST_ACK状态
  • 客户端收到FIN,发送ACK,进入TIME_WAIT状态,服务端收到ACK,进入CLOSE状态
  • 客户端TIME_WAIT持续2倍MSL时长,在linux体系中大概是60s,转换成CLOSE状态

当然在这个例子和上面的图片中,使用客户端和服务端来描述是不准确的,TCP主动断开连接的一方可能是客户端,也可能是服务端。所以使用主动断开的一方,和被动断开的一方替换上面的图可能更为贴切。

不管怎么说,TIME_WAIT的状态就是主动断开的一方,发送完最后一次ACK之后进入的状态。并且持续时间还挺长的。

能不能发送完ACK之后不进入TIME_WAIT就直接进入CLOSE状态呢?不行的,这个是为了TCP协议的可靠性,由于网络原因,ACK可能会发送失败,那么这个时候,被动一方会主动重新发送一次FIN,这个时候如果主动方在TIME_WAIT状态,则还会再发送一次ACK,从而保证可靠性。那么从这个解释来说,2MSL的时长设定是可以理解的,MSL是报文最大生存时间,如果重新发送,一个FIN+一个ACK,再加上不定期的延迟时间,大致是在2MSL的范围。

所以从理论上说,网上调试参数降低TIME_WAIT的持续时间的方法是一种以可靠性换取性能的一种方式。嗯,质量守恒定理还是铁律。

服务端TIME_WAIT过多

回到上面的问题,go写了一个HTTP服务,压测发现TIME_WAIT过多。

首先判断是不是压测程序放在服务的同一台机器...当然不会犯这么低级的错误...

那么这个感觉就有点奇怪了,HTTP服务并没有依赖外部mysql或者redis等服务,就是一个简单的Hello world,而TIME_WAIT的是主动断开方才会出现的,所以主动断开方是服务端?

答案是是的。在HTTP1.1协议中,有个 Connection 头,Connection有两个值,close和keep-alive,这个头就相当于客户端告诉服务端,服务端你执行完成请求之后,是关闭连接还是保持连接,保持连接就意味着在保持连接期间,只能由客户端主动断开连接。还有一个keep-alive的头,设置的值就代表了服务端保持连接保持多久。

HTTP默认的Connection值为close,那么就意味着关闭请求的一方几乎都会是由服务端这边发起的。那么这个服务端产生TIME_WAIT过多的情况就很正常了。

虽然HTTP默认Connection值为close,但是现在的浏览器发送请求的时候一般都会设置Connection为keep-alive了。所以,也有人说,现在没有必要通过调整参数来使TIME_WAIT降低了。

解决方法

按照HTTP协议的头,我们在压测程序发出的HTTP协议头里面加上connection:keep-alive当然能解决这个问题。

还有的方法就是系统参数调优:

sysctl net.ipv4.tcp_tw_reuse=1

sysctl net.ipv4.tcp_tw_recycle=1
sysctl net.ipv4.tcp_timestamps=1

tcp_tw_reuse

这个参数作用是当新的连接进来的时候,可以复用处于TIME_WAIT的socket。默认值是0。

tcp_tw_recycle和tcp_timestamps

默认TIME_WAIT的超时时间是2倍的MSL,但是MSL一般会设置的非常长。如果tcp_timestamps是关闭的,开启tcp_tw_recycle是没用的。但是一般情况下tcp_timestamps是默认开启的,所以直接开启就有用了。

时间: 2024-09-26 22:35:23

也说说TIME_WAIT状态的相关文章

tcp-求网络大牛解决疑难杂症,为何断开连接后,不出现time_wait状态

问题描述 求网络大牛解决疑难杂症,为何断开连接后,不出现time_wait状态 我们都知道,tcp/ip协议断开连接是4次挥手,主动断开的一方,最后会进入time_wait状态,等待2MSL后变成CLOSED,但是我在本地做了一个php网页,代码逻辑就是先sleep,3秒钟然后输出几个字符,但是查看网络状态时,压根找不到time_wait的状态: 以下是通过natstat命令,查看到机器上的状态 1.在服务器sleep的时候,建立连接的双方都是ESTABLISHED 2.网页输出之后,大约过3秒

《UNIX网络编程 卷1:套接字联网API(第3版)》——2.7 TIME_WAIT状态

2.7 TIME_WAIT状态 毫无疑问,TCP中有关网络编程最不容易理解的是它的TIME_WAIT状态.在图2-4中我们看到执行主动关闭的那端经历了这个状态.该端点停留在这个状态的持续时间是最长分节生命期(maximum segment lifetime,MSL)的两倍,有时候称之为2MSL. 任何TCP实现都必须为MSL选择一个值.RFC 1122[Braden 1989]的建议值是2分钟,不过源自Berkeley的实现传统上改用30秒这个值.这意味着TIME_WAIT状态的持续时间在1分钟

网络通讯-为什么ServerSocket关闭后不进入time_wait状态啊?

问题描述 为什么ServerSocket关闭后不进入time_wait状态啊? 为什么ServerSocket关闭后不进入time_wait状态啊? 解决方案 Java的Socket 是对TCP/IP协议之上的封装,正常来说你执行关闭后,我们也看不到TCP关闭过程中的四次握手状态的变化的. 如果你真的想分析四次握手这个过程中通信过程及状态的变化,应该通过抓包工具分析网卡的通信数据包. 参考:http://www.360doc.com/content/14/1201/16/7669533_4296

linux 网络编程之TIME_WAIT状态

                                                         Linux 网络编程之TIME_WAIT状态                                                               刚刚开始看TCP socket的4次握手终止流程图的时候,对于最后的TIME_WAIT状态不是很理解.现在在回过头来研究,发现TIME_WAIT状态是一个很微妙状态.之所以设计TIME_WAIT状态的原因有2个原因:

TCP连接状态详解及TIME_WAIT过多的解决方法

  TIME_WAIT状态原理 ---------------------------- 通信双方建立TCP连接后,主动关闭连接的一方就会进入TIME_WAIT状态. 客户端主动关闭连接时,会发送最后一个ack后,然后会进入TIME_WAIT状态,再停留2个MSL时间(后有MSL的解释),进入CLOSED状态. 下图是以客户端主动关闭连接为例,说明这一过程的.   TIME_WAIT状态存在的理由 ---------------------------- TCP/IP协议就是这样设计的,是不可避

UNIX网络编程:如何处理服务器中大量的TIME_WAIT

出现条件: 服务器主动关闭 短连接服务加剧 根据TCP协议定义的3次握手断开连接规定,发起socket主动关闭的一方 socket将进入TIME_WAIT状态,TIME_WAIT状态将持续2个MSL(Max Segment Lifetime),TIME_WAIT状态下的socket不能被回收使用. 具体现象是对于一个处理大量短连接的服务器,如果是由服务器主动关闭客户端的连接,将导致服务器端存在大量的处于TIME_WAIT状态的socket, 甚至比处于Established状态下的socket多

tcp短连接TIME_WAIT问题解决方法大全(1)——高屋建瓴

tcp连接是网络编程中最基础的概念,基于不同的使用场景,我们一般区分为"长连接"和"短连接",长短连接的优点和缺点这里就不详细展开了,有心的同学直接去google查询,本文主要关注如何解决tcp短连接的TIME_WAIT问题. 短连接最大的优点是方便,特别是脚本语言,由于执行完毕后脚本语言的进程就结束了,基本上都是用短连接.但短连接最大的缺点是将占用大量的系统资源,例如:本地端口.socket句柄.导致这个问题的原因其实很简单:tcp协议层并没有长短连接的概念,因此

tcp链接的几种状态&tcpdump抓包

linux服务器上的11种tcp状态   说明: 通常情况下:一个正常的TCP连接,都会有三个阶段:1.TCP三次握手;2.数据传送;3.TCP四次挥手 里面的几个概念: SYN: (同步序列编号,Synchronize Sequence Numbers) ACK: (确认编号,Acknowledgement Number) FIN: (结束标志,FINish) TCP三次握手(创建 OPEN) 客户端发起一个和服务创建TCP链接的请求,这里是SYN(J) 服务端接受到客户端的创建请求后,返回两

tcp短连接TIME_WAIT问题解决方法大全(5)——tcp_max_tw_buckets

参考官方文档(http://www.kernel.org/doc/Documentation/networking/ip-sysctl.txt),解释如下:tcp_max_tw_buckets - INTEGERMaximal number of timewait sockets held by system simultaneously.If this number is exceeded time-wait socket is immediately destroyedand warning