名站技術分析 — facebook奇特的頁面加載技術


沒事使用代理上了下facebook,註冊進入我的首頁後,習慣性的查看源代碼,發現了1個頗有意思的現象,首頁內容很多,但源代碼中HTML的代碼卻不多,但去多出了不少段的javascript代碼,這些js代碼都是用於動態生成html的,facebook爲何須要這樣作了?出於職業習慣,研究研究:javascript

 

1、html代碼。php

   先看看首頁查看的源代碼,由於源代碼比較大,因此把圖片壓縮了下,可能看不太清楚,只須要注意圖中紅色是html代碼,其他黑壓壓一片的就所有是JS代碼:css


正在上傳...取消html

 

 

 

2、JS代碼java

   看到黑壓壓的JS代碼是否是被嚇一跳,下面就截取一段JS來分析(其他段的JS都是相似的),facebook源代碼中充斥了相似於下面的JS代碼:面試

 

<script>ajax

big_pipe.onPageletArrive({數據庫

    "id":"pagelet_welcome_box","phase":1,"is_last":false,"append":false,"bootloadable":[],瀏覽器

    "css":["lDRwi","eon+N"],緩存

    "js":["F+B8D","IdQlc"],

    "resource_map":[],"requires":[],"provides":[],

    "onload":["window.__UIControllerRegistry[\"c4c13a3ed2dd1e0e349b72\"] = new UIPagelet(\"c4c13a3ed2dd1e0e349b72\", \"\\\/pagelet\\\/generic.php\\\/WelcomeBoxPagelet\\\/\", {}, {});; ;"],

    "onafterload":[],"onpagecache":[],"onafterpagecache":[],"refresh_pagelets":[],"invalidate_cache":[],

    "content":{

        "pagelet_welcome_box":"<div id=\"c4c13a3ed2dd1e0e349b72\"><div class=\"UIImageBlock clearfix fbxWelcomeBox\"> ...這裏省略N多HTML"

        },

    "page_cache":true

});

</script>

 

讓咱們再看看big_pipe.onPageletArrive函數到底作了什麼了?咱們只關注參數中的id,js,css,content4個參數,能夠看出js和css都是進行過編碼,下面是解碼後咱們關注的代碼:

<script>

big_pipe.onPageletArrive({

    "id":"pagelet_welcome_box",

    "css":{

        name: "css/c5mv8gd5gwoc4kk0.pkg.css"

        permanent: true

        src: "http://static.ak.fbcdn.net/rsrc.php/zBP3B/hash/abee68r4.css"

        type: "css"

    },

    "js":{

        name: "js/19khsprwvtvokwow.pkg.js"

        permanent: false

        src: "http://static.ak.fbcdn.net/rsrc.php/zAVXU/hash/e8mwcqsi.js"

        type: "js"

    },

    "content":{

        "pagelet_welcome_box":"<div id=\"c4c13a3ed2dd1e0e349b72\"><div class=\"UIImageBlock clearfix fbxWelcomeBox\"> ...這裏省略N多HTML"

        }

});

</script>

看到還原後的JS,你應該猜出onPageletArrive函數是幹嗎的吧,其實onPageletArrive最主要實現就是把"content"中的html內容插入到對應id(上面的"pagelet_welcome_box")的html元素中,並下載對應的css和JS。

 

3、chunk、flush

    看到上面的分析後,你們必定奇怪,facebook爲何要生成那麼多段JS,再用js去動態插入html代碼,這不是脫了褲子放屁,畫蛇添足嗎?還不如直接生成html代碼了。facebook固然不會那麼笨了,讓咱們先監控下facebook的http請求,監控圖以下:

 

 

    注意上圖中紅色部分,原來facebook使用了chunk對頁面進行分塊輸出。這就比較容易理解了,facebook首頁的js代碼段不是1次就所有輸出的,而是一段一段進行輸出的。

    什麼是chunk和如何使用chunk,請參考個人另1篇博文:flush讓頁面分塊,逐步呈現

 

總結

   facebook使用chunk技術讓頁面分塊輸出成不少JS段,這樣作的好處就是服務器和客戶端能夠並行進行處理,不用等服務器所有處理完畢,客戶端才進行處理。

   舉個博客園首頁的列子,博客園首頁分爲下面幾塊("推薦博客排行","首頁隨筆列表","最新新聞"...),

   咱們通常對該http請求處理以下:

     1. 瀏覽器發送http請求

     2. 服務器處理請求(從緩存讀取前50個推薦博客,從數據庫讀取"首頁隨筆列表",從數據庫讀取"最新新聞"),生成首頁的html代碼。

     3. 服務器發送html代碼給客戶端

     四、瀏覽器接收到響應,處理html(下載css,js,image,執行js等等)

   能夠看出傳統的http請求4個過程當中,每一個過程都必須等待前1個過程完成後才能執行,這樣就存在很大的資源浪費。

 

   facebook的對該http請求的處理以下:

     1. 瀏覽器發送http請求

     2. 服務器處理請求(從緩存讀取前50個推薦博客,生成"推薦博客"的js代碼段,flush輸出該代碼段,

服務器繼續讀取"首頁隨筆列表",並生成輸入js代碼段。

服務器繼續讀取"最新新聞",並生成輸入js代碼段。

     3. 瀏覽器接收到js代碼段,下載該代碼段所需的js和css。插入html代碼。

   在這個處理流程中,最大的特色就是2,3是並行進行處理的,服務器處理完一部分數據就把已經處理好的數據交給瀏覽器進行呈現處理,本身再繼續處理其餘的數據。

 

PS:文章看完了,有些同窗可能會想,爲何不像博客園同樣,前臺所有用ajax來異步讀取"推薦博客" ,「最新新聞」的數據了,這樣作就不會出現由於要處理太多數據而讓客戶端等待過久的問題了。我以爲對於facebook這種併發量巨大的網站,使用這種方法無疑會產生太多的請求,好比facebook首頁用了14個chunk,若是使用ajax,則須要多14個request請求,這將增長很多服務器的壓力吧。    

文末也給你們,分享主要有C/C++,Linux,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒體,CDN,P2P,K8S,Docker,TCP/IP,協程,DPDK技術,面試技巧方面的資料技術討論。

感興趣的朋友戳這裏能夠加羣:812855908

相關文章
相關標籤/搜索