- 使用高效的數據交換格式 - 為客戶端與服務器之間傳輸的數據選擇高效的編碼.
- 在可能的情況下使用預先壓縮的數據 - 使用專用算法對諸如音頻、視頻和圖像進行壓縮或按比較縮放以適應通道與設備
- 壓縮每一個請求與響應負載 - 壓縮文本負載以減少帶寬, 同時又不太影響服務器與客戶端代碼
實際上, 可以通過壓縮服務器響應或是客戶端請求為非媒體負載開啟負載壓縮.
1. 響應壓縮
響應負載壓縮是最簡單的一種 HTTP 負載壓縮形式. HTTP 響應由返回給客戶端的用于響應上一個 HTTP 請求的響應頭與響應體構成. 響應壓縮會對響應體應用數據壓縮算法, 但不會操縱 HTTP 頭
在 iOS HTTP 負載中, 默認情況下, 所有的 HTTP NSURLConnection 請求都是開啟壓縮的. 接收到的負載會自動解壓縮并以最初的格式呈現在代碼中. 解壓縮的計算代碼要比傳輸 10 倍字節的通信代價低; 因此, 激活響應壓縮幾乎總是有益無害的
在默認請況下, NSURLConnection 會向每個請求添加好下 HTTP 頭:
Accept-Encoding: gzip, deflate
Accept-Encoding 頭告訴服務器, 客戶端可以接收使用 gzip 或 DEFLATE 壓縮的負載, 不過服務器可以自己選擇是否壓縮響應. 這樣, 通過響應負載壓縮來提升性能的關鍵就在于配置服務器以支持壓縮
有些瀏覽器無法正確處理 DEFLATE 壓縮, 因此最常用的壓縮其實是 gzip
比如, 配置 Apache Web 服務器的過程涉及加載壓縮模塊并針對特定的文檔類型激活輸出過濾器
LoadModulefilter_module library-path/mod_filter.so
LoadModuledeflate_module library-path/mod_deflate.solibrary-path 的值會根據 Apache 的安裝位置而發生變化
filter_module 是個常用的模塊, 并且可能已經被加載了. deflate_module 則不太常用, 不過也是 Linux、OSX 與 Windows 上標準 Apache 安裝的組成部分
deflate_module 支持的是 gzip 而非 DEFLATE 壓縮
為那些能夠從壓縮中獲益的內容類型添加輸出過濾器(非圖片、音頻和視頻)
禁用負載壓縮, 可以通過清除自動設定的 Accept-Encoding 頭來實現
對請求的響應不會再被服務器壓縮. 響應壓縮是優化應用網絡帶寬使用的一種簡單手段, 只需要對服務層做很小的修改即可實現
2. 請求壓縮
與響應壓縮不同, 請求壓縮的實現更為復雜, 因為它既需要客戶端與服務端的協調實現.?
模式一:?
iOS 應用首先查詢服務器來判斷是否支持壓縮, 然后根據服務器的響應來調整其行為請求壓縮會為移動應用帶來很大的好處, 因為廣域無線傳輸速率是非對稱的, 為發送給設備的數據提供了更大的帶寬, 而對設備發出的數據則提供了很小的帶寬. 之所以使用這種非對稱的帶寬, 原因在于大多數 Web 流量都是非對稱的. 如果應用定義了標準的非對稱模式, 那么你絕對應該考慮使用請求壓縮. 比如, 如果應用上傳到服務器, 那么應用就會通過上傳負載的壓縮而獲益(傳輸到服務器以及回傳給設備時就會消耗 80KB 的帶寬, 在請求與響應開啟了壓縮, 那么同樣一次往返, 數據只會消耗 12KB 的帶寬)
要想創建請求壓縮, 首先需要在 Web 服務器上定義好輸入過濾器
Apache 并不會在通過 PHP 或 mod_jk 模塊等資源過濾器發送數據前對其解壓縮, 因此, 如果通過資源過濾器向 Web 應用傳遞了壓縮數據, 那么目標 Web 應用就要負責負載的解壓縮
與響應壓縮一樣, 客戶端應用不應該將 CPU 時間浪費在壓縮諸如 PDF、加密數據、圖像、音頻及視頻等已經壓縮的內容上. 然而, 代表預先壓縮的數據的 Base64 數據常常會從請求壓縮中獲益, 比如, 如果要以 Base64 格式上傳 JPEG 文件, 那么可以對 Base64 數據進行壓縮, 相較于未壓縮的 Base64 數據, 壓縮后的數據體積會降低 30% 左右
在 Apache 中, 用于響應壓縮的模塊也可以執行請求壓縮. 如下配置片段會加載所需模塊:
接下來需要為 DEFLATE 模塊定義輸入過濾器
如果帶有 Content-Encoding:gzip 頭的請求到達 HTTP 服務器, HTTP 服務器就會嘗試解壓縮請求體并將其傳給過濾器鏈中的下一個過濾器. 出于說明的目的, 這個示例請求壓縮應用帶有一段簡單的 Perl腳本, 它會將接收到的響應體負載回顯出來, 腳本并不關心接收到的負載是不是壓縮過的
接下來, 為 iOS 應用添加壓縮代碼. 需要壓縮負載并向請求添加 Content-Encoding 頭. 示例壓縮代碼使用了 libz.dylib 框架, 這需要項目在編譯任何壓縮代碼前行先鏈接到該框架
示例應用實現了壓縮并提供了一種方式以執行多個請求(包含了針對你所選擇的 URL 的示例負載). 除了請求所消耗的平均時間與總時間外, 還會顯示出負載的大小. 時間包含了計算出的壓縮所需的時間. ?
通過 DSL 可以看到收益, 因為 DSL 連接對于上下游的速率來說通常是非對稱的. 值得注意的是, 在 Edge 網絡上要 10 秒鐘才能完成的請求, 如果對請求和響應進行了壓縮, 處理時間會降到 3 秒以下