定位 time_wait 集群分布来源需先区分 nginx 与客户端或上游服务之间产生:查客户端侧用 ss 命令统计高频建连断开的 ip;查上游侧用 ss 过滤 upstream 端口;再结合自定义日志分析 upstream_addr 切换频次与响应时间。

直接看 TIME_WAIT 分布,比单纯调大参数更有效。重点不是压低总数,而是识别哪类连接在持续“短连+主动关闭”,再针对性干预。
定位 TIME_WAIT 集群分布来源
先区分是 Nginx 与客户端之间,还是 Nginx 与上游服务之间产生的 TIME_WAIT:
- 查客户端侧:用
ss -ant | awk '$1 ~ /ESTABLISHED|TIME_WAIT/ && $5 ~ /:80|:443/ {print $5}' | sort | uniq -c | sort -nr | head -10,看哪些客户端 IP 或网段高频建连后快速断开 - 查上游侧:在 Nginx 机器上执行
ss -ant | awk '$1 ~ /TIME_WAIT/ && $4 ~ /:8080|:9000/'(替换成你 upstream 端口),确认是否集中在某几台后端 - 结合日志:开启
log_format full '$remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" "$upstream_addr" $upstream_response_time';,观察$upstream_addr字段是否频繁切换、响应时间是否普遍偏短(
按分布特征调整 Nginx 连接行为
发现上游侧 TIME_WAIT 高?说明反向代理层没复用连接。需在 upstream 块中显式启用长连接:
- 配置
keepalive 256;(数值建议为后端实例数 × 32~64) - 对应 server 块内必须加
proxy_http_version 1.1;和proxy_set_header Connection '';,否则 HTTP/1.0 会强制断连 - 避免在 location 中误写
proxy_set_header Connection "close";—— 这会覆盖 keepalive 效果
若客户端侧 TIME_WAIT 高,且多为移动 App 或小程序访问,大概率是客户端未发 Connection: keep-alive 或主动断连。此时应:
- 在
http块设keepalive_timeout 15s;(不宜过长,防空闲连接堆积) - 搭配
keepalive_requests 200;,让单连接承载更多请求后再释放 - 对静态资源 location,可单独设
keepalive_timeout 300s;,因图片/CSS/JS 天然适合长连
协同系统内核做精准回收
仅靠 Nginx 配置无法解决所有场景,尤其当集群中存在大量 NAT 设备或四层负载均衡时:
- 启用
net.ipv4.tcp_tw_reuse = 1(安全可用,支持时间戳机制的现代内核均兼容) - 禁用
net.ipv4.tcp_tw_recycle = 0(NAT 环境下必关,否则会导致部分用户请求失败) - 缩短回收窗口:
net.ipv4.tcp_fin_timeout = 25,让 FIN_WAIT2 尽快转为 TIME_WAIT,加速进入可重用阶段 - 扩大端口池:
net.ipv4.ip_local_port_range = "1024 65535",避免本地端口耗尽
验证优化是否生效
改完别急着上线,用三组命令交叉验证:
- 实时连接状态:
ss -s | grep -E "(TIME_WAIT|total)",观察 TIME_WAIT 占比是否从 >30% 降至 - 上游连接复用率:
curl -s http://127.0.0.1/nginx_status | grep 'Active connections\|Reading\|Writing\|Waiting'(需开启 stub_status),Waiting 数值显著上升说明 keepalive 生效 - 错误关联检查:
grep "connect() failed" /var/log/nginx/error.log | tail -20,确认不再出现 “No buffer space available” 或 “Cannot assign requested address” 类报错











