tcp 连接 time-wait 状态过多问题解释
前言
两条竖线分别是表示:
- 主动关闭(active close)的一方
- 被动关闭(passive close)的一方
网络上类似的图有很多,但是有的细节不够,有的存在误导。有的会把两条线分别标记成 client 和 server。给读者造成困惑。对于断开连接这件事,客户端和服务端都能作为主动方发起,也就是 active close 可以是客户端,也可以是服务端。而对端相应的就是 passive close。不管谁发起,状态迁移如上图。
问题描述
模拟高并发的场景,会出现批量的 time-wait 的 tcp 连接:
短时间后,所有的 time-wait 全都消失,被回收,端口包括服务,均正常。即,在高并发的场景下,time-wait 连接存在,属于正常现象。
线上场景中,持续的高并发场景:
- 一部分 time-wait 连接被回收,但新的 time-wait 连接产生;
- 一些极端情况下,会出现大量的 time-wait 连接;
所以,上述大量的 time-wait 状态 tcp 连接,有什么业务上的影响吗?
Nginx 作为反向代理时,大量的短链接,可能导致 Nginx 上的 tcp 连接处于 time_wait 状态:
- 每一个 time_wait 状态,都会占用一个本地端口,上限为 65535(16 bit,2 Byte);
- 当大量的连接处于 time_wait 时,新建立 tcp 连接会出错,address already in use : connect 异常;
统计 tcp 连接的状态:
// 统计:各种连接的数量
$ netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'
ESTABLISHED 1154
TIME_WAIT 1645
tips: tcp 本地端口数量,上限为 65535 ,这是因为 tcp 头部使用 16 bit 存储端口号,因此约束上限为 65535。
问题分析
大量的 time-wait 状态 tcp 连接存在,其本质原因是什么?
- 大量的短连接存在;
- 特别是 HTTP 请求中,如果 connection 头部取值被设置为 close 时,基本都由服务端发起主动关闭连接;
- tcp 四次挥手关闭连接机制中,为了保证 ACK 重发和丢弃延迟数据,设置 time_wait 为 2 倍的 MSL(报文最大存活时间);
time-wait 状态:
- tcp 连接中,主动关闭连接的一方出现的状态;(收到 FIN 命令,进入 time-wait 状态,并返回 ACK 命令)
- 保持 2 个 MSL 时间,即 4 分钟;(MSL 为 2 分钟)
解决办法
解决上述 time_wait 状态大量存在,导致新连接创建失败的问题,一般解决办法:
- 客户端,HTTP 请求的头部,connection 设置为 keep-alive,保持存活一段时间,现在的浏览器,一般都这么进行了;
- 服务器端,允许 time_wait 状态的 socket 被重用;
- 服务器端,缩减 time_wait 时间,设置为 1 MSL;(即 2 分钟)
顺便提一嘴服务端出现大量 close_wait 的原因。多是由于服务端处理请求耗时过长,导致客户端超时,发起关闭链接,导致服务端大量的 close_wait。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
2020-12-10 SQL 中 left join 的底层原理
2017-12-10 多线程编程学习五(线程池的创建)