nginx upstream keepalive未生效的根本原因是协议、头部、连接池三者未严格对齐:必须在location中配置proxy_http_version 1.1和proxy_set_header connection "",并在upstream块内正确声明keepalive n,缺一不可。

配置了 upstream keepalive 却仍是短连接,说明连接池没真正生效——keepalive 指令本身只是“物理容器”,不配齐协议和头部控制,Nginx 仍会走 HTTP/1.0 短连接流程。问题几乎都出在三处缺失:协议版本未升级、Connection 头未清理、或后端未配合。
必须补全的三项基础配置
这三项缺一不可,任意一项遗漏都会让 keepalive 形同虚设:
-
强制使用 HTTP/1.1:在
location块中加proxy_http_version 1.1;。HTTP/1.0 不支持长连接,Nginx 默认就用它发请求,不写这行,后端永远收不到 keep-alive 意图。 -
清空 Connection 请求头:加
proxy_set_header Connection "";。这是关键一步——若客户端带Connection: close,Nginx 默认透传,后端收到后立刻断连;空字符串表示由 Nginx 自主管理连接复用。 -
upstream 中正确声明 keepalive:确保
keepalive N写在upstream { ... }块内,且不在server或location中误放(否则启动报错)。
检查后端是否真正支持并维持长连接
Nginx 只负责“发出长连接请求”,最终是否复用,取决于后端响应和自身配置:
- 用
curl -I http://backend-ip:port/health查看响应头,确认含Connection: keep-alive(HTTP/1.1 默认行为,一般无需手动加)。 - 核对后端超时设置:Tomcat 的
connectionTimeout、Node.js 的server.keepAliveTimeout、Spring Boot 的server.tomcat.connection-timeout,必须大于 Nginx 的keepalive_timeout(建议至少多 10 秒)。 - 避免后端在错误响应、调试模式或 WAF 干预时返回
Connection: close——这类响应会让 Nginx 立即释放该连接,无法进入复用池。
验证是否真的复用而非假象
光看配置没用,得从连接状态和流量中确认:
- 执行
ss -tnp | grep :后端端口 | grep ESTAB | wc -l,压测时观察连接数是否稳定在keepalive设定值附近(如设 32,实际维持在 25–32),而非剧烈波动或持续增长。 - 用
tcpdump -i any port 后端端口 -w upstream.pcap抓包,过滤tcp[tcpflags] & (tcp-syn|tcp-fin) != 0,看 SYN 和 FIN 是否成对密集出现(短连接特征)还是间隔拉长、复用明显。 - 检查 Nginx error log,留意
upstream prematurely closed connection或Connection reset by peer——大概率是keepalive_requests过小或后端主动断连。
调优关键参数避免“连接假死”
即使复用开启,参数不合理也会导致连接频繁重建或堆积失效:
- keepalive_requests:默认 100 太保守,生产建议 1000–5000。值太小 → 连接刚复用几次就被关;值太大 → 若后端空闲超时早于 Nginx,连接变“僵尸”,后续请求失败。
- keepalive_timeout:设为 30–45 秒较稳妥,且必须小于后端空闲超时(如后端设 60 秒,Nginx 最多设 50 秒)。
- keepalive 数值:按后端单实例最大并发 × 0.6~0.8 ÷ worker_processes 计算。例如后端扛 200 并发、Nginx 有 4 个 worker,建议设 30–40,而非盲目填 1024。











