V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
NGINX
NGINX Trac
3rd Party Modules
Security Advisories
CHANGES
OpenResty
ngx_lua
Tengine
在线学习资源
NGINX 开发从入门到精通
NGINX Modules
ngx_echo
ShihanW
V2EX  ›  NGINX

请教一个 nginx 转发的问题

  •  
  •   ShihanW · 42 天前 · 1585 次点击
    这是一个创建于 42 天前的主题,其中的信息可能已经有所发展或是发生改变。

    请问 V 友,nginx 如何使用路由转发不同的服务啊,比如机器上有两个服务,一个部署在 8080 端口(假设服务名为 a ),另一个在 8888 (服务名 b ),我的预期是分别设置/a 和/b 用以转发这两服务,并且它们的子路由也要转发,例如它们都有登陆,就分别为/a/login/b/login,但是我在访问/a 页面时点击登陆,浏览器路由就自动变成/login了,忽略了/a,这要这么办呢,难道我还要在 nginx 里对它们的子路由单独设置转发规则吗。

    我现在是这样配置的

    {
        listen 443;
        
        location /a {
            proxy_pass http://localhost:8080;
        }
        
        location /b {
            proxy_pass http://localhost:8888;
        }
    }
    
    
    14 条回复    2024-03-17 15:08:46 +08:00
    klo424
        1
    klo424  
       42 天前
    GPT 的答案

    ```bash
    server {
    listen 80;
    server_name example.com;

    location /a/ {
    proxy_pass http://localhost:8080/;
    proxy_set_header Host $host;
    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 $scheme;

    # 如果服务 a 使用相对路径构建链接,需要进行重写
    # rewrite ^/a/(.*)$ /$1 break;
    }

    location /b/ {
    proxy_pass http://localhost:8888/;
    proxy_set_header Host $host;
    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 $scheme;

    # 如果服务 b 使用相对路径构建链接,需要进行重写
    # rewrite ^/b/(.*)$ /$1 break;
    }
    }
    ```
    iseki
        2
    iseki  
       42 天前 via Android
    这个问题要程序自己处理干净,尽量不假设自己一定在根,不然只能采用古老的重写页面内链的办法了(但很遗憾,这在现代复杂 Web 应用场景下不工作)。
    现实中很多应用是不支持把自己配置到非根位置的…这就没太好的办法了。
    google2020
        3
    google2020  
       42 天前
    因为 a 前端路由的 root 还是 /,反代并不会改变代码,所以访问 root+/login 的时候还是 /login ,而不是 /a/login

    你可以改变 a 的代码,把 root 改成 /a ,或者添加 root 变量,然后在 nginx 反代代码里用 sub_filter 替换
    Puteulanus
        4
    Puteulanus  
       42 天前
    这个得你后端支持动态的路径,或者支持配置 url prefix ,不然它返回一个 /login 的 302 或者 a 标签给前端,nginx 要管这个得上专门的反代模块用规则去替换后端返回的内容了
    NotFoundEgg
        5
    NotFoundEgg  
       42 天前
    {
    listen 443;

    location /a/ {
    proxy_pass http://localhost:8080/a/;
    }

    location /b/ {
    proxy_pass http://localhost:8888/b/;
    }
    }
    oranges0196
        6
    oranges0196  
       42 天前
    按目前已有信息,赞同 2 楼的答案。
    你要先确定好自己的前端项目 a 的跳转地址是不是想要的 example.com/a/login ,然后再看 nginx 的路由。
    虽然 nginx 也有办法实现 a 项目跳转 example.com/login 路由到 a ,b 项目跳转到跳转 example.com/login 路由到 b ,但是不建议这样做
    IvanLi127
        7
    IvanLi127  
       42 天前
    web 应用得支持部署在子目录才行,先去确认吧
    Curtion
        8
    Curtion  
       42 天前
    这种需要 A 服务的代码处理,它在跳转过程中不能使用绝对路径
    wheat0r
        9
    wheat0r  
       42 天前
    现在的应用还不让放到子目录的话,让开发自裁吧
    ShihanW
        10
    ShihanW  
    OP
       42 天前
    @Curtion
    @oranges0196
    @iseki
    @google2020
    @Curtion
    因为部署的服务都是第三方,无法获取源码修改内链😭
    ShihanW
        11
    ShihanW  
    OP
       42 天前
    感谢大家的回复
    dropdatabase
        12
    dropdatabase  
       41 天前 via iPhone
    @ShihanW 你可以用域名区分 就没这个问题了
    wenyiduo8
        13
    wenyiduo8  
       41 天前
    核实下你的语句,按我的理解,你的 proxy_pass http://localhost:8080;
    8080 后面有 / 才会出现这种情况啊。
    没有/
    /a/login 会路由到 http://localhost:8080/a/login
    有/
    /a/login 会路由到 http://localhost:8080/login
    ShihanW
        14
    ShihanW  
    OP
       41 天前
    @dropdatabase
    你说的没错,不过前提是子服务的前端链接的地址不能是从根路由开始才行。
    ----------分割-----------------
    @wenyiduo8
    我找到区分办法了,部署的 a 和 b 两个服务都自定义 base_url ,然后结合 @dropdatabase 提出的建议,完美解决我的需求。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   2955 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 30ms · UTC 13:16 · PVG 21:16 · LAX 06:16 · JFK 09:16
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.