[转帖]《Linux性能优化实战》笔记(十九)—— DNS 解析原理与故障案例分析
一、 域名与 DNS 解析
域名主要是为了方便让人记住,而 IP 地址是机器间的通信的真正机制。以 time.geekbang.org 为例,最后面的 org 是顶级域名,中间的 geekbang 是二级域名,而最左边的 time 则是三级域名。点(.)是所有域名的根,所有域名都以点作为后缀。
把域名转换为 IP 地址的服务,就是域名解析服务(DNS)。对应的服务器就是域名服务器,网络协议则是 DNS 协议。DNS 协议在 TCP/IP 栈中属于应用层,不过实际传输还是基于 UDP 或者 TCP协议(UDP 居多) ,并且域名服务器一般监听在端口 53 上。
既然域名以分层的结构进行管理,相对应的,域名解析也是用递归的方式,发送给每个层级的域名服务器,直到得到解析结果。通常来说,每级 DNS 服务器都会有最近解析记录的缓存。当缓存命中时,直接用缓存中的记录应答;如果缓存过期或者不存在,才需要用刚刚提到的递归方式查询。
所以,系统管理员在配置 Linux 系统的网络时,除了需要配置 IP 地址,还需要配置DNS 服务器,这样才可以通过域名来访问外部服务。可以执行下面的命令来查询你的DNS配置
-
$ cat /etc/resolv.conf
-
nameserver 114.114.114.114
另外,DNS 服务通过资源记录的方式,来管理所有数据,它支持 A、CNAME、MX、NS、PTR 等多种类型的记录。比如
A 记录,用来把域名转换成 IP 地址;CNAME 记录,用来创建别名; NS 记录,则表示该域名对应的域名服务器地址。
比如以 time.geekbang.org 为例,执行下面的 nslookup 命令,就可以查询到这个域名的 A 记录,可以看到,它的 IP 地址是 39.106.233.176:
-
$ nslookup time.geekbang.org
-
# 域名服务器及端口信息
-
Server: 114.114.114.114
-
Address: 114.114.114.114#53
-
-
# 非权威查询结果
-
Non-authoritative answer:
-
Name: time.geekbang.org
-
Address: 39.106.233.17
这里要注意,由于 114.114.114.114 并不是直接管理 time.geekbang.org 的域名服务器,所以查询结果是非权威的。使用上面的命令,你只能得到 114.114.114.114 查询的结果。
前面还提到,如果没有命中缓存,DNS 查询实际上是一个递归过程,那有没有方法可以知道整个递归查询的执行呢?其实除了 nslookup,另外一个常用的 DNS 解析工具 dig ,就提供了 trace 功能,可以展示递归查询的整个过程。
# +trace表示开启跟踪查询 # +nodnssec表示禁止DNS安全扩展 $ dig +trace +nodnssec time.geekbang.org ; <<>> DiG 9.11.3-1ubuntu1.3-Ubuntu <<>> +trace +nodnssec time.geekbang.org ;; global options: +cmd . 322086 IN NS m.root-servers.net. . 322086 IN NS a.root-servers.net. . 322086 IN NS i.root-servers.net. . 322086 IN NS d.root-servers.net. . 322086 IN NS g.root-servers.net. . 322086 IN NS l.root-servers.net. . 322086 IN NS c.root-servers.net. . 322086 IN NS b.root-servers.net. . 322086 IN NS h.root-servers.net. . 322086 IN NS e.root-servers.net. . 322086 IN NS k.root-servers.net. . 322086 IN NS j.root-servers.net. . 322086 IN NS f.root-servers.net. ;; Received 239 bytes from 114.114.114.114#53(114.114.114.114) in 1340 ms org. 172800 IN NS a0.org.afilias-nst.info. org. 172800 IN NS a2.org.afilias-nst.info. org. 172800 IN NS b0.org.afilias-nst.org. org. 172800 IN NS b2.org.afilias-nst.org. org. 172800 IN NS c0.org.afilias-nst.info. org. 172800 IN NS d0.org.afilias-nst.org. ;; Received 448 bytes from 198.97.190.53#53(h.root-servers.net) in 708 ms geekbang.org. 86400 IN NS dns9.hichina.com. geekbang.org. 86400 IN NS dns10.hichina.com. ;; Received 96 bytes from 199.19.54.1#53(b0.org.afilias-nst.org) in 1833 ms time.geekbang.org. 600 IN A 39.106.233.176 ;; Received 62 bytes from 140.205.41.16#53(dns10.hichina.com) in 4 ms
- 第一部分,是从 114.114.114.114 查到的一些根域名服务器(.)的 NS 记录。
- 第二部分,是从 NS 记录结果中选一个(h.root-servers.net),并查询顶级域名 org.的 NS 记录。
- 第三部分,是从 org. 的 NS 记录中选择一个(b0.org.afilias-nst.org),并查询二级域名 geekbang.org. 的 NS 服务器。
- 最后一部分,就是从 geekbang.org. 的 NS 服务器(dns10.hichina.com)查询最终主机 time.geekbang.org. 的 A 记录。
这个输出里展示的各级域名的 NS 记录,其实就是各级域名服务器的地址,可以让你更清楚DNS 解析的过程。
很多时候,我们也希望能对局域网内部的主机进行域名解析,可以把主机名和 IP 地址的映射关系,写入本机的 /etc/hosts 文件中。这样,指定的主机名就可以在本地直接找到目标 IP。
-
$ cat /etc/hosts
-
127.0.0.1 localhost localhost.localdomain
-
::1 localhost6 localhost6.localdomain6
-
192.168.0.100 domain.com
或者,你还可以在内网中,搭建自定义的 DNS 服务器,专门用来解析内网中的域名。而内网 DNS 服务器,一般还会设置一个或多个上游 DNS 服务器,用来解析外网的域名。
清楚域名与 DNS 解析的基本原理后,接下来,我就带你一起来看几个案例,实战分析DNS 解析出现问题时,该如何定位。
二、 案例分析
案例 1:DNS 解析失败
例如执行 nslookup time.geekbang.org 报错
-
nslookup time.geekbang.org
-
#报错如下
-
;; connection timed out; no servers could be reached
这个命令阻塞很久后,还是失败了,报了 connection timed out 和 no servers could be reached 错误。看到这里,估计你的第一反应就是网络不通了,到底是不是这样呢?我们用 ping 工具检查试试。
-
ping -c3 114.114.114.114
-
-
PING 114.114.114.114 (114.114.114.114): 56 data bytes
-
64 bytes from 114.114.114.114: icmp_seq=0 ttl=56 time=31.116 ms
-
64 bytes from 114.114.114.114: icmp_seq=1 ttl=60 time=31.245 ms
-
64 bytes from 114.114.114.114: icmp_seq=2 ttl=68 time=31.128 ms
-
--- 114.114.114.114 ping statistics ---
-
3 packets transmitted, 3 packets received, 0% packet loss
-
round-trip min/avg/max/stddev = 31.116/31.163/31.245/0.058 ms
这个输出中,你可以看到网络是通的。
要怎么知道 nslookup 命令失败的原因呢?这里其实有很多方法,最简单的一种,就是开启 nslookup 的调试输出,查看查询过程中的详细步骤,排查其中是否有异常。
-
nslookup -debug time.geekbang.org
-
#输出
-
;; Connection to 127.0.0.1 #53(127.0.0.1) for time.geekbang.org failed: connection refused.
-
;; Connection to ::1 #53(::1) for time.geekbang.org failed: address not available.
可以看到,nslookup 连接环回地址(127.0.0.1 和 ::1)的 53 端口失败。这里就有问题了,为什么会去连接环回地址?
你可能已经想到了症结所在——可能是因为没有配置 DNS 服务器。那我们就执行下面的命令确认一下:
cat /etc/resolv.conf
果然,这个命令没有任何输出,说明的确没有配置 DNS 服务器。
到这一步,很自然的,我们就知道了解决方法。在 /etc/resolv.conf 文件中,配置上 DNS 服务器就可以了。配置好后,重新执行 nslookup 命令。自然,我们现在发现,这次可以正常解析了:
-
echo "nameserver 114.114.114.114" > /etc/resolv.conf
-
nslookup time.geekbang.org
-
#输出
-
Server: 114.114.114.114
-
Address: 114.114.114.114#53
-
-
Non-authoritative answer:
-
Name: time.geekbang.org
-
Address: 39.106.233.176
案例 2:DNS 解析不稳定
还是运行 nslookup 命令,解析 time.geekbang.org 的 IP 地址。不过,这次要加一个 time 命令,输出解析所用时间。
-
time nslookup time.geekbang.org
-
#输出
-
Server: 8.8.8.8
-
Address: 8.8.8.8#53
-
-
Non-authoritative answer:
-
Name: time.geekbang.org
-
Address: 39.106.233.176
-
-
real 0m10.349s
-
user 0m0.004s
-
sys 0m0.0
可以看到,这次解析非常慢,居然用了 10 秒。如果多次运行上面的 nslookup 命令,可能偶尔还会碰到下面这种错误:
-
time nslookup time.geekbang.org
-
#输出
-
;; connection timed out; no servers could be reached
-
-
real 0m15.011s
-
user 0m0.006s
-
sys 0m0.006s
换句话说,跟上一个案例类似,也会出现解析失败的情况。综合来看,现在 DNS 解析的结果不但比较慢,而且还会发生超时失败的情况。这是为什么呢?碰到这种问题该怎么处理呢?
其实,根据前面的讲解,我们知道,DNS 解析,说白了就是客户端与服务器交互的过程,并且这个过程还使用了 UDP 协议。那么,对于整个流程来说,解析结果不稳定,就有很多种可能的情况了。比方说:
- DNS 服务器本身有问题,响应慢并且不稳定;
- 客户端到 DNS 服务器的网络延迟比较大;
- DNS 请求或者响应包,在某些情况下被链路中的网络设备弄丢了
根据上面 nslookup 的输出,可以看到,现在客户端连接的 DNS 是 8.8.8.8,这是Google 提供的 DNS 服务,出问题的概率
应该比较小。基本排除了第一个可能。那是不是本机到 DNS 服务器的延迟比较大呢?
可以用ping 来测试服务器的延迟。比如,你可以运行下面的命令:
-
ping -c3 8.8.8.8
-
#输出
-
PING 8.8.8.8 (8.8.8.8): 56 data bytes
-
64 bytes from 8.8.8.8: icmp_seq=0 ttl=31 time=137.637 ms
-
64 bytes from 8.8.8.8: icmp_seq=1 ttl=31 time=144.743 ms
-
64 bytes from 8.8.8.8: icmp_seq=2 ttl=31 time=138.576 ms
-
--- 8.8.8.8 ping statistics ---
-
3 packets transmitted, 3 packets received, 0% packet loss
-
round-trip min/avg/max/stddev = 137.637/140.319/144.743/3.152 ms
从 ping 的输出可以看到,延迟已经达到了 140ms,这也就可以解释,为什么解析这么慢了。实际上,如果你多次运行上面的 ping 测试,还会看到偶尔出现的丢包现象。
-
ping -c3 8.8.8.8
-
#输出
-
PING 8.8.8.8 (8.8.8.8): 56 data bytes
-
64 bytes from 8.8.8.8: icmp_seq=0 ttl=30 time=134.032 ms
-
64 bytes from 8.8.8.8: icmp_seq=1 ttl=30 time=431.458 ms
-
--- 8.8.8.8 ping statistics ---
-
3 packets transmitted, 2 packets received, 33% packet loss
-
round-trip min/avg/max/stddev = 134.032/282.745/431.458/148.713 ms
这也进一步解释了,为什么 nslookup 偶尔会失败,正是网络链路中的丢包导致的。碰到这种问题该怎么办呢?显然,既然延迟太大,那就换一个延迟更小的 DNS 服务器,比如电信提供的 114.114.114.114。
配置之前,我们可以先用 ping 测试看看,它的延迟是不是真的比 8.8.8.8 好。可以看到,它的延迟只有 31ms:
-
ping -c3 114.114.114.114
-
#输出
-
PING 114.114.114.114 (114.114.114.114): 56 data bytes
-
64 bytes from 114.114.114.114: icmp_seq=0 ttl=67 time=31.130 ms
-
64 bytes from 114.114.114.114: icmp_seq=1 ttl=56 time=31.302 ms
-
64 bytes from 114.114.114.114: icmp_seq=2 ttl=56 time=31.250 ms
-
--- 114.114.114.114 ping statistics ---
-
3 packets transmitted, 3 packets received, 0% packet loss
-
round-trip min/avg/max/stddev = 31.130/31.227/31.302/0.072 ms
这个结果表明,延迟的确小了很多。我们继续执行下面的命令,更换 DNS 服务器,然后,再次执行 nslookup 解析命令:
-
echo nameserver 114.114.114.114 > /etc/resolv.conf
-
time nslookup time.geekbang.org
-
#输出
-
Server: 114.114.114.114
-
Address: 114.114.114.114#53
-
-
Non-authoritative answer:
-
Name: time.geekbang.org
-
Address: 39.106.233.176
-
-
real 0m0.064s
-
user 0m0.007s
-
sys 0m0.006s
你可以发现,现在只需要 64ms 就可以完成解析,比刚才的 10s 要好很多。到这里,问题看似就解决了。不过,如果你多次运行 nslookup 命令,估计就不是每次都有好结果了。比如,在我的机器中,就经常需要 1s 甚至更多的时间。
-
time nslookup time.geekbang.org
-
#输出
-
Server: 114.114.114.114
-
Address: 114.114.114.114#53
-
-
Non-authoritative answer:
-
Name: time.geekbang.org
-
Address: 39.106.233.176
-
-
real 0m1.045s
-
user 0m0.007s
-
sys 0m0.004s
案例 3:利用 DNS 缓存继续优化
1s 的 DNS 解析时间还是太长了,对很多应用来说也是不可接受的。该怎么解决这个问题呢?我想你一定已经想到了,那就是使用 DNS 缓存。这样,只有第一次查询时需要去 DNS 服务器请求,以后的查询,只要 DNS 记录不过期,使用缓存中的记录就可以了。
不过要注意,除了最新版本的 Ubuntu(18.04及以上)外,其他版本并没有自动配置 DNS 缓存。所以,想要为系统开启 DNS 缓存,就需要你做额外的配置。比如,最简单的方法,就是使用 dnsmasq。
dnsmasq 是最常用的 DNS 缓存服务之一,还经常作为 DHCP 服务来使用。它的安装和配置都比较简单,性能也可以满足绝大多数应用程序对 DNS 缓存的需求。执行下面的命令,就可以启动 dnsmasq:
-
/etc/init.d/dnsmasq start
-
#输出
-
* Starting DNS forwarder and DHCP server dnsmasq [ OK ]
然后,修改 /etc/resolv.conf,将 DNS 服务器改为 dnsmasq 的监听地址,这儿是127.0.0.1。接着,重新执行多次 nslookup 命令:
echo nameserver 127.0.0.1 > /etc/resolv.conf time nslookup time.geekbang.org #输出 Server: 127.0.0.1 Address: 127.0.0.1#53 Non-authoritative answer: Name: time.geekbang.org Address: 39.106.233.176 real 0m0.492s user 0m0.007s sys 0m0.006s time nslookup time.geekbang.org #输出 Server: 127.0.0.1 Address: 127.0.0.1#53 Non-authoritative answer: Name: time.geekbang.org Address: 39.106.233.176 real 0m0.011s user 0m0.008s sys 0m0.003s
可以看到,只有第一次的解析很慢,需要 0.5s,以后的每次解析都很快,只需要11ms,并且后面每次 DNS 解析需要的时间也都很稳定。
[转帖]《Linux性能优化实战》笔记(十九)—— DNS 解析原理与故障案例分析的更多相关文章
- 深挖计算机基础:Linux性能优化学习笔记
参考极客时间专栏<Linux性能优化实战>学习笔记 一.CPU性能:13讲 Linux性能优化实战学习笔记:第二讲 Linux性能优化实战学习笔记:第三讲 Linux性能优化实战学习笔记: ...
- Linux性能优化实战学习笔记:第三十六讲
一.上节总结回顾 上一节,我们回顾了经典的 C10K 和 C1000K 问题.简单回顾一下,C10K 是指如何单机同时处理 1 万个请求(并发连接 1 万)的问题,而 C1000K 则是单机支持处理 ...
- Linux性能优化实战学习笔记:第四十五讲
一.上节回顾 专栏更新至今,四大基础模块的最后一个模块——网络篇,我们就已经学完了.很开心你还没有掉队,仍然在积极学习思考和实践操作,热情地留言和互动.还有不少同学分享了在实际生产环境中,碰到各种性能 ...
- Linux性能优化实战学习笔记:第四十六讲
一.上节回顾 不知不觉,我们已经学完了整个专栏的四大基础模块,即 CPU.内存.文件系统和磁盘 I/O.以及网络的性能分析和优化.相信你已经掌握了这些基础模块的基本分析.定位思路,并熟悉了相关的优化方 ...
- Linux性能优化实战学习笔记:第二十八讲
一.案例环境描述 1.环境准备 2CPU,4GB内存 预先安装docker sysstat工具 apt install docker.io sysstat nake git 案例总共由三个容器组成: ...
- Linux性能优化实战学习笔记:第三十二讲
一.上节总结 专栏更新至今,四大基础模块的第三个模块——文件系统和磁盘 I/O 篇,我们就已经学完了.很开心你还没有掉队,仍然在积极学习思考和实践操作,并且热情地留言与讨论. 今天是性能优化的第四期. ...
- Linux性能优化实战学习笔记:第三十五讲
一.上节回顾 前面内容,我们学习了 Linux 网络的基础原理以及性能观测方法.简单回顾一下,Linux网络基于 TCP/IP 模型,构建了其网络协议栈,把繁杂的网络功能划分为应用层.传输层.网络层. ...
- Linux性能优化实战学习笔记:第三十八讲
一.上节回顾 上一节,我们学习了 DNS 性能问题的分析和优化方法.简单回顾一下,DNS 可以提供域名和 IP 地址的映射关系,也是一种常用的全局负载均衡(GSLB)实现方法. 通常,需要暴露到公网的 ...
- Linux性能优化实战学习笔记:第三十九讲
一.上节回顾 上一节,我带你学习了 tcpdump 和 Wireshark 的使用方法,并通过几个案例,带你用这两个工具实际分析了网络的收发过程.碰到网络性能问题,不要忘记可以用 tcpdump 和W ...
- Linux性能优化实战学习笔记:第四十讲
一.上节回顾 上一节,我们学习了碰到分布式拒绝服务(DDoS)的缓解方法.简单回顾一下,DDoS利用大量的伪造请求,导致目标服务要耗费大量资源,来处理这些无效请求,进而无法正常响应正常用户的请求. 由 ...
随机推荐
- LeetCode 947. 移除最多的同行或同列石头 并查集
传送门 思路 干货太干就不太好理解了,以下会有点话痨( ̄▽ ̄)" 首先题目给了一个二维stones数组,存储每个石子的坐标,因为在同行或者同列的石子最终可以被取到只剩下一个,那么我们将同行同 ...
- node.js 命令必须加 npx 才能执行
问题描述 在 Windows 上搭建 Hexo 环境,已经从官网下载安装 node-v18.18.2-x64.msi,并且通过 npm 命令成功安装 hexo. PowerShell 中,直接执行 h ...
- Spring Cloud 学习推荐
学习 Spring Boot Spring tutorials | Java Web Development, Spring Cloud Programming tutorials Spring Bo ...
- 自签证书https
1.下载编译好的openssl. http://slproweb.com/products/Win32OpenSSL.html 下载完成后运行安装: 记住你安装到的目录,等下打开这个文件夹(小贴士:最 ...
- 深入浅出Sqoop之迁移过程源码分析
[摘要]Sqoop是一种用于在Apache Hadoop和结构化数据存储(如关系数据库)之间高效传输批量数据的工具 .本文将简单介绍Sqoop作业执行时相关的类及方法,并将该过程与MapReduce的 ...
- 教你用Python自制拼图小游戏,轻松搞定熊孩子
摘要:本文主要为大家详细介绍了python实现拼图小游戏,文中还有示例代码介绍,感兴趣的小伙伴们可以参考一下. 开发工具 Python版本:3.6.4 相关模块: pygame模块: 以及一些Pyth ...
- 了解库开发,我们从STM32标准库开发学起
摘要:从STM32新建工程.编译下载程序出发,让新手由浅入深,尽享STM32标准库开发的乐趣. 自从CubeMX等图像配置软件的出现,同学们往往点几下鼠标就解决了单片机的配置问题.对于追求开发速度的业 ...
- Rust布道者张汉东倾授,入门Rust初学者都要攻破哪些难点?
摘要:Rust语言学习曲线过于陡峭?初学者看懂这张思维导图,快速入门. Rust语言这两年的热度大家有目共睹,作为一个有着突破性变革意义的语言,其光鲜背后也有诸多质疑,对于想要在系统编程语言上更上一层 ...
- 游戏“外挂”?—— AI生成游戏最强攻略
作为一名快乐的肥宅,玩游戏是居家必备,无论是王者荣耀.吃鸡.原神这些大热游戏,还是跳一跳.合成大西瓜.2048.这些风靡一时得小游戏,咱都有涉及.但是为了成为一个"头号玩家",我总 ...
- appuploader 入门使用
回想一下我们发布 iOS 应用,不仅步骤繁琐,非常耗时.一旦其中一步失误了,又得重新来.作为一名优秀的工程师不应该让这些重复的工作在浪费我们的人生.在软件工程里面,我们一直都推崇把重复.流程化的工作交 ...