首页 / 内容指南 / 当前文章

Linux TIME_WAIT持续增长与临时端口耗尽:短连接排查指南

发布于 2026-08-26 · xieyipai.com 编辑部

先用 ss 按本地/远端地址、端口和进程归因 TIME_WAIT,确认谁是主动关闭方。再核对 ip_local_port_range、实际出站四元组数量、连接创建速率和 connect() 错误。如果某客户端持续向少数目标 IP:端口创建短连接,优先启用 HTTP/TCP 连接池、修正应用主动关闭策略、扩展合理的源 IP/目标边界,而不是盲目缩短 TIME_WAIT 或开启不理解的复用参数。

本文目录(16 节)

直接答案

先用 ss 按本地/远端地址、端口和进程归因 TIME_WAIT,确认谁是主动关闭方。再核对 ip_local_port_range、实际出站四元组数量、连接创建速率和 connect() 错误。如果某客户端持续向少数目标 IP:端口创建短连接,优先启用 HTTP/TCP 连接池、修正应用主动关闭策略、扩展合理的源 IP/目标边界,而不是盲目缩短 TIME_WAIT 或开启不理解的复用参数。

一、先判断是正常现象还是资源故障

仅看 TIME_WAIT 总数没有结论。同时采集三类证据:新建连接速率,按本地和远端端口分组的状态数,以及应用层连接失败率。如果数量很高但没有失败、端口余量充足且业务稳定,它可能只是高吞吐的结果。

若同时出现 EADDRNOTAVAIL、Cannot assign requested address、出站超时或 NAT 网关报告端口不足,再将它升级为资源故障。不要把服务端监听队列溢出与客户端临时端口耗尽混为一谈。

二、理解为什么会进入 TIME_WAIT

TCP 主动关闭一方在完成关闭交换后通常进入 TIME-WAIT。这个状态保护新连接免受旧重复报文影响,也能在对端因未收到最终 ACK 而重发 FIN 时再次应答。

因此,“让服务端先关闭”只是转移状态责任,不会消除短连接的成本。需先确认协议语义:哪一方理应发起关闭,以及负载均衡器、代理与应用之间是否存在多段 TCP。

三、用四元组而不是单个端口思考

一条 TCP 连接由源 IP、源端口、目标 IP 和目标端口区分。临时端口的实际压力与目标集合有关:单一源 IP 持续访问单一目标 IP:端口,比分散到多个目标更容易碰到可复用四元组的限制。

按远端 IP:端口聚合 ss 输出,同时检查源 IP 是否被 SNAT 成少数地址。容器或 Pod 内看到的源端口余量,不等于节点、NAT 网关或云出口的实际余量。

四、核对 Linux 临时端口范围

Linux 使用 net.ipv4.ip_local_port_range 定义自动选择本地端口的范围。读取当前值,并与应用显式 bind 的端口、保留端口和容器网络策略一起审查。

扩大范围只是增加余量,不会修复每次请求重建连接的应用设计。修改前确认不与本机服务、防火墙或中间设备策略冲突,并在逐台验证后再扩大。

五、用连接速率估算风险

可以用粗略关系建立预警:某目标的新建连接速率乘以 TIME_WAIT 持续时间,可以估算稳态数量的量级。这不是精确内核公式,但能帮助判断流量倍增后是否会接近四元组余量。

从应用指标获取连接创建率和连接池命中率,从主机获取按目标聚合的 TIME_WAIT,从 NAT/负载均衡设备获取端口分配失败。只有多层指标同时指向一条路径,才能定位真正瓶颈。

六、首选修复是连接复用

对 HTTP/1.1、HTTP/2、数据库和 RPC 客户端,先检查是否正确使用长连接或连接池。连接池太小会排队,太大会对下游造成冲击;关键是让池大小、并发数、空闲超时和下游限制相匹配。

检查代理是否在前端复用连接,却对后端每个请求新建 TCP。还要检查 Connection: close、不合理的 keepalive 超时、健康检查频率和 SDK 是否每次创建新 client。

七、谨慎对待 tcp_tw_reuse

Linux 内核文档对 tcp_tw_reuse 提供了明确语义和安全性警告。它不是“删除 TIME_WAIT”的开关,也不应在没有理解路径、时间戳与对端行为时随意改动。

先用连接复用、合理的端口范围和源 IP 扩展解决容量问题。如果确需调整内核参数,应根据当前内核版本文档,在可回滚的少量节点上验证,监控重传、建连错误和业务正确性。

八、不要使用过时的危险建议

网上常见的 tcp_tw_recycle 建议已不适用于当前 Linux,而且它在 NAT 环境中会带来严重兼容性问题。不要从旧博客复制 sysctl 清单,也不要通过包过滤器或脚本“清理”内核的 TCP 状态。

强制使用 RST 关闭连接也不是通用修复,它可能丢失未发送数据并改变协议语义。修复应降低不必要的连接创建率,而不是破坏 TCP 关闭保护。

九、NAT、容器与负载均衡边界

如果多个容器、节点或客户端经过同一 SNAT 公网 IP 出站,真实瓶颈可能在 NAT 映射表和可用源端口,而非单个 Linux 主机。查看云 NAT 网关、节点 conntrack 和负载均衡器指标。

扩容时要保持路由对称和可观测性。增加多个出站 IP 可以增加四元组空间,但应同时修正短连接根因,否则流量增长后还会再次耗尽。

十、分步修复流程

  1. 记录故障时间、应用实例、目标服务和准确的 connect() 错误。
  2. 用 ss 统计 TCP 状态,按源/目标 IP:端口聚合,不仅保存总数。
  3. 读取临时端口范围和相关内核参数,记录内核版本。
  4. 检查客户端 SDK、代理和连接池的创建/复用率。
  5. 检查容器节点、SNAT、NAT 网关和负载均衡器是否有端口分配失败。
  6. 先修正连接复用,再按需调整端口范围或源 IP 容量。
  7. 通过小流量 Canary 验证新建连接率、TIME_WAIT 数量、连接错误和 P95/P99 延迟。

十一、常见错误

  • 看到 TIME_WAIT 就判定内核故障,没有核对业务错误。
  • 只统计全机总数,不按目标 IP:端口与进程归因。
  • 扩大临时端口范围后不修复连接池,只是延后再次耗尽。
  • 在 NAT 环境复制过时的 tcp_tw_recycle 建议。
  • 忽略云 NAT 或负载均衡器的端口限制,只改 Pod 内 sysctl。
  • 为降低 TIME_WAIT 强制 RST,导致未发送数据丢失。

十二、验收标准

修复后应同时满足:客户端连接池命中率提高,单位请求新建 TCP 数下降,connect() 端口相关错误消失,NAT/主机有足够余量,并且重传率、请求错误率和延迟没有恶化。

不要把“TIME_WAIT 归零”设为验收目标。健康系统仍然会有 TIME_WAIT,目标是它不再造成四元组或 NAT 资源耗尽。

FAQ

1. TIME_WAIT 越少越好吗?

不是。它是 TCP 正常的安全状态。只有当它与端口不足、NAT 耗尽或建连错误形成证据链时,才是需要修复的容量问题。

2. 服务端 TIME_WAIT 多说明什么?

常见于服务端或代理主动关闭连接。需结合协议和抓包确认关闭发起方,不能只从状态数猜测。

3. 扩大 ip_local_port_range 就够了吗?

不一定。它能增加主机可用端口余量,但无法修复短连接风暴,也不会扩大外部 NAT 网关的限额。

4. tcp_tw_reuse 可以直接打开吗?

不应盲目开启。要根据当前 Linux 内核文档、实际路径和回滚能力评估,首先修正连接复用和容量设计。

5. 如何区分主机端口耗尽和 NAT 耗尽?

对比主机 connect() 错误、本地端口余量、NAT 网关端口分配指标和其他共享同一出口 IP 的实例。只有多层证据能确定瓶颈位置。

总结

TIME_WAIT 是线索,不是罪证。可靠的排查顺序是:先确认业务错误,再按四元组和主动关闭方归因,检查主机与 NAT 的端口余量,然后用连接池和合理容量降低新建连接率。保留 TCP 关闭保护,比追求状态数归零更重要。

参考资料

  • RFC 9293: Transmission Control Protocol (TCP)

https://www.rfc-editor.org/rfc/rfc9293.html

  • RFC 1337: TIME-WAIT Assassination Hazards in TCP

https://www.rfc-editor.org/rfc/rfc1337.html

  • Linux manual page: tcp(7)

https://man7.org/linux/man-pages/man7/tcp.7.html

  • Linux kernel documentation: IP sysctl

https://www.kernel.org/doc/html/latest/networking/ip-sysctl.html