天天看點

Facebook讓網站速度提升一倍的BigPipe技術分析

近來[url=http://www.facebook.com/note.php?note_id=389414033919]Facebook高調宣布将網站性能提高一倍[/url],平均通路時間從5s降至2.5s,公布了名為BigPipe的優化技術的一些概況.性能提升一倍這個結果無疑是極其誘人的,如果各個網站都能應用這種技術拿到這樣的結果,那BigPipe很有可能會成為匹敵Ajax的技術革新.它究竟是怎樣的?會給你的應用帶來這樣的提升麼?

[b]先來摘要:[/b]

BigPipe原理:再簡單不過了,這就像在餐館吃飯,先選好桌子點好菜(确定使用者布局和要展現的子產品),單子下到廚房後,多個大廚就可以同時上陣(服務端并發),做好一樣端上來一樣吃一樣(用戶端并發).

BigPipe不具備普适性:網站性能優化再發展下去也不會增加一條類似"盡量減少http數","将CSS放在頁面上部"這樣不加任何說明和限制的優化準則---"使用Bigpipe提高網站速度",也就是說它不可能為所有應用都帶來提升,或者說bigpipe可能給你的應用帶來提升,但不會像Facebook那麼大.

BigPipe适用的場合:首先,[color=red]網頁第一個請求時間較長[/color]( >500ms? ),在整個網頁展現過程中不再是前端性能優化常說的可以忽略的10-20%.其次頁面上的[color=red]動态内容可以劃分在多個區塊内顯示,且各個區塊之間的關系不大[/color],因為隻是用戶端和服務端并發是不夠的,服務端各個資料中心也要能夠并發才能最好的發揮bigpipe,[color=red]各個區塊的動态資料在服務端也能夠通過url或cookie中的key并發獲得[/color](在facebook,整個key為userid).除了SNS外,大概搜尋結果頁可能可以用上,比如淘寶搜尋結果頁的主搜尋,類目導航,相關推薦和廣告可以使用BigPipe技術,不過回過頭看第一個限制,如果搜尋頁本身很快,那帶來的改進不會如Facebook明顯.

BigPipe的啟示:通過上面的這些限制看到Bigpipe是Facebook量身定做的優化方案,帶來的一點提示是大家可以根據自己的應用為自己的應用定制優化方案,flush,ajax,靜态資源combo,動态資料combo都是性能優化的手段,如何選擇要看實際情況.

[b]詳細分析:[/b]

之前的一篇文章"[url=http://limu.iteye.com/blog/755628]在Yslow 34 Rules之後 -- 網站性能優化思路和進展[/url]"中提到網站性能優化進入精耕細作階段,盡可能的滿足各種Rules可以保證你能獲得一個性能不錯網站,而更進一步的優化則需要理清優化思路,結合具體應用的實際下功夫.Facebook的BigPipe技術就是這樣發展出來的一種高度契合SNS類應用的優化技術.可以這麼說,網站性能優化再發展下去也不會增加一條類似"盡量減少http數","将CSS放在頁面上部"這樣不加任何說明和限制的優化準則---"使用Bigpipe提高網站速度",也就是說它不可能為所有應用都帶來提升.我們通過分析這種技術的産生過程,分析SNS類網站頁面的特點,看看和你的應用有沒有比對的地方,來确定你的應用是否應該選用這種技術.另外也可以學習Facebook性能優化的套路,仔細考慮下自己應用的特點,是不是也能爆出讓人眼前一亮的方案.

下面就開始分析Facebook網頁的特點,網站性能優化的任何資料都經常見到"網頁展現過程百分之八十至九十的時間消耗在了前端"這樣的話,這種斷言主要來自這類最常見的HTTP瀑布圖,如下:

[img]http://dl.iteye.com/upload/attachment/307506/4ebce116-cb0d-3f6b-b403-34ebf601475b.png[/img]

在網頁的生命周期中,到達動态伺服器的資料請求往往隻是第一個HTML文本請求.相對于這個HTML到達浏覽器之後再引入的一系列腳本,圖檔等等請求以及後續的渲染過程,第一個請求所占時間相當少.是以一般而言,再怎麼做服務端的優化,對于整個展現過程的加快的幫助微小.但Facebook不同,下面是我的Facebook的個人首頁的首個HTTP請求時間:

[img]http://dl.iteye.com/upload/attachment/307511/ced0681b-7f88-35d2-ad3b-da17f7dc1690.png[/img]

長達3.173s,刨除網絡響應因素,僅接收資料階段,時間也達到了1.65s.Facebook有慢的理由,因為SNS網站的頁面是高度定制化的,每個區塊的資料都需要大量的計算得來.是以對于Facebook來說,要提升整體頁面響應時間,服務端的時間不得不考慮進去.如何優化?YSlow優化規則中"[url=http://developer.yahoo.com/performance/rules.html#flush]提早Flush[/url]"給了很好的提示."提早Flush"規則建議在</head><body>之間調用flush(),讓這部分内容先輸出給浏覽器端,這樣浏覽器端可以在服務端還在生成主體HTML的同時先顯示标題,同時下載下傳<head>中的css和js檔案,說到底是服務端和浏覽器端并發處理頁面展現.但Facebook如果僅做到這樣的"提早flush",對性能的提升不會很明顯.因為大量的時間消耗在<body>主體内容的生成時段.是以很自然想到需要分塊flush,分塊渲染.而Facebook頁面恰恰可以分塊:

[img]http://dl.iteye.com/upload/attachment/311820/e5e65eba-044e-3c1d-96f4-42cc31625728.jpg[/img]

我們看到Facebook分塊後還有一個特點,就是各個區塊的資訊都是動态的,而動态資訊都是根據userid查詢得來,各個區塊之間并沒有關聯,"好友動态"和"書簽"完全沒有關系.這樣的特性可以帶來另一個好處,就是服務端并發,Facebook首先取到目前使用者的頁面定制資訊,生成布局,flush出去,然後在服務端就可以根據取到的使用者已定制展現子產品清單,并發請求各個資料中心,這樣在背景各類應用可以按照統一接口,以區塊劃分,去除了各系統間的耦合.

原理再簡單不過了,這就像在餐館吃飯,先選好桌子點好菜(确定使用者布局和要展現的子產品),然後單子下到廚房後,多個大廚就可以同時上陣(服務端并發),做好一樣端上來一樣吃一樣(用戶端并發).這樣從浏覽器端到服務端,在接收資料的這1.5s左右時間之内,真正成了一個流水線.同樣的那些限制條件也很好解釋,吃快餐就完全沒必要一盤菜取一次,每盤菜之間沒什麼關系.好處也顯而易見,每個大廚做自己最擅長的,效率效果都會最優.

[b]Bigpipe作為完整技術方案的若幹技術細節:[/b]

我想任何了解flush(),chunked http,Javascript的開發者都能快速開發出Bigpipe的Demo.先輸出布局HTML,包含若幹pagelet(Facebook稱頁面區塊為pagelet)的容器div.動态資料到達後輸出一段inline script,裡面包含響應的html串和一些配置資訊等等,調用onPageletArrived()方法将html片段插入pagelet容器中.上段代碼意思下:

這裡想讨論的是,使用這種方案會引入哪些其他問題,Facebook又是如何解決的.

[b]腳本阻滞:[/b]

我們知道直接在html中引入外部腳本會造成頁面阻滞,即使使用無阻腳本下載下傳的一系列方法引入外部js,但因為JS單線程,當這些腳本load進來之後運作時也會發生阻滞.因為Facebook頁面多樣,依賴腳本大小不一,這些阻滞會對頁面的快速展現造成影響.

Facebook做法是在ondomready之前隻在頭部輸出一個很小的外部腳本,作為bigpipe的支撐.其餘所有子產品如果依賴外部腳本(比如某一子產品需要月曆控件支援),都會在domready事件之後加載.這樣做即保證了所有頁面所有子產品都能在domready前快速形成展現,又可以保證無腳本阻滞的快速的domready時間.

[b]最快可互動時間:[/b]

domready再快也至少是在頁面第一個使用bigpipe輸出的chunked的http請求完成之後,對于Facebook來說,這很可能是2秒之後了.那在這2s期間,如果隻是頁面展現了而不能互動(點選月曆無反應),那方案依然不夠完美.

Facebook的做法是,在domready後所依賴腳本已被加載之前,點選行為将會生成一個額外的腳本請求,隻将這個點選所依賴的腳步預先load進來.這樣保證了最快的可互動時間.[url=http://ajaxian.com/archives/facebook-javascript-jsconf]Facebook在另一篇文章[/url]中對這個技術進行了詳細的描述.

Bigpipe原理簡單,實作不複雜,但Facebook卻用了1年的時間才形成完備的解決方案.生成方案需要時間,而解決随之而來的腳本阻滞,保障最快互動時間等等問題也會消耗大量時間.

[b]總結一下:[/b]

Bigpipe在Facebook獲得巨大成功,我想在于對細節的深度挖掘.如果第一個請求時間不用那麼長,那相當于去吃麥當勞還分兩次拿薯條和漢堡.如果服務端不能并發,那肯定達不到如此好的優化效果.如果不排除外聯腳本的下載下傳和運作阻滞帶來的不确定性,也得不到如此高的展現速度.同時如果不對domready前的click按需加載處理,可互動性會大打折扣.當然Facebook可能還有更多我們不知道的類似的技術細節,所有這些細節聯合起來,才能得到這樣漂亮的結果.

系統優化是個浩大的工程,在Yslow Rules這類規則預設遵守之後,要想再獲得突破,那隻能從自身的應用出發做選最合适的方案.同時Bigpipe出現不意味着Ajax過時了落伍了.頁面的動态資料來自多個資料中心,那麼用Bigpipe吧.如果一個頁面上的動态資料可以用一個Ajax請求獲得,那完全沒必要用它.大多數應用第一個http請求的時間依然隻用了很短的時間,是以Ajax還是主流.

繼續閱讀