前言:对于web开发者而言,特别是使用HTML5技术来编写网页或者web应用,了解其背后的工作原理是写出高效代码的有效捷径,结合最近在看的webkit以及chromium,感触颇深,希望能够通过webkit技术浅析这一系列向大家分享一些学习心得。
域名解析(DNS)
1.什么是域名解析?
通常情况下,人们都是使用域名来访问网络资源的,所以在建立TCP连接前需要解析域名,而域名解析就是把域名指向网站空间IP,让人们通过注册的域名可以方便地访问到网站的一种服务。
2.webkit是如何实现DNS的?
在Chromium中,使用HostResolverlmpl类来解析域名,具体调用的函数是“getaddrinfo()”,该函数是一个阻塞式函数,所以Chromium就使用了单独的线程来处理它。同样,考虑到效率的原因,Chromium使用HostCache类来保存解析后的域名,最多时可以达到1000个域名和地址的映射关系会被储存起来(打开chrome浏览器,在地址栏中输入chrome://net-internals/#dns就可以看见当前域名解析和HostCache的详情了)。看起来DNS的解析好像很简单,没有什么可以深究的,实则不然,域名解析也有可以优化的空间,因为优化可以减少用户等待的时间。
Chromium的网络模块由两个重要目标,其一是安全,其二就是速度,下面我们就来简单介绍一下。
3.DNS预取和TCP预连接
一次DNS查询的平均时间大概在60~120ms之间或者更长,而TCP的三次握手时间大概也是几十毫秒或者更长,看似是一个很短的时间,但是相对于网页的渲染来说,这是一个相当长的时间,如何有效的缩短这段时间,Chromium给出了自己的解决方案—DNS预取和TCP预连接。
首先讲一下DNS预取,他的主要思想就是利用现有的DNS机制,提前解析网页中可能的网络连接。具体来说,就是当用户正在浏览当前网页的时候,Chromium提取网页中的超链接,将域名抽取出来,利用比较少的CPU和网络带宽来解析这部分域名或IP地址,这样一来,用户根本感觉不到这一过程。但是当用户单击这些链接的时候,由于已经提前做好了DNS解析,可以节省不少时间,特别是对于域名解析比较慢的时候,效果尤其明显。(DNS预取技术针对多个域名采取并行处理的方式,每个域名的解析均是由新开启的一个线程来处理的,结束后此线程即退出)
当然,我们也可以显式指定预取哪些域名来让Chromium解析,这非常直接了当。特别是对于那些需要重定向的域名,具体做法如下:
<link rel="dns-prefetch" href="http://this-is-a-dns-prefetch-example.com">
。DNS预取技术不仅应用于网页中的超链接,当我们在地址栏中输入地址后,候选项同输入的地址很匹配的时候,在我们敲下回车键获取该网页之前,Chromium已经开始使用DNS预取技术解析该域名了。
接下来是TCP预连接,Chromium使用追踪技术来获取用户从什么网页跳转到另外一个网页,可以利用这些数据,一些启发式的规则和其他暗示来预测用户下面回单击什么超链接,当有足够的把握的时候,他便会DNS预取,更进一步,还可以预先简历TCP连接。听起来是不是特别6?不错,Chromium就是这么6!同DNS预取技术一样,追踪技术不仅应用于网页中的超链接,当用户在地址栏中输入地址的时候,也同样适用!
4.如何高效的使用资源?
4.1.前言
webkit和Chromium为了高效的下载资源,设计出了各种各样的策略和新技术(我们这里只说了DNS和TCP连接,其实还有很多,后面我在慢慢补充吧(^__^) ),
那么对于我们开发者来说,是不是就可以直接使用它们而不需要优化代码本身了呢?当然不是,谁会嫌弃自己的性能太高了呢?
4.2.DNS和TCP连接
通过上面的描述,DNS解析和TCP连接占用了大量的时间,所以为了高效的加载网页,网页开发者可以从以下几个方面着手来减少这一部分的时间。
- 减少链接的重定向。有些网页中使用了大量的重定向,可能还会有很多次重定向,这不仅要求浏览器建立多次连接,同时也需要进行多次的DNS解析,这会阻碍DNS预取技术的应用,所以用该尽量避免。
- 利用DNS预取机制,网页的开发者当然知道需要链接的URL,为了浏览器也知道这些链接,开发者可以指定需要预取的url,我在上面也已经给出了示例。
- 避免错误的链接请求,有些网页中包含了一些失效的链接,当浏览器试图获取该链接对应的资源的时候,就会占用网络资源。
4.3.资源的数量
我们也可以通过减少网页中所需的资源数量来改善网页的加载,网页开发者可以从以下几个方面着手改变以减少这一部分的时间。
- 在HTML网页中内嵌小型的资源,也就是当资源比较小的时候,开发者可以将他们直接放在网页中,可能的资源如CSS,JavaScript和图片等。前两者比较好理解,对于图片而言,当图片比较小的时候,我们可以使用base64编码来将其变成字符串,直接放在网页中。例如设置一个元素背景的时候,可以按照下面的方式来操作"background:url(<img src='data:img/jpg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD...)"
- 合并一些资源,例如css,JavaScript和图片,常见的是一些网页中大量使用的小图片,可以将其 合并成一张大图片以供使用,减少TCP连接的数量,同时对后面的渲染也有帮助。
4.3资源的数据量
对于每个资源而言,可以通过减少它的数据量来提高网页的加载速度,我们可以从以下几个方面着手:
- 使用浏览器本地磁盘缓存机制,因为我们知道HTTP协议支持资源的失效机制,可以通过对资源设置适当的失效期来减少浏览器对资源的重复获取。
- 启用资源的压缩技术,例如对于图片而言,可以使用zip压缩技术,然后再HTTP消息头中说明该资源经过压缩,这样可以有效减少网络传输的数据量。
其实还有许多其他的技巧可以帮助资源的加载效率,例如减少无用的空格,启用异步资源加载,在这里就不一一介绍了。