Nginx 的 map + rewrite 组合是旧 API 无损迁移首选方案:map 在 http 块预定义路径映射,rewrite 在 location 中用 last 触发内部重定向,配合 proxy_pass 转发至新版服务,实现客户端无感、低延迟、可灰度的平滑下线。

旧 API 下线前,最稳妥的方式不是直接停用,而是把所有旧路径自动、精准地映射到新服务地址——Nginx 的 map + rewrite 组合,正是为此类无损迁移量身定制的方案。它不依赖后端改代码,不增加代理跳转延迟,还能按规则精细控制,是灰度下线与路径重构的首选手段。
用 map 预定义路径映射关系,清晰可维护
map 指令在 Nginx 全局作用域(通常写在 http 块)中建立键值映射,将旧路径前缀映射为对应的新路径前缀或目标服务标识。它只做字符串匹配,不触发重写,开销极低,且支持正则、默认值和嵌套判断。
例如,将三类旧 API 前缀分别导向不同新版路径:
map $uri $new_path {
default "";
~^/api/v1/users/(.*)$ /api/v2/profiles/$1;
~^/api/v1/orders/(.*)$ /api/v3/transactions/$1;
~^/api/v1/products/(.*)$ /api/v2/items/$1;
}
- 匹配顺序从上到下,第一个成功匹配的规则生效;
default ""表示未匹配时留空,便于后续判断 - 正则捕获组
(.*)保留原始参数,确保 query string 自动透传 - 变量名
$new_path是自定义的,语义明确,方便后续逻辑复用
用 rewrite 按需触发内部重写,保持客户端无感
在 server 或 location 块中,通过 rewrite 指令检查 $new_path 是否非空,仅当有映射结果时才执行内部重定向。关键在于使用 last 标志,让 Nginx 重新匹配 location,走新路径的处理逻辑(比如 proxy_pass 到新版服务),而浏览器 URL 不变。
location /api/v1/ {
if ($new_path != "") {
rewrite ^(.*)$ $new_path last;
}
return 404; # 无匹配则拒绝旧路径访问
}
- 避免在
if中直接写rewrite(Nginx 官方不推荐),先用 map 计算好再判断,更安全稳定 -
last是核心:它终止当前 location 匹配,用新 URI 再次查找 location,实现“路径替换+逻辑切换”一体化 - 末尾
return 404是兜底策略,防止遗漏规则导致旧接口意外暴露
配合 proxy_pass 转发到新版服务,隐藏真实后端
新版路径(如 /api/v2/profiles/...)需由独立 location 捕获,并转发至实际服务。此时可结合 upstream 实现负载均衡或健康检查,与旧路径解耦。
location /api/v2/ {
proxy_pass https://backend-v2/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
<p>location /api/v3/ {
proxy_pass <a href="https://www.php.cn/link/720a860f1a870a7f103b2518f7f9843a">https://www.php.cn/link/720a860f1a870a7f103b2518f7f9843a</a>;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}</p>-
proxy_pass末尾带斜杠/,表示截断前缀,否则路径会原样拼接(如proxy_pass http://b/+ 请求/api/v2/x→ 后端收到/x) - 所有 header 透传确保后端能获取真实客户端信息,便于日志、鉴权等处理
- 不同版本路径可指向不同 upstream,天然支持灰度发布与流量切分
验证与上线前的关键检查点
上线前必须逐项确认,避免 500、循环重写或静默失败:
- 用
nginx -t检查语法,特别注意 map 变量是否在 http 块定义、rewrite 是否在正确上下文 - 开启
error_log /path/to/error.log notice;,观察是否有 “rewrite or internal redirection cycle” 报错 - 用 curl 测试典型路径:
curl -v http://your.domain/api/v1/users/123,确认响应头Server和 body 来自新版服务,且状态码为 200 - 检查 access log 中旧路径是否全部被重写,无残留 404 或直接命中旧后端的日志


















