nginx反向代理结合lua实现动态路径改写与后端路由,核心是在rewrite_by_lua_block阶段实时计算目标地址和uri,配合resolver、set_by_lua_block及共享字典完成灰度、ab测试等场景的轻量级动态路由。

直接用 Nginx 反向代理 + Lua 脚本改写转发路径,核心不是“替换字符串”,而是把路径决策逻辑从配置文件里抽出来,在请求到达时实时计算目标后端地址和 URI 结构。关键在于阶段选择、变量控制和 resolver 配合。
用 rewrite_by_lua_block 动态重写 URI 并决定 proxy_pass 目标
这个阶段在 location 匹配之后、proxy_pass 执行之前运行,适合做路径解析、参数提取和目标判断。
- 在 location 块中用 rewrite_by_lua_block 读取请求头、参数或 cookie,比如:
ngx.var.arg_env == "prod"或ngx.var.http_x_device_type == "mobile" - 根据条件设置自定义变量,例如:
ngx.var.backend_host = "api-prod.example.com"和ngx.var.new_uri = "/v2" .. ngx.var.uri - 再用 rewrite 指令重写 $uri(注意加 break 防止循环),或直接让后续的
proxy_pass http://$backend_host使用新变量
用 set_by_lua_block 构造可解析的动态 upstream 地址
Nginx 的 proxy_pass 不支持任意变量拼接,但支持带 resolver 的变量形式,前提是变量值是合法域名+端口。
- 在 server 或 http 块里声明 resolver(如
resolver 8.8.8.8 valid=30s;),启用 DNS 缓存 - 用 set_by_lua_block 把目标服务名(如
"service-a-v2.internal")或 IP+端口(如"10.0.1.5:8080")写入$upstream_target - proxy_pass 写成
proxy_pass http://$upstream_target;——Nginx 会走 resolver 解析该变量,实现动态寻址
结合共享字典(lua_shared_dict)做轻量级路由规则中心
不依赖外部数据库也能实现“配置即服务”,适合灰度、AB 测试、服务注册等边缘场景。
- 在 http 块定义共享字典:
lua_shared_dict route_rules 10m; - 用独立 location(如
/admin/route)接收 HTTP 请求,通过ngx.shared.route_rules:set(key, value)写入规则 - 主业务 location 中用
ngx.shared.route_rules:get(ngx.var.host)或ngx.shared.route_rules:get(ngx.var.arg_service)获取目标地址或路径前缀 - 配合
rewrite或proxy_pass即可完成动态路径改写与转发
路径重写要注意 proxy_pass 的斜杠行为
URI 改写后能否正确拼接到后端,取决于 proxy_pass 末尾是否有斜杠,以及 rewrite 是否用了 break。
-
proxy_pass http://backend/;+rewrite ^/old/(.*)$ /new/$1 break;→ 后端收到/new/xxx -
proxy_pass http://backend;+rewrite ^/old/(.*)$ /new/$1 break;→ 后端收到完整路径/old/new/xxx(未去除前缀) - 想彻底替换路径,推荐统一用
proxy_pass http://backend/;,并确保 rewrite 用 break 终止当前 location 处理流程











