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_pass
到IP频繁变化的DNS记录。 Nginx缓存过期的IP地址,从而导致对错误IP地址的请求。如何在过期时如何阻止Nginx缓存IP地址?
#1 楼
这是一个有趣的问题,并且AFAIK不能正常工作。您可以尝试使用上游模块,并使用指令进行故障转移,以查看其是否可以作为黑客使用。2018编辑:发生了很多变化。查看@ohaal的答案以获得有关此内容的真实信息。
评论
令人惊讶的是,当我转到上游时,一切都按预期进行。然后,我将其标记为正确答案
–xiamx
2011-2-27在22:20
根据文档,有一个特殊的上游服务器标志解析,仅在商业版本中可用(请参阅nginx.org/en/docs/http/ngx_http_upstream_module.html#server)
–omribahumi
15年7月19日在13:48
@gansbrest该网站似乎是垃圾邮件网站?我想请您删除您的回复。
– majikman
18年6月28日在0:02
令人遗憾的是,到2020年,上游模块仍无法解决此问题。一次解析地址并永远使用该地址是没有用的。
–菲尔
20年9月3日在8:23
#2 楼
在nginx / 1.4.2。上,已接受的答案对我不起作用。在
proxy_pass
中使用变量会强制重新解析DNS名称,因为NGINX将变量与静态配置不同地对待。从NGINX proxy_pass
文档:参数值可以包含变量。在这种情况下,如果将地址指定为域名,则在描述的服务器组中搜索该名称,如果找不到,则使用解析器确定该名称。
例如:
server {
...
resolver 127.0.0.1;
set $backend "http://dynamic.example.com:80";
proxy_pass $backend;
...
}
注意:解析器(即要使用的名称服务器)必须可用并且已配置为可以正常工作(而
/etc/hosts
文件中的条目将不可用) 默认情况下,版本1.1.9或更高版本的NGINX缓存使用响应的TTL值和可选的
valid
参数回答,从而可以覆盖缓存时间:resolver 127.0.0.1 [::1]:5353 valid=30s;
在版本1.1.9之前,无法调整缓存时间,nginx始终将答案缓存5分钟。.
评论
这不会在每个请求上强制进行dns查询吗?听起来像是糟糕的表现...
–lucascaro
2015年3月10日,下午3:42
不,请阅读源代码。在这种设置中,将动态查找“ foo.example.com”的ip地址,并将结果缓存5分钟。为了清楚起见,我将其添加到了答案中。
–ohaal
2015年3月10日在9:43
在花了我大部分时间后-在具有nginx 1.1.19的Ubuntu 12.04上,设置内部位置无法正常工作。谨防
–omribahumi
15年7月19日在13:38
注意:对于docker,它的DNS解析器位于127.0.0.11,因此对于开发人员,我使用此解析器:解析器127.0.0.11 [:: 1]:5353 valid = 15s;
– Dalibor Filus
18年6月1日在11:18
这是一个令人讨厌的陷阱,让我整整一天都无法调试:如果在proxy_pass指令中使用变量,则路径的解释会更改。执行此操作时,原始请求的路径将被完全覆盖,并替换为proxy_pass中给定的路径。您必须使用url中没有路径的proxy_pass以避免这种行为。
– Sam Svenbjorgchristiensensen
20年3月2日在1:02
#3 楼
但是最重要的评论和ohaal答案中都提供了有价值的信息。但是,我认为提及此官方的nginx文章很重要,该文章发表于2016年,它清楚地解释了nginx在此问题上的行为以及可能的解决方案:
https://www.nginx.com/blog/dns-service-discovery-nginx-plus/
我们确实必须“在变量中设置域名”并使用resolver指令。
但是,使用变量会更改重写行为。您可能必须使用rewrite指令,这取决于您的位置和proxy_pass设置。
PS:会发表评论,但积分不足...
#4 楼
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
注意,您需要安装
gettext
软件包,因为它提供了envsubst
命令。#5 楼
我已经整理了一个脚本来监视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=
[ -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
评论
查看nginx来源,似乎确实对nginx进行了硬编码以缓存其TTL的解析-动态DNS上的TTL是什么?我的ddns上的TTL是60秒,dyndns.com的默认值
另请参见stackoverflow.com/questions/26956979/…
相关:serverfault.com/questions/560632/…