聶永的博客

          記錄工作/學(xué)習(xí)的點(diǎn)點(diǎn)滴滴。

          Servlet 3.0筆記之異步請(qǐng)求Facebook BigPipe簡(jiǎn)單模型實(shí)現(xiàn)

          當(dāng)前的前端技術(shù)明星為Facebook,相繼拋出了Quickling,BigPipe等新鮮概念,引領(lǐng)著前端優(yōu)化的潮流。果然具有大公司的范兒,適時(shí)的回饋給整個(gè)開發(fā)社群,讓全體朝前前進(jìn)了一小步。超贊!
          抽空學(xué)習(xí)了BigPipe,大概相當(dāng)于分段刷新(flush),強(qiáng)制輸出。雖有點(diǎn)舊瓶裝新酒的味道,不過前端已經(jīng)進(jìn)入了細(xì)節(jié)為王的階段,或許在國(guó)內(nèi)已經(jīng)有人在用,但缺乏分享溝通,或者還不成熟,缺乏關(guān)注,缺少重要數(shù)據(jù)用以論證等。
          BigPipe:高性能的“流水線技術(shù)”網(wǎng)頁(yè),或許可以為需要認(rèn)知的人們打開一扇窗戶。
          原文介紹BigPiple:
          BigPipe是一個(gè)重新設(shè)計(jì)的基礎(chǔ)動(dòng)態(tài)網(wǎng)頁(yè)服務(wù)體系。大體思路是,分解網(wǎng)頁(yè)成叫做Pagelets的小塊,然后通過Web服務(wù)器和瀏覽器建立管道并管理他們?cè)诓煌A段的運(yùn)行。這是類似于大多數(shù)現(xiàn)代微處理器的流水線執(zhí)行過程:多重指令管線通過不同的處理器執(zhí)行單元,以達(dá)到性能的最佳。雖然BigPipe是對(duì)現(xiàn)有的服務(wù)網(wǎng)絡(luò)基礎(chǔ)過程的重新設(shè)計(jì),但它卻不需要改變現(xiàn)有的網(wǎng)絡(luò)瀏覽器或服務(wù)器,它完全使用PHP和JavaScript來實(shí)現(xiàn)。
          BigPipe在Facebook應(yīng)用中的工作流程:
          1. 請(qǐng)求解析:Web服務(wù)器解析和完整性檢查的HTTP請(qǐng)求。
          2. 數(shù)據(jù)獲取:Web服務(wù)器從存儲(chǔ)層獲取數(shù)據(jù)。
          3. 標(biāo)記生成:Web服務(wù)器生成的響應(yīng)的HTML標(biāo)記。
          4. 網(wǎng)絡(luò)傳輸:響應(yīng)從Web服務(wù)器傳送到瀏覽器。
          5. CSS的下載:瀏覽器下載網(wǎng)頁(yè)的CSS的要求。
          6. DOM樹結(jié)構(gòu)和CSS樣式:瀏覽器構(gòu)造的DOM文檔樹,然后應(yīng)用它的CSS規(guī)則。
          7. JavaScript中下載:瀏覽器下載網(wǎng)頁(yè)中JavaScript引用的資源。
          8. JavaScript執(zhí)行:瀏覽器的網(wǎng)頁(yè)執(zhí)行JavaScript代碼。
          其帶來效果較為明顯處在于:
          這種高度并行系統(tǒng)的最終結(jié)果是,多個(gè)Pagelets的不同執(zhí)行階段同時(shí)進(jìn)行。例如,瀏覽器可以正在下載三個(gè)Pagelets CSS的資源,同時(shí)已經(jīng)顯示另一Pagelet內(nèi)容,與此同時(shí),服務(wù)器也在生成新的Pagelet。從用戶的角度來看,頁(yè)面是逐步呈現(xiàn)的。最開始的網(wǎng)頁(yè)內(nèi)容會(huì)更快的顯示,這大大減少了用戶的對(duì)頁(yè)面延時(shí)的感知。如果您要自己親眼看到區(qū)別,你可以嘗試以下連接: 傳統(tǒng)模式BigPipe。第一個(gè)鏈接是傳統(tǒng)模式單一模式顯示頁(yè)面。第二個(gè)鏈接是BigPipe管道模式的頁(yè)面。如果您的瀏覽器版本比較老,網(wǎng)速也很慢,瀏覽器緩存不佳,哪么兩頁(yè)之間的加截時(shí)間差別將更加明顯。
          值得一提的是BigPipe是從微處理器的流水線中得到啟發(fā)。然而,他們的流水線過程之間存在一些差異。例如,雖然大多數(shù)階段BigPipe只能操作一次Pagelet,但有時(shí)多個(gè)Pagelets的CSS和JavaScript下載卻可以同時(shí)運(yùn)作,這類似于超標(biāo)量微處理器。BigPipe另一個(gè)重要區(qū)別是,我們實(shí)現(xiàn)了從并行編程引入的“障礙”概念,所有的Pagelets要完成一個(gè)特定階段,如多個(gè)Pagelet顯示區(qū),它們都可以進(jìn)行進(jìn)一步JavaScript下載和執(zhí)行。
          啟用了BigPipe后,服務(wù)器端優(yōu)先輸出頁(yè)面整體布局,瀏覽器渲染布局;服務(wù)器按照串行方式,一段段按優(yōu)先級(jí)順序,輸出片段內(nèi)容到瀏覽器端,瀏覽器執(zhí)行JS函數(shù),同時(shí)可能會(huì)同時(shí)請(qǐng)求新的JS文件(盡可能不要涉及外部JS),下載特定樣式文件(這個(gè)時(shí)候可以產(chǎn)生并發(fā)連接)。瀏覽器渲染頁(yè)面單個(gè)組件(Pagelet),組件同時(shí)加載CSS、JS文件時(shí),不會(huì)影響到下一個(gè)組件的渲染工作。以往的頁(yè)面模型在于,瀏覽器接收所有數(shù)據(jù),然后一次性渲染,顯示最終結(jié)果給客戶。
          BigPipe涉及到的一些問題,原文沒有涉及,來自淘寶的李牧在他的博客中(Facebook讓網(wǎng)站速度提升一倍的BigPipe技術(shù)分析)提出一些疑問:
          腳本阻滯:
                   我們知道直接在html中引入外部腳本會(huì)造成頁(yè)面阻滯,即使使用無阻腳本下載的一系列方法引入外部js,但因?yàn)镴S單線程,當(dāng)這些腳本load進(jìn)來之后運(yùn)行時(shí)也會(huì)發(fā)生阻滯.因?yàn)镕acebook頁(yè)面多樣,依賴腳本大小不一,這些阻滯會(huì)對(duì)頁(yè)面的快速展現(xiàn)造成影響.
                  Facebook做法是在ondomready之前只在頭部輸出一個(gè)很小的外部腳本,作為bigpipe的支撐.其余所有模塊如果依賴外部腳本(比如某一模塊需要日歷控件支持),都會(huì)在domready事件之后加載.這樣做即保證了所有頁(yè)面所有模塊都能在domready前快速形成展現(xiàn),又可以保證無腳本阻滯的快速的domready時(shí)間.
                  最快可交互時(shí)間:
                   domready再快也至少是在頁(yè)面第一個(gè)使用bigpipe輸出的chunked的http請(qǐng)求完成之后,對(duì)于Facebook來說,這很可能是2秒之后了.那在這2s期間,如果只是頁(yè)面展現(xiàn)了而不能交互(點(diǎn)擊日歷無反應(yīng)),那方案依然不夠完美.
                   Facebook的做法是,在domready后所依賴腳本已被加載之前,點(diǎn)擊行為將會(huì)生成一個(gè)額外的腳本請(qǐng)求,只將這個(gè)點(diǎn)擊所依賴的腳步預(yù)先load進(jìn)來.這樣保證了最快的可交互時(shí)間.Facebook在另一篇文章中對(duì)這個(gè)技術(shù)進(jìn)行了詳細(xì)的描述.
                   Bigpipe原理簡(jiǎn)單,實(shí)現(xiàn)不復(fù)雜,但Facebook卻用了1年的時(shí)間才形成完備的解決方案.生成方案需要時(shí)間,而解決隨之而來的腳本阻滯,保障最快交互時(shí)間等等問題也會(huì)消耗大量時(shí)間. 
          較為全面的了解了BigPipe,下面使用使用JAVA Servlet 3.0 異步特性,簡(jiǎn)單模擬BigPipe實(shí)現(xiàn),沒有涉及到頁(yè)面組件單獨(dú)請(qǐng)求的JS、CSS文件等,僅僅用以演示其過程(最終效果大打折扣)。
          我們目標(biāo)頁(yè)面大致結(jié)構(gòu)如下,在 The 1KB CSS Grid 生成結(jié)構(gòu)上修改。 moz-screenshot-2
          異步Servlet代碼:

          傳統(tǒng)MVC模式在這里貌似去除了,一切在服務(wù)器端生成,可借助Freemarker或者靜態(tài)頁(yè)面輔助,減輕純手工拼接HTML代碼的麻煩。
          生成客戶端代碼:
          moz-screenshot-3_thumb[1].png (800×441)
          在Servlet代碼中,每輸出一段HTML腳本都會(huì)迫使當(dāng)前線程沉睡一定時(shí)間,用戶在瀏覽頁(yè)面時(shí),按照優(yōu)先級(jí)順序一段一段的輸出,用戶體驗(yàn)不錯(cuò)。下面的截圖,可以略微感知一下。
          image
          話說若使用BigPipe,須分段刷新,則服務(wù)器無法獲得最終輸出內(nèi)容長(zhǎng)度,只能采用chunked壓縮編碼格式輸出內(nèi)容,能節(jié)省網(wǎng)絡(luò)流量;但不利于SEO,按照Facebook做法就是,若搜索爬蟲訪問,就會(huì)按照正常方式生成頁(yè)面。另一方面,BigPipe的應(yīng)用場(chǎng)景適合計(jì)算量大、較為耗時(shí)、擁有若干相互獨(dú)立模塊的頁(yè)面,中小頁(yè)面不太適合。

          posted on 2011-02-22 20:47 nieyong 閱讀(2770) 評(píng)論(0)  編輯  收藏 所屬分類: Servlet3

          公告

          所有文章皆為原創(chuàng),若轉(zhuǎn)載請(qǐng)標(biāo)明出處,謝謝~

          新浪微博,歡迎關(guān)注:

          導(dǎo)航

          <2011年2月>
          303112345
          6789101112
          13141516171819
          20212223242526
          272812345
          6789101112

          統(tǒng)計(jì)

          常用鏈接

          留言簿(58)

          隨筆分類(130)

          隨筆檔案(151)

          個(gè)人收藏

          最新隨筆

          搜索

          最新評(píng)論

          閱讀排行榜

          評(píng)論排行榜

          主站蜘蛛池模板: 九江市| 宝兴县| 安多县| 涿鹿县| 荔波县| 淄博市| 蓝山县| 陇西县| 高雄县| 通州市| 望江县| 偃师市| 青浦区| 松江区| 克什克腾旗| 苍溪县| 伊川县| 浙江省| 杂多县| 都匀市| 永城市| 新兴县| 睢宁县| 巴青县| 句容市| 洛川县| 安庆市| 霍城县| 扶沟县| 江城| 龙海市| 福泉市| 奇台县| 盐城市| 犍为县| 双柏县| 时尚| 松桃| 河西区| 彰化县| 临西县|