也说说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是默认开启的,所以直接开启就有用了。

相关实践学习
深入解析Docker容器化技术
Docker是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux机器上,也可以实现虚拟化,容器是完全使用沙箱机制,相互之间不会有任何接口。Docker是世界领先的软件容器平台。开发人员利用Docker可以消除协作编码时“在我的机器上可正常工作”的问题。运维人员利用Docker可以在隔离容器中并行运行和管理应用,获得更好的计算密度。企业利用Docker可以构建敏捷的软件交付管道,以更快的速度、更高的安全性和可靠的信誉为Linux和Windows Server应用发布新功能。 在本套课程中,我们将全面的讲解Docker技术栈,从环境安装到容器、镜像操作以及生产环境如何部署开发的微服务应用。本课程由黑马程序员提供。     相关的阿里云产品:容器服务 ACK 容器服务 Kubernetes 版(简称 ACK)提供高性能可伸缩的容器应用管理能力,支持企业级容器化应用的全生命周期管理。整合阿里云虚拟化、存储、网络和安全能力,打造云端最佳容器化应用运行环境。 了解产品详情: https://www.aliyun.com/product/kubernetes
目录
相关文章
|
开发者
华为手机如何进行ADB调试
华为手机如何进行ADB调试
1732 0
|
SQL Java 数据库连接
计算机组成原理——浮点数的表示
计算机组成原理——浮点数的表示
1175 0
计算机组成原理——浮点数的表示
|
数据可视化 搜索推荐 API
如何在 FlowUs、Notion笔记软件使用白板和代码绘制流程图(二)
关于如何在 FlowUs 这样的效率工具中如何使用流程图的话题,上次我们在文章中推荐了 ProcessOn 和 Draw.io 这两款工具。具体可以阅读原文。 除了专门的流程图工具,还有其他解决方案吗? 1. 使用白板工具绘制流程图或者思维导图。 2. 使用代码绘制流程图
803 0
|
消息中间件 监控 NoSQL
设计一个百万级的消息推送系统(下)
本次分享的内容不但可以满足物联网领域同时还支持以下场景: 基于 WEB 的聊天系统(点对点、群聊)。 WEB 应用中需求服务端推送的场景。 基于 SDK 的消息推送平台。
|
机器学习/深度学习 人工智能 算法
嵌入式端音频开发(Unisound篇)之 7.1 蜂鸟M离线语音芯片简介
嵌入式端音频开发(Unisound篇)之 7.1 蜂鸟M离线语音芯片简介
786 0
嵌入式端音频开发(Unisound篇)之 7.1 蜂鸟M离线语音芯片简介
|
Python Windows
【windows】python 安装 pytesseract
1. 使用豆瓣源,再命令行安装 pip install pytesseract -i https://pypi.douban.com/simple 1 2. 下载驱动 到这个网站 驱动下载
461 0
【windows】python 安装 pytesseract
|
Web App开发 移动开发 测试技术
uCosII移植STM32F103教程
本文介绍如何快速移植uCosII源码到STM32F103工程,使用标准库进行快速开发
2192 0
uCosII移植STM32F103教程
|
存储 弹性计算 运维
有哪些因素会影响云服务器访问速度?
对一个网站来说,网站的访问速度十分重要,是网站友好体验中最基本的一项,云服务器的速度是可以反映出设备的质量问题的,如果想要有更快的网站访问速度。那么,就需要了解影响云主机访问速度的一些因素。
691 0

热门文章

最新文章