http各個版本(1/1.1/2)對比
目錄:
- http1.1 長連線
- HTTP 1.1支援只發送header資訊(不帶任何body資訊)
- http1.1 host請求頭
- HTTP2.0使用多路複用技術(Multiplexing)
- HTTP/2新增首部壓縮(Header Compression):採用HPACK演算法
- HTTP/2新增服務端推送(Header Compression)
參考的文章:
http1.1 長連線
HTTP1.1預設使用長連線,可有效減少TCP的三次握手開銷。
HTTP 1.0規定瀏覽器與伺服器只保持短暫的連線,瀏覽器的每次請求都需要與伺服器建立一個TCP連線,伺服器完成請求處理後立即斷開TCP連線
當一個網頁檔案中包含了很多影象的地址的時候,那就需要很多次的http請求和響應,每次請求和響應都需要一個單獨的連線,每次連線只是傳輸一個文件和影象,上一次和下一次請求完全分離。即使影象檔案都很小,但是客戶端和伺服器端每次建立和關閉連線卻是一個相對比較費時的過程,並且會嚴重影響客戶機和伺服器的效能。當一個網頁檔案中包含JavaScript檔案,CSS檔案等內容時,也會出現類似上述的情況。
為了克服HTTP 1.0的這個缺陷,HTTP 1.1支援持久連線
HTTP 1.1還允許客戶端不用等待上一次請求結果返回,就可以發出下一次請求,但伺服器端必須按照接收到客戶端請求的先後順序依次回送響應結果,以保證客戶端能夠區分出每次請求的響應內容,這樣也顯著地減少了整個下載過程所需要的時間。
通過請求頭中connection欄位在表明是否支援長連結
在http1.1中,client和server都是預設對方支援長連結的(即connection的值預設我Keep-Alive), 如果client使用http1.1協議,但又不希望使用長連結,則需要在header中指明connection的值為closer(connection預設為Keep-Alive);如果server方也不想支援長連結,則在response中也需要明確說明connection的值為closer。不論request還是response的header中包含了值為closer的connection,都表明當前正在使用的tcp連結在當天請求處理完畢後會被斷掉。以後client再進行新的請求時就必須建立新的tcp連結了。
HTTP 1.1支援只發送header資訊(不帶任何body資訊)
如果伺服器認為客戶端有許可權請求伺服器,則返回100,否則返回401。客戶端如果接受到100,才開始把請求body傳送到伺服器。這樣當伺服器返回401的時候,客戶端就可以不用傳送請求body了,節約了頻寬。另外HTTP還支援傳送內容的一部分。這樣當客戶端已經有一部分的資源後,只需要跟伺服器請求另外的部分資源即可。這是支援檔案斷點續傳的基礎。
RANGE:bytes是HTTP/1.1新增內容,HTTP/1.0每次傳送檔案都是從檔案頭開始,即0位元組處開始。RANGE:bytes=XXXX表示要求伺服器從檔案XXXX位元組處開始傳送,這就是我們平時所說的斷點續傳
!
http1.1 host請求頭
HTTP1.0是沒有host域的,HTTP1.1才支援這個引數。
1.0中WEB瀏覽器無法使用主機頭名來明確表示要訪問伺服器上的哪個WEB站點,這樣就無法使用WEB伺服器在同一個IP地址和埠號上配置多個虛擬WEB站點。在HTTP 1.1中增加Host請求頭欄位後,WEB瀏覽器可以使用主機頭名來明確表示要訪問伺服器上的哪個WEB站點,這才實現了在一臺WEB伺服器上可以在同一個IP地址和埠號上使用不同的主機名來建立多個虛擬WEB站點。
HTTP 1.1還提供了與身份認證、狀態管理和Cache快取等機制相關的請求頭和響應頭。
HTTP2.0使用多路複用技術(Multiplexing)
多路複用允許同時通過單一的 HTTP/2 連線發起多重的請求-響應訊息。
"HTTP1.1在同一時間對於同一個域名的請求數量有限制,超過限制就會阻塞請求"。多路複用底層採用增加二進位制分幀層的方法,使得不改變原來的語義、首部欄位的情況下提高傳輸效能,降低延遲。
二進位制分幀將所有傳輸資訊分割為更小的幀,用二進位制進行編碼,多個請求都在同一個TCP連線上完成,可以承載任意數量的雙向資料流。HTTP/2更有效的使用TCP連線,得到效能上的提升。
二進位制分幀層把資料轉換為二進位制的同時,也把資料分成了一個一個的幀。幀是HTTP/2中資料傳輸的最小單位;每個幀都有
在一個TCP連結中,可以同時雙向地傳送幀,而且不同流中的幀可以交錯傳送,不需要等某個流傳送完,才傳送下一個。也就是說在一個TCP連線中,可以同時傳輸多個流,即可以同時傳輸多個HTTP請求和響應,這種同時傳輸不需要遵循先入先出等規定,因此也不會產生阻塞,效率極高。stream_ID
欄位,表示這個幀屬於哪個流,接收方把stream_ID
相同的所有幀組合到一起就是被傳輸的內容了。而流是HTTP/2中的一個邏輯上的概念,它代表著HTTP/1.1中的一個請求或者一個響應,協議規定client發給server的流的stream_ID
為奇數,server發給client的流ID是偶數。需要注意的是,流只是一個邏輯概念,便於理解和記憶的,實際並不存在。
HTTP/2新增首部壓縮(Server Push):採用HPACK演算法
在 HTTP/1 中,HTTP 請求和響應都是由「狀態行、請求 / 響應頭部、訊息主體」三部分組成。一般而言,訊息主體都會經過 gzip 壓縮,或者本身傳輸的就是壓縮過後的二進位制檔案(例如圖片、音訊),但狀態行和頭部卻沒有經過任何壓縮,直接以純文字傳輸。
隨著 Web 功能越來越複雜,每個頁面產生的請求數也越來越多,根據 HTTP Archive 的統計,當前平均每個頁面都會產生上百個請求。越來越多的請求導致消耗在頭部的流量越來越多,尤其是每次都要傳輸 UserAgent、Cookie 這類不會頻繁變動的內容,完全是一種浪費。
Hapck原理:
具體規則可以描述為:
- 通訊雙方共同維護了一份靜態表,包含了常見的頭部名稱與值的組合
- 根據先入先出的原則,維護一份可動態新增內容的動態表
- 用基於該靜態哈夫曼碼錶的哈夫曼編碼資料
當要傳送一個請求時,會先將其頭部和靜態表對照,對於完全匹配的鍵值對,可以直接使用一個數字表示,如method: GET,對於頭部名稱匹配的鍵值對,可以將名稱使用一個數字傳輸,同時告訴服務端將它新增到動態表中,以後的相同鍵值對就用一個數字表示了。這樣,像cookie這些不經常變動的值,只用傳送一次就好了。
HTTP/2新增服務端推送(Header Compression)
即伺服器傳送/user.html
時,就可以主動把/user.js
和style.css
push給瀏覽器,使資源提前達到瀏覽器;除了靜態檔案,還可以推送比較耗時的API,只是需要提前將引數和cookie等資訊通過某個方式告知服務端(如和路由關聯)。Apache、GO的net/http、node-spdy都實現了server push(但ngnix沒有=_=)
Server push是HTTP/2協議裡面唯一一個需要開發者自己配置的功能。其他功能都是伺服器和瀏覽器自動實現,無需開發者介入。
在HTTP1.1時代,也有提前獲取資源的方法,如preload和prefetch,前者是在頁面解析初期就告訴瀏覽器,這個資源是瀏覽器馬上要用到的,可以立刻傳送對資源的請求,當需要用到該資源時就可以直接用而不用等待請求和響應的返回了;後者是當前頁面用不到但下一頁面可能會用到的資源,優先順序較低,只有當瀏覽器空閒時才會請求prefetch標記的資源。從應用層面上看,preload和server push並沒有什麼區別,但是server push減少瀏覽器請求的時間,略優於preload,在一些場景中,可以將兩者結合使用。