文章转载自:https://segmentfault.com/a/1190000022365954

1 问题现象

我们使用 Nginx 的时候,经常会用到 Proxy 功能,为了方便管理,后端站点或者服务一般用域名来表示。

在运维过程中,有一次后端需要切换,按理说,只需要更改 DNS 解析到新的 IP 就能完成切换,然后发现更改 DNS 解析后,走 Nginx 怎么也访问不了后端,而在 Nginx 机器上直接 curl 后端是没有问题的。

问题找了半天发现是 Nginx 会缓存 DNS 解析,需要重载 Nginx 才会刷新。

2 问题重现

在测试机(centos6.5)上安装 Nginx(1.10.2),写入测试用的 Nginx Server 配置,配置非常简单,就是 www.test.com 转给 proxy.test.com,最后会返回 200 OK

server {

listen 80;

server_name www.test.com;

location / {
proxy_set_header Host proxy.test.com;
proxy_pass http://proxy.test.com;
}

}

server {

listen 80;

server_name proxy.test.com;

location / {
return 200 'OK';
}

}

然后在 /etc/hosts 文件下写入本地解析,www.test.com 解析到本机,proxy.test.com 解析到一个不存在的地址

127.0.0.1 www.test.com

10.10.10.114 proxy.test.com

重启 Nginx

/usr/sbin/nginx -s reload

执行测试,手动 curl www.test.com,访问不存在的 IP 会被 hang 住,最后超时并打印了一条错误日志

2020/04/14 10:10:09 [error] 21634#0: *3 upstream timed out (110: Connection timed out) while connecting to upstream, client: 127.0.0.1, server: www.test.com, request: "GET / HTTP/1.1", upstream: "http://10.10.10.114:80/", host: "www.test.com"

这个时候,我们再调整 hosts 文件,改为正确的 IP

127.0.0.1 www.test.com

127.0.0.1 proxy.test.com

然后再手动 curl www.test.com,发现还是被 hang 住,查看日志,发现超时日志里面写的还是旧 IP

2020/04/14 10:17:30 [error] 21634#0: *5 upstream timed out (110: Connection timed out) while connecting to upstream, client: 127.0.0.1, server: www.test.com, request: "GET / HTTP/1.1", upstream: "http://10.10.10.114:80/", host: "www.test.com"

使用 /usr/sbin/nginx -s reload 命令重载 Nginx,刷新缓存,再次请求 curl www.test.com,就没有问题了

3 问题探索

我也没看过 Nginx 代码,对于 DNS 缓存问题还是只能手动探索

3.1 什么时候缓存的

常用 Nginx 的同学都知道,如果 Nginx proxy_pass 里面的域名不能解析的话,是无法启动 Nginx 的,我看网友说启动的时候仅仅是检测是否能解析,只有在第一次请求的时候才会缓存,那么还是手动测试一下。

先设置为错误 IP,并重启 Nginx

[root@chengqm ~]# grep 'proxy.test.com' /etc/hosts

10.10.10.114 proxy.test.com

[root@chengqm ~]# /etc/init.d/nginx restart

Stopping nginx: [ OK ]

Starting nginx: [ OK ]

在没有请求前,把解析改为正确 IP

[root@chengqm ~]# sed -i 's#10.10.10.114 proxy.test.com#127.0.0.1 proxy.test.com#g' /etc/hosts

[root@chengqm ~]# grep 'proxy.test.com' /etc/hosts

127.0.0.1 proxy.test.com

首次请求

[root@chengqm ~]# curl www.test.com

还是 hang 住并打印一条日志

2020/04/14 10:32:55 [error] 23405#0: *1 upstream timed out (110: Connection timed out) while connecting to upstream, client: 127.0.0.1, server: www.test.com, request: "GET / HTTP/1.1", upstream: "http://10.10.10.114:80/", host: "www.test.com"

结论: 在 1.10.2 版本 Nginx 中,启动 Nginx 的时候就会缓存 DNS 解析,其他版本还没有试。

3.2 DNS轮询情况下,会不会只缓存一个

既然 Nginx 会做 DNS 缓存,那么使用 DNS 轮询的情况下,只缓存第一个解析的 IP 还是所有,我们来测试一下。

在本机搭建 Named 服务,并加上两个域名的解析,其中,proxy.test.com 使用了 DNS 轮询,一个是错误 IP,一个是正确IP

www IN A 127.0.0.1

proxy IN A 127.0.0.1

proxy IN A 10.10.10.114

本地 DNS 地址指向本机

[root@chengqm ~]# cat /etc/resolv.conf

nameserver 127.0.0.1

重启 Nginx

[root@chengqm ~]# /etc/init.d/nginx restart

Stopping nginx: [ OK ]

Starting nginx: [ OK ]

手动请求 www.test.com,可以看到,第一次请求成功,第二次卡了一段时间后返回成功

查看第二次请求的日志,发现有一个失败的和成功的,意味着 Nginx 确实去请求了错误的 IP,当不通的时候就会换下一个 IP 进行请求

结论: Nginx 会缓存所有 DNS 解析

4 缓存问题的解决方案

4.1 每次更改 DNS 解析都重载 Nginx

重载 Nginx 一定会刷新缓存,这是最保险也是最麻烦的一种方案,如果体量小还可以接受,如果 Nginx 实例比较多就有些困难,除非有批量运维工具帮忙。

4.2 使用 Nginx 的 resolver

我们在使用 Nginx 过程中,有时需要根据 Url 传值动态选择 host 进行代理转发,这种模式下,一开始是不会去进行 DNS 解析的,只有请求的时候才会进行 DNS 解析,并且要设置 resolver 指定 DNS 服务器 IP。

这个时候,我们就可以使用 resolver 语法来解决 DNS 缓存的问题,比如说,我在原来的 Nginx 配置里指定 DNS IP,并设置缓存 60 秒。

server {

listen 80;

server_name www.test.com;

resolver 127.0.0.1 valid=60s;
resolver_timeout 3s; set $proxy_url "proxy.test.com";
location / {
proxy_set_header Host proxy.test.com;
proxy_pass http://$proxy_url;
}

}

4.3 使用模块nginx-upstream-dynamic-servers

模块地址: nginx-upstream-dynamic-servers

该模块在第一次启动的时候会进行一次解析,解析完后,在 DNS 服务器设定的 TTL 过期时间内不会再次更新,过期后会再次发起解析请求

使用方法

http {

resolver 8.8.8.8;

upstream example {

server example.com resolve;

}

}

使用这种方法的时候,DNS TTL 时间需要设置短一些。

4.4 使用模块 ngx_upstream_jdomain

文档对应地址: domain_resolve

ngx_upstream_jdomain 模块是一个依赖 DNS 解析实现的 upstream 负载均衡,该模式下,允许使用域名来写 upstream 后端。该模块默认情况下,会每秒做一次 DNS 解析,使用方法如下

http {

resolver 8.8.8.8;

resolver_timeout 10s;

upstream backend {
jdomain www.baidu.com port=80 interval=5; # 每 5 秒解析一次
}
server {
listen 8080; location / {
proxy_pass http://backend;
}
}

}

4.5 使用其他版本 Nginx

Tengine Tengine 的 ngx_http_upstream_dynamic 模块可以提供动态的 DNS 解析
NGINX Plus Plus版本提供了动态解析的语法

Nginx缓存了DNS解析造成后端不通--代理的更多相关文章

  1. 《nginx 一》dns解析 nginx安装

    DNS域名解析 整个过程大体描述如下,其中前两个步骤是在本机完成的,后8个步骤涉及到真正的域名解析服务器:1.浏览器会检查缓存中有没有这个域名对应的解析过的IP地址,如果缓存中有,这个解析过程就结束. ...

  2. 分析DNS解析时间

    提高网页的打开速度,一般地我们会选择使用CDN,利用“就近原则”让用户在最短的时间内获取到服务器资源,实际应用当中采用CDN的方式提高网站访问速度的效果也是最明显的.这也就是为什么国外的空间打开速度远 ...

  3. 我眼中的 Nginx(六):深入 Nginx/Openresty 服务里的 DNS 解析

    张超:又拍云系统开发高级工程师,负责又拍云 CDN 平台相关组件的更新及维护.Github ID: tokers,活跃于 OpenResty 社区和 Nginx 邮件列表等开源社区,专注于服务端技术的 ...

  4. nginx无网络启动失败——proxy_pass域名DNS解析出错

    问题: nginx启动或者reload的时候,会对proxy_pass后面的域名进行DNS解析,如果解析失败,启动就会失败或者reload失败. 我们是to B的产品,客户的环境可能是不通公网的,因此 ...

  5. 刷新DNS解析缓存

    为了提高网站的访问速度,系统会在成功访问某网站后将该网站的域名.IP地址信息缓存到本地.下次访问该域名时直接通过IP进行访问. 一些网站的域名没有变化,但IP地址发生变化,有可能因本地的DNS缓存没有 ...

  6. 浏览器 DNS缓存与DNS prefetch (DNS预解析)

    浏览器 DNS缓存 浏览器DNS缓存的时间跟DNS服务器返回的TTL值无关. 注:TTL(Time-To-Live),就是一条域名解析记录在DNS服务器中的存留时间. 浏览器在获取网站域名的实际IP地 ...

  7. Service系统服务(四):搭建单区域DNS服务器、特殊DNS解析、配置DNS子域授权、搭建并测试缓存DNS

    一.搭建单区域DNS服务器 目标: 本例要求要求为DNS区域tedu.cn搭建一台DNS服务器,以便用户能通过域名的方式访问网站.测试阶段主要提供以下正向记录: svr7.tedu.cn ---> ...

  8. 清除DNS解析缓存

    接下来在弹出的命令提示符窗口中输入“ipconfig /displaydns”,我们会看到系统中有多条我们之前使用过的DNS地址,如下图所示 5 然后,我们接着输入命令“ipconfig /flush ...

  9. 刷新DNS解析缓存+追踪+域名解析命令

    刷新DNS解析缓存 命令:ipconfig /flushdns 用于改完host之后. 追踪IP: 命令:tracert www.baidu.com 域名解析: 命令:nslookup www.bai ...

随机推荐

  1. pyinstaller打包一些三方库后,报资源不存在

    在目录site-packages\PyInstaller\hooks下新建对应文件hook-对应三方库名字.py,如hook-ngender.py 编辑hook-ngender.py: from Py ...

  2. 千万小心,99%的Java程序员会踩这些坑

    前言 作为Java程序员的你,不知道有没有踩过一些基础知识的坑. 有时候,某个bug查了半天,最后发现竟然是一个低级错误. 有时候,某些代码,这一批数据功能正常,但换了一批数据就出现异常了. 有时候, ...

  3. 【Codeforces1706A】 Another String Minimization Problem

    官方标签 贪心.字符串 题目描述 输入 输出 样例输入 6 4 5 1 1 3 1 1 5 2 4 1 1 1 1 1 2 4 1 3 2 7 7 5 4 5 5 5 3 5 样例输出 ABABA B ...

  4. SpringBoot到底是什么?

    摘要:Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程. 本文分享自华为云社区<SpringBoot到底是什么?如何理解p ...

  5. 聊聊 C++ 中的几种智能指针 (下)

    一:背景 上一篇我们聊到了C++ 的 auto_ptr ,有朋友说已经在 C++ 17 中被弃用了,感谢朋友提醒,今天我们来聊一下 C++ 11 中引入的几个智能指针. unique_ptr shar ...

  6. AtCoder Beginner Contest 260 G // imos(累积和算法)

    题目传送门:G - Scalene Triangle Area (atcoder.jp) 题意: 给定大小为N*N的OX矩阵,若矩阵的(s,t)处为O,其覆盖范围为:满足以下条件的所有位置(i,j) ...

  7. 别梦依稀咒逝川,Ruby二十八年前|M1芯片Mac os系统配置Ruby(3.0.0) on Rails(6.1.1)开发环境(2021最新攻略)

    原文转载自「刘悦的技术博客」https://v3u.cn/a_id_188 在每个开发者心里,都会有一门"最好"的语言,在这个世界的某个深处,在一些矫矫不群的人们心中,这门语言的名 ...

  8. Java版的防抖(debounce)和节流(throttle)

    概念 防抖(debounce) 当持续触发事件时,一定时间段内没有再触发事件,事件处理函数才会执行一次,如果设定时间到来之前,又触发了事件,就重新开始延时. 防抖,即如果短时间内大量触发同一事件,都会 ...

  9. 【Java面试】怎么防止缓存击穿的问题?

    "怎么防止缓存击穿?" 这是很多一二线大厂面试的时候考察频率较高的问题. 在并发量较高的系统中,缓存可以提升数据查询的性能,还能缓解后端存储系统的并发压力.可谓是屡试不爽的利器. ...

  10. 完整代码:安卓小软件“CSV联系人导入导出工具”

    完整代码:安卓小软件"CSV联系人导入导出工具" 开发了一个安卓小软件"CSV联系人导入导出工具",欢迎测试.本软件可以帮你快速备份和恢复联系人,不用担心号码遗 ...