《WebKit技術內幕》知識提煉 —— 資源加載和網絡棧

WebKit 資源加載機制

資源

HTML 支持的資源主要包括:HTML、JavaScript、CSS、圖片、SVG、CSS Shader、視頻、音頻、字幕、字體、XSL樣式表等算法

這些資源在 WebKit 中都有不一樣的類表示,公共基類是 CachedResource。其中 HTML文本的類型爲 MainResource,對應的資源類型叫 CachedRawResource類。瀏覽器

資源緩存

基本思想是創建一個緩存池,優先從緩存池中讀取數據。這裏的所說的緩存池是內存緩存。WebKit 從資源池中查找資源的關鍵詞是URL,只要URL不一樣,就被認爲是兩個不一樣的資源緩存

資源加載器

分爲三種:安全

  • 針對每種資源類型的特定加載器,僅加載某一種資源,而且沒有公共基類,加載器屬於它的調用者。如 ImageLoader 屬於 HTMLImageElement
  • 緩存機制加載器 CachedResourceLoader 全部特定加載器都共享它來查找並插入緩存資源,屬於 HTML 文檔的對象
  • 通用資源加載器 ResourceLoader類,WebKit 須要從網絡或者文件中獲取資源的時候使用,只負責獲取資源數據

過程

資源加載過程

例子:有一個 「img」 元素,「src」是一個有效 URL 地址,當 HTML 解釋器解析到該元素的該屬性,WebKit 會建立一個 ImageLoader 對象來加載該資源,ImageLoader建立一個緩存資源請求CachedResourceRequest,並調用CachedResourceLoader 查找緩存資源,若是命中緩存則返回給調用者,若是沒有命中則建立一個資源請求ResourceRequest ,而且調用通用資源加載器加載資源,具體到下面的 ResourceHandleInternal ,依賴於每一個 WebKit 移植的實現策略。服務器

存在默寫資源會阻塞主線程渲染過程,當前的主線程渲染被阻塞時,WebKit 會啓動另一個線程去遍歷後面的 HTML 網頁,收集須要的資源 URL,並能夠併發下載這些資源。網絡

資源的生命週期

資源池使用 LRU(Least Recently Used 最近最少使用)算法,而且在這個基礎上添加了協商緩存。若是命中緩存,那麼發送一個 HTTP 請求給服務器,說明資源在本地的一些信息,如資源更新時間,服務器根據信息判斷,若是沒有更新,則返回狀態碼 304,那麼直接使用原資源;不然下載最新資源。多線程

Chromium 多進程資源加載

Renderer 進程在網頁的加載過程當中須要獲取資源,但因爲安全性(沙箱模型打開的時候,Renderer進程是沒有權限獲取資源的)和效率上(資源能夠共享),Renderer 進程的資源獲取其實是經過進程間通訊將任務交給 Browser 進程來完成。架構

網絡棧

WebKit 的資源加載的優化實際上是交由各個移植來實現的,WebCore 沒有什麼也別的基礎設施,每一個移植的網絡實現是很是不同的。併發

網絡棧的基本組成

除了 HTTP 協議、DNS 解析等,還包含了 Chromium 爲了減小網絡時間而引入的新技術,例如 SPDY,QUIC異步

網絡棧結構

網絡棧調用過程

  1. URLRequest 類被調用時,會根據 URL 的 「scheme」(協議類型,如:「http://」,「file://」等) 來決定要建立什麼類型的請求,Chromium 使用工廠模式處理不一樣類型的請求,例如 「http://」 類型則會使用 URLRequestJobManager 建立一個 URLRequestJob 類,具體使用哪一個工廠則是一個責任鏈模式,優先判斷是不是用戶自定義的 「scheme」 。
  2. URLRequestJob 被建立後,先從 Cookie 管理器中獲取與該 URL 相關的信息,以後使用 HttpTransactionFactory 對象建立 HttpTransaction 對象開啓一個 Http 鏈接的事務。若是請求對應的回覆已經在磁盤緩存中,那麼 Chromium 無需再創建 HttpTransaction
  3. HttpNetworkTransaction 使用 HttpNetworkSession 類來管理會話。經過 HttpStreamFactory 對象來創建 TCP Socket 鏈接。以後 HttpStreamFactory 建立 HttpStream 對象,來處理對象和網絡之間數據的讀寫。
  4. Chromium 中與服務器創建鏈接的套接字是 SteamSocket 類,它是一個抽象類,再 POSIX 系統和 Windows 系統上有不一樣實現。
域名解析(DNS)

Chromium 使用 HostResolverImpl 類來解析域名,具體調用的是 「getaddrinfo()」,是一個阻塞式函數,因此使用單獨的線程處理。爲了考慮效率,使用 HostCache 類來保存解析後的域名,還有 DNS 預解析機制。

磁盤本地緩存

要求:

  • 要有相應的機制來移除合適的緩存資源
  • 瀏覽器崩潰時不破壞磁盤文件
  • 能夠經過同步或異步的方式高效快速的訪問
  • 避免同時存儲相同的資源
  • 操做一個項的時候不受其餘請求影響
  • 磁盤不支持多線程訪問,磁盤的緩存操做要放到單獨的線程
  • 支持老版結構

實現上主要有兩個類,Backend(整個磁盤緩存) 和 Entry(表中的表項)。至少須要一個索引文件和四個數據文件。索引文件用來索引,數據文件又稱塊文件。

索引文件: 包括一個索引頭部和索引地址;頭部用來表示該索引文件的信息(索引文件版本號、索引項數量、文件大小等信息);索引地址表保存各個表項對應的索引地址,直接將文件映射到內存地址。從內存地址能夠找到數據文件,數據文件也是一個文件頭加上後面的塊文件,每一個塊的大小是固定的,當超過 512 字節的時候會爲其分配多個塊。但最多不超過四個,超過一般會用單獨的文件存儲。若是一個表項要分配四個塊,那麼是和塊索引位置是對齊的(起始塊的位置是4的倍數)

表項結構 分爲兩個部分,第一部分標記本身,包括元數據信息和自身內容。另外一部分常常發生變更,主要爲表項的回收算法服務,保存了回收算法所需的信息(LRU回收算法)。

高性能網絡棧

DNS 預取和 TCP 預鏈接

一次 DNS 查詢約 60~120ms,而 TCP 的三次握手也大約幾十毫秒

DNS 預取:利用現有的 DNS 機制,提早解析網頁中可能的鏈接。不是使用前面提到的 Chromium 網絡棧,而是直接利用系統的域名解析機制,不會阻礙當前網絡棧的工做,針對多個域名採起並行處理的方式,每一個域名的解析由一個新線程處理,結束後退出。網頁開發者能夠顯示指定哪些域名來讓 Chromium 解析,使用方法:<link rel="dns-prefetch" href='"htttp://...">。 用戶地址欄也同理。

TCP 預連接:使用追蹤技術獲取用戶從什麼網頁跳轉到另外一個網頁,利用這些數據、和一些啓發規則來 DNS 預取和 TCP 預連接,這對用戶隱私是一個巨大挑戰。

HTTP 管線化

HTTP1.1 開始增長了管線化技術,能夠將多個 HTTP 請求一次性提交給服務器,無需等待服務器回覆,由於它可能將多個HTTP 請求填充在一個 TCP 數據包內。能在高延遲的連接環境下有明顯的性能提高。

侷限性:須要經過永久鏈接完成,而且只有 GET 和 HEAD 等請求能夠進行管線化。

SPDY

爲了解決網絡延遲和安全問題,根據 Google 官方數據,能夠將網絡加載時間減小 64%,HTTP2.0 將引入 SPDY 協議,將其做爲基礎來編寫。

SPDY

SPDY 協議是一種新的會話層協議,是一種棧式結構,被定義在 HTTP 協議和 TCP 協議之間,核心是多路複用,僅使用一個鏈接來傳輸一個網頁中的衆多資源。本質上並無改變 HTTP 協議,只是將 HTTP 協議頭經過 SPDY 來封裝傳輸,數據傳輸方式也沒有發生變化。因此比較容易部署,服務器只須要插入 SPDY 協議的解釋層,從 SPDY 的消息頭中獲取各個資源的 HTTP 頭便可。但 SPDY 必須創建在 SSL 層之上。

特徵:

  • 利用一個 TCP 鏈接來傳輸不限個數的資源請求的讀寫數據流,提升 TCP 鏈接的利用率,減小 TCP 鏈接的維護成本
  • 能夠調整這些資源請求的優先級
  • 對請求使用壓縮技術
  • 能夠嘗試發送一些信息給瀏覽器,告訴瀏覽器後面可能須要哪些資源,更極端能夠主動發送資源給瀏覽器。
QUIC

QUIC 是一種新的網絡傳輸協議,目標是改進 UDP 數據協議的能力,解決傳輸層的傳輸效率,並提供數據的加密,SPDY 能夠在 QUIC 上工做。

更多

《WebKit技術內幕》知識提煉 —— WebKit 架構和模塊

相關文章
相關標籤/搜索