关键在于upstream初始化阶段:请求头解析完毕后,变量展开、uri重写、header注入同步完成;随后由upstream框架驱动异步转发、错误重试与响应处理。

掌握 ngx_http_proxy_module 的核心阶段演进时序,关键不是背诵“哪个阶段在前、哪个在后”,而是理解它在 Nginx HTTP 请求生命周期中**在哪几个关键节点被触发、做了什么、依赖哪些前置条件**。它不独立运行,而是在 upstream 阶段深度介入,整个过程围绕“准备→改写→转发→收尾”展开。
真正起作用的不是“八个阶段”,而是 upstream 初始化时机
很多人误以为 proxy 模块在某个固定 phase(比如 content phase)执行,其实它核心动作始于 upstream 初始化阶段,由 ngx_http_upstream_init_request 触发。此时:
- 客户端请求行和头部已完整解析,
$proxy_host、$proxy_port等变量可安全展开; - 若
proxy_pass含变量(如proxy_pass http://$backend;),变量在此刻求值; - 若指向 named upstream(如
proxy_pass http://backend;),会调用对应init_upstream回调(如轮询初始化); - 若为直连 URL(如
proxy_pass http://127.0.0.1:8000/;),则动态构造匿名 upstream,并仅初始化一个 peer 节点。
URI 重写与 Header 注入发生在 upstream 阶段内部
proxy 模块不会等到响应返回才动作——它在 upstream 阶段就完成关键改写:
安全更新和维护 CLI Proxy API(CPA)部署与配置。用于 CPA 镜像升级、配置变更、认证目录兼容修复、上线验证与回滚。适用于用户提到“CPA 更新/升级/配置改了/容器重建/回滚”等场景。
-
location /api/ { proxy_pass http://srv/; }→ 匹配部分/api/被截断,转发 URI 变为/users(原始请求是/api/users); -
proxy_set_header Host $http_host;和proxy_set_header X-Real-IP $remote_addr;在 upstream 准备发送请求前注入,不是在 content handler 中执行; - 所有
proxy_*指令(如超时、buffer 控制)都在此阶段生效,影响后续连接建立与数据读写行为。
转发与错误处理由 upstream 框架统一调度
proxy 模块本身不直接调用 send/recv,而是交由 upstream 框架驱动:
- 连接建立、请求发送、响应接收全部走事件驱动异步流程;
-
proxy_next_upstream error timeout invalid_header http_500;这类容错逻辑,在 upstream 收到失败响应或超时后,由框架自动触发重试(切换 peer 或重连); - 502/504 等错误响应,本质是 upstream 框架未能从后端获得合法 HTTP 响应,proxy 模块只负责按配置透传或兜底返回。
配置生效顺序取决于模块 ctx_index,而非书写位置
ngx_http_core_module 的 ctx_index 固定为 0,是所有 HTTP 模块中最早初始化、最晚 postconfiguration 的。这意味着:
- 所有 location 树构建、指令合并、handler 链初始化均由 core module 主导;
-
proxy_pass和proxy_set_header这类指令能否被识别,取决于它们是否注册在正确 ctx_index 的模块中; - 同名指令若在多个模块中定义(如自定义模块也实现 proxy_pass),只有
ctx_index最小者生效——core module 优先级最高,proxy module 次之。










