大量 TIME_WAIT 的 net.ipv4.tcp_max_tw_buckets 与 tcp_tw_reuse

2次阅读

TIME_WaiT占满tcp_max_tw_buckets会导致新建连接被内核静默丢弃,客户端收不到SYN-ACK,服务端无新连接日志;tcp_tw_reuse对此无效,因它仅适用于客户端主动发起连接的端口复用,不作用于服务端被动关闭产生的TIME_WAIT。

大量 TIME_WAIT 的 net.ipv4.tcp_max_tw_buckets 与 tcp_tw_reuse

TIME_WAIT 占满 net.ipv4.tcp_max_tw_buckets 会怎样

连接直接被内核丢弃,表现为客户端收不到 SYN-ACK、服务端日志里看不到新连接建立,ss -s 显示 tw 数接近或等于 tcp_max_tw_buckets 值。这不是“慢”,是彻底拒连。

  • linux 内核在 TIME_WAIT 状态的 socket 达到 tcp_max_tw_buckets 阈值后,会静默丢弃新建连接请求(SYN 包),不返回 RST
  • 该限制是全局硬上限,和端口范围、内存无关,只看当前存活的 TIME_WAIT 数量
  • tcp_tw_reuse 在此场景下完全无效——它只影响 *主动发起连接* 的客户端重用,不缓解 *服务端被动关闭* 导致的桶满问题

为什么 tcp_tw_reuse 对服务端高并发短连接没用

因为 tcp_tw_reuse 只允许客户端把处于 TIME_WAIT 的端口重新用于 *向外发起新连接*,而 Web 服务、API 网关这类典型服务端,大量连接是由客户端关闭(FIN+ACK)、服务端响应 FIN 后进入 TIME_WAIT —— 这个状态的 socket 属于服务端,但 tcp_tw_reuse 不作用于服务端的 TIME_WAIT socket。

  • 服务端调用 close() 或对端先关闭时,服务端进入 TIME_WAIT,此时端口被占用且不可重用,tcp_tw_reuse 不触发
  • 真正起效的场景是:本机作为客户端(比如 Python requests 调用下游 API),且设置了 SO_LINGER 或快速重试,才可能复用本地 TIME_WAIT 端口
  • 开启 tcp_tw_reuse 还可能引发 TIME_WAIT socket 被提前回收,导致对方重传 FIN 被丢弃,出现偶发 RST

更靠谱的解法:调小 tcp_fin_timeout + 确保对端先关闭

缩短 TIME_WAIT 持续时间比硬调大 tcp_max_tw_buckets 更安全。默认 60 秒太保守,多数网络环境 30 秒足够;关键是要让客户端(而非服务端)发 FIN,把 TIME_WAIT 推给对方。

  • echo 30 > /proc/sys/net/ipv4/tcp_fin_timeout:让 TIME_WAIT 最多存 30 秒,不是立即消失,但能加速释放
  • nginx / apache 可配 keepalive_timeoutlingering_close,鼓励长连接或让客户端主动断开
  • 反向代理层(如 Nginx)加 proxy_set_header Connection 'close',强制上游 http 连接在响应后关闭,避免服务端陷入 TIME_WAIT
  • 不要盲目调大 tcp_max_tw_buckets:值过大(如设为百万级)会导致哈希表查找变慢,反而拖累新建连接性能

检查与验证命令必须带 -o-n

查 TIME_WAIT 真实数量不能只看 netstat -an | grep TIME_WAIT | wc -l,那会漏掉未解析的地址和统计不准;ss 是唯一可靠选择,但必须加 -o(显示 timer)和 -n(禁用 DNS 解析)才能反映真实状态。

  • ss -o state time-wait sport = :80 | wc -l:精确统计 80 端口上的 TIME_WAIT 数(服务端视角)
  • ss -s | grep -i tw:输出类似 1284795 times tcp_tw_bucket alloc,这个 alloc 计数才是内核实际分配过的总数,比当前瞬时数更有参考价值
  • cat /proc/sys/net/ipv4/tcp_max_tw_bucketscat /proc/sys/net/ipv4/tcp_fin_timeout 必须同时查,单看一个没意义

调整完别只盯着数字降没降,得用 ss -i 抓几个 TIME_WAIT socket 看 timer 字段是否真在倒数——很多配置改了但没生效,是因为没运行 sysctl -p 或容器里 /proc 不可写。

text=ZqhQzanResources