tcp_timestamps 不能随便关闭,因其支撑 paws 机制,关闭后在高带宽长肥管道(rtt>1s)下会导致合法数据包被丢弃,引发连接重置或大量重传;应保持开启(=1),除非确认所有客户端均在同局域网且 rtt 极短。

tcp_tw_recycle 被移除后,为什么 tcp_timestamps 不能随便关?
因为 tcp_timestamps 不只是为 tcp_tw_recycle 服务的——它直接影响 PAWS(Protect Against Wrapped Sequence numbers)机制。关闭它,在高带宽、长肥管道(如跨公网、RTT > 1s)场景下,会导致合法数据包被内核丢弃,表现为连接随机重置、大量 retransmission 或 connection reset by peer。
实操建议:
-
tcp_timestamps = 1应保持开启,除非你 100% 确认所有客户端都在同一个局域网、RTT - 不要为了“解决 TIME_WAIT 多”而关它——那是治标害本
- 检查是否真有 PAWS 丢包:抓包看是否有
[TCP Dup ACK]后紧跟[TCP RST],同时/proc/net/netstat中PAWSPassive和PAWSActive计数明显下降
替代 tcp_tw_recycle 的真正有效手段是调 net.netfilter.nf_conntrack_tcp_timeout_established
这个参数控制 conntrack 表里 ESTABLISHED 状态连接的超时时间,默认 432000 秒(5 天)。它和 tcp_tw_recycle 完全无关,但常被误认为“同类”,其实它是 netfilter 层的连接跟踪生命周期开关,影响的是 NAT、防火墙、Docker 等依赖 conntrack 的场景。
实操建议:
- 若你用 Docker/K8s 或做了 SNAT,且发现
nf_conntrack_count接近nf_conntrack_max,连接新建失败(Connection refused或Cannot assign requested address),才需要调它 - 合理值一般设为 300–1200 秒(5–20 分钟),具体看业务平均连接持续时间;设太低会导致短连接被提前踢出 conntrack 表,引发 “No route to host” 或重复 SYN
- 改完必须 reload conntrack:运行
conntrack -F清空旧表(注意这会中断已有连接)
TIME_WAIT 真正该管的不是回收策略,而是源头连接管理
tcp_tw_recycle 本质是用有风险的激进回收换短期资源释放,现代内核(>= 4.12)直接删了它,就是因为代价远大于收益。现在要压 TIME_WAIT,得从应用层和协议层入手。
实操建议:
- 服务端避免主动关闭连接(即让客户端发 FIN);HTTP/1.1 加
Connection: keep-alive,gRPC 默认复用连接 - 客户端用连接池(如 Go 的
http.Transport.MaxIdleConns、Python 的urllib3.PoolManager),别每次请求都新建 socket - 确需快速复用本地端口时,设
SO_LINGER为 0(慎用!只适用于明确知道对端已关闭的场景),或启用net.ipv4.tcp_fin_timeout(仅影响 FIN_WAIT_2,不直接减少 TIME_WAIT 数量)
检查当前生效值与实际瓶颈,别只盯 sysctl 参数
很多问题根本不在 TCP 栈参数,而在 conntrack 表满、socket 耗尽、或应用没正确 close fd。盲目调参反而掩盖真实瓶颈。
实操建议:
- 查 conntrack 压力:
cat /proc/sys/net/netfilter/nf_conntrack_count和cat /proc/sys/net/netfilter/nf_conntrack_max - 查 TIME_WAIT 数量:
ss -s | grep -i time_wait,再用ss -tan state time-wait sport = :<port></port>看具体端口分布 - 查 socket 资源限制:
cat /proc/<pid>/limits | grep "Max open files"</pid>,以及ulimit -n - 确认是否真有连接失败:看
/proc/net/snmp中TcpAttemptFails和TcpEstabResets是否异常升高
最常被忽略的一点:net.netfilter.nf_conntrack_tcp_timeout_established 只在启用了 conntrack(即加载了 nf_conntrack 模块)且实际用到它(比如 iptables 有 state 规则、Docker 运行中)时才起作用。裸机上没开 NAT 或防火墙规则,调它完全无效。









