Hpack 個人理解篇

抽象

該規(guī)范定義了HPACK,HPACK的壓縮格式有效地表示要在HTTP / 2中使用的HTTP標頭字段。

解決問題

HTTP1.X 由于其設(shè)計的缺陷,被大家詬病已久,其中頭疼的問題之一,就是無意義的重復的頭部。
而 HTTP/2 的實現(xiàn)就是參考了 SPDY 協(xié)議, 但是專門為頭部壓縮設(shè)計了一套壓縮算法,就是我們的 HPACK 。
該規(guī)范定義了HPACK,這是一種新型壓縮機,它消除了冗余標頭字段,將漏洞限制為已知安全性攻擊,并且在受限條件下使用時具有有限的內(nèi)存要求環(huán)境。

Hpack 理解

靜態(tài)索引表

因為表中的參數(shù)都是提前定義好的,只有固定的幾十個值,當遇到不在靜態(tài)表中的,就會加入到動態(tài)表。
靜態(tài)索引表用 index 表示在表中的位置,在需要替換時,根據(jù) index 索引進行替換即可,這樣就會大大縮減替換時候的開銷。

動態(tài)索引表

動態(tài)表是一個由先進先出的隊列維護的有空間限制的表,里面同樣維護的是頭部與對應(yīng)的索引。
每個動態(tài)表只針對一個連接,每個連接的壓縮解壓縮的上下文有且僅有一個動態(tài)表。
動態(tài)表就是,當一個頭部沒有出現(xiàn)過的時候,會把他插入動態(tài)表中,下次同名的值就可能會在表中查到到索引并替換掉頭部。為什么我說是可能呢,因為動態(tài)表是有最大空間限制的。
動態(tài)表的大小 = (每個 Header 的字節(jié)數(shù)的和+32) * 鍵值對個數(shù)
32是為了頭所占用的額外空間和計算頭被引用次數(shù)而估計的值。
那么動態(tài)表是如何管理大小呢,2種情況下,動態(tài)表會被修改:
壓縮方用上述方式要求動態(tài)修改動態(tài)表的大小。在這種情況下,如果新的值更小,并且當前大小超過了新值,就會從舊至新,不斷的刪除頭,直到小于等于新的大小。
收到或發(fā)出一個新的頭部,會觸發(fā)插入和可能的刪除操作。 RFC 里面說的比較復雜,我用等價的語義解釋一下。新的值被插到隊首,一樣從舊到新刪除直到空間占用小于等于最大值。那么在這種情況下,如果新來的頭比最大值還要大,就等于變相的清除了動態(tài)表。
動態(tài)索引表中最新的值是索引值最小的,最舊的值是索引值最大的。
動態(tài)表與靜態(tài)表共同組成了索引表的索引空間。

編碼

無符號整數(shù)編碼

在 HPACK 中一個無符號整數(shù),并不總是在一個字節(jié)的開始,但是總是在一個字節(jié)的末尾結(jié)束。


image.jpeg

在這張圖中 0-2 bit 表示占位,而在圖中 value 表示占了5 bit ,因此,根據(jù)2^n-1 公式可得,上圖中表示小于32位時一個字節(jié)就可以表示,當大于32位時又是另一種情況,如下圖:


image.jpeg

第一個字節(jié)的 n 個 bit 全部置1,之后用整體字符數(shù)量-(2^n-1)獲得實際使用位數(shù),最終以0表示結(jié)尾。最終,將首字節(jié)1占位去掉,最終獲得到寫入真實字符。

字面字符串編碼

image.jpeg

StringData: 如果是 huffman 編碼,則使用 huffman 編碼后的字符串,否則就是原始串。

靜態(tài)HUFFMAN編碼

Huffman 編碼是一個根據(jù)字符出現(xiàn)的概率重新編排字符的二進制代碼,從而壓縮概率高的字符串,進而壓縮整個串的長度。
我個人也不是很了解,只是知道一些基礎(chǔ),細細如何壓縮計算,我也沒理解,如果有對Huffman理解較深的大家可以交流。

Hpack 對 Http 帶來的影響

1、為了解決CRIME 帶來的安全隱患
2、無意義的重復的頭部
3、通過靜態(tài)索引表和動態(tài)索引表,提升壓縮性能,減少壓縮損耗
4、減少響應(yīng)帶寬損耗

請求頭部

:method:GET, :path:/ and :scheme:https總是出現(xiàn)在靜態(tài)字典里,所以每個都會被編碼為一個字節(jié)。另外一些頭部項只有鍵會被壓縮成一個字節(jié): :authority, accept, accept-encoding, accept-language, cookie 和 user-agent 會出現(xiàn)在靜態(tài)字典。
沒有匹配到的頭部會被插入到動態(tài)字典給之后的請求使用。
顯而易見,在請求頭部里的大多數(shù)項都是重復的。這意味他們每個都可以被編碼至一到兩個字節(jié),這樣提升是顯而易見的。

響應(yīng)頭部

假設(shè)可以完全匹配到 12 個頭部里的 7 個。剩下的 5 個中,4 個頭部的鍵可以被全部匹配到,以及 6 個字符串(譯者注:5 個頭部鍵值共有 10 個字符串,6 個字符串包括 1 個鍵和 5 個值)將會使用 Huffman 編碼進行有效編碼。
假設(shè)兩個 expires 頭部幾乎是完全相同的,但因為它們不能完全匹配,所以它們只可以用 Huffman 編碼進行壓縮。
請求越多,動態(tài)表會越大,那么更多頭部會被匹配到,壓縮比率就會更高

測試 Hpack

如果你已經(jīng)安裝了 nghttp2,你可以用一個叫 h2load 的工具測試你的網(wǎng)站里 HPACK 的壓縮效率。
附上如何使用 h2load:
http://www.nghttp2.org/documentation/h2load-howto.html
個人還在研究如何查看,這個自己也沒搞的太清楚

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容