跳到主要內容

談以壓縮、cache機制加速網路應用

談到壓縮資料時必須先有個概念
壓縮資料可以減少資料的傳輸成本,但相對的會增加計算上的成本
CPU可能會因為壓縮的工作而降低系統的整體處理能力,使用上必須依需求選擇
當然現行系統主要的資料傳遞需求仰賴網路,通常啟用壓縮會是較好的選擇


以網路應用實務上的一般情況來說,效率的瓶頸主要是資料的傳輸
上圖是分別以3G和4G通信取得20KB資料的時間,可以看出資料量大時的影響
另一個要點則是行動裝置的電量,行動裝置使用網路時會大幅減少其電池使用時間

網路應用的JavaScript和CSS是最需要進行壓縮的項目
因為下載完成前,瀏覽器會處於block狀態,不會執行任何動作
如上舉例,下載完後並進行解壓縮會比下載未壓縮檔案來的快

目前壓縮工具的主流選擇有YUICompressorGoogle Closure、UglifyJS

YUICompressor是由Yahoo所開發的Java壓縮器,目前的版本是2.4.7
經過設定後可以讓Web Container傳送壓縮過的CSS和JavaScript檔案

Google Closure的使用可以參考使用Google Closure壓縮Javascript檔案

UglifyJS是基於node.js的壓縮工具,現在的JQuery也改用它,不過因為我跟node.js不熟就不提了

這幾項工具通常也有線上的版本
YUI的線上工具滿多的,隨便打YUI compressor online就可以找到很多
例如:http://refresh-sf.com/yui/

Google Closure online:http://closure-compiler.appspot.com/home

CSS compressor:http://www.csscompressor.com/


除了壓縮傳送的檔案外,也能就HTTP的串流更進一步壓縮
作法有兩種
1.即時壓縮
   對Server端跟Client端耗費較多的CPU及記憶體資源,以交換較低的頻寬使用量
2.同時部署靜態檔案的壓縮及無壓縮版
   透過一個filter根據client端的狀態來決定回傳檔案的版本

就小量的資料來說,壓縮反而降低效能,實務上最好選擇超過某個大小才啟用壓縮
以Java Web開發來說,一般常用的web container都能使用JDK內建的GZIP壓縮器
啟用可以看Glassfish 效能調校Tomcat,Apache配置GZip壓縮(HTTP壓縮)功能兩篇

JDK的GZIP壓縮器在處理多執行緒的請求時表現較差
原因是其實作在配置記憶體時會有lock競爭
如果使用像Oracle Solaris的libumen之類記憶配置可以解決這問題(應該要$+不熟的就不多說了)
另外開源的LZF壓縮器也是一個選擇
LZF本身的壓縮效率較GZIP差,但相反的有較快的解壓縮速率

另一種加速網路應用的方式就是使用cache
現在的大型網站要應付大量的使用者,都會利用distributed cache
後續的說明以Java Web開發為主,但概念在各開發工具是相差不遠的
cache機制能儲存完整的頁面或耗資源的資料庫查詢結果作為共用、重複利用
最常被使用的項目就是Memcached,輕量而且高效的成熟技術
當然這個項目在開發規模僅有1台Server之類的小型環境並不適用
技術上會用到在cache內儲存和取出物件

要將物件儲存在 cache 內,首先要建立這個物件的 binary 檔
以Java物件和JSON資料的轉換及序列化來說,serializer的lib常見選擇有以下3種:
1.org.json
   一般人最容易找到的入門lib吧(笑)
   不過已經久沒在更新了,效率上也幾乎落後給各家lib
   例如在JSONObject轉String的過程中因為沒用 String Buffer 而有大量臨時性的String物件
   可以很輕鬆地轉換 Java物件到JSONObject,但反過來卻很困難
2.GSon
   Google的開源lib,轉換效率略遜於Jackson
   但因為本體很小(近190k而已)而被廣泛使用在mobile上
3.Jackson
   整體效率最好的lib之一

上述實作可以再多寫幾篇文章了,這邊只提概念就先不多說了

大部分的container都是將session資料儲存在記憶體中,所以當系統故障時就會遺失session
只是對於某些程式來說沒有辦法接受遺失session的資料
解決的方式之一是複製運作在Server上的session複製到備份Server的記憶體中
要將存在session內的Java物件傳送到其他的container或其他儲存區,一樣得透過serialize機制
撇開實作,Glassfish的解決方法是透過Java serialize機制及壓縮資料傳輸大小達成這個需求

session有一部分的成本是和物件大小相關
包含做serialize和deserialize的成本、在網路上的傳輸時間都和物件大小成正比
且有多層繼承的物件在序列化時的成本會更多
所以session本身的內容越單純,對效能越好
對於複雜的物件,可以考慮透過 transient 關鍵字省去資料在序列化的過程被保存session中
直到要使用時,若找不到屬性再從資料庫或其他來源重新建立

留言