项目中有一个站点一直采用nginx反向代理将请求转发请求到源站的对应域名下,之前在第一次配置的时候,配置文件写法如下:
location / {
proxy_set_header Host xxx.abc.com;
proxy_set_header Accept-Encoding "gzip";
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass https://xxx.abc.com;
}
配置完成后,重启nginx,一切运行正常。
但是过了不知道多久,突然有一天这个比分站点不能访问了,服务器返回了这样一个提示:
Unable to locate the server named "localhost" --- the server does not have a DNS entry. Perhaps there is a misspelling in the server name, or the server no longer exists. Double-check the name and try again.
这个时候我用浏览器直接访问被代理的站点xxx.abc.com时,却是正常的,说明源站并没有问题,那问题出在哪里呢?
回到刚才的那个提示,里面的“DNS”让我很在意,会不会被代理的源站ip地址有变化,而nginx缓存了之前解析的ip地址,造成请求转发到了旧ip上,才会出现站点不能访问的情况?于是重启nginx,果然站点转发又正常了。查阅了一些资料后,了解到proxy_pass 后面跟域名的话并不是每次请求都会解析出这个域名的ip,而是会在第一次向proxy_pass要转发的对应域名发送请求时,通过操作系统的dns解析域名并缓存ip,这个缓存时间非常的长,记忆中这个缓存起码有2个月了。这也证实了我的想法。
那么如何才能让nginx不缓存这个解析出来的ip呢?或者是别缓存那么长的时间?
这个问题肯定不是我一个人遇到的,于是查询了一些资料,得到了解决办法。首先被转发的域名不能直接跟在proxy_pass的后面,而是要将域名赋值给一个变量,将变量配置在proxy_pass的后面,其次还要用resolver指定解析域名的dns,最后的配置内容如下:
resolver 172.18.7.1 172.18.7.2 valid=30s;
set $proxy_pass_url https://xxx.abc.com;
location / {
proxy_set_header Host xxx.abc.com;
proxy_set_header Accept-Encoding "gzip";
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass $proxy_pass_url;
}
其中resolver后面跟的是指定的dns地址,多个dns用空格隔开,valid用来配置解析的缓存时间,不配置的话则根据dns响应的TTL值缓存。
配置好重启测试,一切OK!我测试的时候用的是自己搭建的dns服务,通过在dns服务器上用tcpdump抓包,确认了nginx会根据配置的valid缓存时间来决定是否需要去dns服务器重新解析域名。
那么问题来了,如果在nginx对应的服务器上配置hosts,nginx会优先使用hosts配置来解析域名吗?
带着疑问,我特意在nginx的服务器上改了转发域名的hosts,让它指向一个错误的ip,重启nginx后,一切正常。这说明nginx不会去hosts文件找解析ip,这也是正常逻辑,否则nginx上的配置就显得太无力了,毕竟都特意配了dns地址了,nginx还是要相信配置才合理。
参考资料:http://nginx.org/en/docs/http/ngx_http_core_module.html#resolver
https://www.zhihu.com/question/61786355
https://www.rootop.org/pages/4307.html