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 秒,这对于您的用例来说可能太长了:
您无法重现此问题我并不感到惊讶,因为您现有的配置似乎没有任何问题;也许这个问题在较早的版本中表现出来了?
【讨论】:
以上是关于nginx 反向代理未检测到丢失的负载均衡器的主要内容,如果未能解决你的问题,请参考以下文章