文章出處

  上篇我補充了下SSI的知識,SSI是一個十分常見的技術,記得多年前我看到很多門戶網站頁面的后綴是.shtml,那么這就說明很多門戶網站都曾經使用過SSI技術,其實現在搜狐網站也還在用shtml,如下圖所示:

 

  由此可見SSI在互聯網的應用還是非常廣泛的。其實互聯網很多網頁如果我們按照動靜分離策略拆分,絕大部分都是可以當做靜態資源處理,例如新聞網站,文學網站,這些網頁生成后,大部分的資源都是不變的,說白了這些網頁本質就是一個靜態頁面,我們開發他們時候也不需要服務端的參入,每一個網站都有自己固定的板式,假如每個新網頁都要完完整整的開發,重復性的工作實在太多了,出錯的概率也非常高,在本系列第二篇里我曾經詳細介紹了velocity的布局模板技術,其實SSI也可以制作出一套固定的模板,開發時候我們只需要在定義好的模板里添加或者修改我們需要更改的內容就可以完成一個頁面的制作,可見SSI技術為了我們開發網頁提供了很大的便利。

  與SSI相對應的還有ESI,這個技術不是太常用,在網上能收集到的資料也不是太多,網上有限的資料也基本都是和淘寶相關的,不過仔細研究下淘寶對ESI的運用,對于理解網站靜態化處理是非常有借鑒意義的,下面我將重點講講ESI的知識。首先看個場景啊。

  我們登錄支付寶網站,到了個人首頁我們發現在支付寶下面有一個條目,如下圖所示:

        

  這是支付寶默認給我們顯示的【生活好助手】,右邊有個箭頭,我們點開它,如下圖所示:

 

  我們看到這里有添加的按鈕,通過添加按鈕,我們可以添加其他常用的組件圖標。(注意:我這里只是以支付寶這個功能為例,支付寶是否按照我說的設計,這個我就不清楚了)

  如果我們按照自己個性化添加了自己的組件,不同的人添加的常用組件也會是不盡相同的,如果我們自己開發的網站也有這樣的功能,那么我們該如何設計了?我們一般都會很直觀的把這個新增的組件信息存儲在數據庫里,用戶每次登錄時候該信息也會隨之從數據庫里讀取,但是這個場景對于像支付寶這種用戶量極大,日均訪問量極高的大型網站,這種個性化又非核心的功能都從數據庫里讀取,那么它對數據庫造成的壓力一定是十分巨大的,在存儲的瓶頸里我們講了那么多優化數據庫的手段,其核心手段有一個就是減少對數據庫價值不高的操作,而這種個性化配置跟支付寶的支付操作相比起來,價值度實在太低,因此我們最好的選擇是避免數據庫承擔過多此類的操作。

  不過像上面這個場景里的功能,它所使用的數據又不是那種可有可無的,假如數據存儲的不可靠造成數據丟失還是會造成不必要的麻煩,所以我們還是會把這些信息做持久化存儲。此外像上面的【生活好助手】條目還是頁面的一個重要組成部分,因此像SSI那種使用html注釋指令,當指令無法正常解析,就直接返回到瀏覽器,因為是注釋,所以頁面也不會顯示它,SSI的這種做法用在上面場景肯定是不太合適的。這樣的場景在電商網站里是十分常見的,例如一個商品頁面,頁面里會有商品的圖片,還有商品的詳細介紹,這些內容其實都是會用持久化系統進行存儲,同時它們本身也是網頁的重要做成部分,如果碰到問題就忽略最終會造成頁面顯示錯誤。

  結合上面的場景我們來討論下ESI技術了,ESI技術和SSI技術類似,其實也和jsp里的include指令類似,它也是在頁面里使用一個指令標簽web容器解析這個標簽后將獲取的數據替換掉這個標簽。我們來看看ESI的使用方法,我們可以在velocity里自定義一個esi標簽,velocity里的使用如下所示:

esiTool.setTemplate('test.vm').addQueryData('id', 100)

 

  velocity引擎解析vm模板,最終會把vm解析成html頁面,這個時候該頁面里使用esi標簽的地方就被轉化為:

<esi:include src="test.vm.esi?id=100" />

 

  當頁面到了服務端web容器之前的靜態web容器(該web容器要安裝好解析esi的模塊),靜態web容器就會解析這個esi標簽,靜態web容器會以test.vm.esi?id=100 作為key,到緩存系統里查找信息,如果查到了信息,緩存服務器就直接返回,用返回內容替換掉esi標簽,如果緩存里沒有找到則會直接請求持久化系統,持久化系統返回信息后,緩存系統將信息緩存起來,同時也將信息返回至靜態web容器,那么下次用戶再訪問同樣內容就會直接從緩存里讀取了。

  ESI技術和SSI很像,只不過ESI技術是和緩存技術配合起來的,同時ESI標簽也不像SSI標簽那樣使用注釋的形式,因此ESI標簽是一定要被解析的,如果僅僅是緩存,ESI和SSI比較起來也沒顯得那么有優勢和特別,但是對于電商這種場景而言ESI的現實意義非常大,電商網站也是一個由用戶產生內容的網站,每一個商家的店鋪雖然我們都知道它是屬于淘寶或天貓的,但是單獨一個商家的店鋪都是個性化很強的,與其他店鋪差異很大,為了買賣商品,商家會上傳自己商品的圖片,還會使用圖片和文字描述自己的商品,單個商品頁面我們做動靜分離分析,很容易分辨出動態內容和靜態內容,但是如果一個電商平臺擁有超乎想象數量的商家,那么每個頁面的圖片,文字和商家頁面的關系就會變得有點微妙了。由于電商網站的圖片特別多,那么電商網站系統一般都會設計一套管理這些小圖片的分布式存儲系統,例如淘寶的TFS文件系統,它是專門針對圖片使用的分布式文件系統,這些文件系統里存儲的圖片會和商家緊密關聯,這就讓圖片本身擁有了一定的動態屬性,但是對于每個商家頁面而言,商家自己的圖片資源都是可以靜態化的,也就是說圖片的讀取是要通過商家信息進行計算的,計算出的結果對于商家而言又是靜態的,可以被緩存的。但是這個靜態資源的處理時候就變得復雜了,而這些是SSI無法完成的。

  首先我們直接從文件系統讀取圖片,效率是非常低效,因此我們還是會把它們緩存在內存里,但是由于不同圖片和不同商戶是相關聯,那么對于緩存查找時候是需要一定的條件,不同商戶對自己頁面的設計方案也會有所不同,一般商戶這些資源,存儲系統肯定會按照設計模板的維度存儲,不同商家由于商品和文化的不一樣,那么使用的模板也不一樣,因此資源返回靜態web容器前還需要一個整合過程,這樣場景下的靜態資源獲取其實是需要一定邏輯計算的,那么這個計算一般都會在開發時候由代碼完成,所以從上面ESI使用的例子看到,開發人員會使用velocity的esi標簽,這個標簽開發人員可以設置參數,velocity引擎最終會將這個標簽解析成靜態web容器可以解析的esi標簽,標簽里有這樣的代碼test.vm.esi?id=100,文件后面會帶上參數,那么這個參數其實是動態的,那么這個參數也就是緩存系統獲取正確信息的規則了。這樣我們就完成了靜態資源獲取的邏輯計算,計算完畢后這些資源會在一段時間里長期有效,因此它就演變為靜態資源,可以被緩存了。ESI比SSI強大多了,同時ESI也可以完成SSI的功能,所以使用了ESI也就沒必要用SSI了。

  像我們平時做web開發時候可能沒有太留心一個問題,一般的web開發里使用的靜態資源例如圖片,css文件,js文件我們都會放置在一個resource包里,如果是企業開發,這個web應用上線時候也就直接打包在web工程里,一些互聯網網站也只不過會將這些資源放置在單獨的靜態服務器上,我平時開發時常聽到有人說,項目里圖片太多了,應該合并下,css文件和js文件也太多了也要合并下,這個多到底多多少了,幾十個文件,幾百個文件,這個要和社交網站,電商網站這種用戶可以產生圖片的網站比起來那就是小巫見大巫了,因為用戶能產生內容的網站靜態資源會隨著時間推移文件規模變得異乎尋常的大,所以此類網站的靜態資源已經沒法放置在項目下,它就要求我們需要有新的手段管理這些靜態資源,并且有新的手段使用這些靜態資源,那么像TFS文件存儲系統出現了,緩存技術出現了,最后我們在應用里使用ESI技術把它們整合到我們網頁里,通過這個分析我們就能明白ESI適用的業務場景了。

  網站靜態化處理我們首先要按規則拆分動靜資源,拆分出來的靜態資源該如何處理就是網站靜態化處理的關鍵所在,把靜態資源處理從服務端的web應用里剝離出來,不讓服務端的web應用參入過多的靜態資源解析,這樣就可以為服務端的web應用減少不必要的處理操作,從而達到提升服務端web應用的運行效率,接著我們就把拆分出來的靜態資源處理操作往前推移到靜態web服務器,前兩篇文章和今天的文章我著重講解了靜態web服務器處理靜態資源的手段,那么這里有個問題了,這些處理可以再往前推到瀏覽器來完成嗎?答案當然是否定的,首先瀏覽器的緩存是非常不可靠的,如果用戶把瀏覽器設置為不緩存任何數據的模式,那么瀏覽器就沒法緩存數據了,而用戶的行為那是根本沒法控制的,其次瀏覽器緩存的數據量是有限的,如果我們要在瀏覽器進行緩存也是緩存最有價值緩存的數據,更重要的一點,為了做好網站靜態化處理我們對網頁的動靜資源做了拆分,但是拆分出的靜態資源也并不是完全不需要進行任何邏輯處理就能使用的,例如前面講到的ESI適用的場景我們就發現,有些靜態資源的獲取還是要很多條件的參入,而這些條件是由動態數據產生的,那么這樣的靜態數據瀏覽器是沒法做緩存的,這點也說明了拆分出來的靜態化資源絕大部分還是要停留在服務端的,居然只能停留在服務端,那么最為高效的處理這些靜態資源的地方就是CDN和靜態web容器了。所以在本系列的第一篇里我講到網站生產部署時候最好是在服務端web應用之前放置一個靜態web容器,如果有了這樣的靜態web容器做反向代理,那么我們就可以讓它來完成靜態資源的相關操作,而且靜態web容器還能輔助完成一些邏輯上的處理,從而彌補了CDN的不足之處。當然這么做的好處不僅僅只有這些,第二篇文章里我曾經討論了反向代理的好處,可能大家印象還不是很深刻,我將會在后面文章里對反向代理做更加深入的分析。

  講完了ESI的妙用后,我下面將講講本篇的主題緩存了。其實單獨講緩存真的沒啥太多內容,不過在網站靜態化處理里的緩存還是和存儲里講到的分布式緩存有所不同,分布式緩存的數據都是存儲在內存里,而網站靜態處理的緩存既有存儲在內存里還有存儲在硬盤上,當然存儲在內存里讀取速度會更快,但是網站的讀取效率還和資源距離用戶的遠近有關系,例如瀏覽器的緩存其實是把靜態內容緩存在硬盤上,但是因為不需要通過網絡獲取資源,因此它的讀取效率就顯得特別高了,除了這個因素外還有個因素,我們前面做動靜拆分的目的就是想拆分出靜態資源,讓這些靜態資源遠離服務端的web應用,這樣可以減少服務端不必要的壓力,從而達到提升服務端web應用處理能力,而把靜態資源放置在靜態web容器處理,它的處理靜態資源效率又會高于在服務端web應用的處理,從而也達到提升靜態資源讀取的效率。不過如果靜態資源最終只能放置在服務端,那么這個時候我們把靜態資源存入到緩存里即內存里效率肯定比在硬盤上高,所以CDN的服務節點一般都是采取將靜態資源存儲在內存里,就算是服務端web應用前的靜態web容器,如果我們讓靜態資源緩存在內存里,效率肯定也是比在硬盤上高。

  好了,今天就寫到這里,最后祝大家生活愉快,新年快樂。


文章列表


不含病毒。www.avast.com
arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()