[譯]BigPipe:高性能的「流水線技術」網頁

16

原文地址:http://www.facebook.com/note.php?note_id=389414033919
譯文地址:http://isd.tencent.com/?p=2419
做者:蔣長浩javascript

Facebook的網站速度作爲最關鍵的公司任務之一。在2009年,咱們成功地實現了Facebook網站速度提高兩倍 。而正是咱們的工程師團隊的幾個關鍵的創新使它成爲可能。在本文中,我將向你們介紹咱們的祕密武器之一,咱們稱之爲BigPipe的偉大底層技術。php

BigPipe是一個從新設計的基礎動態網頁服務體系。大致思路是,分解網頁成叫作Pagelets的小塊,而後經過Web服務器和瀏覽器創建管道並管理他們在不一樣階段的運行。這是相似於大多數現代微處理器的流水線執行過程:多重指令管線經過不一樣的處理器執行單元,以達到性能的最佳。雖然BigPipe是對現有的服務網絡基礎過程的從新設計,但它卻不須要改變現有的網絡瀏覽器或服務器,它徹底使用PHP和JavaScript來實現。html

動機前端

爲了更好的瞭解BigPipe,咱們須要瞭解一下現有的動態Web服務系統,它的歷史能夠追溯到萬維網的初期,但如今與初期相比卻並無多少改變。現代網站有着遠遠高於10年前的動態效果和互動性,但傳統的網頁服務系統早已沒法跟上當今互聯網速度的要求。在傳統的模式,用戶請求的生命週期以下:java

1. 瀏覽器發送一個HTTP請求到Web服務器。
2. Web服務器解析請求,而後讀取數據存儲層,制定一個HTML文件,並用一個HTTP響應把它發送到客戶端。
3. HTTP響應經過互聯網傳送到瀏覽器。
4. 瀏覽器解析Web服務器的響應,使用HTML文件構建了一個的DOM樹,而且下載引用的CSS和JavaScript文件。
5. CSS資源下載後,瀏覽器解析它們,並將它們應用到DOM樹。
6. JavaScript資源下載後,瀏覽器解析並執行它們。node

傳統模式在現代網站中效率是很是低下的,由於不少系統的操做順序,不能互相重疊。一些如延時加載JavaScript、並行下載等優化技術已被網絡社區普遍採用,以此來克服的一些限制。然而,這些優化卻不多涉及Web服務器和瀏覽器的執行順序形成的瓶頸。當Web服務器正忙生成一個頁面,瀏覽器處於閒置狀態,浪費其週期無所事事。當Web服務器完成生成頁面,並將其發送到瀏覽器,瀏覽器則成爲性能瓶頸而且Web服務器對其無從幫助。重疊Web服務器的生成時間與瀏覽器的渲染時間,咱們不只能夠減小最終的時間延遲,也能使網頁更早顯示用戶可見區域給用戶,從而大大減小用戶對延遲的感知。web

Web服務器的產生時間和瀏覽器的渲染時間重疊,是特別有用的,如Facebook這樣內容豐富的網站。一個典型的Facebook的網頁包含許多來源不一樣的數據資料:好友名單,好友動態,廣告等。在傳統的網頁呈現模式的用戶將不得不等到這些查詢數據都返回並生成最終文件,而後將其發送到用戶的電腦。任何一個查詢延遲都將拖慢整個最終文件的生成。編程

BigPipe如何工做瀏覽器

要利用該Web服務器和瀏覽器之間的並行性,BigPipe首先分解網頁成多個可調用的Pagelets。正如流水線微處理器劃分一個指令的生命週期爲(如「取指令」,「指令解碼」,「執行」,「寫回寄存器」等)多個階段,BigPipe的頁面生成過程分爲如下幾個階段:緩存

1. 請求解析:Web服務器解析和完整性檢查的HTTP請求。
2. 數據獲取:Web服務器從存儲層獲取數據。
3. 標記生成:Web服務器生成的響應的HTML標記。
4. 網絡傳輸:響應從Web服務器傳送到瀏覽器。
5. CSS的下載:瀏覽器下載網頁的CSS的要求。
6. DOM樹結構和CSS樣式:瀏覽器構造的DOM文檔樹,而後應用它的CSS規則。
7. JavaScript中下載:瀏覽器下載網頁中JavaScript引用的資源。
8. JavaScript執行:瀏覽器的網頁執行JavaScript代碼。

前三個階段執行,由Web服務器,最後四個階段是由瀏覽器執行。每一個Pagelet必須通過全部這些階段順序,但BigPipe在不一樣的階段使幾個Pagelets同時執行。


(Facebook主頁的Pagelets,每一個矩形對應一個Pagelet。)

上面的圖片使用Facebook主頁爲例子來講明如何將網頁是分解成Pagelets。該主頁包括幾個Pagelets:「做者Pagelet」,「導航Pagelet」,「新聞動態Pagelet」,「請求框Pagelet」,「廣告pagelet」,「朋友推薦」和「聯繫」等他們是相互獨立的。當「導航Pagelet」顯示給用戶,「新聞動態Pagelet」仍然能夠在服務器上正在生成。

在BigPipe,一個用戶請求的生命週期是這樣的:在瀏覽器發送一個HTTP請求到Web服務器。在收到的HTTP請求,並在上面進行一些全面的檢查,網站服務器當即發回一個未關閉的HTML文件,其中包括一個HTML 標籤和標籤的開始標籤。標籤包括BigPipe的JavaScript庫來解析Pagelet之後收到的答覆。在標籤,有一個模板,它指定了頁面的邏輯結構和Pagelets佔位符。例如:

渲染後的第一個反應到客戶端,Web服務器繼續一個接一個生成Pagelets只要一個Pagelet生成,他將當即刷新到客戶端在一個JSON編碼的對象,包括全部的CSS,JavaScript的pagelet,它的HTML內容,以及一些元數據所需的資源。例如:

在客戶端在收到Pagelet經過「onPageletArrive」發出的指令,BigPipe的JavaScript庫將首先下載它的CSS資源;在CSS資源被下載完成後,BigPipe將在Pagelet的標記HTML顯示它的innerHTML。多個Pagelets的CSS可在同一時間下載,它們能夠根據其各自CSS的下載完成狀況來確認顯示順序。在BigPipe中,JavaScript資源的優先級低於CSS和頁面內容。所以,BigPipe不會在全部Pagelets顯示出來以前下載任何Pagelet中的JavaScript。而後,全部Pagelets的JavaScript異步下載。最後Pagelet的JavaScript初始化代碼根據其各自的下載完成狀況來肯定執行順序。

這種高度並行系統的最終結果是,多個Pageletsr的不一樣執行階段同時進行。例如,瀏覽器能夠正在下載三個Pagelets CSS的資源,同時已經顯示另外一Pagelet內容,與此同時,服務器也在生成新的Pagelet。從用戶的角度來看,頁面是逐步呈現的。最開始的網頁內容會更快的顯示,這大大減小了用戶的對頁面延時的感知。若是您要本身親眼看到區別,你能夠嘗試如下連結: 傳統模式BigPipe。第一個連接是傳統模式單一模式顯示頁面。第二個連接是BigPipe管道模式的頁面。若是您的瀏覽器版本比較老,網速也很慢,瀏覽器緩存不佳,哪麼兩頁之間的加截時間差異將更加明顯。

性能測試結果

下圖是傳統模式和BigPipe性能數據比較圖,數據是75%用戶對一個頁面中最重要的內容(例如:新聞動態被認爲是在Facebook主頁上最重要的內容)的感知延遲時間。收集數據方式是加載Facebook主頁50次而且禁用瀏覽器緩存。該圖顯示BigPipe使用戶在大多數瀏覽器中感覺到的延遲減小了一半。


(Facebook主頁的延遲時間對比)

值得一提的是BigPipe是從微處理器的流水線中獲得啓發。然而,他們的流水線過程之間存在一些差別。例如,雖然大多數階段BigPipe只能操做一次Pagelet,但有時多個Pagelets的CSS和JavaScript下載卻能夠同時運做,這相似於超標量微處理器。BigPipe另外一個重要區別是,咱們實現了從並行編程引入的「障礙」概念,全部的Pagelets要完成一個特定階段,如多個Pagelet顯示區,它們均可以進行進一步JavaScript下載和執行。

在Facebook,咱們鼓勵創造性思考。咱們不斷的嘗試創新技術,以使咱們的網站更快。

做者蔣長浩目前是Facebook的研究科學家,他致力於研究使網站更快的各類創新。

(譯者還找到了幾篇關於BigPipe的文章,若是有興趣你們能夠了解下:Facebook創新之BigPipe:優化頁面加載時間名站技術分析 — facebook奇特的頁面加載技術Facebook讓網站速度提高一倍的BigPipe技術分析Facebooks BigPipe Done in JavaOpen BigPipe javascript implementationTutorial: Implementing Facebook’s BigPipe Using ASP.Net MVCBigPipe Done in Node.js

 

感謝你的閱讀,本文由 騰訊ISUX 版權全部,轉載時請註明出處,違者必究,謝謝你的合做。
註明出處格式:騰訊ISUX (https://isux.tencent.com/bigpipe-pipelining-web-pages-for-high-performance.html)

相關文章
相關標籤/搜索