ngx_http_upstream_keepalive_module 是轻量级连接缓存模块,通过 keepalive N 指令为每个 upstream server 缓存最多 N 个空闲连接,复用时从 LRU 队列获取,归还时插入队首,不主动建连、无健康检查,依赖 proxy 模块协同管理生命周期。

nginx 的 ngx_http_upstream_keepalive_module 是实现 upstream 连接复用的核心模块,它不创建新连接,而是从空闲连接池中获取、复用或归还 HTTP 后端连接,显著降低 TCP 握手与 TLS 开销。它的本质是“连接缓存”,而非传统意义的“连接池管理器”——没有主动建连、健康检查或超时驱逐逻辑,完全依赖上游模块(如 ngx_http_proxy_module)协同完成生命周期控制。
keepalive 指令如何影响连接行为
该模块通过 keepalive N 指令启用,其中 N 表示每个 upstream server 可缓存的最大空闲连接数。注意:
-
不是并发连接上限:实际并发连接可远超
N,因为活跃请求仍会新建连接;N仅限制“用完即空闲、尚未关闭”的连接数量 - 作用域为单个 server:若 upstream 块中有多个 server,每个 server 独立维护自己的 keepalive 队列
-
不兼容 keepalive_timeout:HTTP/1.1 的
keepalive_timeout属于 client 端连接管理,与此模块无关;本模块的空闲连接在归还后立即进入 LRU 队列,超时由ngx_event_expire_timers()统一触发,默认 60s(不可配置)
连接复用的关键流程:借、用、还
一次典型复用发生在 proxy_pass 阶段,流程如下:
-
借:调用
ngx_http_upstream_get_keepalive_peer(),遍历当前 server 的 keepalive 连接链表,找到第一个可用 socket(已 connect、未 error、未超时),设置pc->connection并返回成功 -
用:复用连接直接发送请求,跳过
ngx_event_connect_peer();若失败(如 RST、超时),连接被标记close = 1,后续将被丢弃 -
还:请求结束且响应体收完后,若 upstream 配置了
keepalive且连接状态正常,调用ngx_http_upstream_free_keepalive_peer()将连接插入空闲队列头部(LRU),并关闭读写事件监听
常见误用与调试要点
实际部署中易出现“连接不复用”或“连接泄漏”,原因多为配置或协议不匹配:
-
HTTP 协议版本不一致:upstream server 必须支持 HTTP/1.1 或明确返回
Connection: keep-alive;若后端返回Connection: close或使用 HTTP/1.0 且无 keep-alive header,nginx 不会归还连接 -
proxy_http_version 未设为 1.1:默认为 1.0,需显式配置
proxy_http_version 1.1;,否则请求头不带Connection: keep-alive -
proxy_set_header Connection '':清空原始 Connection 头,避免客户端传来的
close影响复用;但若后端依赖某些 Connection 指令(如 upgrade),需谨慎处理 -
调试方法:开启
error_log /path/to/log debug;,搜索"keepalive" "free" "get"关键字;也可用ss -tnp | grep :port观察 ESTABLISHED 连接数是否稳定在N × server_num附近
源码级关键结构与约束
理解其轻量设计有助于规避陷阱:
-
ngx_http_upstream_keepalive_cache_t:每个 upstream server 对应一个,含cache(空闲连接链表)、free(空闲连接数)、max_cached(即N) - 无连接预热:模块不主动建连,首个请求仍需三次握手;空闲连接仅来自已使用过的连接
-
无连接验证:归还时不发 probe 包,下次复用时才检测是否有效(通过
send()或recv()返回值判断);失效连接会在get阶段被跳过或在free阶段被 close -
线程安全依赖锁:LRU 链表操作加
ngx_shmtx_lock(&cache->mutex),但在单 worker 场景下实际未启用共享内存锁,仅做占位










