这篇文章,主要是想搞明白,
在 Nginx 中,「模块 Module」和「指令 Command」是什么关系。
这是个很容易混淆的概念。
很多人以为 http、server、location 是模块,其实不是的。
在 Nginx 中,
模块,是功能单元,从源码层面来看,通常一个 .c 源代码文件对应一个功能模块。
指令,是配置文件中的关键字,由模块注册提供。
下次再看到 Nginx 的配置文件时,记住:

哪些才是模块
Nginx 的模块都是 C 语言写的,在 src/ 目录下。
其实有很多的模块。

这些模块,可以分类。
在 ngx_module_s 结构体里面,有一个 type 字段,也就是模块类型。
我使用命令分析了一下,一共可分成 6 大类。
不管具体的模块名字有多花,最终都必须归属到这 6 个 type 之一。

从源码目录也能看到这种分类,只有 NGX_CONF_MODULE 没有独立目录。

为什么呢?因为它不是功能模块,而是配置系统,只在启动时工作: Nginx 启动、解析配置、初始化完成、CONF 模块任务就完成了,所以没必要单独建目录。
另外,misc/ 和 os/ 不是模块目录,是为了适配不同操作系统,跨平台兼容的工具代码。
回到模块体系,Nginx 的设计很严格,所有功能模块都必须归属于这 6 大类型之一。
但是 HTTP、Stream 就已经挺复杂的,它是怎么靠 6 个类型就搞得这么多功能点的呢?
其实主要不是靠增加新类型扩展,而是在单一类型的内部,通过 hook 和请求处理阶段机制,把复杂功能拆分成多个小模块,共同协作完成。

我通过查看编译后生成的 objs/ngx_modules.c 文件,整理出了完整的模块列表。
下面是我的配置命令:

我没有带 --with-http_v3_module,因为它需要支持 QUIC 的 OpenSSL,但系统默认的 OpenSSL 不支持 QUIC,搞起来比较麻烦。
./configure 执行后会自动生成 objs/ngx_modules.c,这个文件定义了 ngx_module_names[] 数组,里面是所有将被编译进 nginx 的模块列表。
我觉得还是全部列出来,完整的感受一下比较好,下图中一共有 110 个模块。

源码里有这么多模块,但不是所有模块都会被编译进去。
编译时需要通过 --with-xxx 显式启用某些模块,否则最终的 nginx 不支持这些功能。
比如,stream 模块默认就是不启用的,需要在编译时显式指定 --with-stream 才会被编译进 nginx。
如果编译时不带 --with-stream,最终的 nginx 就不支持 stream 功能(TCP/UDP 代理)。
总结来看:Nginx 有 6 大模块类型,各司其职。
HTTP、Stream、Mail 负责协议处理,Event 负责并发,Core 提供基础功能,Conf 在启动时解析配置并关联各模块。
一个模块可以注册多个指令
在 Nginx 中,指令用 ngx_command_t 结构体表示。
下面是 ngx_http_core_module 模块注册指令的代码。
一个模块可以注册多个指令,每个指令都有自己的名称和处理函数。
这个处理函数,会在配置解析阶段被调用。
这里注册的 listen 指令,对应的处理函数是 ngx_http_core_listen。

指令的处理函数什么时候被调用?
简单来说,Nginx 启动或 reload 配置时,解析到这个指令就会调用。
具体的流程是:
- Nginx 启动或执行 nginx -s reload;
- 读取 nginx.conf,逐行解析;
- 遇到 listen 80; 这样的指令;
- 查找 listen 对应的 ngx_command_t 结构;
- 调用它的 set 回调函数,也就是 ngx_http_core_listen;
- 解析参数(80、ssl、backlog 等),保存到配置结构体;
比如我们的线上环境,是这样配置的,


这些参数(ssl、http2、reuseport、backlog 等)都是在 ngx_http_core_listen 函数中解析的。
一个指令可以有多个参数,处理函数会逐一解析并保存到配置结构体中。
注意区分:配置解析 vs 请求处理
两者完全不同阶段,容易混淆。
但搞明白了,就能看清 Nginx 的运行机制,
配置解析只在启动时做一次,而请求处理是持续进行的。
1、指令的处理函数
在启动或reload时调用,用于解析配置。
比如:ngx_http_core_listen 解析 listen 指令的参数。
2、请求处理函数
在运行时调用,用于处理每个 HTTP 请求。
比如:proxy_pass 指令在启动时调用 ngx_http_proxy_pass 解析配置,在请求到来时调用 ngx_http_proxy_handler 转发请求。
总结
Nginx 中「模块」和「指令」的关系:
模块:
- 功能单元,通常对应一个 .c 源文件;
- 分为 6 大类型:CORE、CONF、EVENT、HTTP、MAIL、STREAM;
- 源码中有上百个模块,但有些是编译时需通过 --with-xxx 选项启用的;
指令:
- 配置文件中的关键字(如 listen、proxy_pass);
- 由模块注册提供,一个模块可注册多个指令;
- 每个指令有专属的处理函数,用于解析配置参数;
- 指令的处理函数在启动/reload 时调用,和请求处理函数完全不同;
下次你看配置文件时,记住:http/server/location不是模块。
当你想知道有哪些模块时,去看看 objs/ngx_modules.c...
理解这些基础,才能更好看懂 Nginx 的架构设计。