前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >服务器TIME_WAIT和CLOSE_WAIT

服务器TIME_WAIT和CLOSE_WAIT

作者头像
earthchen
发布2020-09-24 11:37:33
9890
发布2020-09-24 11:37:33
举报
文章被收录于专栏:earthchen的专栏earthchen的专栏

time_wait和close_wait

tcp连接和关闭中常见的三种状态是:

  • ESTABLISHED 表示正在通信
  • TIME_WAIT 表示主动关闭
  • CLOSE_WAIT 表示被动关闭。

下面给出三次握手和四次握手的图

有时服务器会在网络状态上出现异常,一半来说是以下两种情况:

  • 服务器保持了大量TIME_WAIT状态
  • 服务器保持了大量CLOSE_WAIT状态

服务器保持了大量TIME_WAIT状态

TIME_WAIT是主动关闭连接的一方,所以,此时不应该叫服务器,应该是客户端。

TIME_WAIT是主动关闭连接的一方保持的状态,对于爬虫服务器来说他本身就是“客户端”,在完成一个爬取任务之后,他就会发起主动关闭连接,从而进入TIME_WAIT的状态,然后在保持这个状态2MSL(max segment lifetime)时间之后,彻底关闭回收资源。为什么要这么做?明明就已经主动关闭连接了为啥还要保持资源一段时间呢?这个是TCP/IP的设计者规定的,主要出于以下两个方面的考虑:

  1. 防止上一次连接中的包,迷路后重新出现,影响新连接(经过2MSL,上一次连接中所有的重复包都会消失)
  2. 可靠的关闭TCP连接。在主动关闭方发送的最后一个 ack(fin) ,有可能丢失,这时被动方会重新发fin, 如果这时主动方处于 CLOSED 状态 ,就会响应 rst 而不是 ack。所以主动方要处于 TIME_WAIT 状态,而不能是 CLOSED 。另外这么设计TIME_WAIT 会定时的回收资源,并不会占用很大资源的,除非短时间内接受大量请求或者受到攻击。

值得一说的是,对于基于TCP的HTTP协议,关闭TCP连接的是Server端,这样,Server端会进入TIME_WAIT状态,可 想而知,对于访问量大的Web Server,会存在大量的TIME_WAIT状态,假如server一秒钟接收1000个请求,那么就会积压240*1000=240,000个 TIME_WAIT的记录,维护这些状态给Server带来负担。当然现代操作系统都会用快速的查找算法来管理这些TIME_WAIT,所以对于新的 TCP连接请求,判断是否hit中一个TIME_WAIT不会太费时间,但是有这么多状态要维护总是不好。 HTTP协议1.1版规定default行为是Keep-Alive,也就是会重用TCP连接传输多个 request/response,一个主要原因就是发现了这个问题。

也就是说HTTP的交互跟上面画的那个图是不一样的,关闭连接的不是客户端,而是服务器,所以web服务器也是会出现大量的TIME_WAIT的情况的。

解决思路

就是让服务器能够快速回收和重用那些TIME_WAIT的资源。

服务器保持了大量CLOSE_WAIT状态

TIME_WAIT状态可以通过优化服务器参数得到解决,因为发生TIME_WAIT的情况是服务器自己可控的,要么就是对方连接的异常,要么就是自己没有迅速回收资源,总之不是由于自己程序错误导致的。

但是CLOSE_WAIT就不一样了,从上面的图可以看出来,如果一直保持在CLOSE_WAIT状态,那么只有一种情况,就是在对方关闭连接之后服务器程序自己没有进一步发出ack信号。换句话说,就是在对方连接关闭之后,程序里没有检测到,或者程序压根就忘记了这个时候需要关闭连接,于是这个资源就一直被程序占着。个人觉得这种情况,通过服务器内核参数也没办法解决,服务器对于程序抢占的资源没有主动回收的权利,除非终止程序运行。

解决思路

将大量CLOSE_WAIT的解决办法总结为一句话那就是:查代码。因为问题出在服务器程序里头啊。

http 是客户端还是服务段主动关闭连接

在不考虑keepalive的情况下

http1.0
  • 带content-length,body长度可知,客户端在接收body时,就可以依据这个长度来接受数据。接受完毕后,就表示这个请求完毕了。客户端主动调用close进入四次挥手
  • 不带content-length ,body长度不可知,客户端一直接受数据,直到服务端主动断开
http1.1
  • 带content-length body长度可知客户端主动断开
  • 带Transfer-encoding:chunked body会被分成多个块,每块的开始会标识出当前块的长度,body就不需要通过content-length来指定了。但依然可以知道body的长度 客户端主动断开
  • 不带Transfer-encoding:chunked且不带content-length 客户端接收数据,直到服务端主动断开连接

即 :如果能够有办法知道服务器传来的长度,都是客户端首先断开。如果不知道就一直接收数据。知道服务端断开

考虑keep-alive情况

http 1.1中默认启用Keep-Alive,如果加入”Connection: close “,才关闭。目前大部分浏览器都是用http1.1协议,也就是说默认都会发起Keep-Alive的连接请求了,所以是否能完成一个完整的Keep-Alive连接就看服务器设置情况。

也就是当开启的时候,都是服务端主动关闭

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018-11-28,,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • time_wait和close_wait
    • 服务器保持了大量TIME_WAIT状态
      • 解决思路
    • 服务器保持了大量CLOSE_WAIT状态
      • 解决思路
    • http 是客户端还是服务段主动关闭连接
      • 在不考虑keepalive的情况下
      • 考虑keep-alive情况
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档