核心是盯住“连接生命周期错位”——客户端、nginx、后端对“空闲”和“该断”的判断不一致,导致连接滞留、端口占满;需通过ss统计estab/time-wait分布、验证upstream keepalive配置与响应头、比对三类proxy超时参数,并协同后端调整资源回收节奏。

核心是盯住“连接生命周期错位”——不是连接没释放,而是客户端、Nginx、后端三者对“空闲”和“该断”的判断不一致,导致连接长期滞留、端口被占满。
查当前连接状态分布
先确认是否真存在连接堆积,而不是误判:
- 在 Nginx 服务器上运行:
ss -tn state established | wc -l,看 ESTABLISHED 连接总数是否接近本地端口上限(默认约 28000) - 按后端分组统计:
ss -tn state established | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -nr,识别是否某台后端连接数远高于其他节点 - 检查 TIME_WAIT 是否异常高:
ss -tn state time-wait | wc -l;若持续 > 30000,说明短连接频繁新建,keepalive 可能未生效
验 upstream keepalive 是否真正启用
配置写了不等于生效,必须逐层验证:
- 确认
upstream块中明确写了keepalive 32(数值建议 16–64),且没有被 include 覆盖或注释掉 - 对应
location中必须有:proxy_http_version 1.1;和proxy_set_header Connection "";,缺一不可 - 用
curl -I http://your-domain/查响应头,确认返回中不含Connection: close;若出现,说明后端主动断连,Nginx 无法复用
核对三类超时参数是否匹配后端行为
超时设错是连接卡死的主因,重点比对:
-
proxy_read_timeout必须略大于后端心跳间隔(如后端每 30 秒 ping 一次,此值应设 60–90 秒);WebSocket 场景可设 86400,但前提是后端 keepAliveTimeout ≥ 86400 -
proxy_connect_timeout控制建连,建议 1–3 秒;过长会让失败连接阻塞 worker -
proxy_send_timeout设为 10–20 秒,避免大请求上传时误断;若后端接收慢,可单独调高,但不要全局拉长
协同后端服务确认资源回收节奏
Nginx 无法单方面决定连接何时释放,必须与后端对齐:
- Tomcat 需设置
connectionTimeout> Nginx 的proxy_read_timeout,否则服务先断,Nginx 还在发数据,触发 reset 或 502 - Kubernetes 环境下,检查 Pod 的
terminationGracePeriodSeconds是否 ≥ 30 秒,并配preStophook(如sleep 30),给 Nginx 留出自然释放活跃连接的时间 - 在后端日志中搜索 “close idle connection” 或类似关键词,确认其实际关闭行为是否与配置一致











