tcp_tw_reuse 是什么
net.ipv4.tcp_tw_reuse 允许本机作为客户端发起新连接时,在协议层面确认安全的前提下复用一个尚处于 TIME_WAIT 状态的本地端口。TIME_WAIT 是主动关闭方必须持有的状态,Linux 上固定约 60 秒(2MSL),短连接密集时大量端口被占住。开启复用的价值在于让出站短连接不必干等端口释放,代价是依赖 TCP 时间戳做旧报文判别。它只作用于本机主动发起的连接,对服务端被动关闭留下的 TIME_WAIT 无效。
基本信息
| 参数 | net.ipv4.tcp_tw_reuse |
|---|---|
| 取值 | 0 关闭 / 1 允许复用 / 2 仅本机回环流量复用,较新内核可能作为默认值,以回读为准 |
| 依赖参数 | net.ipv4.tcp_timestamps 必须为 1 |
| 作用方向 | 仅本机主动发起的出站连接 |
| TIME_WAIT 时长 | 约 60 秒,Linux 未提供配置项 |
| 配套参数 | net.ipv4.tcp_max_tw_buckets 限制总量,net.ipv4.ip_local_port_range 决定端口池大小 |
典型使用场景
- 出站短连接密集的服务:网关、代理、爬虫、调用第三方接口的客户端易报 Cannot assign requested address
- 压测机与被压端同为短连接:本地端口周转不过来时,先确认方向再考虑是否复用
- 排查端口耗尽:用 ss -s 与状态统计区分是端口池太小还是 TIME_WAIT 堆积太多
- 跨机房调用优化:确认端口复用不是唯一手段后,与连接池、长连接复用一起评估
- 回归验证:调整后持续观察 TIME_WAIT 数量与新建连接的失败率变化
查看与调整
查看与调整
sysctl net.ipv4.tcp_tw_reuse net.ipv4.tcp_timestamps # 复用开关与时间戳依赖
ss -tan state time-wait | wc -l # 当前 TIME_WAIT 总数
ss -s | head # 各状态汇总计数
sysctl -w net.ipv4.tcp_tw_reuse=1 # 临时开启复用
sysctl net.ipv4.ip_local_port_range # 确认出站端口池大小
sysctl net.ipv4.tcp_max_tw_buckets # 确认 TIME_WAIT 总量上限判断是客户端还是服务端在堆积
判断是客户端还是服务端在堆积
ss -tan state time-wait | awk '{print $4}' | awk -F: '{print $NF}' | sort | uniq -c | sort -rn | head # 本地端口分布
ss -tan state time-wait | awk '{print $5}' | awk -F: '{print $1}' | sort | uniq -c | sort -rn | head # 对端分布
# 本地端口集中在高位区间说明是出站连接留下的 TIME_WAIT,此时复用才可能有帮助相关指标读法
| 观察点 | 含义 | 正常与异常 |
|---|---|---|
| TIME_WAIT 数量 | 本机当前处于该状态的套接字数 | 数万条本身不是故障,要看是否伴随端口耗尽 |
| Cannot assign requested address | 建连时本地端口无可用 | 出现即要处理:扩端口池、改长连接或开复用 |
| tcp_timestamps | 复用判定的前置条件 | 为 0 时复用条件不成立,开了也难见效果 |
| tcp_max_tw_buckets 溢出日志 | dmesg 出现 time wait bucket table overflow | 说明总量触顶,处理方向与端口复用不同 |
它解决不了服务端方向的 TIME_WAIT。服务端在主动关闭连接后持有 TIME_WAIT 属于协议正确行为,常见处理方向是改用长连接与连接池、让客户端先关闭、或在四层网关前置做连接复用,而不是改这个参数。
旧资料里常与它并列出现的 net.ipv4.tcp_tw_recycle 已在 Linux 4.12 起从内核移除:该选项依赖时间戳丢弃「看起来过期」的报文,在 NAT 后的客户端上会造成随机连接失败,属于应当废弃的做法,不要再照抄。
复用依赖时间戳判别旧报文,因此会顺带改变对外表现:极少数老旧中间设备对 TCP 时间戳处理异常时可能引起连接问题。若链路上有此类设备,先在小范围验证再推广,而不是一次性全量开启。
有些资料建议用应用侧 SO_LINGER 置 0 强制发 RST 关闭连接来消灭 TIME_WAIT,这会跳过正常四次挥手、已入发送队列的数据可能被直接丢弃,属于危险做法,不应作为常规优化手段推广。