浏览器内核分析3 -- 资源加载和网络栈

1 网络资源

资源加载器

网页加载中需要获取的资源文件很多,有HTML,JavaScript,CSS,图片,SVG,CSS Shader,视频音频字幕,字体文件,XSL样式表等。不同资源有不同的加载器,主要分为三类:

  1. 特定资源加载器:处理特定资源请求,如ImageLoader FontLoader
  2. 缓存资源加载器:从内存中获取资源,CachedResourceLoader
  3. 通用资源加载器:从网络或硬盘中获取资源,ResourceLoader

同步与异步

HTML解析时,可能会碰到很多资源需要加载。这个时候,CSS和PNG等资源会开启异步线程去加载,不会打断HTML解析。而JS文件则会阻塞HTML解析,因为JS可能会改变DOM结构。虽然WebKit使用了预取技术来优化这个问题,但还是建议将js文件放在HTML的末尾。

缓存机制

Webkit使用了一个资源缓存池来缓存资源。以URL为key,就算资源内容完全相同,URL不同也会认为是两个不同的资源。每次资源请求时,先在缓存池中寻找资源,未命中才发起http等请求。这里也会遇到大多数缓存策略碰到的问题,资源生命周期和新鲜度检测机制。

由于缓存池大小受限,故需要将一些资源移出缓存池,Webkit中采用的LRU算法,最近最少使用的会被移除。

由于网络资源可能被更改,故需要检测资源是否还是新鲜的。这里采用了http协议中对于cache的处理。首先根据服务端返回的max-age或expires字段来判断资源是否有效。如果超出这个时间段,则发起if-modified-since请求。服务端可能有三种返回:

  • 304 not modified,资源未更改,不用重新下载了
  • 200 ok,资源更改了,并且将新的资源回传了
  • 404 not found,资源被删除了

2 资源加载过程

以img src=”https://baidu.com/imags/1.png” />为例,大概流程如下

  1. HTML解析到img的src属性时,创建一个ImageLoader对象,并开启另一个线程
  2. ImageLoader创建一个加载资源的CachedResourceRequest
  3. 创建一个CachedResourceLoader对象,先从memoryCache中查找缓存,命中则结束
  4. 未命中,则创建ResourceRequest和ResourceLoader,从disk或网络上获取资源。
  5. 资源获取后经过ResourceHandle处理,得到结果返回给ImageLoader

Markdown

3 Chromium资源加载

Chromium的Renderer进程中不加载资源,交给Browser进程代理。这样的好处有

  • 可以利用沙箱模型,提高安全性
  • 资源加载统一由Browser进程发起,使得多个页面共享资源变得很easy
  • 由Browser进程统一管理资源,避免多个页面发起多个http请求而使浏览器负载过大

资源加载管理器

Chromium中利用ResourceScheduler类来管理资源加载,它会根据request的优先级来调度URLRequest。对于优先极高,同步请求和具有SPDY能力的服务器,会优先调度。

4 网络栈

Chromium通过URLRequest进行网络资源请求,它的主要流程如下

  1. 根据scheme来判断资源类型,创建不同的URLRequestJob,对于http://,创建URLRequestHttpJob
  2. URLRequestHttpJob创建后,从cookie中获取与该URL相关的用户信息
  3. HttpCache先从本地磁盘中查找资源,命中则直接结束
  4. 未命中,则发起http请求。HttpCache创建HttpTransaction对象,开启一个Http连接事务
  5. HttpNetworkTransaction使用HttpNetworkSession管理连接会话,建立TCP socket
  6. 创建HttpStream对象,处理网络数据流的读取
  7. 创建套接字StreamSocket,其中的SSLSocket支持HTTPS请求。

域名解析

Chromium采用HostResolveImpl来做域名解析。域名解析是阻塞式的,故会重新开启一个线程。得到的DNS会由HostCache保存起来。

磁盘缓存

Chromium中有两个类来描述磁盘缓存。Backend代表了缓存表,可以快速查找缓存位置。Entry代表了缓存表中表项,以URL为key。读写表项都由Entry类来处理。同样使用LRU算法来回收缓存空间。

用于在浏览器端保存数据,H5出现后,还可以利用LocalStorage来保存数据。cookie是一连串的key: value对,如下面例子:

test1=webkit;test=chromium;Expires=Sun,30 oct 2016

根据保存位置不同,分为两类

  • 会话型,保存在内存中,浏览器退出会清除
  • 持久型,保存在磁盘中,浏览器退出不会清除

5 高性能网络栈

Chromium做了很多策略来优化网络资源加载,主要有下面这些。

DNS预取

DNS未获取之前,http请求不可能发送到相应服务器。可见域名解析会阻塞资源加载。Chromium采取了DNS预取机制来优化这个问题。当HTML展现后,浏览器会利用少量资源,针对HTML中的URL链接提前做DNS解析。这样当用户点击链接时,已经得到了服务器的DNS了。

多个超链接,每个会开启一个单独的线程,并发执行。另外,当用户在浏览器地址栏中输入URL时,浏览器也会根据之前历史URL来做相关匹配,然后做DNS预取。

TCP预连接

与DNS预取类似,浏览器也可以提前对HTML中的超链接进行TCP连接。当用户点击时,TCP就已经连接好了。这也会加快网络资源获取速度。

HTTP管线化pipelining

在HTTP1.1中,加入了管线化的支持,pipelining技术建立在keep-alive前提下,需要服务器支持。传统方式下,上一次的response得到后,才能发起下一次的request。而pipelining技术则可以将多个request按照先后次序一起发送到服务端,而不必等待上一次的response。这需要服务端按照次序返回response。

SPDY

定义在HTTP层和TCP层的协议,属于会话层。它的特点如下

  1. 采用多路复用技术,一个连接可以传输网页中众多资源。
  2. 根据资源特性和优先级,可以调整资源请求的优先级。比如JS文件下载优先级就比较高
  3. 利用压缩技术,减小包大小
  4. 服务器在发送网页内容时,可以尝试发送一些信息给浏览器,告诉后面可能还有那些资源,浏览器可以提前知道并决定是否需要下载。更极端的是,服务器可以主动将这些未请求的资源发给浏览器。
已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页