HTTP/2
HTTP/2相比HTTP/1而言提供了更加高效的傳輸方式,解決了HTTP/1.x中存在的很多問題,協議增加了二進制幀控制層,大多數改動都封裝在這一層。以下會簡單對比HTTP/1.0 & HTTP/1.1 從而引申出HTTP/2的改進。
-
HTTP/1.0 & HTTP/1.1
- 1.1新增對長鏈接的支持:1.0中每次client與server建立TPC鏈接並完成請求處理以后,TCP鏈接即斷開,而在1.1中HTTP支持使用keep-alive選項來開啟長鏈接,也就是HTTP連接會維持一段時間,這樣在這段時間內這個連接上的數據就能夠直接傳輸而不需要再次進行耗時的TCP建立連接的過程了。長短連接的關系問題可以參考HTTP長鏈接短鏈接
- 1.1新增了對請求流水(piplining)的支持,就是圖中第二欄所示。
但是這里也有一個問題就是頭部阻塞,HTTP/1.1必須按順序接收三個請求,所以如果其中某一個請求失敗,client必須等待請求重發並接收成功后才能繼續向下處理
- 1.1添加了更多的Catch緩存策略選項,比如:Entity tag,If-Unmodified-Since, If-Match, If-None-Match等,參考這個http緩存機制原理
- 增加了一些錯誤通知類型
- 支持host頭域,這個主要是為了適應虛擬主機的使用
- 允許部分請求資源,而不是像以前一樣必須返回整個對象
-
HTTP/2新增詳細,這里我基本上是搬運了HTTP/2英文 良心翻譯
- HTTP2.0並沒有改變之前HTTP的語義,也就是說高層的Api並沒有改變,它是在底層通過二進制frame來改變性能的
- 二進制幀層:
http/1.x使用換行符分割文本,而HTTP/2則改用二進制來進行傳輸,雖然麻煩一些但是在效率和正確性上都得到了保證。- ASCII 協議能夠很容易的看出來和開始使用。然而它們是沒有效率的,且很難正確設計:可選的空白,改變終止序列和其他的毛病使得協議很難區別出payload。雖然二進制協議用起來需要做很多工作,但是它們能表現出更好的性能。
- 消息傳遞方式:最小的消息單元為幀,是消息的切片,傳輸時可以亂序,可以組裝。frame組成邏輯上的消息,即request和response。同一個TCP連接上有很多雙向流供frame流通。注意,所有的通信都在同一個TCP連接上進行。
- 多路復用解決頭阻塞問題:HTTP/2使用的是frame為單元的二進制消息單元進行通信的,並且提供了亂序傳遞,然后組裝的消息處理方式,使得多路數據可以混雜在一起進行傳遞,這也使得其中某個消息的丟棄並不會影響到其他消息的正常傳遞,所以也就沒有了1.1中的頭部阻塞問題。這一特性使得HTTP協議的速度有了一個大的提升。
當然,也有部分資料提出由於HTTP/2通常基於TCP實現,所以依舊存在丟包會等待重傳的問題(HOL阻塞),這里又引申出QUIC協議,這里本文就不在深入介紹啦。 - 可以設定流的優先級和依賴
- 服務推送:HTTP/1.x在現代網頁渲染的時候為了處理一個完整的網頁可能同時簇發幾十甚至上百個請求,這是沒有必要的,實際上服務器完全可以通過特定的請求和預先恰當的定義,分析得到前端需要哪些資源,然后由server主動推送這些資源。HTTP/2提供了這種能力。
- 頭部壓縮:同樣的,現代網頁簇發多個request,但是它們的頭很可能是沒啥區別的,這是很大的浪費。甚至有的時候消息頭的大小會超過實際需要的數據,這是不合理的。
為了解決這個問題,HTTP/2引入了頭部壓縮。個人認為它實際上是在服務端建立了一個頭部索引,client可以通過特定的索引來獲取頭信息,而不需要完整的攜帶它們,對於新的頭選項client和server協作更新並保存。如圖所示: