我们的反向代理具有以下配置:
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亚马逊仍然认为它是有效的,但不会) t从外部解析(我们的服务器尝试访问它们的服务器。)
我已从一种配置中完全删除了解析器,将看到它的去向。我们无法使用内部服务器来复制此文件,因此我们必须依靠等待第三方服务器循环运行(大约每周一次)。
我不确定这个解析器是不是一个问题,原因仅在于重启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;
}
请注意,我必须将其设置在内部,因为它使用了动态变量。
答案 0 :(得分: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;
答案 1 :(得分:0)
在中使用变量没有什么特别的-任何变量的使用都会使nginx涉及到每个请求的解析器(如果在服务器组中找不到-也许您有冲突?),甚至可以摆脱它。如果您已经在其中使用$backend
,则$2
中的数字。
关于解释错误消息-您必须弄清楚是否发生这种情况是因为现有连接被断开,还是因为nginx仍在尝试连接到旧地址。
您可能还想研究降低http://nginx.org/r/proxy_pass中的_time
值;它们似乎都设置为60s,对于您的用例来说可能太长了:
对于您无法重现此问题,我并不感到惊讶,因为您的现有配置似乎没有任何问题。也许该问题在较早的修订版中就已体现出来了?