这篇文章上次修改于 899 天前,可能其部分内容已经发生变化,如有疑问可询问作者。
1 DNS
DNS(Domain Name System),即域名系统,是互联网中最基础的一项服务,主要提供域名和 IP 地址之间映射关系的查询服务。
DNS 协议属于应用层,传输时基于 TCP 或 UDP(UDP 居多),监听的端口一般是 53。
域名解析是以递归的方式(从顶级域名开始),发送给每个层级的域名服务器,直到得到解析结果。该过程由 DNS 服务器负责。
每级服务器都会有最近解析记录的缓存,当缓存命中时,直接用缓存中的结果应答即可。缓存过期或不存在时,才需要递归查询。
查看域名服务器配置:
$ cat /etc/resolv.conf
nameserver 114.114.114.114
当访问某个网址时,需要通过 DNS 的 A 记录查询域名对应的 IP 地址:
$ 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
time.geekbang.org 的 IP 地址是 39.106.233.176。
dig 工具可展开整个递归查询过程:
# +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 记录表示域名对应的域名服务区地址。
- 从 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 记录。
有时候也需要对局域网内部的主机进行域名解析,可将主机名和 IP 地址的映射关系写入本机的 /etc/hosts 文件中。也可以在内网中搭建自定义的 DNS 服务器。
2 案例
2.1 DNS 解析失败
执行 DNS 查询:
$ nslookup time.geekbang.org
;; connection timed out; no servers could be reached
阻塞后失败。调试:
$ 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.
发现连向的是环回地址,说明没有配置 DNS 服务器地址,验证:
$ cat /etc/resolv.conf
没有输出。配置 DNS 服务器地址后再次解析:
$ 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.2 DNS 解析不稳定
$ 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
DNS 解析耗时达到 10s,较慢,多次运行上述命令可能还会发送丢包错误。可能的原因:
- DNS 服务器本身响应慢且不稳定。通过 nslookup 输出得知 8.8.8.8 是谷歌提供的,有问题的可能性较低。
- 本机到 DNS 服务器的网络延迟较大。可能性较大。
- 或者 DNS 请求或响应包在某些情况下被链路中的网络设备弄丢了。
查看本机到 8.8.8.8 的网络延迟:
$ 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
网络延迟达到 140ms,延迟较大,多次运行还会出现丢包现象。
更换一个延时更小的 DNS 服务器,如 114.114.114.114:
$ 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 完成解析,比之前好了很多。
但多次运行 nslookup 命令,并不是每次结果都很好,有时候会达到 1s,这时候需要开启 DNS 缓存(Ubuntu 18.04 及之后的版本会自动开启:
$ /etc/init.d/dnsmasq start
* Starting DNS forwarder and DHCP server dnsmasq [ OK ]
修改 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
可以看到除了第一次查询较慢外,后续的 DNS 解析都比较稳定。
参考
倪朋飞. Linux 性能优化实战.
没有评论