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

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

我正在使用 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

指向proxy_passIP 频繁变化的 DNS 记录。Nginx 会缓存过期的 IP 地址,导致请求指向错误的 IP 地址。

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

答案1

这是一个有趣的问题,据我所知,这种方法不太管用。你可以尝试使用上游模块并使用故障转移指令来查看它是否可以作为黑客手段。

2018 年编辑:很多事情都发生了变化。查看@ohaal 的回答获得有关此的真实信息。

答案2

在 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;
    ...
}

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

默认情况下,NGINX 1.1.9 或更高版本使用响应的 TTL 值缓存答案以及可选的valid范围允许覆盖缓存时间:

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

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

答案3

gansbrest 的评论和 ohaal 的回答中有很多有价值的信息。

但我认为有必要提一下这篇 2016 年发布的官方 nginx 文章,它清楚地解释了 nginx 在这个问题上的行为和可能的解决方案: https://www.nginx.com/blog/dns-service-discovery-nginx-plus/

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

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

附言:本来想发表评论但积分还不够……

答案4

我编写了一个脚本来监视上游 conf.d 文件夹的 dns 更改,并在检测到时重新加载 nginx。这是第一次尝试,肯定可以改进(下一次,我将使用 nginx -T 专门解析上游。同样的想法可以用于 proxy_pass 指令):

#!/bin/bash

get_upstreams() {
  local files=$@
  grep -hEo '(server\s+)[^:;]+' $files | cut -d' ' -f 2
}

resolve_hosts() {
  local hosts=$@
  for h in $hosts; do dig +short $h; done | sort -u
}

watch_dir=$1

[ -d $watch_dir ] || exit 2

upstreams=$(get_upstreams $watch_dir/*)
ips=$(resolve_hosts $upstreams)
if [ ! "$ips" ]; then
  echo "Found no resolvable hosts in $watch_dir files."
fi

host_hash=$(echo $ips | /usr/bin/sha512sum)

echo $host_hash
echo $ips

while [ -d $watch_dir ]; do
  sleep 30
  upstreams=$(get_upstreams $watch_dir/*)
  ips=$(resolve_hosts $upstreams)
  new_hash=$(echo $ips | /usr/bin/sha512sum)
  if [ "$host_hash" != "$new_hash" ]; then
    echo Detected an upstream address change.  $ips
    echo Reloading nginx
    echo $new_hash
    echo $ips
    /sbin/service nginx reload
    host_hash=$new_hash
  fi
done

相关内容