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

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_timeout和lingering_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_buckets和cat /proc/sys/net/ipv4/tcp_fin_timeout必须同时查,单看一个没意义
调整完别只盯着数字降没降,得用 ss -i 抓几个 TIME_WAIT socket 看 timer 字段是否真在倒数——很多配置改了但没生效,是因为没运行 sysctl -p 或容器里 /proc 不可写。










