Nginx反向代理的后端连接按需建立且优先复用:在upstream阶段选peer后,由ngx_http_upstream_connect触发建连,先查keepalive池,失败才调用ngx_event_connect_peer异步发起TCP连接,全程事件驱动、非阻塞。

当 Nginx 作为反向代理运行时,ngx_http_proxy_module 负责将客户端请求转发到后端服务器。其后端连接的建立并非在收到请求头后立即发起,而是延迟到真正需要发送请求体或等待响应时才触发——核心在于“连接复用”与“按需建连”的设计思想。
后端连接的真正发起时机
连接不是在 ngx_http_proxy_handler 中直接建立的,而是在后续的写事件驱动阶段(如发送请求头/体)中,由 ngx_http_upstream_connect 统一调度。该函数会先尝试复用已存在的空闲连接(来自 upstream 的 keepalive 连接池),失败后才调用 ngx_event_connect_peer 发起新连接。
- 若配置了
proxy_http_version 1.1和proxy_set_header Connection '',Nginx 更倾向复用连接 - 若后端拒绝复用(如返回
Connection: close),当前连接会在读完响应后主动关闭,并从连接池中移除 - 超时控制由
proxy_connect_timeout决定,底层通过ngx_event_connect_peer设置 connect timer
upstream 与 peer 的初始化关键点
在 ngx_http_proxy_create_request 完成请求构造后,Nginx 进入 upstream 阶段:调用 ngx_http_upstream_init_request 初始化 upstream 上下文,并通过 ngx_http_upstream_get_peer 选择后端 peer(支持 round-robin、ip_hash 等算法)。此时只是逻辑选节点,尚未建连。
- peer 获取成功后,
u->peer.connection仍为 NULL,表示物理连接未建立 -
ngx_http_upstream_connect是第一个真正调用 socket 相关操作的函数,它内部调用ngx_event_connect_peer -
ngx_event_connect_peer封装了connect()系统调用,并根据返回值区分同步成功、同步失败、异步进行三种情况
异步连接的事件驱动处理
Linux 下绝大多数情况下 connect() 返回 EINPROGRESS,Nginx 将 socket 设为非阻塞,并注册写事件监听器 ngx_http_upstream_connect_peer_handler。当 socket 可写时(即 TCP 三次握手完成),该 handler 被触发,再调用 ngx_http_upstream_connect 继续后续流程(如发送请求头)。
- 连接成功后,
u->peer.connection被赋值,后续所有 I/O(send/recv)都基于此 connection - 若连接失败(如超时、被拒),
ngx_http_upstream_next触发重试逻辑:标记当前 peer 不可用、尝试下一个 peer 或返回错误 - 整个过程不阻塞 worker 进程,符合 Nginx 的事件驱动模型本质
连接复用与健康检查的协同机制
连接复用依赖于 upstream 模块的 keepalive 功能(需显式开启 keepalive 指令)。空闲连接保存在 u->conf->keepalive_pool 中,由独立的 idle timer 管理。健康检查(如 health_check)则通过定时发起探测请求更新 peer 状态,两者共用同一套 peer 状态位(failed, down)。
- 复用前会校验连接是否活跃(
ngx_http_upstream_check_broken_connection)、peer 是否 still alive - 若复用连接发送失败(如 ECONNRESET),会立即关闭该连接并标记 peer failed,避免后续请求继续使用
- 健康检查成功可将 peer 状态从
down恢复为live,使其重新进入负载均衡候选集
理解这套流程的关键,在于把握 upstream 框架对连接生命周期的抽象:从 peer 选择 → 连接获取(复用 or 新建)→ 异步建连 → 请求转发 → 响应接收 → 连接归还/关闭,每个环节都由清晰的回调和状态机驱动,而非线性阻塞执行。










