nginx采用异步事件驱动架构,通过epoll/kqueue内核事件机制按需响应连接生命周期,预分配静态连接池并复用结构体,upstream连接按lru队列复用,状态变化即时触发动作,内存与事件严格绑定,真正节省资源在于不创建和快释放。

Nginx 的异步事件驱动架构不是靠轮询或后台线程管连接池,而是把连接生命周期完全交给 epoll(Linux)或 kqueue(BSD)事件循环来调度。它不“主动管理”,而是“按需响应”:连接的获取、复用、释放、超时,全都由内核通知触发回调函数,全程非阻塞。
连接池结构本身是静态预分配的
每个 worker 进程启动时,就一次性分配好 worker_connections 个 ngx_connection_t 结构体,组成固定大小的数组。这些结构体不等于活跃 TCP 连接,只是元数据容器池。它们通过 free_connections 链表统一管理:
- 新连接到来(accept),从链表头取一个结构体,绑定 socket、注册读事件;
- 连接关闭后,不释放内存,只重置字段(如 fd 设为 -1、清空 read/write 指针),再插回链表头部;
- 整个数组生命周期与 worker 进程一致,无 malloc/free 开销。
Upstream 连接复用由事件精准驱动
后端连接池(即 keepalive 缓存)不是常驻集合,而是按 upstream server 粒度维护的 LRU 队列:
- 复用发生在
ngx_http_upstream_connect()中:先尝试从对应 server 的空闲队列取连接,成功则直接注册读/写事件,跳过 connect() 和 TLS 握手; - 归还发生在响应收完且满足 keepalive 条件时:调用
ngx_http_upstream_keepalive_free(),关闭读写监听,仅保留 socket 句柄,插入队首; - 超时清理由事件定时器触发(
ngx_event_add_timer()),到期执行close(),不依赖扫描。
连接状态变化即触发动作,不等超时
连接是否该淘汰,不由时间倒计时决定,而由实际事件判断:
- 读超时(read timeout)、写失败(write error)、收到 RST 或 FIN,都会立即触发 cleanup 回调,从池中移除并 close;
-
proxy_next_upstream error timeout http_502这类配置,也是在对应事件发生时立刻切换连接,而非等待。
内存与事件严格绑定,避免悬空引用
- 每个连接有自己的
c->pool,随ngx_connection_t创建而生、关闭而毁,适合放 SSL 上下文、长连接缓冲区; - 每个请求有独立
r->pool,请求结束即整池释放; - 所有 upstream 复用相关的临时结构、回调上下文、buffer,都必须分配在对应内存池里;若把
r->pool里分配的指针存到c->data,下次复用该连接时,指针已失效。
真正节省资源的是“不创建”和“快释放”
- 不为每个请求 fork 进程或开线程,单 worker 用一个事件循环管数千连接;
- 空闲连接不占 CPU,只占少量 socket 和结构体内存;
-
keepalive_timeout设太长反而积压无效连接,建议设为 20–45 秒,且必须小于后端自身的空闲超时值。











