TCP 的 TIME_WAIT 状态是 TCP 连接终止过程中 主动关闭连接的一方(通常是先调用 close() 或主动发送 FIN 的一端)进入的一个重要状态。理解其原理、副作用和优化策略对高性能网络编程和服务器调优至关重要。


🔍 一、TIME_WAIT 是什么?

  • 何时进入?
    当 TCP 连接经历四次挥手正常关闭时:
    1. 主动关闭方发送 FIN → 进入 FIN_WAIT_1
    2. 收到对端 ACK → 进入 FIN_WAIT_2
    3. 收到对端 FIN → 发送 ACK → **进入 ****TIME_WAIT**
  • 停留时长:
    TIME_WAIT 状态持续 2 * MSLMaximum Segment Lifetime,报文最大生存时间)。
    • Linux 默认 MSL = 60秒TIME_WAIT 时长为 120秒(2分钟)。
  • 本质作用:
    1. 可靠终止:
      确保主动关闭方最后发出的 ACK 能到达对端(重传未收到的 ACK)。
      若对端没收到 ACK,会重传 FIN,此时处于 _TIME_WAIT_ 的主动方仍能响应。
    2. 清理旧数据:
      阻止网络中 延迟到达的旧报文 被新连接接收(造成数据错乱)。
      例如:相同五元组的新连接 vs 迟到的旧包(2MSL 时间足以让网络中滞留的包失效)。

简单总结:TIME_WAIT 是 TCP 协议用于安全收尾的保障机制,防止网络出现“幽灵包”破坏连接健壮性。


⚠️ 二、副作用:为什么开发者/运维关注它?

高并发短连接服务(如 HTTP 服务器、API 网关)中,主动关闭方是服务器时会产生显著影响:

问题成因后果
1️⃣** 占用端口资源**每个 TIME_WAIT
连接占用一个本地 (源IP, 源端口, 目标IP, 目标端口)
四元组。
客户端端口耗尽(尤其客户端用短连接访问同一服务端),无法发起新连接
2️⃣** 内存占用**内核需维护 TCP 控制块(struct tcp_sock
),每个连接占用约 2-4KB
内存。
海量 TIME_WAIT
(如 10万+)消耗数百 MB 内存,可能导致 OOM
3️⃣** 增加延迟**若服务端因端口被占满而拒绝连接,客户端需重试或等待。用户体验下降(连接超时)。
4️⃣** SYN 建连失败(间接)**net.ipv4.tcp_tw_reuse/recycle
等优化参数若配置不当,可能导致 NAT 环境 SYN 被丢弃。
新连接握手失败(典型表现:cannot assign requested address

📌 关键认知:

  • 客户端主动关闭 → TIME_WAIT 出现在客户端(对服务端影响小);
  • 服务端主动关闭 → TIME_WAIT 集中在服务端(高并发时成为瓶颈)。

🛠️ 三、可以关闭吗?优化策略是什么?

绝不能彻底关闭 TIME_WAIT!
它的设计解决了 TCP 可靠性和健壮性的核心问题。但可通过以下合理优化缓解其副作用:

推荐优化方案:
策略原理配置方法(Linux)适用场景
1️⃣** 调整短连接为长连接**减少连接创建/销毁次数,从源头降低 TIME_WAIT
数量。
- HTTP 层:客户端/服务端开启 Keep-Alive

- RPC 层:配置连接池复用连接。
所有高并发短连接服务首选方案!
2️⃣** 让客户端主动关闭连接**TIME_WAIT
分散到海量客户端,避免服务端端口耗尽。
服务端设置 HTTP Header:Connection: close
(强制客户端主动关闭)。
服务端压力过大时的应急方案(但牺牲连接复用能力)。
3️⃣** 开启 ****tcp_tw_reuse**允许内核复用处于 TIME_WAIT
的端口,前提是新连接的序列号 > 旧连接最后序列号(防旧包)。
sysctl -w net.ipv4.tcp_tw_reuse=1

(仅对 出向连接 生效,客户端角色最有用)
适合作为客户端的程序(如 Nginx 反向代理的后端连接)
4️⃣** 增加端口范围 + 缩短 MSL**提升可用端口数上限;加快 TIME_WAIT
回收速度。
bash<br>sysctl -w net.ipv4.ip_local_port_range="1024 65000"<br>sysctl -w net.ipv4.tcp_fin_timeout=30 # ⚠️ 风险选项<br>配合 tcp_tw_reuse
使用(修改 MSL 需编译内核,一般不建议)
5️⃣** 使用 **SO_LINGER**
选项**
强制用 RST
代替 FIN
关闭连接(跳过 TIME_WAIT
),极其危险!
代码中设置 Socket 选项:
l_onoff = 1; l_linger = 0;
→ 发送 RST
暴力断连
除非绝对可控(如内网中间件),生产环境禁用!破坏 TCP 可靠性。
被废弃/高危参数:
  • net.ipv4.tcp_tw_recycle (Linux 4.1+ 已移除):
    • 曾经用于快速回收 TIME_WAIT 端口,但基于 per-host 的 PAWS 机制破坏了 NAT 网络(多个客户端共享公网IP)下的连接。
    • 结果: 造成 SYN 被丢弃(表现为随机连接失败)。
    • 结论:永远不要再使用!

🔐 四、最佳实践总结

场景优化建议
HTTP 服务端1. 开启 Keep-Alive 长连接
2. 调整 tcp_tw_reuse=1
(若需作为客户端代理)
3. 扩大端口范围
数据库/缓存客户端1. 开启连接池复用
2. 设置 tcp_tw_reuse=1
(客户端角色)
高性能网关/代理服务器1. 增端口数
2. 长连接复用
3. 用 tcp_tw_reuse=1
(代理主动连接后端)
应急情况设置服务端 Connection: close
(客户端主动关 → 分散 TIME_WAIT
到客户端)

📜 终极原则:
优先长连接 → 其次端口复用(tcp_tw_reuse)→ 拒绝 tcp_tw_recycle 和暴力 SO_LINGER
理解协议设计,避免为性能牺牲稳定性!


💎 理解本质

TIME_WAIT 是 TCP 鲁棒性设计的典范,看似消耗资源,实则是网络可靠通信的基石。优化时需权衡:保持协议安全边界的前提下,合理利用内核提供的能力,而非暴力破坏协议逻辑

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

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

相关文章

《GuardHFL: Privacy Guardian for Heterogeneous Federated Learning》——论文阅读

研究背景&#xff1a;异构联邦中各客户端模型结构&#xff0c;精度&#xff0c;算力都不同&#xff0c;无法像传统联邦那样共享梯度&#xff0c;只能通过“查询-响应”使用辅助数据来训练模型。这种方法存在严重隐私问题&#xff1a;直接共享查询样本会泄露敏感信息&#xff0c…

Spring AI 进阶之路01:三步将 AI 整合进 Spring Boot

引子 当 LLM 的浪潮以不可阻挡之势席卷全球&#xff0c;从改变用户交互到重塑商业模式&#xff0c;我们每一位开发者都身处这场技术变革的中心。作为庞大的 Java 生态中的一员&#xff0c;你是否也曾思考&#xff1a;当 Python 似乎成为 AI 的“官方语言”时&#xff0c;我们这…

pycharm2025导入anaconda创建的各个AI环境

目录1.pycharm下载及安装2.导入anaconda的环境到pycharm项目中1.pycharm下载及安装 建议从官网下载&#xff0c;不要乱下载。 https://www.jetbrains.com.cn/en-us/pycharm/ 右上角可以切换中英文&#xff0c;在此切换为中文。 点击下载&#xff0c;如下页面: 点击中间下载w…

获取IPv6地址的三种方式

DHCPv6无状态自动分配IP地址Server 配置&#xff1a;<Huawei>system-view[Huawei]ipv6[Huawei]dhcp enable[Huawei]dhcpv6 pool pool1[Huawei-dhcpv6-pool-pool1]dns-server 2002::2[Huawei-dhcpv6-pool-pool1]dns-domain-name example.com[Huawei-dhcpv6-pool-pool1]qui…

[Oracle数据库] Oracle 复杂查询

对于刚接触 Oracle 数据库的初学者来说&#xff0c;简单查询&#xff08;如SELECT * FROM 表名&#xff09;可能不难掌握&#xff0c;但面对复杂业务场景时&#xff0c;就需要更强大的查询能力。本文将围绕 Oracle 复杂查询的核心知识点展开&#xff0c;包括条件逻辑、分组函数…

Redis-plus-plus API使用指南:通用操作与数据类型接口介绍

&#x1f351;个人主页&#xff1a;Jupiter.&#x1f680; 所属专栏&#xff1a;Redis 欢迎大家点赞收藏评论&#x1f60a;目录通用 API连接 Redis1. get/set2. exists 方法3. del 方法4. keys 方法5. expire 方法6. ttl 方法7. type 方法8. flushall 方法String 类型 API1. ge…

基于遗传编程的自动程序生成

这里写目录标题核心概念与工作原理1. 个体表示&#xff1a;树结构2. 初始化种群3. 适应度评估4. 选择5. 遗传操作&#xff08;繁殖&#xff09;6. 新一代种群形成7. 终止条件基于遗传编程的符号回归示例问题示例GP实现符号回归&#xff08;Deap&#xff09;GP实现符号回归&…

flowable汇总查询方式

背景&#xff1a;小程序开发申请流程。使用flowable流程框架。用户需要在后台统揽用户申请的汇总表。 设计思路&#xff1a;通过查询流程实例分页查询获取数据&#xff0c; 其中可以通过查询条件进行查询&#xff0c;查询条件是流程申请时添加到流程变量当中的&#xff0c;方便…

力扣438:找到字符串中所有的字母异位词

力扣438:找到字符串中所有的字母异位词题目思路代码题目 给定两个字符串 s 和 p&#xff0c;找到 s 中所有 p 的 异位词 的子串&#xff0c;返回这些子串的起始索引。不考虑答案输出的顺序。 思路 我们先不看异位词这个条件&#xff0c;如何在字符串s中找到字符串p。我们可以…

ruoyi-vue(十一)——代码生成

大部分项目里其实有很多代码都是重复的&#xff0c;几乎每个基础模块的代码都有增删改查的功能&#xff0c;而这些功能都是大同小异&#xff0c; 如果这些功能都要自己去写&#xff0c;将会大大浪费我们的精力降低效率。所以这种重复性的代码可以使用代码生成。一 代码生成使用…

neo4j导入导出方法

在 Neo4j 中&#xff0c;如果需要将数据从 一个环境导出&#xff0c;再 导入到另一个环境&#xff08;如从开发环境迁移到生产环境&#xff09;&#xff0c;可以通过以下方法实现&#xff1a;方法 1&#xff1a;使用 neo4j-admin 导出和导入&#xff08;完整数据库迁移&#xf…

Diamond基础2:开发流程之LedDemo

文章目录1.关联VS Code2.Diamond工程目录3.Led Demo开发流程4.烧写bit文件5.传送门1.关联VS Code 和Vivado一样&#xff0c;Diamond也可以使用第三方的编辑器&#xff0c;VS Code编辑器因为可以安装各种插件&#xff0c;并且对verilog开发的支持也算完善&#xff0c;所以很受欢…

Golang 后台技术面试套题 1

文章目录1.网络1.1 浏览器从输入网址到展示页面&#xff0c;描述下整个过程&#xff1f;1.2 HTTP 502&#xff0c;503 和 504 是什么含义&#xff1f;区别以及如何排查&#xff1f;1.3 HTTPS 通信过程为什么要约定加密密钥 code&#xff0c;用非对称加密不行吗&#xff1f;1.4 …

【科研绘图系列】R语言绘制蝶形条形图蝶形柱状堆积图

文章目录 介绍 加载R包 数据下载 导入数据 数据预处理 画图 系统信息 参考 介绍 【科研绘图系列】R语言绘制蝶形条形图&蝶形柱状堆积图 加载R包 library(tidyverse) library(ggsignif) library(RColorBrewer) library(dplyr) library(reshape2) library(grid

Jeecg后端经验汇总

Jeecg是一个不错的低代码平台&#xff0c;极大的降低了很多开发人员接私活的难度&#xff0c;也极大的降低了开发全套功能的难度。但是一码归一码&#xff0c;开发人员的水平很一般&#xff0c;如下&#xff1a;&#xff08;1&#xff09;普通用户可以修改管理员密码&#xff0…

ethernet_input到应用层处理简单分析

1、驱动层&#xff1a;从硬件读取数据并构造pbuf中断触发后&#xff0c;驱动层的接收任务&#xff08;或轮询函数&#xff09;会从网卡硬件读取数据&#xff0c;并将其封装为 LWIP 可识别的pbuf结构体&#xff08;LWIP 的数据缓冲区&#xff09;。关键函数&#xff1a;驱动自定…

C#WPF实战出真汁05--左侧导航

1、左侧导航设计要点清晰的信息架构 确保导航结构层次分明&#xff0c;主分类与子分类逻辑清晰&#xff0c;避免过度嵌套。使用分组、缩进或分隔线区分不同层级&#xff0c;保持视觉可读性。直观的图标与标签 为每个导航项搭配简洁的图标&#xff0c;强化视觉识别。标签文字需简…

大模拟 Major

题目来源&#xff1a;2025 Wuhan University of Technology Programming Contest 比赛链接&#xff1a;Dashboard - 2025 Wuhan University of Technology Programming Contest - Codeforces 题目大意&#xff1a; 模拟 16 支队伍的瑞士轮比赛结果&#xff0c;规则太多&…

【手撕JAVA多线程】1.从设计初衷去看JAVA的线程操作

目录 前言 概述 主动阻塞/唤醒 代码示例 实现 为什么必须在同步块中使用 计时等待是如何实现的 被动阻塞/唤醒 为什么要有被动阻塞/唤醒 实现&#xff08;锁升级&#xff09; 前言 JAVA多线程相关的内容很多很杂&#xff0c;但工作中用到的频率不高&#xff0c;用到…

UE5多人MOBA+GAS 46、制作龙卷风技能

文章目录创建龙卷风GA创建蒙太奇创捷一系列GE添加数据表添加到角色中创建龙卷风GA GA_Tornado 添加标签 // 龙卷风冷却CRUNCH_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(Ability_Tornado_Cooldown)// 通用技能伤害CRUNCH_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(Ability_Generic_Dama…