webkit资源加载机制
资源
网络和资源加载是网页的加载和渲染工程中的第一步,也是必不可少的一步。网页本身就是一种资源,而且网页一般还需要依赖很多其他累心的资源,例如图片、视频等。以为资源的加载设计网络和资源的缓存等机制,而且他们在正个渲染过程中的占比并不少。如何获取资源以及高效的管理资源。
资源类型
- HTML:html页面。包括格式各样的html元素
- JavaScript:JavaScript代码,可以内嵌也可以单独文件存在。
- css样式表:css样式资源,因为css代码出了可以内嵌也可单独文件存在
- 图片:各种编码的图片资源,包括png、jpeg等
- svg:用于绘制svg的2d矢量图形
- css shader:支持css shader文件,目前webkit支持
- 视频、音频、字幕:多媒体资源及支持视频字幕文件(textTrack)
- 字体文件:css支持的自定义字体,css3隐忍的自定义字体文件
- xsl样式表:使用xslt于洋编写的xslt代码文件
资源缓存
建立一个资源的缓存池,当webkit需要请求资源的时候,先从资源池中查找是否存在相应的资源,如果有。webkit则去除一遍使用;如果没有,webkit建立新的CachedResource子类的对象,并发送真正的请求给服务器,webkit收到资源后将设置到该资源类的对象中区,以便于缓存后下次使用。这里的缓存指的是内存缓存,而不同于后面再网路栈部分的磁盘缓存。
资源加载器
- 针对每种资源类型的特定加载器,其特点是仅加载某一种资源。
- 资源缓存机制的资源加载器的特点是所有特定加载器共享它来查找并插入缓存资源—CachedResiurceLoader类。特定加载器先是通过缓存机制的资源加载器来查找是否有缓存资源,它属于HMTL文档对象
- 通用的资源加载器—-ResourceLoader类,是在webkit需要从网络或者文件系统获取资源的时候使用该类只负责获取资源的数据,因此被所有特定资源加载器所有共享。
过程
在加载JavaScript资源的时候 webkit会启动一个线程去遍历后面的html网页,收集所需要的url资源,然后发送请求,就这样的可以避免被阻碍。与此同时,webkit能够并发下载这些资源,甚至并发下载JavaScript代码资源。
资源的生命周期
资源池使用LRU(LeastRecentUsed 最近最少使用算法)。
发送http请求服务器304表面无需更新。
chromium多进程资源加载
多进程
在chromium架构的Renderer进程中,RescourseHandleInternal类通过IOCResource-LoaderBridge类同Browser进程通信。IPCResourceLoaderBridge类继承自ResourceLoaderBridge类,其作用是负责发送请求的对象和回复结果的解释工作,实际消息的接受和排放交给ResourceDispatcher类来处理。
在Browser进程中,首先由ResourceMessageFilter类来过滤Renderer进程的消息,如果与资源请求相关,则该过滤类请求给ResourceDispatcherHostImpl类,随机ResourceDisoatcherHostImpl类chuangjianBrowser进程中的ResourceLoader对象来处理。
工作方式和资源共享
网络栈
webkit的网络设施
webkit的资源加载其实是各个一直来实现的,所以webcore没有什么基础设施,每个移植实现是非常不一样的。
chromium网络栈
网络栈的基本组成
网络栈结构
首先URLRequest类被上层调用并启动请求的时候,他会根据URL的scheme来九鼎需要创建什么类型的请求。scheme也就是RRL的协议类型。例如:http:// file:// 也可以是自定义的scheme 例如Android系统的 file://amdroid_asset/。URLRequsetHttpJob类。为了支持自定义的scheme处理方式,Chromium使用工厂模式。URLRequestJob类和他的工厂类URLRequestJobFactory的管理工作都有URLRequestHttpJob类。
代理
- ProxyService:对于一个URL,HttpStreamFactory类使用ProxyService类在去哦去代理信息。ProxyService类首先会坚持当前的代理设置是不是最新的,如果不是,他依赖ProxyConfigService来重现获取代理信息。该类不处理实际任务,而是使用ProxyResolver类来做实际的代理工作。
- ProxyConfigService: 获取地理信息的类,可获取平台的代理设置,在:Linux、Windows上有不同的实现。
- ProxyScriptFetcher:Chromium支持代理的JavaScript脚本,该类负责从代理的URL中获取获取改脚本。
- ProxyResolve:实际扶着代理的解释和指向,通常启用新的线程来吃力,因为当前可能对呗域名的解析所阻碍。
- ProxyResolveV8: ProxyResolver的子类,使用v8引擎来解析和执行脚本。
域名解析(DNS)
使用HostCache类来保存解析后的域名,最多时会有多达1000个的域名和地址映射关系会存储起来。
磁盘本地缓存
特性
- 虽然需要缓存的资源可能很多,但磁盘空间不是无限放大的,所有必须要有相应的机制来移除合适的缓存资源,以便加入新的资源。
- 能够确保在浏览器崩溃是不破坏磁盘文件,至少能够保护原先在磁盘中的数据。
- 能够高效和快速访问磁盘中现有的数据结构,支持同步和异步两种访问方式。
- 能够避免同时存储两个相同的资源。
- 能都很方便的从磁盘中删除一个项,同时可以在操作一个项的时候不受其他请求的影响。
- 磁盘不支持多线程访问,所以需要把,所有磁盘缓存的操作放入单独的一个线程。
- 升级版本时,如果磁盘的内部存储结构发生改变,Chromium仍然能够支持老版本的结构。
结构
Cookie机制
cookie格式就是一系列的 “关键字+值”对,
cookie的时效性可以将cookie分成两种类型,第一种是会话型Cookie(session Cookie),这些Cookie只是保存在内存中,当浏览器退出的时候后既清除这些Cookie。如果Cookie没有设置失效时间,就是会话Cookie。第二种是持续性Cookie(Persistent Cookie),也就是当浏览器退出的时候,仍然保留Cookie的内容。该类型的Cookie有一个幼小期,在有效期内,每次访问该Cookie所属域的时候,都需要将该Cookie发送给服务器,这样服务器能过有效追踪用户的行为。
Chromium中支持Cookie的机制也较为简单和清晰,CookieMonster是Cookie机制中最重要的类,实际上相当于Cookie管理器,它包括几个作用:第一是实现CookieStore的接口,它是对外的接口,调用者可以设置和获取Cookie;第二是报告各种Cookie的事件,例如更新信息等,主要使用Delegate类;第三是Cookie对象的集合,也就是CanonicalCookie的集合,每个使用CanonicalCookie对象标识一个域的Cookie结合。最后是持续型Cookie的存储,上面讲的数据都是保存在内存中的,当需要存储到磁盘的时候后使用PersistentCookieStore类,具体有SQLitePersistentCookieStore类负责实际的存储动作。
安全机制
HTTP是一种使用明文来传输数据的应用程协议。构建在SSL之上的HTTPS提供了安全的网络传输机制,现在已被广泛应用于网络上。典型的是电子商务、银行支付方面的应用。基本上所有的浏览器都支持该协议。
高性能网络栈
Chromium的网络模块有两个重要目标,一是安全,二是速度。
DNS预取和TCP预连接(Preconnenct)
一次DNS查询平均时间大概是60~120ms之间或者更长,而TCP的三次握手时间大概也是几十毫秒或者更长。这是一个非常长的时间。如何有效的减少这段时间,Chromium给出了自己的答案—-DNS预取和TCP预连接,他们都是由Chromium的“Predictor”机制来实现的。
首先是DNS预取技术。他的主要思想是利用现有的DNS机制,体现解析网页中可能的网络连接。具体来讲,当用户正在浏览当前网页的时候,Chromium提取网页中的超链接,将域名抽取出来,利用较少的CPU和网络带宽来解析这些域名或IP地址,这样一来,用户根本感觉不到这一过程1,。当用户单击这些链接的时候,可以节省不少时间,特别在域名解析比较慢的时候,效果特别明显。
网页的开发者可以显示指定预取那些域名来让Chromium解析,这样直接了当,特别对于那些需要重定向的域名,具体做法如下:
<link rel="dns-prefetch" href="http://this-is-a-dns-prefetch-example.com">
当然,NDS预取技术不仅应用于网页超链接,当用户在地址栏输入地址后,候选项同输入的地址很匹配的时候,在用户敲下回车键获取该网页之前,Chromium已经开始使用DNS预取技术解析该域名了。
HTTP管线化(Pipelining)
HTTP1.1开始增加管线化技术。Chromium当然也支持这一技术,但它需要服务器的支持,两者配合才能实现HTTP管线化。HTTP管线化技术是一项同时将多个HTTP请求一次性提交给服务器的技术,因此无需等待服务器的回复,因为他可能将多个HTTP请求填充在一个TCP数据包内。HTTP管线化需要在网络上传输较少的TCP数据包,因此减少了网络负载。
SPDY
SPDY就是为了解决网页延迟和安全性问题。
SPY协议是一种新的会话层协议,因为网络协议是一种栈式结构,它被定义在HTTP协议和TCP协议之间
SPDY协议的核心思想是多路复用,仅适用一个连接来传输一个网页中的众多资源,
- 利用一个TCP连接传输不限个数的资源请求的读写数据流,这与之前的为每个资源请求都建立一个TCp连接大大不同,这明显提高了TCP连接的利用率,减少了TCP连接的维护成本。前面我们也说过,建立一个TCp连接的事件为几十毫秒或者更长,这显然能够减少时间。
- 根据资源请求的特性和优先级,SPDY可以调整这些资源请求的优先级。
- 只对这些请求使用压缩技术,课大大减少需要传送的字节数。
- 当用户浏览某些网页,支持SPDY协议的服务器在发送网页内容时煤科院创世发送一些信息给浏览器,告诉后面可能需要哪些资源,浏览器可以提前知道并决定师父需要下载。更极端的情况是,服务器可以主动发送资源。
QUIC
QUIC是一种新的网络传输协议,主要目标是改进UDP数据协议的能力。同SPDY建立在传输层之上不同,QUIC索要解决的问题就是传输成的传输效率,并提供了数据的加密。
高效的资源使用策略
DNS和TCP连接
通过上面的描述可知,DNS解析和TCP连接占用大量的时间,所以为了高效的加载网页,网页开发者可以从方面着手改变以减少这一部分的时间。
- 减少链接的重定向。有些网页中使用了大量的重定向,可能还会有多次重定向,这不仅要求浏览器建立多次链接,同时也需要多次DNS解析,这回主要DNS预取技术的应用。
- 利用DNS预取机制。网页的开发者当然知道需要链接的URL,为了让浏览器也知道这些链接,开发者可以指定需要预取的URL。
- 搭建支持SPDY协议的服务器。
-
资源数量
在HTML网页中内嵌小型的资源,也就是当资源比较小的时候,开发者可以将它们直接放入网页中,可能的资源如CSS、JavaScript和图片等。前两者比较直接,对于图片而言,当图片比较小的时候,开发者得以通过base64编码技术将它编程字符串,直接放入网页中。
合并一些资源,例如CSS、JavaScript和图片。常见的是一些网页中大量使用小图片,可以将它们合并成一张大图片以供使用,因为我们知道浏览器建立TCP连接需要比较长的时间,所以这样不见能减少TCP连接建立的数量,而且对后面的渲染也会有帮助。
资源的数据量
使用浏览器本地磁盘缓存机制。因为我们知道HTTP协议支持资源的失效机制,可以通过对志愿设置适当的失效期来减少浏览器对资源的重复获取。
- 启用资源压缩技术。