【网络】简单聊一下 TIME_WAIT

问题背景

笔者在看自己服务状态数据的时候,会发现有很多 tcp 的连接,也会发现有很多处于不同状态下的 tcp 连接,TIME_WAIT 的连接数有83个,为了弄清楚这个 TIME_WAIT 是什么,整理了下面的笔记用于梳理概念
在这里插入图片描述

基础流程

TCP的三次握手和四次挥手是TCP协议建立和终止连接的基本过程。

在这里插入图片描述

三次握手过程如下:

  1. 客户端发送SYN包(同步序列编号)给服务器,等待服务器确认。
  2. 服务器收到SYN包后,会确认客户的SYN(发送一个ACK),同时也会发送一个SYN包,这个步骤称为SYN+ACK。
  3. 客户端收到服务器的SYN+ACK后,还需向服务器发送确认包ACK。至此,完成三次握手,客户端和服务器开始传送数据。

四次挥手过程如下:

  1. 当数据传送完毕后,客户端会发送一个FIN包给服务器,请求关闭连接。
  2. 服务器收到FIN包后,会发送一个ACK给客户端,确认接收到了FIN包,但不会立即关闭连接,因为服务器可能还有数据需要处理和发送。
  3. 当服务器数据发送完毕后,会向客户端发送FIN包,请求关闭连接。
  4. 客户端收到FIN包后,会发送一个ACK给服务器,然后进入TIME_WAIT状态。TIME_WAIT状态持续一段时间后,如果没有再收到服务器的消息,那么就关闭连接。至此,完成四次挥手。

为什么有 TIME_WAIT

TIME_WAIT状态在TCP四次挥手的最后阶段出现。在TCP连接被关闭后,操作系统会等待一段时间(通常是2倍的最大分段生存时间),以确保对方收到了关闭连接的确认。这个等待时间就是TIME_WAIT。对于复杂的网络状态,TCP 的实现提出了多种应对措施,TIME_WAIT 状态的提出就是为了应对其中一种异常状况。 此状态的存在主要有两个原因:

  1. 保证最后一个确认消息能被对方收到。如果直接关闭连接,那么对方可能会因为没有收到确认消息而无法关闭连接。
  2. 避免“旧的重复分组”在新的连接中被错误接收。由于网络原因,有可能会有一些旧的重复分组在网络中滞留,如果直接开启新的连接,这些旧的重复分组可能会被新的连接误认为是自己的数据。

为了理解 TIME_WAIT 状态的必要性,我们先来假设没有这么一种状态会导致的问题。暂以 A、B 来代指 TCP 连接的两端,A 为主动关闭的一端。

  • 四次挥手中,A 发 FIN, B 响应 ACK,B 再发 FIN,A 响应 ACK 实现连接的关闭。而如果 A 响应的 ACK 包丢失,B 会以为 A 没有收到自己的关闭请求,然后会重试向 A 再发 FIN 包。

    如果没有 TIME_WAIT 状态,那么A回复ACK立刻关闭,所以B重发的会让A响应重置,A 不再保存这个连接的信息,收到一个不存在的连接的包,A 会响应 RST 包,导致 B 端异常响应。

    此时, TIME_WAIT 是为了保证全双工的 TCP 连接正常终止。

  • 我们还知道,TCP 下的 IP 层协议是无法保证包传输的先后顺序的。如果双方挥手之后,一个网络四元组(src/dst ip/port)被回收,而此时网络中还有一个迟到的数据包没有被 B 接收,A 应用程序又立刻使用了同样的四元组再创建了一个新的连接后,这个迟到的数据包才到达 B,那么这个数据包就会让 B 以为是 A 刚发过来的。

    此时, TIME_WAIT 的存在是为了保证网络中迷失的数据包正常过期。

不同场景下的 TIME_WAIT 的具体影响

基于不同的使用场景,我们一般区分为“长连接”和“短连接”

长链接

长连接,指在一个连接上可以连续发送多个数据包,在连接保持期间,如果没有数据包发送,需要双方发链路检测包。

是一种在客户端和服务器之间维持长时间连接的通信机制。与传统的短链接请求-响应模型不同,长链接允许客户端向服务器发出请求并保持连接打开,以等待服务器在有数据更新时立即响应。

长链接的工作原理通常如下:

  1. 客户端发起连接请求: 客户端向服务器发送一个连接请求。
  2. 服务器保持连接打开: 服务器接收到连接请求后,保持连接打开并等待数据变化或其他事件的发生。
  3. 服务器响应: 当服务器有数据更新或满足其他条件时,它立即响应客户端请求,并发送数据给客户端。
  4. 客户端处理响应: 客户端接收到服务器的响应后,可以处理数据更新或执行其他操作。
  5. 连接保持开放: 连接保持开放,客户端和服务器可以继续在连接上进行通信。

长连接的优点是:

这种长链接机制的优势在于实时性更强,因为服务器可以立即将更新推送给客户端,而无需等待客户端发起新的请求。这对于实时通信、即时消息推送以及需要及时获取数据更新的应用场景非常有用。

  • 减少了建立连接和断开连接的开销,提高了传输效率。
  • 减少了连接数,节省了服务器资源。
  • 便于维护和管理。

长连接的缺点是:

长链接也有一些缺点,例如在一些网络环境中可能存在连接超时的问题,而且在维持大量长连接时可能增加服务器的负载。因此,开发人员需要根据具体的应用场景和需求来选择适当的通信机制。

  • 可能会导致连接泄漏,造成资源浪费。
  • 可能会导致连接超时,影响传输效率。

长连接的应用场景包括:

  • 聊天软件:客户端和服务器之间需要保持长连接,以便及时交换消息。
  • 文件传输:服务器和客户端之间需要保持长连接,以便传输大文件。
  • 实时数据传输:服务器和客户端之间需要保持长连接,以便实时传输数据。
package mainimport ("fmt""net""time"
)func handleLongConnection(conn net.Conn) {defer conn.Close()for {// 读取客户端发送的数据buffer := make([]byte, 1024)_, err := conn.Read(buffer)if err != nil {fmt.Println("Error reading:", err)return}// 处理数据fmt.Println("Received:", string(buffer))// 模拟长连接,等待一段时间再回复客户端time.Sleep(time.Second * 5)// 向客户端发送响应response := []byte("Server response")conn.Write(response)}
}func main() {listener, err := net.Listen("tcp", ":8080")if err != nil {fmt.Println("Error listening:", err)return}defer listener.Close()fmt.Println("Server listening on :8080 for long connection")for {conn, err := listener.Accept()if err != nil {fmt.Println("Error accepting connection:", err)continue}// 启动长连接处理协程go handleLongConnection(conn)}
}

短连接

短连接是指在数据传送过程中,只在需要发送数据时,才去建立一个连接,数据发送完成后,则断开此连接,即每次连接只完成一项业务的发送。

在计算机网络中,短连接(short connection)是指在数据传送过程中,只在需要发送数据时,才去建立一个连接,数据发送完成后,则断开此连接,即每次连接只完成一项业务的发送。

短连接的优点是**:**

  1. 资源释放: 短连接在完成数据传输后会立即释放资源,不需要维持长时间的连接状态,因此能够更有效地释放系统资源。
  2. 简单易实现: 短连接模型相对简单,易于实现和维护。每个请求都是独立的,不需要维持连接状态。
  3. 连接灵活性: 短连接适用于一些场景,如HTTP请求,每次请求都是独立的,适合短暂的数据交互。
  4. 适用于并发: 短连接模型适用于并发连接,因为每个连接都是独立的,不会影响其他连接。

短连接的缺点是:

  1. 连接建立开销: 每次建立连接都需要进行握手过程,包括TCP的三次握手,这会增加网络开销。
  2. 频繁的连接断开和建立: 对于高频率的短连接,频繁的连接断开和建立可能会增加系统开销,尤其是在高并发的情况下。
  3. 维护开销: 如果应用中存在频繁的连接建立和断开,服务器需要维护大量的连接状态信息,可能会增加服务器的负担。
  4. 实时性差: 短连接可能无法满足实时性要求较高的应用场景,因为连接建立和断开的开销可能影响数据的实时传输。

短连接的应用场景包括:

  • 浏览器和服务器之间的HTTP请求。
  • 邮件服务器和客户端之间的SMTP/POP3/IMAP协议。
  • 聊天软件客户端和服务器之间的聊天协议。
package mainimport ("fmt""net"
)func handleShortConnection(conn net.Conn) {defer conn.Close()// 读取客户端发送的数据buffer := make([]byte, 1024)_, err := conn.Read(buffer)if err != nil {fmt.Println("Error reading:", err)return}// 处理数据fmt.Println("Received:", string(buffer))// 向客户端发送响应response := []byte("Server response")conn.Write(response)
}func main() {listener, err := net.Listen("tcp", ":8081")if err != nil {fmt.Println("Error listening:", err)return}defer listener.Close()fmt.Println("Server listening on :8081 for short connection")for {conn, err := listener.Accept()if err != nil {fmt.Println("Error accepting connection:", err)continue}// 启动短连接处理handleShortConnection(conn)}
}

正常的TCP客户端连接在关闭后,会进入一个TIME_WAIT的状态,持续的时间一般在1~4分钟,如果短时间内(例如1s内)进行大量的短连接,则可能出现这样一种情况:客户端所在的操作系统的socket端口和句柄被用尽,系统无法再发起新的连接!如果 TIME_WAIT 连接过多,会消耗大量的系统资源,会耗尽可用的网络端口,从而阻止新的连接建立。因此,对于处于 TIME_WAIT 状态的连接,需要进行合理的管理和控制。

举例来说:假设每秒建立了1000个短连接(Web场景下是很常见的,例如每个请求都去访问),假设TIME_WAIT的时间是1分钟,则1分钟内需要建立6W个短连接,由于TIME_WAIT时间是1分钟,这些短连接1分钟内都处于TIME_WAIT状态,都不会释放,而Linux默认的本地端口范围配置是:net.ipv4.ip_local_port_range = 32768 ~ 61000 不到3W,因此这种情况下新的请求由于没有本地端口就不能建立了。

缓解办法

代码侧

GOLANG

go 里面 Transport 默认参数有个 MaxIdleConns 是100,还有 Timeout 是 90s,这两个参数会导致 client 自动发起 FIN,代码侧可以优化这边的逻辑,不同的语言应该有对应的优化方法。

在这里插入图片描述

系统侧

在TCP连接中,TIME_WAIT状态是在连接关闭后等待一段时间的状态,以确保对方收到了最后的ACK。这是为了处理网络中的滞留数据报文(可能在网络中延迟到达),防止它们被新的连接误认为是旧的连接的问题。

降低TIME_WAIT状态对于提高连接的重用速度是有风险的,因为它可能导致旧的数据报文在网络中被混淆。然而,如果你仍然想要降低TIME_WAIT状态的等待时间,可以在系统上进行一些调整。请注意,对于这样的操作,你应该非常小心,因为它可能会对网络稳定性产生负面影响。

在Linux系统上,你可以通过修改内核参数来调整TIME_WAIT状态的等待时间。

  • net.ipv4.tcp_max_tw_buckets:指定系统同时保持 TIME_WAIT 的最大数量。
  • net.ipv4.tcp_tw_reuse:如果设置为 1,则允许 TIME_WAIT 状态的连接被重用。
  • net.ipv4.tcp_tw_recycle:如果设置为 1,则允许 TIME_WAIT 状态的连接在 FIN_WAIT-2 状态时被快速回收。

以下是一些可能的方法:

方法一:通过sysctl修改

通过sysctl可以动态地调整内核参数。

sudo sysctl -w net.ipv4.tcp_tw_reuse=1
sudo sysctl -w net.ipv4.tcp_tw_recycle=1
  • net.ipv4.tcp_tw_reuse=1 允许将TIME_WAIT状态的连接端口重用。
  • net.ipv4.tcp_tw_recycle=1 尝试根据时间戳来快速回收TIME_WAIT状态的连接。

这种方法修改是暂时的,重启后会失效。

方法二:修改sysctl配置文件

将上述配置添加到 /etc/sysctl.conf 文件中,以便在系统启动时应用。

echo "net.ipv4.tcp_tw_reuse=1" | sudo tee -a /etc/sysctl.conf
echo "net.ipv4.tcp_tw_recycle=1" | sudo tee -a /etc/sysctl.conf
sudo sysctl -p

这种方法在系统重启后仍然有效。

请注意,在一些情况下,使用 net.ipv4.tcp_tw_recycle 可能会导致问题,因为它可能与一些网络设备不兼容。在生产环境中,修改这些参数前应该进行充分测试,以确保它们不会对系统的稳定性和性能产生负面影响。

总的来说,TIME_WAIT 是TCP连接管理中的一个重要环节,尽管它可能会引发一些问题,但适当的管理和调优可以最大程度地减轻这些问题的影响,保证网络连接的正常运行。

总结

在 Go 中,HTTP客户端(例如**http.Client**)发起的HTTP请求的完成过程可能涉及到TCP连接的正常关闭,从而触发发送TCP FIN(Finish)标志。这是正常的TCP连接关闭行为,其触发条件包括:

  1. HTTP请求完成: 当HTTP请求完成(例如,成功获取到响应或发生错误)时,客户端的**http.Transport**可能会将连接放回到连接池以便复用,或者决定是否关闭连接。
  2. 连接池空闲时: 如果连接池中没有空闲的连接,并且该连接也没有被标记为永久保持活跃(通过**Transport.DisableKeepAlives**设置),那么连接可能会被关闭。
  3. 达到最大空闲连接数: 如果连接池中的连接数量达到了 http.TransportMaxIdleConnsMaxIdleConnsPerHost 设置的最大空闲连接数,那么一些连接可能会被关闭。
  4. 连接过期: http.Transport 会根据连接的空闲时间进行管理。如果连接在一段时间内未被使用,可能会被关闭。

这些操作是为了维护连接池的健康状态,确保连接的新鲜性,并防止长时间空闲的连接占用资源。触发TCP FIN标志是连接关闭的一部分,用于通知对端连接即将关闭。

引用

CHATGPT

BARD

https://www.xiaolincoding.com/network/3_tcp/tcp_tcpdump.html#解密-tcp-三次握手和四次挥手

https://claire-chang.com/2020/03/01/tcp連線階段與time_wait意義/

https://zhenbianshu.github.io/2018/12/talk_about_tcp_timewait.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/218352.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

rocketmq window测试小Demo 解决找不到或无法加载主类的问题

文章目录 rocketMQ启动1.下在相关的二进制文件2.配置环境变量3.启动NameServer4.启动broker5. MQ 启动!5.1 测试发送数据 6.关闭服务 rocketMQ启动 1.下在相关的二进制文件 下载地址,点击即达 2.配置环境变量 3.启动NameServer 在文件夹下执行cmd进…

Redis7--基础篇9(SpringBoot集成Redis)

1. jedis、lettuce、Redistemplate的关系 第一代为jedis,之后推出了lettuce,然后springboot继承了Redistemplate,现推荐使用Redistemplate。 总的来说,jedis、lettuce、Redistemplate都是java操作Redis数据库的驱动。 2. 本地Ja…

深度学习(六):paddleOCR理解及识别手写体,手写公式,表格

1.介绍 1.1 什么是OCR? 光学字符识别(Optical Character Recognition, OCR),ORC是指对包含文本资料的图像文件进行分析识别处理,获取文字及版面信息的技术,检测图像中的文本资料,并且识别出文本的内容。…

一键删除TXT文本符号,高效批量处理,轻松提升工作效率!

你是否经常处理大量的TXT文本文件,但其中充满了各种符号和不需要的字符?这不仅影响文本的阅读体验,还可能对后续的数据处理和分析造成困扰。现在,我们为你带来一款全新的TXT文本处理工具,一键删除符号,高效…

【数据结构—栈的实现(数组栈)】

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言 一、栈 1.1栈的概念及结构 二、栈的实现 2.1头文件的实现—Stack.h 2.2源文件的实现—Stack.c 2.3源文件的测试—test.c 三、栈的实际测试数据展示 3.1正常的出…

【图像分类】【深度学习】【Pytorch版本】 DenseNet模型算法详解

【图像分类】【深度学习】【Pytorch版本】 DenseNet模型算法详解 文章目录 【图像分类】【深度学习】【Pytorch版本】 DenseNet模型算法详解前言DenseNet讲解Dense Block(稠密块)Dense Layer(稠密层)Transition Layer 过渡层DenseNet模型结构 DenseNet Pytorch代码完整代码附加…

鱼fish数据集VOC+yolo-1400张(labelImg标注)

鱼类,是最古老的脊椎动物。易蓄积重金属。 部分不同染色体数目的杂交的后代依然有生育能力。它们几乎栖居于地球上所有的水生环境,从淡水的湖泊、河流到咸水的大海和大洋。 今天要介绍鱼的数据集。 数据集名称:鱼 fish 数据集格式&#xf…

五分钟快速掌握Maven的核心概念

前两天在一个技术群,有人还在问maven中groupId、artifactId、version这些关键字的含义是什么,于是,我觉得还是很有必要来聊聊Maven中的这些核心概念。 成功不是将来才有的,而是从决定去做的那一刻起,持续累积而成。 …

一次持续 15 年的网络安全“攻防之战”

2003 年 7-8 月,冲击波病毒爆发,对网络安全造成严重影响,尤其是校园网。冲击波病毒不仅使得校园网变得卡顿,还会在学生电脑上强制弹出一个倒计时窗口,60 秒后自动关机,给学生正常使用电脑和网络造成了极大不…

Visual Studio Code (Vscode)配置LaTeX

Visual Studio Code (Vscode)配置LaTeX 实操记录 第一步高效检索,找到官方的、靠谱的安装教程,最好多找几个,英文、中文教程都需要 LaTeX WorkshopInstallation and basic settingsHow to install LaTeX (with previews & autocomplete…

Godot导出Android包报错:无效的包名称

问题描述 使用Godot为项目导出Android平台包时报错,提示:“无效的包名称:项目名称不符合包名格式的要求。请显式指定包名。” 解决办法 修改导出配置项“包->唯一名称”。 该项缺省值“org.godotengine.$genname”不能直接使用&#x…

Paper Reading: (ACRST) 基于自适应类再平衡自训练的半监督目标检测

目录 简介工作重点方法CropBankFBRAFFRTwo-stage Pseudo-label Filtering 实验与SOTA比较消融实验 简介 题目:《Semi-Supervised Object Detection with Adaptive Class-Rebalancing Self-Training》,AAAI’22, 基于自适应类再平衡自训练的半…

外汇天眼:心理素质决定交易成败!

在交易市场中,参与者非常多,成功的却极少。 成功的交易者几乎完全凭借个人的聪明才智,迎难而上,依靠顽强的毅力、坚韧不拔的性格以及冒险精神,战胜自己交易路上的一切挫折。 而这其中交易者的心理素质与其盈亏紧密相关…

【复现】vid2vid_zero

问题及解决方法总结。 code:GitHub - baaivision/vid2vid-zero: Zero-Shot Video Editing Using Off-The-Shelf Image Diffusion Models 1.AttributeError: UNet2DConditionModel object has no attribute encoder 据说是预训练模型结构不匹配,偷懒把a…

架构师进阶,微服务设计与治理的 16 条常用原则

今天将从存储的上一层「服务维度」学习架构师的第二项常用能力 —— 微服务设计与治理。 如何设计合理的微服务架构? 如何保持微服务健康运行? 这是我们对微服务进行架构设计过程中非常关注的两个问题。 本文对微服务的生命周期定义了七个阶段&#x…

安装apisix详细教程

安装: docker安装ApiSi 常见问题-提前查阅 1-端口被占用 确保所需的所有端口(默认的 9080/9091/9443/2379/9000)未被其他系统/进程使用 #查询端口占用情况 netstat -antp |grep 9443 如果端口冲突可尝试修改apisix的端口配置, …

Vue 双向绑定:让数据与视图互动的魔法!(下)

🤍 前端开发工程师(主业)、技术博主(副业)、已过CET6 🍨 阿珊和她的猫_CSDN个人主页 🕠 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 🍚 蓝桥云课签约作者、已在蓝桥云…

CentOS 7.x操作系统的ECS云服务器上搭建WordPress网站

WordPress是使用PHP语言开发的博客平台,在支持PHP和MySQL数据库的服务器上,您可以用WordPress架设自己的网站,也可以用作内容管理系统(CMS)。本教程介绍如何在CentOS 7.x操作系统的ECS实例上搭建WordPress网站。 背景…

springboot listener、filter登录实战

转载自&#xff1a; www.javaman.cn 博客系统访问&#xff1a; http://175.24.198.63:9090/front/index 登录功能 1、前端页面 采用的是layui-admin框架&#xff0c;文中的验证码内容&#xff0c;请参考作者之前的验证码功能 <!DOCTYPE html> <html lang"zh…