• 欢迎访问举个栗子网站
  • 小说APP下载 xsz.tw 不带广告的小说站

解决nginx反代ddns的一个问题

程序 举个栗子 1年前 (2018-04-17) 724次浏览 0个评论 扫描二维码

如题,使用 nginx 做反向代理,将请求发送到一个域名(例如: proxy_pass http://www.lizi.tw  该域名对应的 IP 是 A) ,刚开始运行一切正常,但是当运行了一段时间以后,域名对应的 IP 变了(例如 http://www.lizi.tw 对应的 IP 由 A 变为 B),nginx 的转发仍然还在向原先的 IP 发送请求,导致业务中断,此时 reload nginx 后才会重新恢复正常,且日志显示数据转发到新的 IP B 了,请问如何让 nginx 自动去重新解析域名,而不用每次出现问题了人工去 reload? 请大神指点

作者:黑板擦
链接:https://www.zhihu.com/question/61786355/answer/268735267
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

时隔几个月,遇到了其他问题,忽然找到了解决这个问题的方法,现在分享一下背景:此处只针对 nginx 向后端做代理,且后端代理为域名形式 的这种情况做分析

1、正常情况下 启动 nginx 后(或者 -t / reload nginx 时),nginx 会通过操作系统配置的 DNS 服务器去解析域名对应的 IP

2、当 nginx 配置文件中的所有涉及到的域名都可以被正常解析到以后,才能启动(或者检查/重新加载)通过

3、这里需要提醒一点,在 ../sbin/nginx -t 或者 ../sbin/ngins -s reload 只是检查域名是否可以解析通过,并不会在此时缓存域名对应 IP,只有在通过 nginx 第一次向proxy_pass 后端对应的域名做代理数据转发时,这里 nginx 会通过操作系统配置的 DNS 服务器解析域名,此时才会缓存域名对应的 IP,且会缓存很长时间,甚至一个月(整个过程均有生产实例证明,且抓包验证)

我遇到的问题:

生产的实例

1、我们内网的数据通过 nginx 转发到第三方合作公司对应的域名,此处简称为 域名 A

2、第三方公司的域名 A 做了 CDN,对应多个 IP(IP1,IP2,IP3…),且随时都有可能因某种原因,丢弃其中一个 IP

3、某一天该第三方公司将他们的域名 A 对应的地址 IP3 废弃不用了,域名不再往 IP3 上解析了

4、但是我们的 nginx 因为曾经请求域名 A 时缓存了 IP3,导致后续的许多交易数据仍旧是给 IP3 发送,造成交易失败,这种情况在我们没有 reload nginx 之前,存在了 2 周左右,说明 nginx 缓存这个 IP3 缓存了很长时间,这就是造成了我们交易失败的原因(当时排查了好几天),后来多方联系核对后,才知道第三方公司早在 3 周前就废弃了这个 IP3,(可能为了全网的 DNS 都刷新,域名 A 不再向 IP3 解析后,但是 IP3 所对应的服务器还继续沿用了一段时间,所以我们是在废弃后的第二周才开始报错)

分析与解决:

1、既然是因为 nginx 缓存域名对应 IP 的 DNS 记录造成的,那么怎么才能解决呢,方法有两种:

(1)、手动 reload nginx,让 nginx 重新解析域名,这个时候解析到域名对应的 IP 是最新的,不会包含已经被废弃的 IP3

(2)、设置 nginx 的 DNS 缓存时间,比如 600s 失效,然后重新去解析

2、方法(2)当然是最好的,但是 nginx 的 DNS 缓存时间在哪里设置呢,我没有找到!

3、但是我找到另外一种方法 — nginx 的 resolvernginx 的 resolver

解决方案

1、默认 nginx 会通过操作系统设置的 DNS 服务器(/etc/resolv.conf)去解析域名

2、其实 nginx 还可以通过自身设置 DNS 服务器,而不用去找操作系统的 DNS

3、下面来讲一个这个 resolver 示例配置如下:

server {
       listen      8080;
       server_name localhost;
       resolver 114.114.114.114 223.5.5.5 valid=3600s;
       resolver_timeout 3s;
       set $qq "**";
       location / {
          <a href="https://www.lizi.tw/tag/proxy" title="查看更多关于 proxy 的文章" target="_blank">proxy</a>_pass http://$qq;
       }
   }

参数说明:

# resolver 可以在 http 全局设定,也可在 server 里面设定
# resolver 后面指定 DNS 服务器,可以指定多个,空格隔开
# valid 设置 DNS 缓存失效时间,自己根据情况判断,建议 600 以上
# resolver_timeout 指定解析域名时,DNS 服务器的超时时间,建议 3 秒左右

#注意:当 resolver 后面跟多个 DNS 服务器时,一定要保证这些 DNS 服务器都是有效的,因为这种是负载均衡模式的,当 DNS 记录失效了(超过 valid 时间),首先由第一个 DNS 服务器(114.114.114.114)去解析,下一次继续失效时由第二个 DNS 服务器(223.5.5.5)去解析,亲自测试的,如有任何一个 DNS 服务器是坏的,那么这一次的解析会一直持续到 resolver_timeout ,然后解析失败,且日志报错解析不了域名,通过页面抛出 502 错误。

#重点:如上例,在代理到后端域名 http://**时,千万不要直接写在 proxy_pass 中,因为 server 中使用了 resolver,所以必须先把域名定义到一个变量里面,然后在 proxy_pass http://$变量名,否则 nginx 语法检测一直会报错,提示解析不了域名

后记

整个过程亲测,没有问题如果有其他更好的方式或者见解,请回复一起探讨哈

http://nginx.org/en/docs/http/ngx_http_core_module.html


举个栗子 , 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:解决 nginx 反代 ddns 的一个问题
喜欢 (0)
举个栗子
关于作者:
建筑工地上施工员,闲暇时弄个博客打发时间,
发表我的评论
取消评论
表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址