|
1. 技術(shù)背景—FaceBook頁面加載技術(shù)
試想這樣一個(gè)場景,一個(gè)經(jīng)常訪問的網(wǎng)站,每次打開它的頁面都要要花費(fèi)6秒;同時(shí)另外一個(gè)網(wǎng)站提供了相似的服務(wù),但響應(yīng)時(shí)間只需3 秒,那么你會(huì)如何選擇呢?數(shù)據(jù)表明,如果用戶打開一個(gè)網(wǎng)站,等待3~4 秒還沒有任何反應(yīng),他們會(huì)變得急躁,焦慮,抱怨,甚至關(guān)閉網(wǎng)頁并且不再訪問,這是非常糟糕的情況。所以,網(wǎng)頁加載的速度十分重要,尤其對于擁有遍布全球的5億用戶的Facebook(全球最大的社交服務(wù)網(wǎng)站)這樣的大型網(wǎng)站,有著大量并發(fā)請求、海量數(shù)據(jù)等客觀情況,速度就成了必須攻克的難題之一。
2010年初的時(shí)候,F(xiàn)acebook 的前端性能研究小組開始了他們的優(yōu)化項(xiàng)目,經(jīng)過了六個(gè)月的努力,成功的將個(gè)人空間主頁面加載耗時(shí)由原來的5 秒減少為現(xiàn)在的2.5 秒。這是一個(gè)非常了不起的成就,也給用戶來帶來了很好的體驗(yàn)。在優(yōu)化項(xiàng)目中,工程師提出了一種新的頁面加載技術(shù),稱之為Bigpipe。目前淘寶和Facebook面臨的問題非常相似:海量數(shù)據(jù)和頁面過大,如果可以在詳情頁、列表頁中使用bigpipe,或者在webx中集成bigpipe,將會(huì)帶來明顯的頁面加載速度提升。
2. 相關(guān)介紹
2.1 網(wǎng)站前端優(yōu)化的重要性
《高性能網(wǎng)站建設(shè)指南》一書中指出,只有10%~20%的最終用戶響應(yīng)時(shí)間是花費(fèi)在從Web服務(wù)器獲取HTML文檔并傳送到瀏覽器中的。如果希望能夠有效地減少頁面的響應(yīng)時(shí)間,就必須關(guān)注剩余的80%~90%的最終用戶體驗(yàn)。做個(gè)比較,如果對后臺(tái)業(yè)務(wù)邏輯進(jìn)行優(yōu)化,效率提高了50%,但最終的頁面響應(yīng)時(shí)間只減少了5%~10%,因?yàn)樗嫉谋戎剌^少。如果對前端進(jìn)行性能優(yōu)化,效率提升50%,則會(huì)使最終頁面響應(yīng)時(shí)間減少40%~45%。這是多么可觀的數(shù)字!另外,前端的性能優(yōu)化一般比業(yè)務(wù)邏輯的優(yōu)化更加容易。所以,前端優(yōu)化投入小,見效快,性價(jià)比極高,需要投入更多的關(guān)注。
2.2 BigPipe與AJAX
Web2.0的重要特征是網(wǎng)頁顯示大量動(dòng)態(tài)內(nèi)容,即web2.0注重網(wǎng)頁與用戶的交互。其核心技術(shù)是AJAX,如今所有主流網(wǎng)站都或多或少使用AJAX。與AJAX類似,BigPipe實(shí)現(xiàn)了分塊兒的概念,使頁面能夠分步輸出,即每次輸出一部分網(wǎng)頁內(nèi)容。接下來討論BigPipe與AJAX的區(qū)別。
簡單的說,BigPipe比AJAX有三個(gè)好處:
1. AJAX 的核心是XMLHttpRequest,客戶端需要異步的向服務(wù)器端發(fā)送請求,然后將傳送過來的內(nèi)容動(dòng)態(tài)添加到網(wǎng)頁上。如此實(shí)現(xiàn)存在一些缺陷,即發(fā)送往返請求需要耗費(fèi)時(shí)間,而BigPipe技術(shù)使瀏覽器并不需要發(fā)送XMLHttpRequest請求,這樣就節(jié)省時(shí)間損耗。
2. 使用AJAX時(shí),瀏覽器和服務(wù)器的工作順序執(zhí)行。服務(wù)器必須等待瀏覽器的請求,這樣就會(huì)造成服務(wù)器的空閑。瀏覽器工作時(shí),服務(wù)器在等待,而服務(wù)器工作時(shí),瀏覽器在等待,這也是一種性能的浪費(fèi)。使用BigPipe,瀏覽器和服務(wù)器可以并行同時(shí)工作,服務(wù)器不需要等待瀏覽器的請求,而是一直處于加載頁面內(nèi)容的工作階段,這就會(huì)使效率得到更大的提高。
3. 減少瀏覽器發(fā)送到請求。對一個(gè)5億用戶的網(wǎng)站來說,減少了使用AJAX額外帶來的請求,會(huì)減少服務(wù)器的負(fù)載,同樣會(huì)帶來很大的性能提升。
基于以上三點(diǎn),F(xiàn)acebook 在進(jìn)行頁面優(yōu)化時(shí)采用了BigPipe技術(shù)。目前淘寶主搜索結(jié)果頁中,需要加載類目,相關(guān)搜索,寶貝列表,廣告等內(nèi)容,前端這里使用php的curl的批處理來并發(fā)的訪問引擎獲取相應(yīng)的數(shù)據(jù),并進(jìn)行分步輸出。這種模式還是與bigpipe有些不同,這點(diǎn)后面會(huì)講到。一般來講,在頁面比較大,而且比較復(fù)雜,樣式表和腳本比較多的情況下,使用BigPipe來優(yōu)化輸出頁面是比較合適的。另外非常重要的一點(diǎn),BigPipe并不改變?yōu)g覽器的結(jié)構(gòu)與網(wǎng)絡(luò)協(xié)議,僅使用JS就可以實(shí)現(xiàn),用戶不需要做任何的設(shè)置,就會(huì)看到明顯的訪問時(shí)間縮短。
3. 目前的問題
接下來討論現(xiàn)有的瓶頸。面對網(wǎng)頁越來越大的情況,尤其是大量的css文件和js文件需要加載,傳統(tǒng)的頁面加載模型很難滿足這樣的需求,直接結(jié)果就是頁面加載速度變慢,這絕不是我們希望看到的。目前的技術(shù)實(shí)現(xiàn)中,用戶提出頁面訪問請求后,頁面的完整加載流程如下:
1. 用戶訪問網(wǎng)頁,瀏覽器發(fā)送一個(gè)HTTP請求到網(wǎng)絡(luò)服務(wù)器。
2. 服務(wù)器解析這個(gè)請求,然后從存儲(chǔ)層取數(shù)據(jù),接著生成一個(gè)html文件內(nèi)容,并在一個(gè)HTTP Response中把它傳送給客戶端。
3. HTTP response在網(wǎng)絡(luò)中傳輸。
4. 瀏覽器解析這個(gè)Response ,創(chuàng)建一個(gè)DOM樹,然后下載所需的CSS和JS文件。
5. 下載完CSS 文件后,瀏覽器解析他們并且應(yīng)用在相應(yīng)的內(nèi)容上。
6. 下載完JS 后,瀏覽器解析和執(zhí)行他們
圖1
完整流程見圖1。圖中左側(cè)表示服務(wù)器,右側(cè)表示瀏覽器。瀏覽器先發(fā)送請求,然后服務(wù)器進(jìn)行查找數(shù)據(jù),生成頁面,返回html代碼,最后瀏覽器進(jìn)行渲染頁面。這種模式有非常明顯的缺陷:流程中的操作有著嚴(yán)格的順序,如果前面的一個(gè)操作沒有執(zhí)行結(jié)束,后面的操作就不能執(zhí)行,即操作之間是不能重疊。這樣就造成性能的瓶頸:服務(wù)器生成一個(gè)頁面的內(nèi)容時(shí),瀏覽器是空閑的,顯示空白內(nèi)容;而當(dāng)瀏覽器加載渲染頁面內(nèi)容時(shí),服務(wù)器又是空閑的,時(shí)間與性能的浪費(fèi)由此產(chǎn)生。
圖2
考慮圖2中現(xiàn)有的服務(wù)模型,橫軸表示花費(fèi)的時(shí)間。黃色表示在服務(wù)器的生成頁面內(nèi)容的時(shí)間,白色表示網(wǎng)絡(luò)傳輸時(shí)間,藍(lán)色表示在瀏覽器渲染頁面的時(shí)間。可以看出,現(xiàn)有的模式造成很大的時(shí)間浪費(fèi)。考慮圖3中的情況,圖中綠色表示服務(wù)器從春儲(chǔ)層取查數(shù)據(jù)花費(fèi)的時(shí)間,在海量數(shù)據(jù)下,當(dāng)執(zhí)行一條很費(fèi)時(shí)的查詢語句時(shí)(如下圖右側(cè)),服務(wù)器就就阻塞在那里沒有其他操作,而瀏覽器更是得不到任何反饋。這會(huì)造成非常不友好的用戶體驗(yàn),用戶不知道什么原因使他們等待很長時(shí)間。
圖3
4. BigPipe思想與原理
面對上述問題,我們看下BigPipe的解決辦法。BigPipe提出分塊的概念,即根據(jù)頁面內(nèi)容位置的不同,將整個(gè)頁面分成不同的塊兒—稱為pagelet。該技術(shù)的設(shè)計(jì)者Changhao Jiang是研究電子電路的博士,可能從微機(jī)上得到了啟發(fā),將眾多pagelet加載的不同階段像流水線一樣在瀏覽器和服務(wù)器上執(zhí)行,這樣就做到了瀏覽器和服務(wù)器的并行化,從而達(dá)到重疊服務(wù)器端運(yùn)行時(shí)間和瀏覽器端運(yùn)行時(shí)間的目的。使用BigPipe不僅可以節(jié)省時(shí)間,使加載的時(shí)間縮短,而且可以同過pagelet的分步輸出,使一部分的頁面內(nèi)容更快的輸出,從而獲得更好的用戶體驗(yàn)。BigPipe中,用戶提出頁面訪問請求后,頁面的完整加載流程如下:
1. Request parsing:服務(wù)器解析和檢查http request
2. Datafetching:服務(wù)器從存儲(chǔ)層獲取數(shù)據(jù)
3. Markup generation:服務(wù)器生成html 標(biāo)記
4. NETwork transport : 網(wǎng)絡(luò)傳輸response
5. CSS downloading:瀏覽器下載CSS
6. DOM tree construction and CSS styling:瀏覽器生成DOM 樹,并且使用CSS
7. JavaScript downloading: 瀏覽器下載頁面引用的JS文件
8. JavaScript execution: 瀏覽器執(zhí)行頁面JS代碼
這個(gè)8 個(gè)流程幾乎與上文中提到現(xiàn)有的模式?jīng)]有區(qū)別,但這整個(gè)流程只是一個(gè)pagelet 的完整流程,而多個(gè)pagelet 的不同操作階段就可以像流水線一樣進(jìn)行執(zhí)行了。
圖4
圖4 中,可以看出BigPipe對原有的模式進(jìn)行的改進(jìn)。瀏覽器發(fā)送訪問請求,然后瀏覽器分步返回不同的pagelet的內(nèi)容,具體實(shí)現(xiàn)將在后面介紹。考慮圖5中的改進(jìn),BigPipe 打破了原有的順序執(zhí)行,將頁面分成不同的pagelet ,如此一來,所有的pagelet 的執(zhí)行時(shí)間累加起來還是原有的時(shí)間。但是, 通過疊加不同pagelet 的不同階段的執(zhí)行時(shí)間,使總的運(yùn)行時(shí)間大大減少,這就是Bigpipe減少頁面加載時(shí)間的秘密。
FaceBook的頁面被分成了很多不同的pagelets,如圖:
圖5
5. BigPipe實(shí)現(xiàn)原理
了解了BigPipe 的核心思想后,我們討論它的實(shí)現(xiàn)原理。當(dāng)瀏覽器訪問服務(wù)器時(shí),服務(wù)器接受請求并對其進(jìn)行檢查。如果請求有效,服務(wù)器端不做任何的查詢,而是立刻返回一個(gè)http response給瀏覽器,內(nèi)容是一段html代碼,包括html<head> 標(biāo)簽和<body> 標(biāo)簽的一部分。<head>標(biāo)簽包括BigPipe的js文件和css文件,這個(gè)js文件用來解析后面接收的http response,因?yàn)楹竺鎮(zhèn)鬏數(shù)膬?nèi)容都為js腳本。未封閉的<body>標(biāo)簽中,是顯示頁面的邏輯結(jié)構(gòu)和pagelet 的占位符的模板,例如:
<body>
<div></div>
<div></div>
<div></div>
<div>
<div>
<div id=”hotnews”></div>
<div id=”societynews”></div>
<div id=”financialnews”></div>
<div id=”ITnews”></div>
<div id=”sportsnews”></div>
</div>
<div></div>
</div>
<div></div>
it知識(shí)庫:BigPipe學(xué)習(xí)研究,轉(zhuǎn)載需保留來源!
鄭重聲明:本文版權(quán)歸原作者所有,轉(zhuǎn)載文章僅為傳播更多信息之目的,如作者信息標(biāo)記有誤,請第一時(shí)間聯(lián)系我們修改或刪除,多謝。