核心问题是连接长期卡在established状态不释放,压垮后端连接上限;需用ss命令验证堆积、检查upstream keepalive/http/1.1/connection头缺失、确保keepalive_timeout<后端空闲超时且参数协同对齐。

核心问题不是“超时”,而是连接长期卡在 ESTABLISHED 状态不释放,最终压垮后端连接数上限(如 Tomcat 的 maxConnections 或 MySQL 的 max_connections)。关键在于 Nginx 的 upstream keepalive 连接池没真正生效,或与后端策略错配。
确认是否真存在连接堆积
先别改配置,用命令验证现象:
- 查当前到后端的真实活跃连接数:
ss -tn state established '( dport = :8080 )' | wc -l(把8080换成你的后端端口) - 对比理论最大值:如果 upstream 配了
keepalive 32、Nginx 有worker_processes 4,那最多应有32 × 4 = 128个空闲长连接;若实际查出 600+,说明连接没回收 - 抓包看连接行为:
tcpdump -i any host 192.168.1.10 and port 8080 -c 20,观察是否有大量连接持续数分钟无数据却未断开
检查 Nginx 配置是否触发“假长连”
以下任一缺失都会让 keepalive 形同虚设:
Linux系统管理专家,覆盖12大模块:用户权限、SSH、存储、网络、systemd、防火墙、日志监控、备份恢复、TLS证书、Ansible、容器、IaC。提供配置、验证、加固、监控、备份、自动化、故障排查、回滚闭环。关键词:useradd、sudo、sshd_config、chmod、SEL...
- upstream 块里没写
keepalive N指令(默认完全不启用长连接) - location 中没加
proxy_http_version 1.1(HTTP/1.0 默认关闭连接) - 没写
proxy_set_header Connection ""(若客户端请求带Connection: close,Nginx 会原样透传,导致后端主动断连) -
keepalive_timeout设得过大(如 300s),空闲连接挂太久;建议设为 15–30s,略大于业务平均响应间隔
对齐后端服务的空闲策略
Nginx 不会主动感知后端是否准备关连,必须两端超时协同:
- Tomcat 要设
connectionTimeout > proxy_read_timeout(例如后者是 20s,前者至少 30s),避免后端先断而 Nginx 还在发数据 - Spring Boot 应用检查
server.tomcat.connection-timeout和max-connections,确保不早于 Nginx 的keepalive_timeout - Kubernetes 环境下,Pod 退出前必须通过
preStop Hook+terminationGracePeriodSeconds ≥ keepalive_timeout + 几秒缓冲,否则 Nginx 还在复用,Pod 已销毁
用日志和指标交叉验证泄漏点
仅看配置不够,要抓运行时证据:
- 开启 debug 日志(需编译含
--with-debug,配置error_log /path/to/error.log debug;),重点搜keepalive、reuse、close相关行 - 在 log_format 中加入
$upstream_addr和$upstream_response_time,分析哪些后端被持续选中但响应慢 - 配合后端监控:登录每台应用服务器,执行
netstat -anp | grep :8080 | wc -l,看连接是否集中在某几台机器上










