写点什么

解决 Nginx 路径前缀问题:从 /serviceA 到 /special/serviceA 的平滑迁移

作者:玄兴梦影
  • 2025-10-27
    云南
  • 本文字数:1800 字

    阅读完需:约 6 分钟

解决 Nginx 路径前缀问题:从 /serviceA 到 /special/serviceA 的平滑迁移

问题背景

在实际的微服务架构中,我们经常需要对 API 路径进行重组或添加统一的前缀。最近我遇到了一个典型的场景:

原有配置:

nginx

location ~* ^/(serviceA|serviceB) {    proxy_pass 127.0.0.1;    proxy_connect_timeout 300s;    proxy_send_timeout 300s;    proxy_read_timeout 300s;    proxy_set_header X-Real-IP $remote_addr;    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;    proxy_set_header X-Forwarded-Proto http;}
复制代码

访问方式:

  • http://127.0.0.1/serviceA/1

  • http://127.0.0.1/serviceB/2

新的需求:需要在所有服务前添加 /special 前缀,但后端服务仍然期望接收原始路径:

  • 外部访问:http://127.0.0.1/special/serviceA/1

  • 内部转发:http://127.0.0.1/serviceA/1

解决方案

方案一:使用 rewrite 重写路径(推荐)

nginx

location ~* ^/special/(serviceA|serviceB) {    rewrite ^/special/(.*) /$1 break;    proxy_pass 127.0.0.1;    proxy_connect_timeout 300s;    proxy_send_timeout 300s;    proxy_read_timeout 300s;    proxy_set_header X-Real-IP $remote_addr;    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;    proxy_set_header X-Forwarded-Proto http;}
复制代码

工作原理:

  • rewrite ^/special/(.*) /$1 break 将 /special/serviceA/xxx 重写为 /serviceA/xxx

  • break 标志表示重写后立即停止处理其他重写规则

  • 然后通过 proxy_pass 转发到后端服务

方案二:在 proxy_pass 中使用变量

nginx

location ~* ^/special/(serviceA|serviceB) {    proxy_pass 127.0.0.1/$1;    proxy_connect_timeout 300s;    proxy_send_timeout 300s;    proxy_read_timeout 300s;    proxy_set_header X-Real-IP $remote_addr;    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;    proxy_set_header X-Forwarded-Proto http;}
复制代码

工作原理:

  • 正则表达式 (serviceA|serviceB) 捕获服务名到变量 $1

  • proxy_pass 127.0.0.1/$1 动态构建目标路径

  • 直接转发到对应的服务路径

方案三:兼容新旧路径(平滑迁移)

如果需要在一段时间内同时支持新旧路径,可以这样配置:

nginx

# 新的带 special 前缀的路径location ~* ^/special/(serviceA|serviceB) {    rewrite ^/special/(.*) /$1 break;    proxy_pass 127.0.0.1;    proxy_connect_timeout 300s;    proxy_send_timeout 300s;    proxy_read_timeout 300s;    proxy_set_header X-Real-IP $remote_addr;    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;    proxy_set_header X-Forwarded-Proto http;}
# 原有的直接访问路径(向后兼容)location ~* ^/(serviceA|serviceB) { proxy_pass 127.0.0.1; proxy_connect_timeout 300s; proxy_send_timeout 300s; proxy_read_timeout 300s; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto http;}
复制代码

配置详解

rewrite 指令说明

nginx

rewrite ^/special/(.*) /$1 break;
复制代码
  • ^/special/(.*):匹配以 /special/ 开头的所有路径

  • /$1:将匹配到的内容(不含 /special/)作为新路径

  • break:停止处理后续的 rewrite 规则

正则表达式说明

  • ~*:不区分大小写的正则匹配

  • ^/special/(serviceA|serviceB):匹配以 /special/ 开头,后跟 serviceA 或 serviceB 的路径

  • (serviceA|serviceB):捕获组,匹配到的服务名会被保存在 $1 变量中

测试验证

配置完成后,记得重新加载 nginx:

bash

nginx -s reload
复制代码

测试访问:

bash

# 新的带前缀访问方式curl http://127.0.0.1/special/serviceA/1curl http://127.0.0.1/special/serviceB/2
# 如果选择了方案三,原有的方式仍然可用curl http://127.0.0.1/serviceA/1curl http://127.0.0.1/serviceB/2
复制代码

推荐方案

方案一(rewrite 方式)是最推荐的做法,因为:

  1. 配置清晰,易于理解和维护

  2. 重写逻辑明确,便于后续扩展

  3. 性能影响小

  4. 兼容性好,适用于各种复杂的路径处理场景

总结

通过合理的 Nginx 配置,我们可以轻松实现路径前缀的添加和移除,满足各种路由需求。这种方案特别适用于:

  • API 版本管理

  • 多租户路径隔离

  • 微服务网关路由

  • 平滑迁移和 A/B 测试

关键是要理解 rewrite 和 proxy_pass 的配合使用,以及正则表达式在路径匹配中的灵活应用。

发布于: 刚刚阅读数: 3
用户头像

玄兴梦影

关注

做一个诗意的工程师。 2018-12-30 加入

一个不是诗人的诗人,不是程序员的程序员。

评论

发布
暂无评论
解决 Nginx 路径前缀问题:从 /serviceA 到 /special/serviceA 的平滑迁移_nginx_玄兴梦影_InfoQ写作社区