Nginx连接池按upstream server粒度隔离,嵌入Event Loop事件驱动,复用需满足keepalive条件并受keepalive N和后端协议支持双重约束。

Nginx 的连接池管理不是独立运行的后台服务,而是深度嵌入 Event Loop 的事件驱动流程中,按需复用、按期清理,核心目标是省掉重复 connect 和 TLS 握手开销,同时严防连接泄漏。
连接池按 upstream server 粒度划分
每个 upstream 块里的 server(即后端地址+端口+协议)都有专属连接池,存放在 ngx_http_upstream_server_t 的 connections 链表中。这意味着:
- 10.0.1.10:8080 和 10.0.1.11:8080 是两个完全隔离的池,互不共享连接;
- 即使同一 IP 不同端口(如 :8080 和 :8443),也会分属不同池;
- 池中连接只服务于当前请求上下文,且必须满足 keepalive 条件才能复用。
复用与释放全程由事件循环触发
连接的取用和归还不靠定时扫描或线程轮询,全部通过 epoll/kqueue 就绪事件驱动:
- 发起 upstream 请求时,先调
ngx_http_upstream_get_connection()尝试从池中取空闲连接;成功则跳过 connect,直接注册读写事件; - 响应接收完毕后,若判定可 keepalive(如后端返回
Connection: keep-alive且响应体已读完),就调ngx_http_upstream_keepalive_free()把 socket 解绑并放回对应 server 的池中,同时重置事件状态; - 放回池中的连接会绑定一个定时器,超时(默认 60s,由
keepalive_timeout控制)后由 Event Loop 触发ngx_http_upstream_keepalive_dummy_handler()执行真正 close() 并释放内存。
关键配置决定池是否真正生效
很多连接池“形同虚设”,问题往往出在配置缺失或不匹配:
-
keepalive N;必须显式写在 upstream 块内,N 是每个 worker 进程为该 server 维持的最大空闲连接数(不是全局总数); - 后端必须支持 keepalive:HTTP/1.1 默认协商,但 HTTP/1.0 后端需手动加
add_header Connection keep-alive;; - 若 upstream 模块未启用 keepalive(如 proxy_pass 后没配
proxy_http_version 1.1;和proxy_set_header Connection '';),Nginx 会认为连接不可复用,每次都会新建。
连接池行为受双重生命周期约束
一个连接要被复用,必须同时满足两个条件:
- 它属于目标 server 的连接池;
- 它当前未被其他请求占用,且所属请求尚未关闭读写通道(即请求上下文仍有效)。
换句话说:池里有连接 ≠ 能立刻用。Event Loop 只负责调度“就绪动作”,而“是否可用”由请求状态和 upstream 协议逻辑共同判断。


















