MicleMing.github.io

Blog: https://micleming.github.io/

View My GitHub Profile

## DNS 当你在浏览器上访问一个网站的时候,大部分情况下你使用的是这个网站的域名,而非网站的IP地址。因为IP地址是一连串的数字,不方便记忆。但是IP地址才是是网络上路由器能识别的地址。所以需要一个将域名解析为IP地址的服务,这就是DNS,它是一个将域名和IP地址进行映射的分布式数据库.

域名结构

域名结构和我们在电脑上访问文件时的路径结构类似,只不过一个是用/, 域名里使用dot(.)来进行分割。

域名的每一层叫做一个域,每个域利用.来分开,域名的域也分有不同的种类。最高级的就是顶级域名,接下了是二级域名以此类推。其中顶级域名分为

比如百度的域名:

www.baidu.com

顶级域是com, 接下了是二级域baidu, 三级域www

解析域名

那有了域名之后,是如何将域名映射为IP地址的呢?可以利用dig命令来看下解析的过程

dig www.baidu.com +trace

得到的结果是

; <<>> DiG 9.9.7-P3 <<>> www.baidu.com +trace
;; global options: +cmd
.			1022	IN	NS	h.root-servers.net.
      ...
.			1022	IN	NS	i.root-servers.net.
;; Received 460 bytes from 192.168.6.2#53(192.168.6.2) in 43 ms

com.			172800	IN	NS	a.gtld-servers.net.
      ...
com.			172800	IN	NS	m.gtld-servers.net.

;; Received 1173 bytes from 193.0.14.129#53(k.root-servers.net) in 282 ms

baidu.com.		172800	IN	NS	dns.baidu.com.
      ...
baidu.com.		172800	IN	NS	ns7.baidu.com.
;; Received 697 bytes from 192.52.178.30#53(k.gtld-servers.net) in 228 ms

www.baidu.com.		1200	IN	CNAME	www.a.shifen.com.
a.shifen.com.		1200	IN	NS	ns5.a.shifen.com.
    ...
a.shifen.com.		1200	IN	NS	ns4.a.shifen.com.
;; Received 239 bytes from 220.181.37.10#53(ns3.baidu.com) in 44 ms

从这里可以看出,域名解析时一级一级的从根域名开始进行解析。上面的查询过程其实就是:

通过这一系列的查询后,才拿到域名的IP地址。在弱网和没有缓存的情况下,DNS解析将花费大量的时间,会很大的影响用户体验。而且由于DNS解析是通过UDP进行传输数据的,所以一旦出现丢包,便要重新进行请求解析,在弱网情况下带来的体验极差。

DNS查询过程

当在浏览器输入一个网址,并且按下回车的时候,DNS查询算是发送的第一个请求。那这个查询经历的哪些过程呢?其实主要经历了如下几个步骤:

  1. 查看浏览器缓存,如果没缓存转到第二步
  2. 查看系统缓存(hosts), 如果没有缓存转到第三步
  3. 查看路由器缓存, 如果没有缓存转到第四步(这三步为客户端查找,第四步开始是在服务器查找)
  4. 查看ISPDNS缓存,如果没有缓存转到第五步
  5. 从根域名服务器开始一直查找到相对于的子域名服务器,查找到之后便会对结果进行缓存

通过以上几个过程来查询到一个域名对于的IP地址。在chrome中查看DNS的缓存可以访问

chrome://net-internals/#dns

在这个面板可以看到一个DNS的缓存过期时间TTL(Time-To-Live)以及当前状态。

优化策略

既然知道了DNS的查询过程,那前端工程师在开发过程中该如何对DNS的解析进行优化,减少查询时间呢?主要的思路主要有这么几个:

针对这几条原则,我们可以采取如下措施:

对于前两条,都可以在工程上进行解决,接下来我们来详细了解下DNS Prefetching

在浏览器中开启DNS Prefetching只需要在浏览器中加入这么一段代码

<link rel="dns-prefetch" href="//demo.com">

这段代码会让浏览器主动去执行域名解析,并进行缓存。