net.ipv4.tcp_tw_reuse仅对客户端新出站连接有效,需tcp_timestamps=1配合,服务端无效;ss -i的retrans非累计值;somaxconn与应用backlog取最小值;UDP丢包因无socket或缺SO_REUSEPORT。

为什么 net.ipv4.tcp_tw_reuse 开启后连接仍超时?
因为该参数只对客户端有效,且仅在 TIME_WAIT 状态套接字可被复用于**新 outbound 连接**(即本机主动发起的连接),不适用于服务端接收连接或被动关闭场景。常见误用是把它当成“解决端口耗尽万能开关”,但实际需配合 net.ipv4.tcp_fin_timeout 和连接池策略。
- 必须确保
net.ipv4.tcp_timestamps = 1已启用,否则tcp_tw_reuse不生效 - 若应用使用短连接且并发高(如 HTTP client 频繁调用 API),建议同时调小
net.ipv4.tcp_fin_timeout至 30 秒以内 - 服务端(如 Nginx、Redis)无法靠此参数缓解 TIME_WAIT 压力,应改用连接复用(keepalive)或反向代理层做连接收敛
如何让 ss -i 显示真实重传与拥塞窗口信息?
ss -i 默认输出中 retrans 字段为 0 并不表示无重传——它只显示当前连接最近一次重传事件的计数,且需内核开启 TCP info 支持。要获取稳定可观测数据,得结合 /proc/net/snmp 和 tcpretrans 工具。
- 检查是否启用详细 TCP 统计:
cat /proc/net/snmp | grep -A1 Tcp | tail -1,看RetransSegs是否持续增长 -
ss -i dst只能观察单条连接瞬时状态;批量诊断请用8.8.8.8tcpretrans -C(来自perf-tools包) - 若
cwnd长期卡在 10 MSS 以下,大概率是链路丢包或接收方通告窗口过小,而非本机配置问题
net.core.somaxconn 和应用 listen() 的 backlog 参数谁起作用?
两者共同限制全连接队列长度,最终生效值取二者最小值。很多服务(如 Nginx、Node.js)默认 backlog 设为 511,若系统 net.core.somaxconn 仍为旧版默认值 128,就会 silently 截断连接请求,表现为偶发性 “Connection refused” 或 SYN_RECV 滞留。
- 先确认当前值:
sysctl net.core.somaxconn,生产环境建议设为 65535 - Nginx 需显式配置
listen 80 backlog=65535;;Node.js 的server.listen(port, cb)第二个参数可传 backlog 数值 - 修改后必须重启对应服务进程,仅 reload 不生效(因 listen() 在进程启动时调用)
UDP 应用丢包但 netstat -su 显示 no socket 错误?
这说明数据包到达了 IP 层,但找不到匹配的 UDP socket——常见于端口未监听、进程已崩溃、或 bind() 时未设 SO_REUSEPORT 导致多 worker 场景下部分包被内核丢弃。
- 用
ss -uln | grep :确认端口确实在监听,注意端口号ss输出中的State列应为UNCONN - 若使用多进程/线程模型(如 Gunicorn + UDP handler),必须在每个进程 bind 前设置
SO_REUSEPORT,否则仅第一个进程能收包 -
netstat -su中的no socket计数不会自动清零,需对比前后差值判断是否持续发生
#!/bin/bash
# 快速检查关键网络参数是否就绪
for p in net.core.somaxconn net.ipv4.tcp_tw_reuse net.ipv4.tcp_timestamps; do
v=$(sysctl -n $p 2>/dev/null)
echo "$p = $v"
done
echo "TCP retransmit segments: $(awk '/Tcp:/ {print $13}' /proc/net/snmp 2>/dev/null)"
真正影响稳定的不是单个 sysctl 调优,而是连接生命周期各环节的协同:TIME_WAIT 处理方式是否匹配你的客户端/服务端角色,全连接队列是否被低估,UDP 多实例是否正确启用 SO_REUSEPORT。这些点一旦错位,再精细的拥塞控制参数也压不住丢包。










