簡單來講,HTTP/2,是HTTP協議的第二個主要版本。HTTP/2是HTTP協議自1999年HTTP1.1發佈後的首個更新,主要基於google的SPDY協議。 HTTP/2的特色是:在不改動HTTP語義、方法、狀態碼、URI及首部字段的狀況下,大幅度提升了web性能。css
SPDY是谷歌研發的應用層協議,用戶提高web性能。html
(Head-of-Line Blocking)
HTTP/2的請求再也不基於文本傳輸,具體方式爲:在同一個域名下開啓一個TCP connection
,每一個http請求以流(stream)的方式在此鏈接上傳輸,每一個stream是由若干幀(frame) 組成,frame是HTTP/2資源傳輸的最小單元,frame中的字段identifier
標識此幀屬於哪個流,identifier相同的frame屬於同一流,服務端將identifier相同的幀解析成可用數據。在這個TCP connection中,同時傳輸了多個流的幀數據,這就是HTTP/2的多路複用。ios
每個幀(frame) 都包含length、type、flags、stream identifier、frame playload等字段, 這裏說下幀的type字段,在HTTP/2的標準中定義了10種不一樣的幀type。web
frame的PRIORITY字段用於標識流的權重(1-256)和依賴關係,以正確的順序請求資源對於用戶體驗相當重要。瀏覽器
服務器根據依賴關係和權重進行帶寬分配,高優先級的資源得到更多的帶寬。緩存
權重的大致規則不外乎 根文檔 - 樣式文件 - 字體文件 - 腳本文件 - 背景圖 - 圖標文件 - 圖片。 不一樣的瀏覽器規則會有所差別。安全
ios中瀏覽器的資源權重參考:服務器
ps: 服務端對於高優先級的資源的策略是分配更多的帶寬,可是不會保證此資源必定會優先返回,這是爲了不
線頭阻塞
。cookie
多路複用讓http請求變得廉價,建立一個新流的成本很低,理論上能夠同時發起無限個請求,不過咱們能夠在stream的SETTINGS字段上設置SETTINGS_MAX_CONCURRENT_STREAMS用於限制最大併發數。網絡
HTTP1.x中,咱們經過將重要的js代碼或者css樣式代碼嵌入html頁面中,讓頁面能夠快速響應,可是內嵌代碼最大的弊端是沒法緩存。哪怕只是修改一個小樣式也必須下載整個文件。
這也是其它資源整合的共同弊端,如圖片以base64的方式嵌入代碼、CSS精靈圖(sprite)等,每當修改了精靈圖中的一個小圖,咱們不得不從新下載整張精靈圖。
HTTP/2容許服務端主動推送資源,當TCP connection創建後,服務器能夠主動推送資源而非客戶端發起請求,服務端推送是基於frame的PUSH_PROMISE字段來實現的。並且服務端push的資源是能夠被緩存的。
關於服務端推送一個常見的問題是若是客戶端已經有一份緩存了怎麼辦?
瀏覽器能夠經過PUSH_PROMISE字段判斷資源是否已經緩存,而後經過發送RST_STREAM幀用於終止推送。在這個過程當中,服務端只是推送了資源的地址,並無直接推送資源的實體,這樣的目的也是爲了減小沒必要要的資源傳輸。
HTTP/2規定,由客戶端發起的流的ID(stream identifier)都是奇數,由服務端發起的流ID是偶數。
HTTP/2其實是對HTTP1的一個數據封裝,本質上沒有改變HTTP1的語義,狀態碼、URI 以及header字段等。
要實現對HTTP1的封裝,HTTP/2在傳輸層(TCP, UDP 或者SSL/TSL安全協議層)和應用層之間新增一個二進制分幀層,在分幀層中,HTTP/2將全部信息分割成幀(frame),其中原http header信息被封裝到 HEADER 類型的幀中,內容被封裝到DATA類型的幀中。
二進制分幀是多路複用,頭部信息壓縮,服務端推送, 流量控制等HTTP/2功能的基礎。
在HTTP1.x中,HTTP協議都是由狀態行,消息頭,主體構成,在傳輸過程當中,主體內容通常都是通過gzip壓縮,或者傳說的自己就是二進制流(視頻,圖片)等,而消息頭和狀態行都是純文本傳輸的。
並且不少消息頭中的字段冗餘如 COOKIE,UserAgent等,浪費了大量帶寬,增長了網絡延時。不少時候請求消息頭的大小甚至超過了主體內容的大小。
HTTP/2經過維護靜態字典和動態字典的方式來壓縮首部
1:對於靜態字典中匹配的頭部名稱或頭部名稱和值的組合,可使用一個字符表示,如創建鏈接時:
method:GET 可使用 1表示 (徹底匹配)
cookeie: xxx 可使用 2:xxx表示 (頭部匹配)
複製代碼
2:同時將cookeie: xxx加入動態字典中,這樣後續的整個cookie鍵值對均可以使用一個字符表示:
cookeie: xxx 可使用 3表示 (加入到動態字典)
複製代碼
3:對於靜態字典和動態字典中都不存在的內容,使用了哈夫曼(霍夫曼)編碼來壓縮體積。
不是全部的頭部信息均可以被添加到動態字典中,這時就是使用哈夫曼編碼壓縮的場景。
HTTP1中的狀態行信息如Status等在2.0中都以鍵值對的方式放入頭部中,作爲消息頭的一部分。
動態字典會在每一個TCP鏈接上維護一個,且動態字典的內容是根據請求量逐漸累積的。 因此在HTTP/2的網站中,咱們須要作的再也不是整合資源和散列域名了。而是分散資源和使用一個鏈接,如下兩種狀況下瀏覽器會使用一個鏈接: