nginx 动态模块

nginx 自从 1.9.11 以后就支持动态加载模块了, 不需要重新编译 nginx, 只需要将模块编译为 so 然后在 nginx 的配置文件中加载就行。

下载对应版本 nginx 源码

nginx 版本可用 nginx -v 查看

root@aliyun:/# nginx -v
nginx version: nginx/1.17.9

可以得知目前 docker 容器内的 nginx 版本为 1.17.9, 下载 nginx 源码以及模块源码并解压

wget https://github.com/nginx/nginx/archive/release-1.17.9.tar.gz
tar -xvf release-1.17.9.tar.gz

下载模块源码并配置模块

git clone https://github.com/yaoweibin/ngx_http_substitutions_filter_module.git

Nginx 模块源码中存在着 config 脚本文件, 静态模块和动态模块的配置文件时不同的。新格式的 config 脚本是同时兼容动态模块和静态模块的, 模块的 config脚本还是旧的格式, 则需要根据文档去转换。

有些模块是无法被配置为动态模块的。

新式配置脚本样例

ngx_addon_name=ngx_http_hello_world_module

if test -n "$ngx_module_link"; then
    ngx_module_type=HTTP
    ngx_module_name=ngx_http_hello_world_module
    ngx_module_srcs="$ngx_addon_dir/ngx_http_hello_world_module.c"

    . auto/module
else
    HTTP_MODULES="$HTTP_MODULES ngx_http_hello_world_module"
    NGX_ADDON_SRCS="$NGX_ADDON_SRCS $ngx_addon_dir/ngx_http_hello_world_module.c"
fi

旧式配置脚本样例

ngx_addon_name=ngx_http_response_module
HTTP_MODULES="$HTTP_MODULES ngx_http_response_module"
NGX_ADDON_SRCS="$NGX_ADDON_SRCS $ngx_addon_dir/ngx_http_response_module.c"

转换的方法见: https://www.nginx.com/resources/wiki/extending/converting/

本文提及的 ngx_http_substitutions_filter_module 使用的新式脚本, 因此可以直接被编译为动态模块无需配置。

编译模块

先安装编译时依赖的库(需要安装的库可能不止这些, 跟着报错找的)

sudo apt install make gcc zlib1g-dev libpcre3-dev libssl-dev

由于新版 nginx 目录结构的改版, 源码的目录结构和旧版本的不太一样:

nginx-tree.png

configure 脚本从根目录移到了 auto 目录下

cd 进 nginx 源码目录后使用 --with-compat 和 --add-dynamic-module 参数来配置编译环境

./auto/configure --with-compat --add-dynamic-module=../ngx_http_substitutions_filter_module
make modules

编译出来的模块在 objs\ngx_http_subs_filter_module.so

根据官方文档来讲, 只需要添加两个参数就可以编译动态模块了。但是, 实际环境中 nginx 的编译参数可能是很复杂的, 如果发现编译出来的模块无法正常加载, 可以考虑用 nginx -V 查看编译 nginx 时使用的参数, 将参数加入 configure 命令后再次尝试编译加载模块

加载并使用模块

我使用的 nginx docker 镜像为 nginx 官方的镜像, 模块被存放在 /usr/lib/nginx/modules 下, 将模块挂载入 container 后, 修改 nginx 配置文件 /etc/nginx/nginx.conf, 加入

load_module modules/ngx_http_subs_filter_module.so;

重载容器中的 nginx 配置即可使用新模块

修改完配置文件后可以在 maps 中看到 so 已被加载

module-load.png