关键在于精准调优upstream keepalive连接池,配合proxy_http_version 1.1、proxy_set_header Connection ''和源站返回Connection: keep-alive三者协同,实现零握手复用,降低P95延迟40%~70%。

要真正压榨 CDN 回源时长连接的响应时间红利,关键不是“堆连接”,而是让每个回源连接既够用、又新鲜、还稳定——这靠的是 upstream keepalive 连接池的精准调优,配合协议头、超时、计数三者协同。
核心目标:把每次回源都变成“零握手”复用
HTTP/1.1 默认不复用后端连接。Nginx 默认对每个请求都新建 TCP+TLS 连接到源站,一次建连耗时常达 80–200ms(含三次握手 + TLS 1.2/1.3 协商 + 慢启动)。启用 keepalive 连接池后,只要源站响应头带 Connection: keep-alive,Nginx 就会把空闲连接缓存起来,下个请求直接复用——实测 P95 延迟可降 40%~70%。
upstream keepalive 数值怎么定?看源站承载力,不是拍脑袋
keepalive N 表示:每个 worker 进程为该 upstream server(单个 IP:port)最多缓存 N 个空闲长连接。设太高,源站被打满;设太低,池子总在“建—用—关”中打转。
- 先查源站单实例最大并发连接能力(如 Tomcat maxConnections=200,Node.js server.maxConnections=1000)
- 再按 60%~80% 折算:若源站能稳扛 200 并发,就设 keepalive 120~160
- CDN 回源常见起步值:32(小流量)、128(中高并发)、256(大流量但源站强壮);超过 512 需同步检查源站 TIME_WAIT 和端口资源
必须配齐的三个配套动作,缺一不可
只写 keepalive 128 不生效。以下三项必须同时出现在 location 或 upstream 块中:
- proxy_http_version 1.1:HTTP/1.0 不支持 keepalive,强制升级协议
- proxy_set_header Connection '':清掉客户端可能传来的 Connection: close,防止 Nginx 误判丢弃复用机会
- 源站响应头必须含 Connection: keep-alive:Nginx 只信任明确声明的 keepalive。若源站是 Spring Boot,默认开启;若是 Nginx 自己做源站,需确认 keepalive_timeout 已设且大于 0
防“假复用”:用 keepalive_requests + keepalive_timeout 双控连接寿命
光有连接池还不够。若单个连接被异常客户端霸占、或源站连接老化,复用反而引入延迟抖动和失败率上升。
- 在 upstream 块中加 keepalive_requests 1000:避免单连接无限处理请求(默认 100 太保守,高频回源建议 1000–5000)
- 加 keepalive_timeout 30s:控制空闲连接在池中最多留 30 秒(必须小于源站自身的 keepalive timeout,如源站设 45s,Nginx 才设 30s)
- 二者形成“次数+时间”双退出机制:任一触发即释放连接,保证池中连接始终处于活跃、健康状态
上线后这样验证是否真生效
别只信配置,要看真实连接行为:
- 用 ss -tnp | grep :源站端口 | wc -l 查当前 ESTABLISHED 连接数,压测时应稳定在 worker 数 × keepalive 值 的 70%~90%,而非持续飙升
- 用 curl -v http://cdn域名/xxx 2>&1 | grep "Connection:" 确认响应头含 Connection: keep-alive
- 监控 Nginx 指标 nginx_upstream_keepalive_active(Prometheus)或 Active conn(stub_status),观察复用连接占比是否 >85%


















