要让Nginx真正复用后端TCP连接,必须同时配置proxy_http_version 1.1、proxy_set_header Connection ""和upstream块内的keepalive指令,三者缺一不可;仅设keepalive 32无效,否则仍为每个请求新建连接,导致TIME_WAIT激增、QPS受限。

要让 Nginx 真正复用到后端的 TCP 连接,光写 keepalive 32 没用——必须同时配齐 proxy_http_version 1.1、proxy_set_header Connection "" 和 upstream 块内的 keepalive,三者缺一不可。否则 Nginx 仍会为每个请求新建连接,后端 TIME_WAIT 暴涨,QPS 上不去。
upstream keepalive 必须写在 upstream 块里,不能放 location 或 server 中
很多人把 keepalive 32 直接写在 location 里,Nginx 启动就报错:unknown directive "keepalive"。它只允许出现在 upstream 块内部,且每个 upstream 组只能有一个 keepalive 指令。
-
upstream块必须定义在http块下,不能嵌套在server或location内 -
keepalive 32表示:每个 worker 进程对这组后端中的**单台服务器**最多缓存 32 个空闲连接 - 若你有 4 个 worker + 2 台后端实例,理论最大空闲连接数是 4 × 2 × 32 = 256 条
- 数值别拍脑袋定——按后端单实例最大连接数 × 70% ÷ worker 数反推,比如后端撑 2000 连接、Nginx 有 4 个 worker,建议设
keepalive 32或48
proxy_http_version 1.1 和 proxy_set_header Connection "" 必须成对出现
HTTP/1.0 默认不支持持久连接,Nginx 默认转发时用的就是 1.0。不加 proxy_http_version 1.1,后端收到请求后直接响应并断连,keepalive 形同虚设。
-
proxy_set_header Connection ""是为了清空客户端传来的Connection: close,否则 Nginx 会原样透传,后端误判为短连接而主动关闭 - 不需要加
proxy_set_header Keep-Alive,那是客户端行为,Nginx 作为代理不生成该头 - 这两行必须写在
location或server块中,且作用于所有proxy_pass请求 - 常见错误:只加了
keepalive,漏掉其中任意一项,复用率几乎为零
keepalive_timeout 和 keepalive_requests 不是可选项,而是防堆积关键
只设连接池大小不够,还得管单连接“活多久”和“干多少活”。否则连接要么“老而不死”占满 fd,要么“用完即弃”白配。
-
keepalive_timeout 30s:空闲连接在连接池中最多保留 30 秒;这个值必须小于后端服务的空闲超时(如 Tomcat 的connectionTimeout),否则 Nginx 想复用,后端已关 -
keepalive_requests 500:单个长连接最多处理 500 次请求;默认 100 在高并发 API 场景下太激进,容易触发频繁建连 - 这两个指令都写在
upstream块内,和keepalive同级,不是 http/server 级别的keepalive_timeout - 注意:http 级别的
keepalive_timeout和keepalive_requests只管「客户端 → Nginx」这段,对后端复用完全无影响
验证是否真的复用成功,别信配置,要看数据
配置写完不等于生效。真正复用成功的信号很具体,得用系统命令和日志交叉验证。
- 在 Nginx 机器上执行:
ss -tan | grep :8080 | grep ESTAB | wc -l,压测时连接数应稳定在worker_processes × keepalive附近,而不是随 QPS 持续上涨 - 在后端服务器运行:
ss -s | grep -i time_wait,复用率高时,TIME_WAIT 数量应明显下降 - Nginx 开启 debug 日志后搜
keepalive.*reuse,看到大量 reuse 而非 create connection 才算落地 - 抓包看连续请求是否复用同一源端口 → 目标端口组合;若每次都是新 SYN,说明根本没走连接池
最容易被忽略的是后端服务自身的长连接支持——即使 Nginx 配全了,Tomcat 没开 keepAlive="true"、Go 服务没设 Server.IdleTimeout,或 WAF 返回了 Connection: close,复用照样失败。检查后端响应头和日志,比反复调 Nginx 配置更有效。


















