Linux下用Lua扩展Nginx需通过ngx_lua模块嵌入LuaJIT,利用事件模型与协程实现高并发动态控制,支持鉴权、限流、WAF等;须源码编译集成LuaJIT及依赖模块,并在各处理阶段(如access_by_lua_block、content_by_lua_block)绑定指令;典型应用包括共享字典限流、轻量WAF、灰度路由与子请求聚合;调试时关闭缓存并启用debug日志,生产环境禁用print、慎用阻塞IO,共享字典仅存轻量数据。

Linux 下用 Lua 脚本扩展 Nginx,核心是通过 ngx_lua 模块把 Lua(推荐 LuaJIT)嵌入到 Nginx 工作进程中,让每个请求能在不同处理阶段执行轻量、非阻塞的 Lua 逻辑。这不是简单“调个脚本”,而是利用 Nginx 的事件模型 + Lua 协程实现高并发下的动态控制——比如鉴权、限流、WAF、灰度路由、请求改写等。
编译安装 ngx_lua 支持环境
官方 Nginx 包不含 Lua 支持,必须源码编译集成:
- 先安装 LuaJIT(比原生 Lua 性能高 5–10 倍):下载、
make && make install,并设置LUAJIT_LIB和LUAJIT_INC环境变量; - 安装依赖:
libpcre3-dev(正则)、libssl-dev(HTTPS)、build-essential; - 下载
lua-nginx-module和ngx_devel_kit(部分指令依赖); - 重新 configure Nginx:
./configure --add-module=/path/to/lua-nginx-module --add-module=/path/to/ngx_devel_kit --with-luajit; -
make && sudo make install,完成后验证:nginx -V 2>&1 | grep -o lua应有输出。
配置关键指令与运行阶段
Nginx 把请求划分为 11 个处理阶段(phase),Lua 指令绑定到特定阶段,决定何时介入:
-
init_by_lua_block:Master 进程加载配置时执行一次,适合预加载模块、初始化全局共享字典(lua_shared_dict); -
access_by_lua_block:在访问控制阶段运行,常用于 IP 黑白名单、JWT 解析、频率限制(配合resty.limit.count); -
content_by_lua_block:替代默认内容生成,可完全接管响应(如返回 JSON、转发子请求、调用 Redis); -
header_filter_by_lua_block:修改响应头(如添加X-Processed-By: Lua或动态 CORS 头); -
log_by_lua_block:日志记录前做定制化处理(如脱敏、条件打点)。
注意:set_by_lua* 只能用于变量赋值;rewrite_by_lua* 在重写阶段,慎用耗时操作;所有阻塞式 IO(如 os.execute)禁止使用。
典型高级能力实现示例
不靠后端,直接在 Nginx 层完成业务逻辑:
-
动态限流:用
lua_shared_dict rate_limit 10m;定义共享内存,配合resty.limit.count:new()实现每秒 100 次请求/IP 的精准控制; -
轻量 WAF:在
access_by_lua_block中检查ngx.var.args、ngx.req.get_uri_args()、ngx.var.request_body,匹配 SQL 注入、XSS 特征字符串,命中即ngx.exit(403); -
灰度路由:读取 cookie 或 header 中的
X-Release-Phase,用ngx.exec("@backend_v2")或ngx.redirect()分流到不同 upstream; -
子请求聚合:用
ngx.location.capture("/api/user", { method = ngx.HTTP_GET })同步调用内部接口,再组合多个子请求结果返回,避免客户端多次请求。
调试与生产注意事项
开发易出错,上线需稳:
- 开发期关闭缓存:
lua_code_cache off;(仅限测试环境),否则改 Lua 文件要 reload 才生效; - 启用
error_log /var/log/nginx/error.log debug;查看 Lua 错误细节(debug 级别日志较大,生产慎开); - 所有 Lua 脚本路径用
lua_package_path "/path/to/lua/?.lua;;";显式声明,避免模块找不到; - 禁止在 Lua 中使用
print(输出到标准错误,干扰日志),改用ngx.log(ngx.INFO, "msg"); - 共享字典(
lua_shared_dict)是跨请求、跨 worker 的唯一高速存储,适合存令牌、计数器、黑名单,但不能存大对象或复杂结构。











