標籤:效能最佳化 資料壓縮 http協議 壓縮 gzip
一、HTTP協議頭:
服務端根據用戶端發送的要求標頭中某些欄位自動發送最合適的版本。可以用於這個機制的要求標頭欄位分為兩種:Accept欄位、其他欄位。
| 要求標頭欄位 |
說明 |
回應標頭欄位 |
| Accept-Encoding |
告知伺服器採用何種壓縮方式 |
Content-Encoding |
比如用戶端發送的要求標頭:
- Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
- Accept-Encoding:gzip, deflate, sdch
- Accept-Language:zh-CN,zh;q=0.8
Accept:優先接受text/html....,後在接受image/webp...Accept-Encoding:支援採用gzip、deflate或sdch壓縮過的資源Accept-Language:支援zh-CN和zh兩種語言,q表示權重值(0~1)之間
瀏覽器回應標頭:
- Content-Encoding:gzip
- Content-Type:text/html; charset=UTF-8
表示這個文檔確切的MIME類型是text/html;文檔內容進行了gzip壓縮,回應標頭沒有Content-Language欄位,通常說明返回版本的語言正好是要求標頭Accept-Language中權重最高的那個。
1) 接下來我們來詳細分析下http壓縮的完整過程a、瀏覽器發送http request給web伺服器,request中有Accept-Encoding:gzip,deflate。b、Web伺服器接到request後,產生原始的Response,其中有原始的Content-Type和Content-Length。c、Web伺服器通過Gzip來對Response進行編碼,編碼後header中有Content-Type和Content-Length(壓縮後的大小),並且增加了Content-Encoding:gzip。然後把Response發送給瀏覽器。d、瀏覽器接到Response後,根據Content-Encoding:gzip來對Response進行編碼。擷取到原始response後,然後顯示出網頁。整個流程圖如下:
2)通過fiddler抓包觀察解碼前展示:
解碼後展示:
二、瀏覽器支援的三種http傳輸壓縮演算法
1)sdch壓縮演算法sdch是shared dictionary compression over http的縮寫,即通過字典壓縮演算法對各個頁面中相同的內容進行壓縮,減少相同的內容傳輸。如:一個網站中一般都是共同的頭部和尾部,甚至一些側邊欄也是共同的。之前的方式每個頁面開啟的時候這些共同的資訊都要重新載入,但使用sdch壓縮方式,共同的內容只用傳輸一次就可以。
sdch主要分為3個部分:首次請求,下載字典,其他請求。
------------首次請求----------用戶端:Accept-Encoding: sdch服務端:Get-Dictionary: /path/to/dict
-----------下載字典-----------用戶端根據Get-Dictionary的值來下載字典,普通的HTTP請求。
-----------其他請求-----------用戶端:Accept-Encoding: sdchAvail-Dictionary: xxx伺服器端:根據Avail-Dictionary的值來進行sdch編碼,如果Accept-Encoding裡有gzip,這些資料還會被gzip壓縮,之後返回。
sdch與ajax+pushStatesdch壓縮方式是為了減少相同內容的傳輸,和ajax+pushState相同都是減少相同內容的傳輸。sdch是google出的,但pushState是H5的一個標準,目前已經有Chrome和Firefox支援,之後會有越來越多瀏覽器支援。
2)gzip壓縮演算法 表示實體採用GNU zip編碼,無損壓縮演算法,用於減少傳輸報文的大小,不會導致資訊損失。效率最高,使用最廣泛。 壓縮方式:是在一個文字檔中找出類似的字串,並臨時替換他們,使整個檔案變小。這種形式的壓縮對Web來說非常適合,因為HTML和CSS檔案通常包含大量的重複的字串,例如空格,標籤。 gzip可設定壓縮比率,取值範圍在1(最低)到9(最高)之間,不建議設定太高,雖然有很高的壓縮率,但是佔用更多的CPU資源。 gzip壓縮對圖片壓縮效果相對較差 a)講解gzip使用壓縮演算法的基本原理 gzip對於要壓縮的檔案,首先使用LZ77演算法的一個變種進行壓縮,對得到的結果再使用Huffman編碼的方法(gzip根據情況,會選擇使用靜態Huffman編碼或者動態Huffman編碼)進行壓縮。所以明白LZ77演算法和Huffman編碼的壓縮原理,也就明白gzip壓縮原理。
a-1)LZ77演算法壓縮原理 如果檔案中有兩塊內容相同的話,那麼只要知道前一塊的位置和大小,我們就可以確定後一塊的內容。所以我們可以用(兩者之間的距離,相同內容的長度)這樣一對資訊,來替換後一塊內容。由於(兩者之間的距離,相同內容的長度)這一對資訊的大小,小於被替換內容的大小,所以檔案得到了壓縮。 樣本:有一個檔案內容a.conf http://www.baidu.com/ http://m.baidu.com/ 其中有些部分的內容,前面已經出現過了,下面用()括起來的部分就是相同的部分。 http://www.baidu.com/ (http://)m(.baidu.com) 我們使用(兩者之間的距離,相同內容的長度)這樣一對資訊來替換後一塊內容 http://www.baidu.com/ (22, 7)m(30, 11) (22, 7)中,22為相同內容塊與當前位置之間的距離,7為相同內容的長度。 (30, 11)中,30為相同內容塊與當前位置之間的距離,11為相同內容的長度。 由於(兩者之間的距離,相同內容的長度)這一對資訊的大小,小於被替換內容的大小,所以檔案得到了壓縮。
a-2)Huffman編碼 我們把檔案中一定位長的值看作是符號,比如把8位長的256種值,也就是位元組的256種值看作是符號。我們根據這些符號在檔案中出現的頻率,對這些符號重新編碼。對於出現次數非常多的,我們用較少的位來表示,對於出現次數非常少的,我們用較多的位來表示。這樣一來,檔案的一些部分位元變少了,一些部分位元變多了,由於變小的部分變大的部分多,所以整個檔案的大小還是會減小,所以檔案得到了壓縮。
3)deflate壓縮演算法 DEFLATE是同時使用了LZ77演算法與哈夫曼編碼(Huffman Coding)的一個無損資料壓縮演算法。 它最初是由Phil Katz為他的PKZIP歸檔工具第二版所定義的,後來定義在RFC 1951規範中。
人們普遍認為DEFLATE不受任何專利所制約,並且在LZW(GIF檔案格式使用)相關的專利失效之前,這種格式除了在ZIP檔案格式中得到應用之外也在gzip壓縮檔以及PNG影像檔中得到了應用。
DEFLATE壓縮與解壓的原始碼可以在自由、通用的壓縮庫zlib上找到。
更高壓縮率的DEFLATE是7-zip所實現的。AdvanceCOMP也使用這種實現,它可以對gzip、PNG、MNG以及ZIP檔案進行壓縮從而得到比zlib更小的檔案大小。在Ken Silverman的KZIP與PNGOUT中使用了一種更加高效同時要求更多使用者輸入的DEFLATE程式。
deflate是一種壓縮演算法,是huffman編碼的一種加強。
deflate與gzip解壓的代碼幾乎相同,可以合成一塊代碼。
三、gzip與deflate區別
deflate使用inflateInit(),而gzip使用inflateInit2()進行初始化,比inflateInit()多一個參數:-MAX_WBITS,表示處理raw deflate資料。因為gzip資料中的zlib壓縮資料區塊沒有zlib header的兩個位元組。使用inflateInit2時要求zlib庫忽略zlib header。在zlib手冊中要求windowBits為8..15,但是實際上其它範圍的資料有特殊作用,見zlib.h中的注釋,如負數表示raw deflate。 deflate是最基礎的演算法,gzip在deflate的raw data前增加了10個位元組的gzheader,尾部添加了8個位元組的校正位元組(可選crc32和adler32)和長度標識位元組。
http協議檔案壓縮