Nginx中通过location匹配与Lua执行阶段协同实现高性能动态逻辑处理。精确匹配+access_by_lua_block用于鉴权,前缀匹配+content_by_lua_block用于响应生成,正则+rewrite_by_lua_block用于URI重写;需避免宽泛匹配滥用、阻塞调用及全局状态共享。

在 Nginx 中通过 location 块结合 Lua 脚本,可以实现轻量、高性能的动态逻辑处理,比如权限校验、参数改写、灰度路由、API 网关基础功能等。关键在于合理划分 location 匹配规则,并在合适阶段(如 access_by_lua*、content_by_lua*)嵌入 Lua 代码,避免阻塞或误匹配。
location 匹配与 Lua 执行阶段的选择
location 决定请求由哪个区块处理,而 Lua 阶段决定逻辑何时介入。常见组合:
- 精确匹配 + access_by_lua_block:适合鉴权类逻辑(如检查 token),失败直接返回 401/403;
- 前缀匹配 + content_by_lua_block:适合完全接管响应生成(如内部 API 聚合);
- 正则 location + rewrite_by_lua_block:适合动态重写 URI(如版本号提取、路径标准化);
- 避免在
location /这类宽泛匹配中滥用content_by_lua,否则影响静态资源性能。
典型配置示例:带参数校验的动态接口
假设需拦截 /api/v1/user 请求,校验 app_id 和签名:
location ^~ /api/v1/user {
access_by_lua_block {
local args = ngx.req.get_uri_args()
local app_id = args.app_id
local sign = args.sign
<pre class="brush:php;toolbar:false;"> if not app_id or not sign then
ngx.status = 400
ngx.say('missing app_id or sign')
ngx.exit(ngx.HTTP_BAD_REQUEST)
end
-- 简单签名验证(实际应 HMAC)
if sign ~= ngx.md5(app_id .. "secret_key") then
ngx.status = 401
ngx.say('invalid signature')
ngx.exit(ngx.HTTP_UNAUTHORIZED)
end
}
proxy_pass http://backend;}
注意:access_by_lua_block 在代理转发前执行,可提前拦截;ngx.exit() 会终止后续处理,无需显式 return。
变量传递与上下文共享
Lua 代码可读写 Nginx 变量,实现 location 间数据透传:
- 用
ngx.var.xxx = value设置变量,后续proxy_set_header或其他指令可引用; - 用
ngx.ctx在同一请求的不同 Lua 阶段间共享数据(如access_by_lua中解析的用户 ID,供log_by_lua记录); - 避免在
init_by_lua中定义全局 table 存状态——它被所有 worker 共享,不安全;需用shared_dict或外部存储。
性能与安全提醒
Lua 脚本运行在 Nginx worker 进程内,高效但需谨慎:
- 禁止使用
os.execute、io.open等阻塞系统调用; - 复杂逻辑(如 JSON 解析、网络请求)尽量用
resty.http异步库,避免阻塞事件循环; - 开启
lua_code_cache off仅用于开发调试,生产必须开启以提升性能; - location 中若同时存在
proxy_pass和content_by_lua,二者互斥——Nginx 不允许多个 content handler,需明确选择其一。
不复杂但容易忽略:location 的匹配优先级和 Lua 阶段的执行顺序共同决定了最终行为,建议先画出请求生命周期图,再逐阶段插入逻辑。











