Nginx中Upstream连接并非立即发起TCP握手,而是延迟至下一次事件循环才触发;其通过将connect封装为写事件注册到EventLoop,由epoll/kqueue就绪后调用handler完成实际连接。

在 Nginx 中,Upstream 连接的建立并不是在 ngx_http_upstream_init_request 调用时立即发起 TCP 握手,而是被挂载到 EventLoop 的事件驱动机制中,**延迟到下一次事件循环可执行时才真正触发连接尝试**。核心在于:Nginx 将连接动作封装为一个写事件(ngx_event_t),并将其添加到连接的写事件队列中,由 EventLoop 在合适的时机调用其 handler(通常是 ngx_event_connect_peer)来执行。
连接初始化发生在 upstream 模块的 init 函数中
当请求进入 upstream 阶段(如 proxy_pass),Nginx 会调用对应 upstream 模块的 init 回调(如 ngx_http_proxy_init_upstream),该函数内部会:
- 调用
ngx_http_upstream_create_round_robin_peer或其他 peer 初始化逻辑,准备后端地址和连接参数 - 调用
ngx_http_upstream_connect启动连接流程 -
ngx_http_upstream_connect会创建一个ngx_connection_t(尚未建立 socket),设置其write->handler = ngx_http_upstream_connect_handler - 最终调用
ngx_event_connect_peer—— 此时仅完成 socket 创建(socket())、地址绑定、非阻塞设置等,但 不调用connect(),除非系统调用能立即完成(如本地回环且端口空闲);否则将connect()的后续处理(EINPROGRESS 分支)注册为写事件等待 epoll/kqueue 通知
实际 connect() 调用由 EventLoop 驱动
Nginx 的 EventLoop(主循环中的 ngx_process_events_and_timers)在每次迭代中:
- 调用 I/O 多路复用接口(如
epoll_wait)等待就绪事件 - 遍历就绪事件列表,对每个就绪的写事件(
rev->write == 1)调用其handler - 若该写事件是上游连接的,则 handler 是
ngx_event_connect_peer中设置的回调(如ngx_http_upstream_connect_handler),它会再次尝试connect()或检查是否已完成(通过getsockopt(SO_ERROR))
也就是说,connect() 的真正发起或完成确认,严格依赖于 EventLoop 下一次事件分发时机。即使 upstream 初始化很快,连接也不会“立刻”建好,必须等一次 event loop 周期。
连接建立可能被延迟的常见情况
以下情形会导致 upstream 连接实际发起时间晚于 upstream 阶段开始时刻:
- 当前 EventLoop 正在处理大量已就绪事件(如大量客户端请求读事件),新注册的连接写事件需排队等待下次
epoll_wait返回 - upstream 配置了
resolver且域名未缓存,DNS 解析会先注册读/写事件,解析完成后再走连接流程,进一步延迟 - 使用
keepalive且连接池中无可用空闲连接时,新建连接流程才启动,此时才进入上述事件注册路径 - worker 进程正忙于 CPU 密集型操作(如复杂 rewrite、lua_code_cache off 下的 Lua 执行),导致事件循环响应滞后
调试与验证方法
可通过以下方式观察连接建立时机:
- 开启
error_log /path/to/log debug;,搜索"connect to"、"connected"、"http upstream connect"等日志,对比时间戳与请求进入 upstream 阶段的日志时间差 - 用
strace -p $pid -e trace=connect,sendto,recvfrom,epoll_wait观察系统调用实际发生顺序 - 在自定义 upstream 模块中,在
ngx_event_connect_peer返回前打点,结合ngx_log_debug记录事件注册时刻,再在connect_handler中记录真正 connect 调用时刻
本质上,Nginx 将所有 I/O 操作统一收束到 EventLoop 的单线程事件驱动模型中,upstream 连接也不例外——它不是同步阻塞发起,而是异步调度执行,这是高并发下资源可控和可预测的关键设计。










