天天看點

BigPipe 的工作原理

BigPipe是一個重新設計的基礎動态網頁服務體系。大體思路是,分解網頁成叫做Pagelets的小塊,然後通過Web伺服器和浏覽器建立管道并管理他們在不同階段的運作。這是類似于大多數現代微處理器的流水線執行過程:多重指令管線通過不同的處理器執行單元,以達到性能的最佳。雖然BigPipe是對現有的服務網絡基礎過程的重新設計,但它卻不需要改變現有的網絡浏覽器或伺服器,它完全使用PHP和JavaScript來實作。

  

動機

  為了更好的了解BigPipe,我們需要了解一下現有的動态Web服務系統,它的曆史可以追溯到網際網路的初期,但現在與初期相比卻并沒有多少改變。現代網站有着遠遠高于10年前的動态效果和互動性,但傳統的網頁服務系統早已無法跟上當今網際網路速度的要求。在傳統的模式,使用者請求的生命周期如下:

  1. 浏覽器發送一個HTTP請求到Web伺服器。

  2. Web伺服器解析請求,然後讀取資料存儲層,制定一個HTML檔案,并用一個HTTP響應把它發送到用戶端。

  3. HTTP響應通過網際網路傳送到浏覽器。

  4. 浏覽器解析Web伺服器的響應,使用HTML檔案建構了一個的DOM樹,并且下載下傳引用的CSS和JavaScript檔案。

  5. CSS資源下載下傳後,浏覽器解析它們,并将它們應用到DOM樹。

  6. JavaScript資源下載下傳後,浏覽器解析并執行它們。

  傳統模式在現代網站中效率是非常低下的,因為很多系統的操作順序,不能互相重疊。一些如延時加載JavaScript、并行下載下傳等優化技術已被網絡社群廣泛采用,以此來克服的一些限制。然而,這些優化卻很少涉及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同時執行。

  在BigPipe,一個使用者請求的生命周期是這樣的:在浏覽器發送一個HTTP請求到Web伺服器。在收到的HTTP請求,并在上面進行一些全面的檢查,網站伺服器立即發回一個未關閉的HTML檔案,其中包括一個HTML 标簽和标簽的開始标簽。标簽包括BigPipe的JavaScript庫來解析Pagelet以後收到的答複。在标簽,有一個模闆,它指定了頁面的邏輯結構和Pagelets占位符。

  在用戶端在收到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使使用者在大多數浏覽器中感受到的延遲減少了一半。