Nginx的DNS缓存问题

Cache Problem of Dns in Nginx

在使用Nginx作为反向代理服务器时,有时会遇到DNS缓存问题,导致后端服务IP变化后就无法访问,本文介绍一下如何处理这个问题。

问题场景

下面是一个常见的Nginx配置示例:

server { listen 80; server_name qzy.im; location / { proxy_pass http://some-domain.qzy.im; } }

在这个示例中,Nginx会监听 qzy.im 域名上的 80 端口,然后将路径下的所有请求都转发到 http://some-domain.qzy.im 上。如果域名 some-domain.qzy.im 的IP不会发生变化,那么上面的配置就不会出现问题。

但是,如果 some-domain.qzy.im 的IP是会变化的,那么一旦IP发生变化,服务就无法访问了,这是为什么呢?

问题原因

问题就出在Nginx的DNS缓存上。正常情况下,如果 proxy_pass 后指定的主机使用的是域名,那么Nginx就只会在载入配置的时候解析一次该域名对应的IP,后续请求都会发到这个IP上。即使该域名的IP发生了变化,Nginx也不会向新的IP上转发请求。

解决办法一

如果指定域名的IP变化频率很低,或者说只有人为解析会导致IP变化,那么就可以使用这个最简单的办法。IP变化后执行命令,让Nginx重新加载配置文件即可:

nginx -s reload

解决办法二

如果指定域名的IP变化的频率高,那么解决办法一就很麻烦,这个时候就可以使用这个办法。Nginx提供了设置DNS缓存过期时间的功能,配置方式如下:

resolver <DNS服务器地址(多个地址之间用空格分隔)> valid=<缓存过期时间>; set $host_name "<主机地址>"; proxy_pass $host_name;

上面第1行代码用来配置DNS服务器和缓存过期时间,第2行将需要转发的主机地址设置到一个变量中,最后第3行就实现代理转发。我们将问题场景中的配置改成如下:

server { listen 80; server_name qzy.im; resolver 114.114.114.114 8.8.8.8 valid=10s; set $host_name "http://some-domain.qzy.im"; location / { proxy_pass $host_name; } }

这样,每次通过 proxy_pass 转发请求前,Nginx就会检查 some-domain.qzy.im 的DNS是否过期(上面设置的过期时间值 valid 是10s),如果过期了Nginx就会从DNS服务器获取最新的IP,然后再进行转发。

注意:必须通过一个变量(例如上面的 $host_name)来设置代理,如果直接写成 proxy_pass <主机地址>,则Nginx只会在载入配置的时候解析一次,后面就不会自动刷新了。

参考资源

https://nginx.org/en/docs/http/ngx_http_core_module.html#resolver

https://www.nginx.com/blog/dns-service-discovery-nginx-plus/

文章评论
${fromAuthor ? '郄正元' : '游客'} 作者 ${gmtCreate}
${content}
${subList.length}
发表评论
${commentToArticle ? '' : parentContent}
字数:0/${maxCommentLength}
该邮箱地址仅用于接收其他用户的回复提醒,不会泄露