我们使用 nginx 作为反向代理将请求转发到我们的各个服务器。目前,如果任何上游服务器关闭/不可用,nginx 将无法启动。这令人沮丧,因为这意味着如果我们的任何上游服务器暂时关闭,我们的整个系统都将不可用。

我们希望配置 nginx,以便即使一个或多个上游服务器发生故障,它也能成功启动。

我偶然发现了,如果我理解正确的话,它说使用set要设置的位置proxy_pass作为变量会将主机名解析移动到请求时间而不是启动时间,从而解决了问题。但是,该帖子中的示例以及我在其他地方找到的示例并未描述如何在使用upstream配置块定义多个上游服务器(例如用于负载平衡)时实现此“解决方法”。不幸的是,由于我对 nginx 启动和请求处理阶段和细节的理解很少,我不确定如何在upstream使用块时调整示例“解决方法”。

当上游服务器关闭时,这种方法是否仍能允许 nginx 启动?如果可以,我该如何以及在哪里set引用该变量?如果不行,我该如何实现这一点?

我们的(简化的)nginx 配置:

upstream webserver {
    server webserver:8080;
}

upstream websocketserver {
    server websocketserver:8080;
}

server {
    ...

    # Reverse-proxy web requests to the web server(s)
    location / {
        proxy_pass http://webserver;

        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;
        proxy_set_header X-Forwarded-Host $host;
    }

    # Reverse-proxy Server-Push requests to the WebSocket server(s)
    location /websocket/ {
        proxy_pass http://websocketserver;

        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;
        proxy_set_header X-Forwarded-Host $host;
        proxy_set_header X-Forwarded-Prefix /websocket;
    }
}

(失败)尝试 1,在块中设置变量upstream

upstream webserver {
    set $upstream_webserver webserver:8080

    server $upstream_webserver;
}

server {
    ...

    # Reverse-proxy web requests to the web server(s)
    location / {
        proxy_pass http://webserver;

        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;
        proxy_set_header X-Forwarded-Host $host;
    }
}

结果是

root@039266c002d9:/# nginx -t
2024/10/11 17:29:06 [emerg] 40#40: "set" directive is not allowed here in /etc/nginx/conf.d/psif.conf:9
nginx: [emerg] "set" directive is not allowed here in /etc/nginx/conf.d/app.conf:9
nginx: configuration file /etc/nginx/nginx.conf test failed

(失败)第二次尝试,在块中设置变量server(以便能够在多个location块中重复使用它):

upstream webserver {
    server webserver:8080;
}

server {
    set $upstream_webserver webserver
    ...
    # Reverse-proxy web requests to the web server(s)
    location / {
        proxy_pass http://$upstream_webserver;

        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;
        proxy_set_header X-Forwarded-Host $host;
    }
}

结果是

root@039266c002d9:/# nginx -t
2024/10/11 17:31:44 [emerg] 41#41: host not found in upstream "webserver:8080" in /etc/nginx/conf.d/app.conf:7
nginx: [emerg] host not found in upstream "webserver:8080" in /etc/nginx/conf.d/app.conf:7       
nginx: configuration file /etc/nginx/nginx.conf test failed

如何使用配置块配置 nginx 以使其在上游服务器关闭时启动upstream

3

  • 1
    nginx 并不关心上游是否宕机,但如果宕机,它会解析为 IP。并且该 IP 将被永久缓存。因此,如果您的上游随时间更改 IP,则您无法使用upstream阻止(除非您有 nginx plus)。


    – 

  • 1
    在您的示例中,上游块中只有一个服务器,您根本不需要上游。只需使用resolver ...; set $upstream webserver:8000; proxy_pass http://$upstream;


    – 

  • @AlexeyTen 感谢您对 nginx 行为的澄清。提供的示例经过简化,这就是为什么上游块中只有一个服务器。如果我们假设我的服务器启动和关闭,但不更改 IP,我相信这使得该upstream块仍然适用,那么有没有办法使用该upstream块并在一个或多个服务器无法解析时仍允许 nginx 启动?


    – 


最佳答案
1

upstream {
  ...
  server webserver:8080  max_fails=0  resolve ;
  ...
}

无论您是否配置了主动健康检查,Nginx 都会使用被动健康检查。在这种情况下,使用 max_fails=0(零表示无限次失败)将停止 502……但是,这可能会带来新问题,因为您会告诉 Nginx “嘿,无论如何,只需发送请求……”,这意味着即使没有任何实时上游,它也会继续路由!!!

仔细阅读您的帖子后,我注意到如果您的服务器频繁或随机重启,您可能还会从 slow_start=30s 或其他设置中受益。您可以将其更改为适合您的环境的秒数。

请注意以上所有内容的使用说明: