nginx 的稳定高效源于模块化设计:所有功能以 ngx_module_t 结构体实现,通过统一接口、运行时注册和事件驱动调度解耦;模块仅提供能力描述,由核心统一管理配置解析、phase 处理链和事件回调,彼此隔离无依赖。

nginx 的核心架构之所以稳定、高效且易于扩展,关键在于其模块化设计与高度解耦的实现方式。它不靠继承或强依赖组织代码,而是用“统一接口 + 运行时注册 + 事件驱动调度”三者协同,让各功能模块各司其职、彼此隔离。
模块即结构体:所有功能都以 ngx_module_t 实例存在
nginx 中没有“类”或“服务组件”的概念,每个模块(HTTP 处理、日志、负载均衡、SSL、stream 模块等)最终都表现为一个全局的 ngx_module_t 结构体变量。这个结构体包含:
-
上下文指针(如
ctx字段):指向模块专属的上下文结构(如ngx_http_core_module_ctx_t),用于存放配置解析函数、处理钩子、指令数组等; -
指令数组(
commands):声明本模块支持哪些配置指令(如location、proxy_pass),由 core 在读取配置时统一调用解析; -
生命周期回调(如
init_master、init_module、init_process):让模块在不同阶段介入 nginx 启动流程,但彼此不直接调用; -
类型标识(
type):区分是 CORE / HTTP / EVENT / MAIL / STREAM 模块,决定加载顺序和作用域。
这种设计意味着:添加新功能只需定义自己的 ngx_module_t,填好字段并加入全局模块数组(ngx_modules[]),编译进 nginx 即可被自动识别——无需修改核心逻辑。
配置解析与运行时分离:模块不主动注册,而是被“发现”
nginx 不在模块内部调用 register_handler() 这类注册函数。相反,它在启动早期遍历 ngx_modules[] 数组,对每个模块执行:
- 调用其
create_conf创建配置内存空间; - 逐行扫描配置文件,匹配各模块
commands中声明的指令,交由对应set回调解析; - 最后调用
merge_conf合并父子块配置(如 server 块继承 http 块)。
整个过程由 core 模块统一驱动,模块只提供“能力描述”,不控制流程。因此 HTTP 模块完全不知道 stream 模块是否存在,反之亦然——解耦靠的是协议层隔离与统一调度器,而非代码依赖。
请求处理链:通过 phase handler 数组串联,非硬编码调用
HTTP 请求不是靠 if-else 或 switch 分发到模块,而是走 11 个预定义的 phase(如 NGX_HTTP_POST_READ_PHASE、NGX_HTTP_CONTENT_PHASE)。每个 phase 维护一个 handler 链表,由各模块在 postconfiguration 回调中把自己插入对应 phase。
例如:
- rewrite 模块将
ngx_http_rewrite_handler插入NGX_HTTP_SERVER_REWRITE_PHASE; - access 模块插入
NGX_HTTP_ACCESS_PHASE; - proxy 模块在
NGX_HTTP_CONTENT_PHASE注册自己的 content handler。
请求进入后,nginx 核心按 phase 顺序遍历 handler 链表,依次调用。某个 handler 返回 NGX_OK 继续下一 phase,返回 NGX_HTTP_FORBIDDEN 等则中断流程并返回响应。模块之间无直接调用关系,仅共享 request 结构体(ngx_http_request_t)这一约定数据载体。
事件与进程模型:模块只响应,不调度
nginx 的 event loop(epoll/kqueue/iocp)由 event 模块统一管理。其他模块(如 HTTP、stream)从不直接操作 socket 或调用 epoll_ctl。它们只做两件事:
- 在连接建立时,调用
ngx_add_event()将读/写事件挂到 event loop 上,并传入自己的回调函数(如ngx_http_wait_request_handler); - 当 event loop 触发事件时,调用该回调,模块在此完成实际业务(解析请求头、转发 upstream、生成响应体等)。
这意味着:更换 I/O 多路复用机制(如从 epoll 改为 io_uring)只需重写 event 模块,其余所有模块完全不受影响——真正的运行时解耦。
nginx 的模块化不是语法层面的插件机制,而是一套贯穿内存布局、配置生命周期、请求分发和事件响应的契约体系。每个模块像一个自治的“协作者”,通过固定接口与核心交互,彼此之间没有引用、没有继承、没有隐式依赖。这种设计让 nginx 在十年间持续演进却极少出现架构级重构。











