Nginx 模块和指令的区别:http/server/location 不是模块,是指令

这篇文章,主要是想搞明白,

在 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 配置时,解析到这个指令就会调用。

具体的流程是:

  1. Nginx 启动或执行 nginx -s reload;
  2. 读取 nginx.conf,逐行解析;
  3. 遇到 listen 80; 这样的指令;
  4. 查找 listen 对应的 ngx_command_t 结构;
  5. 调用它的 set 回调函数,也就是 ngx_http_core_listen;
  6. 解析参数(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 的架构设计。

相关推荐
wfj1264 小时前
服务器部署,用 nginx 部署后页面刷新 404 问题,宝塔面板修改(修改 nginx.conf 配置文件)
运维·服务器·nginx
匀泪4 小时前
云原生(nginx环境设定)
java·nginx·云原生
unirst19850075 小时前
nginx中的proxy_set_header参数详解
运维·网络·nginx
市安6 小时前
基于Centos构建Nginx镜像(Dokerfile)
linux·运维·nginx·docker·容器·centos·镜像
小小前端--可笑可笑16 小时前
Vue / React 单页应用刷新 /login 无法访问问题分析
运维·前端·javascript·vue.js·nginx·react.js
a2852816 小时前
nginx的重定向
大数据·数据库·nginx
努力学编程呀(๑•ี_เ•ี๑)1 天前
【405】Not Allowed
java·vue.js·nginx·node.js
哟哟-1 天前
Nginx配置:静态文件访问时动态添加时间戳
运维·前端·javascript·nginx
追夢秋陽1 天前
MacOS 通过Shell 脚本一步到位配置nginx+Php环境
nginx·macos·php·一站式配置