TIME_WAIT 是 TCP 连接正常关闭过程中的一个关键状态,主要出现在主动关闭连接的一方。当系统中存在大量 TIME_WAIT 状态的 TCP 连接时,可能导致 TCP 连接无法建立,以下是运维工作中常见的 TIME_WAIT 高发场景及形成原因。
一、业务场景
- 微服务 API 调用:服务 A 频繁调用服务 B 的 HTTP 接口(未启用 Keep-Alive)
- 短连接:应用每次查询都新建数据库连接(如未配置连接池的 MySQL 访问)
- 爬虫程序:多线程快速抓取网页后立即断开
二、原因分析
1、 临时端口范围有限:
Linux 默认临时端口范围通常为 32768-60999(约 28,000 个)
cat /proc/sys/net/ipv4/ip_local_port_range
2、TIME_WAIT 占用端口:
每个 TIME_WAIT 连接会占用一个本地端口,若短时间内高频率创建/关闭连接,端口会被快速耗尽。
# 计数
ss -ano | grep TIME-WAIT | wc -l
# 新连接报错
netstat: bind: Address already in use
三、内核参数限制
tcp_max_tw_buckets限制:系统默认限制 TIME_WAIT 连接的最大数量(通常为 18,000-30,000),超出后直接丢弃:
cat /proc/sys/net/ipv4/tcp_max_tw_buckets
新连接可能因无法进入 TIME_WAIT 状态而异常关闭。
四、解决方案
1、客户端
- 启用端口复用:允许新连接复用
TIME_WAIT端口,通过net.ipv4.tcp_tw_reuse = 1配置 - 扩大端口范围:增加可用端口数量,net.ipv4.ip_local_port_range = 1024 65000
- 使用长连接:减少连接创建频率,应用层配置 HTTP
Keep-Alive
2、服务端
- 调整
FIN超时:减少 TIME_WAIT 持续时间(默认60s),通过net.ipv4.tcp_fin_timeout = 30来配置 - 增加文件描述符限制:避免 FD 耗尽
五、结论:几个核心要点
1、time_wait 状态的影响
- TCP 连接中,「主动发起关闭连接」的一端,会进入 time_wait 状态
- time_wait 状态,默认会持续 2 MSL(报文的最大生存时间),一般是 2x2 mins
- time_wait 状态下,TCP 连接占用的端口,无法被再次使用
- TCP 端口数量,上限是 6.5w(65535,16 bit)
- 大量 time_wait 状态存在,会导致新建 TCP 连接会出错,address already in use : connect 异常
2、现实场景
- 服务器端,一般设置:不允许「主动关闭连接」
- 但 HTTP 请求中,http 头部 connection 参数,可能设置为 close,则,服务端处理完请求会主动关闭 TCP 连接
- 现在浏览器中, HTTP 请求 connection 参数,一般都设置为 keep-alive
- Nginx 反向代理场景中,可能出现大量短链接,服务器端,可能存在
3、解决办法
- 服务器端允许 time_wait 状态的 socket 被重用
- 缩减 time_wait 时间,设置为 1 MSL(即,2 mins)
通过合理调整内核参数和应用设计,可有效解决 TIME_WAIT 过多导致的连接问题。
TIME_WAIT 本质是 TCP 可靠性的保障机制,运维人员应优先 定位高频短连接源头,再针对性优化。对于每秒万级短连接场景,建议从应用层协议入手重构而非单纯调整内核参数。