關於大型網站技術演進的思考(十)--網站靜態化處理—動靜整合方案(2)

  上篇文章 我簡要的介紹了下網站靜態化的演進過程,有朋友可能認爲這些知識有點過於稀鬆平常了,而且網站靜態化的技術基點也不是那麼高深和難以理解,因此它和時下日 新月異的web前端技術相比,就顯得不倫不類了。其實當我打算寫本系列的之前我個人覺得web前端有一個點是很多人都知道重要,但是有常常低估它作用的, 那就是web前端和web服務端如何融合的這個點上,這個點再加上我們要做出一個規模龐大,高併發,快速響應的網站時候它對於web前端的架構技術的演進 起到了一個不可忽視的作用。

  網站的 web前端要實現高效,第一個要解決的短板就是網絡的延遲性對網站的加載效率的影響,當然很多人會說網速快不快這是網絡運營商的問題,不是網站的問題,但 是大家肯定也見過就算我們用上了千兆寬帶也會有些網站加載速度慢的讓人無法忍受,網站本身的確是沒法控制網絡速度的能力,但是如果我們不降低網絡對頁面加 載效率的影響,其他任何優化網站的手段也就無從談起,原因就是網絡效率對於網頁加載效率的影響是起到大頭作用的,只有這個大頭被解決了,那麼解決其他的小 頭才能發揮作用。

  回到上文 講到的網站靜態化的關鍵點動靜分離,解決這個關鍵點的本質就是爲了降低網速對網站加載效率的影響,但是我們在處理動靜分離問題時候採取的策略不同會對我們 整個網站架構產生重大影響,特別是將網頁做好動靜拆分後,靜態的資源盡力向瀏覽器端推移,這就導致了前端架構出現了以前服務端纔有的MVC模式,這就導致 web前端架構產生了質的變化,如是一些原來適用於flash這樣的重客戶端的技術也被傳統的web前端所採用,MVC模式在web前端進一步演進由此而 出現了MVP(Model-View-Presenter)模式,MVVM(Model-View-ViewModel)模式。也許上篇文章裏有人對講述 動靜分離的原理有點異議,但是當今日新月異的web前端技術就是這些常見技術不斷演化而來,這就是我上篇想表達的內容,我覺得這個系列的特點應該是細節, 這是和上個系列存儲的瓶頸注重思想是有所不同的。

  動態網站 最難以動靜分離的就是頁面了,其他的靜態資源例如:圖片、外部腳本文件等等這些和靜態網站的手法基本一致,其實業界很早就關注了動態網站的動靜分離問題, 並且爲不同的動靜分離方案都進行了總結,今天我就介紹下這些技術。本人web服務端的工作語言是java,因此下面服務端的例子是使用java的web技 術闡述的,其他語言例如php都有與之對應的技術,所以請那些不是使用java作爲服務端工作語言的朋友可以類比學習。

  在java的web開發裏,頁面技術jsp本身就包含了將頁面動靜分離的手段,例如下面的代碼:

<%@ include file=”header.jsp” %>

<body>

         ……….

<%@ include file=”footer.jsp” %>

  一般一個 網站的頭部和尾部都是一樣,因此我們把頭部的代碼單獨放置在一個header.jsp頁面裏,頁面尾部的代碼放置下footer.jsp頁面裏,這樣技術 人員在開發頁面時候就不再需要重複編寫這些重複的代碼,只需要引用即可,這個做法最大的好處就是可以避免不同頁面在相同代碼這塊的不一致性,假如沒有這個 統一引用的話,手動編寫或者複製和粘貼,出錯的概率是非常的高的。

  但是這個 做法有一個問題,問題就是這種動靜分離其實都是作用於單個頁面的,也就是說每個頁面都要手動的重複這個動靜分離的操作,大多數情況這種做法都不會有什麼問 題,但是對於一個大型網站而言這種做法就有可能會製造不必要的麻煩,這裏我截取了一張京東的首頁,如下圖所示:

 

  講述前我 要事先聲明下,京東網站可能不存在我要講述的問題,我這裏只是使用京東網站的首頁做例子來說明,看圖裏的首頁和食品兩個條目,有些公司做這樣的網站時候這 些導航進入的頁面會是一個獨立的工程,每個工程都是由獨立的項目組開發維護的,雖然項目組不同但是他們頁面的整體結構會是一致的,如果按照上面的動靜分離 手段,那麼每個項目組都要獨立維護一份相同的頭部尾部資源,這個時候麻煩來了,如果該公司要新增個新的條目,那麼每個項目組都要更新自己不變的資源,如果 該企業一共分了5個項目組,現在又做了一個新的條目,那麼其他與之無關的項目組都得折騰一次更改統一引用文件的工作,要是做的不仔細就有可能出現頁面展示 不一致的問題,爲了解決這個問題,java的web開發裏就會考慮使用模板語言替代jsp頁面技術,例如模板語言velocity,這些模板語言都包含一 個佈局的功能,例如velocity就有這樣的功能,我們看看velocity的佈局模板實例,如下所示:

<html><head>

    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>

    <title>#springMessage("page_upop_title")</title>

    <meta http-equiv="X-UA-Compatible" content="requiresActiveX=true"/>

    <meta name="keywords" content='#springMessage("page_upop_keywords")'/>

    <meta content='#springMessage("page_upop_description")' name="description"/></head><body oncontextmenu="return false" onselectstart="return false">

    #if($pageHead)

        #parse($pageHead)

    #end

    $screen_content

    #parse($page_footer)</body></html>

  頁面裏我們可以引入這個佈局格式,這個佈局文件其實就是頁面裏不變的東西抽取了出來,它完成了頁面動靜分離,頁面只要應用這個佈局文件即可,到了這裏這個佈局文件和前面的include方式區別不大,那麼我們再看看下面的代碼:

<property name="layoutUrl" value="layout/default.vm"/><!--指定layout文件-->

  這是佈局文件的引用方式,我們可以把佈局文件放置在網絡上,項目裏應用這個文件所在地址即可,這樣我們就把項目裏不變的靜態資源抽取在同一個地方,如果在碰到佈局要做修改,那麼我們只需要改一個地方即可。

  不管服務 端採取何種動靜分離,動靜資源的整合都是有服務端完成,按照上文提到網站靜態化的思想,這些做法不會給網站性能提升帶來任何好處,它們只是給開發,運維提 供了便利而已,按前文的思路,我們要把動靜分離往前移,服務端往前移碰到的第一個點就是靜態的web服務器例如apache或ngnix。

  在講解靜態的web服務器動靜分離前我要先講一下爲什麼我們要在服務端前面加個靜態web服務器的道理。我個人覺得在每個服務端之前都佈置一個靜態web服務器,該服務器起到一個反向代理的作用,而且我覺得不管我們是否使用CDN,最好都這麼做,這麼做有如下好處:

  好處一:方便日誌的記錄。

  好處二:在服務端之前設立了一個安全屏障,即靜態web服務器可以在必要時候過濾有害的請求。

  好處三:可以控制流入到服務端的請求個數,當併發很高時候,可以利用靜態web服務器能承擔更高併發的能力來緩衝服務端的壓力,這裏我補充一些實踐技巧,以java裏常用的web容器tomcat爲例,一般官方給出它的最大併發數應該不會超過200,如果我們在tomcat前放置了一個apache服務器,那麼我們可以把tomcat的最大併發數設置爲無效大,把併發數的控制放置在apache這邊控制,這麼做會給我們系統運維帶來很大的好處,tomcat雖然有一個建議最大併發數,但是實際運行裏java的web容器到底能承受多大併發其實要看具體場景了,因此我們如果可以動態控制apache的併發數,這個操作很方便的,那麼我們就可以動態的調整tomcat這樣容器的承載能力。

  好處四:可以便於我們做動靜分離

  這裏我們以apache爲例子講解將動靜分離前移到apache的一些做法,apache有一個功能叫做SSI,英文全稱是Server Side Include,頁面上我們一般這樣使用SSI,SSI有一種標籤,例如:

<!--#include file="info.htm"-->

  頁面一般 使用註釋的方式引入,這個和jsp的引入有點區別的,SSI的做法其實和服務端的引入類似,只不過使用SSI將本來服務端做的動靜整合交由了apache 完成了,我們可以把靜態文件直接放置在Apache這裏,如果這個靜態web服務器上升到CDN,那麼這些靜態資源就可以在靠近用戶的地方使用,SSI說 白了就是像apache這樣的靜態資源服務器接收到服務端返回後,將一部分內容插入到頁面了,然後將完整頁面返回至瀏覽器。這個做法如果優化的得當,可以 很好的提升網站的加載效率。

  Apache這樣的靜態資源服務器還支持一種動靜整合的技術,這個技術就是ESi,它的英文全稱叫做Edge Side Includes,它和SSI功能類似,它的用法如下所示:

<esi:include src="test.vm.esi?id=100" max-age="45"/>
    它和SSI區別,使用esi標籤獲取的資源來自於緩存服務器,它和SSI相比有明顯的性能優勢,其實網頁特別是一個複雜的網頁我們做了動靜分離後靜態的資源本身還可以拆分,有的部分緩存的時間會長點,有點會短點,其實網頁裏某些動態內容本身在一定時間裏有些資源也是不會發生變化的,那麼這些內容我們可以將其存入到緩存服務器上,這些緩存服務器可以根據頁esi傳來的命令將各個不同的緩存內容整合在一起,由此我們可以發現使用esi我們會享受如下優點:
     優點一:靜態資源會存放在緩存裏,那麼獲取靜態資源的效率會更高。
     優點二:根據靜態資源的時效性,我們可以對不同的靜態資源設置不同的緩存策略,這就增加了動靜分離方案的靈活性。
     優點三:緩存的文件的合併交由緩存服務器完成,這樣就減少了web服務器本身抓取文件的開銷,從而達到提升web服務器的併發處理能力,從而達到提升網站訪問效率的目的。
 
(友情提示:ESI這塊我還了解的不太深入,聽說它其實可以直接使用在jboss上,相關知識我還要繼續收集資料學習)
    SSI和ESI是靜態web服務器處理動靜資源整合的手段,那麼我們再把動靜整合操作往前移,這個時候就到了瀏覽器端了。瀏覽器端的動靜整合的技術稱之爲CSI,英文全稱叫做Client Side Includes,這個技術就是時下javascriptMVC、MVVM以及MVP技術採取的手段,實現CSI一般是採用異步請求的方式進行,在ajax技術還沒出現的年代我們一般採取iframe的方式,不過使用CSI技術頁面加載就會被人爲分成兩次,一次是加載靜態資源,等靜態資源加載完畢,啓動異步請求加載動態資源,這麼一做的確會發生有朋友提到的一種加載延遲的問題,這個延遲我們可以使用適當的策略來解決的,關於CSI的使用是本系列的重點,我會在後面文章裏重點講解。
     好了,今天就寫到這裏,祝大家生活愉快,晚安。

轉自:http://www.cnblogs.com/sharpxiajun/p/4285085.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章