前言
DNS解析时间可能导致大量用户感知延迟,DNS解析所需的时间差异非常大,延迟范围可以从1ms(本地缓存结果)到普遍的几秒钟时间。所以利用DNS预解析是有意义的。
DNS与域名解析
DNS
全称为Domain Name System
,即域名系统,是域名和IP地址相互映射的一个分布式数据库。
域名解析即通过主机名,最终得到该主机名对应的IP地址的过程。
浏览器对网站第一次的域名DNS解析查找流程依次为:
浏览器缓存-系统缓存-路由器缓存-ISP DNS缓存-递归搜索
解决方案
DNS预解析是浏览器试图在用户访问链接之前解析域名,这是计算机的正常DNS解析机制。
域名解析后,如果用户确实访问该域名,那么DNS解析时间将不会有延迟。
最明显的例子,DNS预解析在某个页面中包含非常多的域名非常有效,如搜索结果页。
遇到网页中的超链接,DNS prefetching
从中提取域名并将其解析为IP地址,这些工作在用户浏览网页时,使用最少的CPU和网络在后台进行解析。
当用户点击这些已经预解析的域名,可以平均减少200毫秒耗时(假设用户最近还未访问过该域名),更重要的是用户不会遇到DNS解析最坏的情况(往往超过1秒)。
DNS Prefetching简介
DNS 请求需要的带宽非常小,但是延迟却有点高,这点在手机网络上特别明显。DNS预解析 能让延迟明显减少一些,例如用户点击链接时。在某些情况下,延迟能减少一秒钟。
在某些浏览器中这个预读取的行为将会与页面实际内容并行发生(而不是串行)。正因如此,某些高延迟的域名的解析过程才不会卡住资源的加载。
这样可以极大的加速(尤其是移动网络环境下)页面的加载。在某些图片较多的页面中,在发起图片加载请求之前预先把域名解析好将会有至少 5% 的图片加载速度提升。
使用
X-DNS-Prefetch-Control
头控制着浏览器的DNS预解析功能
X-DNS_prefetch-Control: on|off
on:启用DNS预解析。在浏览器支持DNS预解析的特性时及时不适用该标签浏览器依然会进行预解析。
off:关闭DNS预解析。这个属性在页面上的链接并不是由你控制的或是你根本不想向这些域名引导数据时非常有用。
浏览器支持
链接:http://caniuse.com/#feat=link-rel-dns-prefetch
示例
打开和关闭DNS预读取
你可以通过在服务器端发送 X-DNS-Prefetch-Control 报头,或是在文档中使用值为 http-equiv 的标签:
1 |
<meta http-equiv="x-dns-prefetch-control" content="off"> |
强制查询特定主机名
你可以通过使用 rel 属性值为 link type 中的 dns-prefetch 的 标签来对特定域名进行预读取:
1 |
<link rel="dns-prefetch" href="http://www.xuanfengge.com/"> |
在这个例子中,Firefox将预解析域名”www.xuanfengge.com”。
特性
Chrome会记住最近使用的10个domain,并且在开启浏览器时自动解析,因此在打开这些常用页面的时候,并不会有DNS Lookup的延迟情况。
chrome使用8个线程专门做DNS Prefetching,而且chrome本身不做dns记录的cache,是直接从操作系统读dns。所以直接修改系统的dns记录或者host是可以直接影响chrome。
浏览器会对a标签的href自动启用DNS Prefetching,所以a标签里包含的域名不需要在head中手动设置link。但是在HTTPS下面不起作用,需要meta来强制开启功能。这个限制的原因是防止窃听者根据DNS Prefetching推断显示在HTTPS页面中超链接的主机名。
DNS解析的包很小,一个UDP的包小于100 bytes,却平均可节省200ms。
本地缓存DNS数量有限,可暂存50-200个domain,Chrome会决定该删除哪些domain的缓存,常用的网站会被标记为“最近使用”,不会那么快被删除。而如google.com、yahoo.com等大型网站过期时间大概在5分钟左右,可以更好的适应服务变化。
场景
页面中的静态资源在不同的domain下,如CSS、JS、图片等文件
适合在以下场景中使用:
- 电商网站的商品页大量载入不同domain下的商品图,如淘宝
- 手机网页
- 大型网站
- js或服务端重定向
指令
chrome://histograms/DNS.PrefetchQueue
:查看队列状态chrome://histograms/DNS
:查看从浏览器启动到上一页的DNS记录chrome://dns
:查看个域名DNS统计chrome://net-internals/#dns
:清除host缓存
实验
1. HTTPS页面DNS prefetching
下面的例子,该页面只会预解析b.com,而不会预解析a.com、c.com、d.com。
因为HTTPS需要手动开启才会生效,而且如果明确设置不采用DNS 预解析功能,则会忽略进一步尝试开启。
1 2 3 4 5 6 7 |
<a href="http://a.com"> A) Default HTTPS: No prefetching </a> <meta http-equiv="x-dns-prefetch-control" content="on"> <a href="http://b.com"> B) Manual opt-in: Prefetch domain resolution. </a> <meta http-equiv="x-dns-prefetch-control" content="off"> <a href="http://c.com"> C) Manual opt-out: Don't prefetch domain resolution </a> <meta http-equiv="x-dns-prefetch-control" content="on"> <a href="http://d.com"> D) Already opted out: Don't prefetch domain resolution. </a> |
2. DNS prefetching解析记录
打开页面1:http://www.xuanfengge.com/demo/201705/dns/demo.html
1 2 3 4 5 6 7 8 9 |
<html> <head></head> <body> <a href="http://a.youzan.com">a</a> <a href="http://b.youzan.com">b</a> <a href="http://c.youzan.com">c</a> <a href="http://d.youzan.com">d</a> </body> </html> |
Chrome打开 chrome://histograms/DNS.PrefetchQueue
看DNS记录
目前一共22个DNS记录,有9个命中缓存
打开页面2:http://www.xuanfengge.com/demo/201705/dns/demo1.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
<html> <head></head> <body> <a href="http://a.youzan.com">a</a> <a href="http://b.youzan.com">b</a> <a href="http://c.youzan.com">c</a> <a href="http://d.youzan.com">d</a> <a href="http://a1.youzan.com">a1</a> <a href="http://b1.youzan.com">b1</a> <a href="http://c1.youzan.com">c1</a> <a href="http://d1.youzan.com">d1</a> <a href="http://a2.youzan.com">a2</a> <a href="http://b2.youzan.com">b2</a> <a href="http://c2.youzan.com">c2</a> <a href="http://d2.youzan.com">d2</a> <a href="http://a3.youzan.com">a3</a> <a href="http://b3.youzan.com">b3</a> <a href="http://c3.youzan.com">c3</a> <a href="http://d3.youzan.com">d3</a> <a href="http://a4.youzan.com">a4</a> <a href="http://b4.youzan.com">b4</a> <a href="http://c4.youzan.com">c4</a> <a href="http://d4.youzan.com">d4</a> </body> </html> |
新增20次查询,其中新增4次缓存命中,其它为离散分布在各个时间段。
所以Chrome会对a标签的domain进行预解析。
好专业,以前也知道有预解析,不知道这么详细的内容
太棒了,很专业,有深度的技术博客
相当精彩的博客!