如果找不到上游主机,则设置nginx不会崩溃

时间:2015-09-29 13:47:10

标签: nginx url-rewriting proxypass

我们在Docker的常用域下有几个rails应用程序,我们使用nginx将请求定向到特定应用程序。

our_dev_server.com/foo # proxies to foo app
our_dev_server.com/bar # proxies to bar

Config看起来像这样:

upstream foo {
  server foo:3000;
}

upstream bar {
  server bar:3000;
}

# and about 10 more...

server {
  listen *:80 default_server;

  server_name our_dev_server.com;

  location /foo {
      # this is specific to asset management in rails dev
      rewrite ^/foo/assets(/.*)$ /assets/$1 break;
      rewrite ^/foo(/.*)$ /foo/$1 break;
      proxy_pass http://foo;
  }

  location /bar {
      rewrite ^/bar/assets(/.*)$ /assets/$1 break;
      rewrite ^/bar(/.*)$ /bar/$1 break;
      proxy_pass http://bar;
  }

  # and about 10 more...
}

如果其中一个应用未启动,则nginx会失败并停止:

host not found in upstream "bar:3000" in /etc/nginx/conf.d/nginx.conf:6

我们不需要它们全部启动但是nginx失败了。 如何让nginx忽略失败的上游?

6 个答案:

答案 0 :(得分:64)

  1. 如果您可以使用静态IP,那么只需使用它,它就会启动,如果没有响应则返回503

  2. 使用resolver指令指向可以解析主机的内容,无论它是否正在运行。

  3. 如果您无法执行上述(这将允许Nginx启动/运行),则在location级别解析它:

    location /foo {
      resolver 127.0.0.1 valid=30s;
      # or some other DNS (you company/internal DNS server)
      #resolver 8.8.8.8 valid=30s;
      set $upstream_foo foo;
      proxy_pass http://$upstream_foo:80;
    }
    
    location /bar {
      resolver 127.0.0.1 valid=30s;
      # or some other DNS (you company/internal DNS server)
      #resolver 8.8.8.8 valid=30s;
      set $upstream_bar foo;
      proxy_pass http://$upstream_bar:80;
    }
    

答案 1 :(得分:11)

使用upstream的主要优点是定义一组服务器,而不是可以在不同端口上侦听,并在它们之间配置负载平衡和故障转移 即可。

在您的情况下,您每个上游仅定义1个主服务器,因此必须为

相反,请为proxy_pass使用变量,并记住处理目标服务器关闭时可能出现的错误(404s,503s)。

答案 2 :(得分:2)

对我来说,@ Justin / @ duskwuff的答案的选项3解决了该问题,但是我不得不将解析器IP更改为 127.0.0.11 (Docker的DNS服务器):

location /foo {
  resolver 127.0.0.11 valid=30s;
  set $upstream_foo foo;
  proxy_pass http://$upstream_foo:80;
}

location /bar {
  resolver 127.0.0.11 valid=30s;
  set $upstream_bar foo;
  proxy_pass http://$upstream_bar:80;
}

但是正如@ Justin / @ duskwuff所述,您可以使用任何其他外部DNS服务器。

答案 3 :(得分:1)

针对某人场景的另一个快速简便的修复方法,我可以启动和停止,而我的主服务器不会被炸毁

    extra_hosts:
      - "dockerhost:172.20.0.1" # <-- static ipv4 gateway of the network ip here thats the only sorta downside but it works for me, you can ifconfig inside a container with the network to find yours, kinda a noob answer but it helped me
    networks:
      - my_network
server {
  listen 80;
  server_name servername;

  location / {
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $host;

    proxy_pass https://dockerhost:12345;

    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
  }
}

答案 4 :(得分:0)

我遇到了同样的“找不到主机”问题,因为部分主机是使用$uri而不是$request_uri映射的:

proxy_pass http://one-api-service.$kubernetes:8091/auth;

当请求更改为auth子请求时,$uri失去了初始值。将映射更改为使用$request_uri而不是$uri解决了我的问题:

map $request_uri $kubernetes {
    # ...
}

答案 5 :(得分:-7)

您不能使用--link选项,而是可以使用端口映射并将nginx绑定到主机地址。

示例:使用-p 180:80选项运行第一个泊坞窗容器,使用-p 280:80选项运行第二个容器。

运行nginx并为代理设置这些地址:

proxy_pass http://192.168.1.20:180/; # first container
proxy_pass http://192.168.1.20:280/; # second container