nginx 反向代理未检测到丢失的负载均衡器

Posted

技术标签:

【中文标题】nginx 反向代理未检测到丢失的负载均衡器【英文标题】:nginx reverse proxy not detecting dropped load balancer 【发布时间】:2020-03-06 19:44:30 【问题描述】:

我们的反向代理有以下配置:

location ~ ^/stuff/([^/]*)/stuff(.*)$ 
    set $sometoken $1;
    set $some_detokener "foo";
    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 Authorization "Basic $do_token_decoding";
    proxy_http_version 1.1;
    proxy_set_header Connection "";
    proxy_redirect https://place/ https://place_with_token/$1/;
    proxy_redirect http://place/ http://place_with_token/$1/;
    resolver 10.0.0.2 valid=10s;
    set $backend https://real_storage$2;
    proxy_pass $backend;

现在,所有这些都可以工作......直到real_storage 轮换服务器。例如,假设 real_storage 来自 foo.com。这是一个负载均衡器,它指向两个服务器:1.1.1.1 和 1.1.1.2。现在,1.1.1.1 被删除并替换为 1.1.1.3。但是nginx继续尝试1.1.1.1,导致:

epoll_wait() 报告客户端过早关闭连接,因此在连接上游时上游连接也关闭,客户端:...,服务器:...,请求:“GET ... HTTP/1.1”,上游: “https://1.1.1.1:443/...”,主机:“...”

请注意,上游是旧服务器,由以前的日志显示:

[调试] 1888#1888: *570837 连接到 1.1.1.1:443, fd:60 #570841

这是我们这边或我们real_storage的主机配置错误的东西吗?

*我能找到的最接近我的问题的是https://mailman.nginx.org/pipermail/nginx/2013-March/038119.html ...

更多详情

我们添加了 proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504; 它仍然失败。我现在开始怀疑,由于它是两个 ELB(我们的和他们的),那么我们使用的解析器就是问题所在 - 因为它是亚马逊特定的(每个 https://serverfault.com/a/929517/443939)...and 亚马逊仍然认为它是有效的,但它不会解决外部(我们的服务器试图攻击他们的..)

我已经从一个配置中完全删除了解析器,并会看到它的去向。我们无法使用内部服务器重现这种情况,因此我们必须依靠等待第三方服务器循环(大约每周一次)。

我有点不确定这个解析器是否只是问题,因为重新启动 nginx 将解决问题并获得最新的 IP 对:/

是否有可能我必须在没有 https 的情况下设置 dns 变量?:

    set $backend real_storage$2;
    proxy_pass https://$backend;

我知道你必须使用一个变量,否则重新解析将不会发生,但也许变量的哪一部分非常具体——因为我只在我的查询中看到它像上面那样设置。 ...但没有给出任何理由...我将在第二台服务器上设置它,看看会发生什么...

对于我的第三台服务器,我正在尝试this comment 并将设备移出位置。当然,如果其他人有具体的想法,那么我愿意改变我的测试以进行这一轮:D

set $rootbackend https://real_storage;
location ~ ^/stuff/([^/]*)/stuff(.*)$ 
    set $backend $rootbackend$2;
    proxy_pass $backend;

请注意,我必须将其设置在内部,因为它使用动态变量。

【问题讨论】:

请显示上游配置 @AlexC 是第三方系统,所以不在我们的控制范围内。 您是如何删除 1.1 并将其替换为 1.3、proxy_pass 中的任何健康检查服务器的? 据我所知,它正在被亚马逊删除 - ***.com/a/3833932/779513 我不确定健康检查服务器。 的健康状况很好......但底层 IP 是超时@ThanhNguyenVan 您是使用 AWS ELB 还是仅使用 nginx 进行负载平衡?不确定你给我的链接。 【参考方案1】:

正如@cnst 正确指出的那样,在proxy_pass 中使用变量会使nginx 为每个请求解析real_storage 的地址,但还有更多详细信息:

在 1.1.9 版之前,nginx 以前是 cache DNS answers for 5 minutes。

在版本 1.1.9 之后,nginx 缓存 DNS 答案的时间与其 TTL 相等,Amazon ELB 的默认 TTL 为 60 seconds。

所以在轮换后nginx 继续使用旧地址一段时间是非常合法的。根据文档,可以覆盖 DNS 缓存的过期时间:

resolver 127.0.0.1 [::1]:5353 valid=10s;

resolver 127.0.0.1 ipv6=off valid=10s;

【讨论】:

【参考方案2】:

在http://nginx.org/r/proxy_pass 中使用变量并没有什么特别之处——任何变量的使用都会使 nginx 在每个请求中都涉及到解析器(如果在服务器组中没有找到——也许你有冲突?),你甚至可以摆脱 @ 987654326@ 如果你已经在那里使用$2

至于解释错误消息——你必须弄清楚这是因为现有连接被丢弃,还是因为 nginx 仍在尝试连接到旧地址。

您可能还想考虑降低http://nginx.org/en/docs/http/ngx_http_proxy_module.html 中的_time 值;它们似乎都设置为 60 秒,这对于您的用例来说可能太长了:

http://nginx.org/r/proxy_connect_timeout http://nginx.org/r/proxy_send_timeout http://nginx.org/r/proxy_read_timeout

您无法重现此问题我并不感到惊讶,因为您现有的配置似乎没有任何问题;也许这个问题在较早的版本中表现出来了?

【讨论】:

以上是关于nginx 反向代理未检测到丢失的负载均衡器的主要内容,如果未能解决你的问题,请参考以下文章

nginx反向代理负载均衡

nginx反向代理负载均衡

nginx反向代理负载均衡

Nginx 实践案例:反向代理单台web;反向代理多组web并实现负载均衡

Nginx反向代理+负载均衡

Nginx反向代理+负载均衡