直接调整内核参数可以缓解,但首先要确认是否真的成为瓶颈,优先开启 tcp_tw_reuse 并扩大本地端口范围,避免使用已废弃的 tcp_tw_recycle。
先说结论:大多数情况下不需要过度优化,若确实影响业务,应安全开启复用并扩大端口范围,严禁开启 recycle。
- 先定位:确认 TIME_WAIT 数量是否耗尽本地端口或影响新连接建立
- 先做:调整 sysctl 参数并持久化,优先使用 tw_reuse 和 port_range
- 再验证:观察连接数变化及业务日志,确保无异常丢包
命令速用版
以下是临时生效的命令,重启后失效,用于快速测试:
sysctl -w net.ipv4.tcp_tw_reuse=1
sysctl -w net.ipv4.ip_local_port_range="1024 65535"
sysctl -w net.ipv4.tcp_max_tw_buckets=20000若确认有效,请将对应配置写入 /etc/sysctl.conf 并执行 sysctl -p 持久化。
为什么会这样
TCP 连接关闭时需要四次挥手,主动关闭方发送最后一个 ACK 后进入 TIME_WAIT 状态,持续 2MSL(最大报文段生存时间)。这是为了确保网络中残留的旧数据包失效,以及防止最后一个 ACK 丢失导致对方重传 FIN。在高并发短连接场景下,服务器作为主动关闭方会积累大量 TIME_WAIT 连接,占用本地端口资源,可能导致无法建立新连接。
分步处理
1. 确认当前状态
使用 ss 命令查看 TIME_WAIT 数量,比 netstat 性能更好:
ss -tan | grep TIME_WAIT | wc -l同时检查本地端口范围:
sysctl net.ipv4.ip_local_port_range2. 调整内核参数
编辑 /etc/sysctl.conf,添加或修改以下配置:
net.ipv4.tcp_tw_reuse = 1
net.ipv4.ip_local_port_range = 1024 65535
net.ipv4.tcp_max_tw_buckets = 20000执行 sysctl -p 使配置生效。
3. 注意内核版本差异
Linux 4.12 版本之后,tcp_tw_reuse 仅对出站连接(客户端发起)有效,对入站连接(服务器接收)效果有限。若您的服务器主要是接收请求,该参数可能无法显著减少 TIME_WAIT,此时扩大端口范围更为关键。
怎么验证是否生效
调整后再次运行统计命令,观察 TIME_WAIT 数量是否稳定在预期范围内:
ss -tan | grep TIME_WAIT | wc -l监控业务日志,确认没有因端口耗尽导致的连接错误(如 Cannot assign requested address)。使用 dmesg | grep -i tcp 查看是否有内核 TCP 相关警告。
常见坑
1. 严禁开启 tcp_tw_recycle
该参数在 NAT 环境下会导致连接失败,且已在 Linux 4.12 内核中移除。公开资料中明确建议不要启用此参数,即使旧版本内核存在也不建议使用。
2. tcp_max_tw_buckets 设置过小
若设置过小,超过限制的 TIME_WAIT 连接会被立即清除,可能导致客户端收到重置包。应根据服务器内存和并发量合理设置,公开资料中没有看到可靠的量化数据,建议根据实际监控调整。
3. 混淆 CLOSE_WAIT 和 TIME_WAIT
CLOSE_WAIT 过多通常意味着应用程序未正确关闭连接,调整内核参数无效,需检查代码逻辑。
参考来源
- man7.org, "tcp(7) - Linux manual page", URL: https://www.man7.org/linux/man-pages/man7/tcp.7.html
- Linux Kernel Documentation, "Networking IP Sysctl", URL: https://www.kernel.org/doc/html/latest/networking/ip-sysctl.html