【问题标题】:nginx reverse proxy - how to serve multiple appsnginx 反向代理 - 如何为多个应用程序提供服务
【发布时间】:2020-10-31 08:14:53
【问题描述】:

我正在尝试使用 nginx 构建反向代理,以使我的项目中的所有 Is 都可以从单个地址访问。 对于单个服务,以下配置可以正常工作

/etc/nginx/sites-enabled/reverse-proxy.conf

server {
        listen 80;
        listen [::]:80;
        location  / {

        resolver 127.0.0.1;
        allow "x.x.x.x";
        deny   all;
        proxy_pass http://consul:8500;
    }

}

所以当我在浏览器中调用服务器的 ip x.x.x.x 时,我会看到 Consul UI 和显示 x.x.x.x/ui/dc1 的 URL。除此之外,我看到 UI 成功地请求了资产文件。

我的问题;是否有可能在同一台服务器上托管两个不同的服务,并且只在不同的位置引用它们?例如,如果我想包含 Vault UI,那么我会考虑做这样的事情:

server {
        listen 80;
        listen [::]:80;
        location  /consul {

        resolver 127.0.0.1;
        allow "x.x.x.x";
        deny   all;
        proxy_pass http://consul:8500;
    }

        location  /vault {

        resolver 127.0.0.1;
        allow "x.x.x.x";
        deny   all;
        proxy_pass http://vault:8200;
    }

}

但是我不确定这是否可以通过这种方式完成。我得到的最多的是打开 Consul UI,但没有找到所有其他子请求(即加载资产)。


更新

我认为我的问题是我错误地使用了locationproxy_pass

观察第一个配置(正在运行)

server {
        listen 80;
        listen [::]:80;
        location  / {

        resolver 127.0.0.1;
        allow "x.x.x.x";
        deny   all;
        proxy_pass http://consul:8500;
    }

}

如果我查看 curl 命令curl localhost -L -vvvv

*   Trying 127.0.0.1:80...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 80 (#0)
> GET / HTTP/1.1
> Host: localhost
> User-Agent: curl/7.68.0
> Accept: */*
> 
* Mark bundle as not supporting multiuse
< HTTP/1.1 301 Moved Permanently
< Server: nginx/1.18.0 (Ubuntu)
< Date: Fri, 10 Jul 2020 16:24:38 GMT
< Content-Type: text/html; charset=utf-8
< Content-Length: 39
< Connection: keep-alive
< Location: /ui/
< 
* Ignoring the response-body
* Connection #0 to host localhost left intact
* Issue another request to this URL: 'http://localhost/ui/'
* Found bundle for host localhost: 0x557b754549e0 [serially]
* Can not multiplex, even if we wanted to!
* Re-using existing connection! (#0) with host localhost
* Connected to localhost (127.0.0.1) port 80 (#0)
> GET /ui/ HTTP/1.1
> Host: localhost
> User-Agent: curl/7.68.0
> Accept: */*
> 
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Server: nginx/1.18.0 (Ubuntu)
< Date: Fri, 10 Jul 2020 16:24:38 GMT
< Content-Type: text/html; charset=utf-8
< Content-Length: 7806
< Connection: keep-alive
< Accept-Ranges: bytes
< Last-Modified: Fri, 10 Jul 2020 07:37:44 GMT
< 
<!DOCTYPE html>
<html lang="en" class="ember-loading">
...

我已经可以看到 html 了。但是,如果我将 conf 文件更改为:

server {
        listen 80;
        listen [::]:80;
        location  /consul/ {

        resolver 127.0.0.1;
        allow "x.x.x.x";
        deny   all;
        proxy_pass http://consul:8500;
    }

}

然后尝试将其称为curl localhost/consul -L -vvvv,我得到以下信息:

*   Trying 127.0.0.1:80...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 80 (#0)
> GET /consul HTTP/1.1
> Host: localhost
> User-Agent: curl/7.68.0
> Accept: */*
> 
* Mark bundle as not supporting multiuse
< HTTP/1.1 301 Moved Permanently
< Server: nginx/1.18.0 (Ubuntu)
< Date: Fri, 10 Jul 2020 16:32:35 GMT
< Content-Type: text/html
< Content-Length: 178
< Location: http://localhost/consul/
< Connection: keep-alive
< 
* Ignoring the response-body
* Connection #0 to host localhost left intact
* Issue another request to this URL: 'http://localhost/consul/'
* Found bundle for host localhost: 0x55ba7959f9e0 [serially]
* Can not multiplex, even if we wanted to!
* Re-using existing connection! (#0) with host localhost
* Connected to localhost (127.0.0.1) port 80 (#0)
> GET /consul/ HTTP/1.1
> Host: localhost
> User-Agent: curl/7.68.0
> Accept: */*
> 
* Mark bundle as not supporting multiuse
< HTTP/1.1 404 Not Found
< Server: nginx/1.18.0 (Ubuntu)
< Date: Fri, 10 Jul 2020 16:32:35 GMT
< Content-Length: 0
< Connection: keep-alive

我将不胜感激有关此问题的任何想法

【问题讨论】:

  • nginX 可以为同一个 IP 地址上的多个域(或子域)提供服务。当然,不同的位置也可以代理到不同的后端。

标签: nginx reverse-proxy nginx-reverse-proxy


【解决方案1】:

你是对的,你使用 locationproxy_pass 的方式是错误的。当你使用

location /vault {
    proxy_pass http://vault:8200;
}

构造,您将 URI 按原样传递给上游,而您很可能希望从中删除 /vault 前缀。为此,您应该使用这个:

location /vault/ {
    proxy_pass http://vault:8200/;
}

您可以阅读更多关于第一个和第二个的区别here。但是,这仍然会阻止资产正确加载。

这个问题 - 如何在一些 URI 前缀下代理一些 webapp - 在 stackoverflow 上被一次又一次地询问。唯一正确的方法是让您的代理应用程序仅通过相对 URL 请求其资产(考虑 assets/script.js 而不是 /assets/script.js)或使用正确的前缀(/vault/assets/script.js)。一些编写良好的应用程序能够检测它们是否在这样的 URI 前缀下使用,并在生成资产链接时使用它,一些应用程序允许通过一些设置来指定它,但有些应用程序根本不适合这种使用.如果不满足这些要求,webapp 将无法运行的原因非常明显 - 任何不以 /vault 开头的 URL 都不会匹配您的 location /vault/ { ... } 块,而是通过主 location 块提供服务。因此,最好的方法是修复您的 web 应用程序,但是如果您确实不能,可以使用几种解决方法。

  • 一些 Web 框架已经使用相对 URL 构建了它们的 Web 应用程序,但在 index.html 的头部部分使用了 &lt;base href="/"&gt;。例如,React 或 Angular 使用这种方法。如果你的 webapp 根 index.html 中有这样一行,只需将其更改为 &lt;base href="/vault/"&gt;

  • 使用基于 HTTP Referer 标头值的条件路由。这种方法非常适用于加载资产的单页应用程序,但如果 webapp 包含多个页面,这种方法将不起作用,正确的上游检测逻辑会在第一次从一个页面跳转到另一个页面后中断。这是一个例子:

    map $http_referer $prefix {
        ~https?://[^/]+/vault/     vault;
        # other webapps prefixes could be defined here
        # ...
        default                    base;
    }
    
    server {
    
        # listen port, server name and other global definitions here
        # ...
    
        location / {
            # "unconditional" jump-to-location idea taken from this answer:
            # https://serverfault.com/questions/908086/nginx-directly-send-from-location-to-another-named-location/965779#965779
            try_files /dev/null @$prefix;
        }
        location /vault/ {
            # proxy request to the vault upstream, remove "/vault" part from the URI
            proxy_pass http://vault:8200/;
        }
        location @vault {
            # proxy request to the vault upstream, do not change the URI
            proxy_pass http://vault:8200;
        }
        location @base {
            # default "root" location
            proxy_pass http://consul:8500;
        }
    
    }
    
  • 使用来自ngx_http_sub_modulesub_filter 指令重写响应正文中的链接。这是最难看的一个,但仍然可以用作最后一个可用的选项。这种方法具有明显的性能影响。重写模式应根据您的上游响应正文确定。通常这种类型的配置看起来像

    location /vault/ {
        proxy_pass http://vault:8200/;
        sub_filter_types text/css application/javascript;
        sub_filter_once off;
        sub_filter 'href="/' 'href="/vault/';
        sub_filter "href='/" "href='/vault/";
        sub_filter 'src="/'  'src="/vault/';
        sub_filter "src='/"  "src='/vault/";
        sub_filter 'url("/'  'url("/vault/';
        sub_filter "url('/"  "url('/vault/";
        sub_filter "url(/"   "url(/vault/";
    }
    

【讨论】:

    猜你喜欢
    • 2016-04-13
    • 2023-03-13
    • 2020-08-18
    • 1970-01-01
    • 2020-09-05
    • 2021-08-25
    • 2016-10-31
    • 2016-01-28
    • 2014-07-25
    相关资源
    最近更新 更多