V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
21231sv
V2EX  ›  问与答

关于 nginx 中 proxy_pass 指令我有些疑惑

  •  
  •   21231sv · 2023-08-09 07:16:10 +08:00 · 1168 次点击
    这是一个创建于 471 天前的主题,其中的信息可能已经有所发展或是发生改变。
    upstream example {
        server 172.0.0.1:3000;
        server 172.0.0.2:3000;
    }
    
    server {
        listen 3000;
        server_name _;
        location / {
            proxy_pass http://example;
            proxy_ssl_verify off;
            proxy_set_header Host $http_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;
        }
    }
    

    对于上面这个配置,我理解的是,假如客户端请求的是 http://ip:3000/path?a=1&b=2, nginx 会根据 example 这个 upstream 选择一个后端服务器转发请求,比如 http://172.0.0.1:3000/path?a=1&b=2

    但是我在工作中有碰到过如下配置:

      location ~ ^/api/(.*) {
          proxy_set_header Host $http_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;
          proxy_pass http://172.0.0.3:31081/$1$is_args$args;
          proxy_connect_timeout 300s;
          proxy_send_timeout 300s;
          proxy_read_timeout 300s;
      }
    

    在这个配置中,proxy_pass 指令后面有 $is_args 、$args 这些参数。如果不加参数,客户端请求 url 上的参数就无法转发到 172.0.0.3 服务器上

    我想要的是要把客户端请求 url 中的参数转发到后端,我的疑惑是什么时候 proxy_pass 指令后面需要加 $is_args 、$args 这些参数

    11 条回复    2023-08-09 21:39:07 +08:00
    hankai17
        1
    hankai17  
       2023-08-09 07:31:20 +08:00
    可能跟 upstream 模块有关
    GTim
        2
    GTim  
       2023-08-09 08:05:46 +08:00
    看 172.0.0.3:31081 这台的 nginx 日志
    privil
        3
    privil  
       2023-08-09 08:29:27 +08:00
    (.*) 这个参数在上下文里面不匹配 url 上的参数吧,话说用了那么多年 Nginx ,我也是第一次见第二种写法。直接去掉正则也可以吧。
    location ~ ^/api/ {
    proxy_set_header Host $http_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;
    proxy_pass http://172.0.0.3:31081/;
    proxy_connect_timeout 300s;
    proxy_send_timeout 300s;
    proxy_read_timeout 300s;
    }
    crystom
        4
    crystom  
       2023-08-09 09:08:48 +08:00
    很可能跟末尾有没有斜杠有关系
    dzdh
        5
    dzdh  
       2023-08-09 09:10:21 +08:00
    proxy_pass 到 127.0.0.1:xx 然后看日志
    xiangyuecn
        6
    xiangyuecn  
       2023-08-09 09:45:21 +08:00
    按道理,第二种才是正常写法。

    第一种写多了,只会误导人,来个高级一点的就不会写了。
    wu00
        7
    wu00  
       2023-08-09 09:58:44 +08:00
    @privil 应该做了一层 path strip 吧? /api/xxx => /xxx , 你这个/api/前缀带到服务层就 404 了
    privil
        8
    privil  
       2023-08-09 13:37:26 +08:00
    @wu00 #7 你可以试试我这种写法会不会带过去。我看漏了中间一堆他自己的理解,啥理解,多个 upsteam 是有个默认算法的请求的。脑补严重。
    jifengg
        9
    jifengg  
       2023-08-09 13:51:32 +08:00
    以我有限的 nginx 经验,楼主的第二个配置
    location ~ ^/api/(.*) {
    proxy_pass http://172.0.0.3:31081/$1$is_args$args;
    }
    的目的,是把类似 http://host/api/your/path?key=value 转发到 http://172.0.0.3:31081/your/path?key=value

    是把“/api”这层 path 换成“/”,应该是 172.0.0.3:31081 的 api (?)服务不需要加 “/api”前缀。

    $1 就是 location 正则里面的 第一个 group ,$is_args 是表示是否有 searchPath ,值是"?"或空,$args 则表示 key=value&a=b 这整个 get 参数。

    有个简化的版本可以参考(也是达到“转发时去掉 url 中的/api 的目的”):
    location /api {
    proxy_pass http://172.0.0.3:31081/; #注意这里最后的/不能省
    }
    21231sv
        10
    21231sv  
    OP
       2023-08-09 21:37:28 +08:00
    @xiangyuecn #6 为什么这么说?我看官网上都是第一种写法
    21231sv
        11
    21231sv  
    OP
       2023-08-09 21:39:07 +08:00
    @jifengg #9 这么说,我上次应该就是省略了 31081 后面的 /
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3738 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 05:11 · PVG 13:11 · LAX 21:11 · JFK 00:11
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.