不能直接在运行中的Nginx上加载第三方模块,必须源码编译;仅极少数模块(如nginx-module-vts、njs)支持动态加载,主流模块如lua-nginx-module、echo-nginx-module均不支持。

不能直接在运行中的 Nginx 上“装上”第三方模块——所有非官方内置模块都必须重新编译 Nginx 二进制文件,动态加载仅适用于极少数支持 load_module 的模块(如 ngx_http_image_filter_module 需静态编译,ngx_http_perl_module 等极个别才支持动态)。误以为能像 Apache 一样热加模块,是线上翻车最常见原因。
哪些第三方模块支持动态加载?
真正支持 load_module 指令的第三方模块极少。目前稳定可用的只有:
-
nginx-module-vts(Nginx virtual host traffic status):提供实时流量监控面板,需编译为.so文件后在配置中声明load_module /path/to/ngx_http_vhost_traffic_status_module.so; -
nginx-module-sts(SSL/TLS status module):用于暴露 TLS 握手统计,同样依赖.so动态加载 -
njs模块(从 0.7.0+ 起支持动态加载):启用后可通过load_module /usr/lib64/nginx/modules/ngx_http_js_module.so;加载,再用js_import引入 JS 脚本
注意:nginx-push-stream-module、lua-nginx-module、echo-nginx-module 等主流扩展全部不支持动态加载,强行写 load_module 会报错 unknown directive "load_module" 或启动失败。
限流类模块怎么选:limit_req vs. lua-resty-limit-traffic
limit_req 是 Nginx 官方模块,简单够用但策略固定;真正灵活的动态限流得靠 Lua 模块。关键差异如下:
-
limit_req基于共享内存区(limit_req_zone),只能按 IP、$binary_remote_addr 或自定义变量做固定速率限制,无法实现用户级、token bucket 变长窗口、或与后端鉴权联动 -
lua-resty-limit-traffic支持 redis 后端存储计数器,可结合ngx.var.arg_token提取请求 token 做用户维度限流,还能在access_by_lua_block中提前拒绝 - 性能影响:纯
limit_req几乎无开销;Lua 方案每次请求多一次 Redis round-trip,高并发下需部署本地 Redis 或用shared_dict缓存热点 key
示例:用 Lua 实现按用户 ID 限流(需先 init_by_lua_block 初始化 limit 对象):
access_by_lua_block {
local limit = require "resty.limit.count".new("my_limit", 100, 60)
local key = ngx.var.arg_uid or ngx.var.remote_addr
local delay, err = limit:incoming(key, true)
if not delay then
if err == "rejected" then
return ngx.exit(429)
end
end
}
图片处理类模块避坑指南:image_filter 不等于 GraphicsMagick
ngx_http_image_filter_module 是 Nginx 官方模块,但功能非常基础:
- 只支持缩放(
resize)、裁剪(crop)、旋转(rotate),不支持格式转换(如 webp 输出需额外配image_filter_jpeg_quality)、水印、锐化、滤镜等 - 依赖 libgd,若系统未装
gd-devel,configure 时不会报错,但编译后image_filter指令不可用,日志里只显示unknown directive "image_filter" - 更强大方案是
nginx-http-image-filter-module(非官方增强版)或直接用openresty+lua-resty-image,后者支持调用 ImageMagick CLI 或调用 GD 库原生接口
典型错误:在 CentOS 7 上 configure 时漏掉 --with-http_image_filter_module,又没装 gd-devel,结果配置写对了,reload 却提示指令不存在——本质是模块根本没编译进去。
编译时最容易被忽略的三个检查点
重编译前不确认这三项,90% 会失败或功能异常:
- 用
/usr/local/nginx/sbin/nginx -V查出原始 configure 参数,**必须完全复用**,尤其是--prefix、--user、--with-pcre、--with-openssl等路径和依赖开关,漏一个可能导致 worker 进程崩溃 - 第三方模块源码目录名不能含空格或特殊字符(如
nginx-push-stream-module-master最好重命名为nginx-push-stream-module),否则 configure 报no such file or directory - 如果原 Nginx 是用 yum 安装的(如
nginx-1.20.1-1.el7.ngx.x86_64),它没有源码,也**不提供.so接口**,必须下载对应版本的 tar.gz 源码包,否则即使加了--add-module,make 也会在 linking 阶段找不到符号
最后提醒一句:所有模块路径必须用绝对路径传给 --add-module,相对路径在 make 时会静默失效,且错误信息毫无提示。


















