每次执行proxy_pass时如何强制nginx解析DNS(动态主机名)?

xia*_*amx 81 linux nginx

我正在使用 nginx/0.7.68,在 CentOS 上运行,配置如下:

server {
    listen       80;
    server_name ***;
    index index.html index.htm index.php default.html default.htm default.php;

    location / {
            root   /***;
            proxy_pass   http://***:8888;
            index  index.html index.htm;
    }
    # where *** is my variables
Run Code Online (Sandbox Code Playgroud)

proxy_pass是针对 IP 频繁更改的 DNS 记录。Nginx 缓存过时的 IP 地址,导致请求错误的 IP 地址。

当 IP 地址过期时,如何阻止 nginx 缓存它?

oha*_*aal 137

接受的答案在 nginx/1.4.2 上对我不起作用。

使用变量proxy_pass强制重新解析 DNS 名称,因为 NGINX 对待变量的方式与静态配置不同。从NGINXproxy_pass文档

参数值可以包含变量。在这种情况下,如果地址被指定为域名,则在描述的服务器组中搜索该名称,如果没有找到,则使用解析器来确定。

例如:

server {
    ...
    resolver 127.0.0.1;
    set $backend "http://dynamic.example.com:80";
    proxy_pass $backend;
    ...
}
Run Code Online (Sandbox Code Playgroud)

注意:解析器(即要使用的名称服务器)必须可用并进行配置以使其工作(并且/etc/hosts文件中的条目不会在查找中使用)。

默认情况下,1.1.9 或更高版本的 NGINX 缓存响应使用响应的 TTL 值和可选valid参数允许覆盖缓存时间:

resolver 127.0.0.1 [::1]:5353 valid=30s;
Run Code Online (Sandbox Code Playgroud)

在 1.1.9 版本之前,无法调整缓存时间,nginx总是将答案缓存 5 分钟。.

  • 在花了我一天的大部分时间之后 - 在带有 nginx 1.1.19 的 Ubuntu 12.04 上,`location` 中的 `set` 无法正常工作。谨防 (22认同)
  • 注意:对于 docker,它的 DNS 解析器驻留在 127.0.0.11,所以对于开发,我使用这个:`resolver 127.0.0.11 [::1]:5353 valid=15s;` (11认同)
  • 这是一个非常讨厌的问题,我在尝试调试的一天中迷失了方向:如果您在 proxy_pass 指令中使用变量,则路径的解释会发生变化。执行此操作时,原始请求的路径将被完全覆盖并替换为 proxy_pass 中给出的路径。您必须使用 url 中没有路径的 proxy_pass 以避免这种行为。 (7认同)
  • 我必须将其更改为 `set $backend "http://dynamic.example.com:80$request_uri";`,否则请求路径将为空(正如我上面的评论也提到的那样) (4认同)
  • 我发现,如果正在解析的主机名只是一个短名称(没有域部分),就像通过服务主机名进行 Docker 服务发现的情况一样,那么您需要添加一个尾随点,例如 `set $backend_host "http:// /后端.:1234/abc";`。否则,主机名会在启动时解析一次,就好像没有使用变量一样。 (3认同)

小智 12

gansbrest 评论和 ohaal 回答中提供了有价值的信息。

但我认为重要的是要提到这篇 2016 年发布的 nginx 官方文章,它清楚地解释了 nginx 在这件事上的行为以及可能的解决方案:https : //www.nginx.com/blog/dns-service-discovery-nginx-plus /

我们确实必须“在变量中设置域名”并使用解析器指令。

然而,使用变量会改变重写行为。您可能必须使用 rewrite 指令,这取决于您的位置和 proxy_pass 设置。

PS:本来可以发表评论但还不够积分...


cor*_*ump 8

这是一个有趣的问题,AFAIK 不会很好地工作。您可以尝试使用上游模块并使用故障转移指令来查看它是否可以作为黑客使用。

2018 年编辑:很多事情发生了变化。检查@ohaal答案以获取有关此的真实信息。


小智 7

ohaal 的回答让我们大多数人都在那里,但有一种情况,DNS 解析器不在 127.0.0.1 处(例如,当您处于特殊的容器化环境中时)

在这种情况下,您可能需要将 nginx conf 更改为resolver ${DNS_SERVER};. 然后,在启动 nginx 之前,运行

export DNS_SERVER=$(cat /etc/resolv.conf |grep -i '^nameserver'|head -n1|cut -d ' ' -f2)
envsubst '${DNS_SERVER}' < your_nginx.conf.template > your_nginx.conf
Run Code Online (Sandbox Code Playgroud)

请注意,您需要gettext安装该软件包,因为它提供了envsubst命令。

  • awk '/nameserver/{a=(a?a" "$2:$2)} END{print a}' /etc/resolv.conf 2&gt; /dev/null (3认同)