解讀 HTTP1/HTTP2/HTTP3

這是我參與8月更文挑戰的第9天,活動詳情查看:8月更文挑戰html

HTTP/2 相比於 HTTP/1.1,能夠說是大幅度提升了網頁的性能,只須要升級到該協議就能夠減小不少以前須要作的性能優化工做,雖然如此但HTTP/2並不是完美的,HTTP/3 就是爲了解決 HTTP/2 所存在的一些問題而被推出來的。webpack

HTTP1.1 的缺陷

  1. 高延遲 — 隊頭阻塞(Head-Of-Line Blocking)
  2. 無狀態特性 — 阻礙交互
  3. 明文傳輸 — 不安全性
  4. 不支持服務端推送

一、高延遲--帶來頁面加載速度的下降

雖然近年來網絡帶寬增加很是快,然而咱們卻並無看到網絡延遲有相應程度的下降。網絡延遲問題主要因爲隊頭阻塞(Head-Of-Line Blocking),致使帶寬沒法被充分利用web

隊頭阻塞是指當順序發送的請求序列中的一個請求由於某種緣由被阻塞時,在後面排隊的全部請求也一併被阻塞,會致使客戶端遲遲收不到數據。針對隊頭阻塞,人們嘗試過如下辦法來解決:面試

  • 將同一頁面的資源分散到不一樣域名下,提高鏈接上限。 Chrome有個機制,對於同一個域名,默認容許同時創建 6 個 TCP持久鏈接,使用持久鏈接時,雖然能公用一個TCP管道,可是在一個管道中同一時刻只能處理一個請求,在當前的請求沒有結束以前,其餘的請求只能處於阻塞狀態。另外若是在同一個域名下同時有10個請求發生,那麼其中4個請求會進入排隊等待狀態,直至進行中的請求完成。
  • 合併小文件減小資源數。精靈圖,Spriting合併多張小圖爲一張大圖,再用JavaScript或者CSS將小圖從新「切割」出來的技術。
  • 內聯(Inlining)資源是另一種防止發送不少小圖請求的技巧,將圖片的原始數據嵌入在CSS文件裏面的URL裏,減小網絡請求次數。
  • 減小請求數量。拼接(Concatenation)將多個體積較小的JavaScript使用webpack等工具打包成1個體積更大的JavaScript文件,但若是其中1個文件的改動就會致使大量數據被從新下載多個文件。

二、無狀態特性--帶來的巨大HTTP頭部

無狀態是指協議對於鏈接狀態沒有記憶能力。純淨的 HTTP 是沒有 cookie 等機制的,每個鏈接都是一個新的鏈接。算法

因爲報文Header通常會攜帶"User Agent""Cookie""Accept""Server"等許多固定的頭字段(以下圖),多達幾百字節甚至上千字節,但Body卻常常只有幾十字節(好比GET請求、204/301/304響應),成了徹徹底底的「大頭兒子」。Header裏攜帶的內容過大,在必定程度上增長了傳輸的成本。更要命的是,請求響應報文裏有大量字段值都是重複的,很是浪費。segmentfault

三、明文傳輸--帶來的不安全性

HTTP/1.1在傳輸數據時,全部傳輸的內容都是明文,客戶端和服務器端都沒法驗證對方的身份,這在必定程度上沒法保證數據的安全性。瀏覽器

四、不支持服務器推送消息

SPDY 協議與 HTTP/2 簡介

一、SPDY 協議

上面咱們提到,因爲HTTP/1.x的缺陷,咱們會引入雪碧圖、將小圖內聯、使用多個域名等等的方式來提升性能。不過這些優化都繞開了協議,直到2009年,谷歌公開了自行研發的 SPDY 協議,主要解決HTTP/1.1效率不高的問題。谷歌推出SPDY,纔算是正式改造HTTP協議自己。下降延遲,壓縮header等等,SPDY的實踐證實了這些優化的效果,也最終帶來HTTP/2的誕生。緩存

image.png

HTTP/1.1有兩個主要的缺點: 安全不足和性能不高,因爲揹負着 HTTP/1.x 龐大的歷史包袱,因此協議的修改,兼容性是首要考慮的目標,不然就會破壞互聯網上無數現有的資產。如上圖所示,SPDY位於HTTP之下,TCP和SSL之上,這樣能夠輕鬆兼容老版本的HTTP協議(將HTTP1.x的內容封裝成一種新的frame格式),同時可使用已有的SSL功能。安全

SPDY 協議在Chrome瀏覽器上證實可行之後,就被看成 HTTP/2 的基礎,主要特性都在 HTTP/2 之中獲得繼承。性能優化

二、HTTP/2 簡介

2015年,HTTP/2 發佈。HTTP/2是現行HTTP協議(HTTP/1.x)的替代,但它不是重寫,HTTP方法/狀態碼/語義都與HTTP/1.x同樣。HTTP/2基於SPDY,專一於性能,最大的一個目標是在用戶和網站間只用一個鏈接(connection) 。從目前的狀況來看,國內外一些排名靠前的站點基本都實現了HTTP/2的部署,使用HTTP/2能帶來20%~60%的效率提高。

HTTP/2由兩個規範(Specification)組成:

  1. Hypertext Transfer Protocol version 2 - RFC7540
  2. HPACK - Header Compression for HTTP/2 - RFC7541

HTTP/2 新特性

一、二進制傳輸

HTTP/2傳輸數據量的大幅減小,主要有兩個緣由:以二進制方式傳輸和Header 壓縮。咱們先來介紹二進制傳輸,HTTP/2 採用二進制格式傳輸數據,而非HTTP/1.x 裏純文本形式的報文 ,二進制協議解析起來更高效。HTTP/2 將請求和響應數據分割爲更小的幀,而且它們採用二進制編碼

它把TCP協議的部分特性挪到了應用層,把原來的"Header+Body"的消息"打散"爲數個小片的二進制"幀"(Frame),用"HEADERS"幀存放頭數據、"DATA"幀存放實體數據。HTP/2數據分幀後"Header+Body"的報文結構就徹底消失了,協議看到的只是一個個的"碎片"。

image.png

HTTP/2 中,同域名下全部通訊都在單個鏈接上完成,該鏈接能夠承載任意數量的雙向數據流。每一個數據流都以消息的形式發送,而消息又由一個或多個幀組成。多個幀之間能夠亂序發送,根據幀首部的流標識能夠從新組裝

二、Header 壓縮

HTTP/2並無使用傳統的壓縮算法,而是開發了專門的"HPACK」算法,在客戶端和服務器兩端創建「字典」,用索引號表示重複的字符串,還採用哈夫曼編碼來壓縮整數和字符串,能夠達到50%~90%的高壓縮率。

具體來講:

  • 在客戶端和服務器端使用「首部表」來跟蹤和存儲以前發送的鍵-值對,對於相同的數據,再也不經過每次請求和響應發送;
  • 首部表在HTTP/2的鏈接存續期內始終存在,由客戶端和服務器共同漸進地更新;
  • 每一個新的首部鍵-值對要麼被追加到當前表的末尾,要麼替換表中以前的值

例以下圖中的兩個請求, 請求一發送了全部的頭部字段,第二個請求則只須要發送差別數據,這樣能夠減小冗餘數據,下降開銷

三、多路複用

在 HTTP/2 中引入了多路複用的技術。多路複用很好的解決了瀏覽器限制同一個域名下的請求數量的問題,同時也接更容易實現全速傳輸,畢竟新開一個 TCP 鏈接都須要慢慢提高傳輸速度。

你們能夠經過 該連接 直觀感覺下 HTTP/2 比 HTTP/1 到底快了多少。

在 HTTP/2 中,有了二進制分幀以後,HTTP /2 再也不依賴 TCP 連接去實現多流並行了,在 HTTP/2中:

  • 同域名下全部通訊都在單個鏈接上完成。
  • 單個鏈接能夠承載任意數量的雙向數據流。
  • 數據流以消息的形式發送,而消息又由一個或多個幀組成,多個幀之間能夠亂序發送,由於根據幀首部的流標識能夠從新組裝。

這一特性,使性能有了極大提高:

  • 同個域名只須要佔用一個 TCP 鏈接,使用一個鏈接並行發送多個請求和響應,這樣整個頁面資源的下載過程只須要一次慢啓動,同時也避免了多個TCP鏈接競爭帶寬所帶來的問題。
  • 並行交錯地發送多個請求/響應,請求/響應之間互不影響。
  • 在HTTP/2中,每一個請求均可以帶一個31bit的優先值,0表示最高優先級, 數值越大優先級越低。有了這個優先值,客戶端和服務器就能夠在處理不一樣的流時採起不一樣的策略,以最優的方式發送流、消息和幀。

image.png

如上圖所示,多路複用的技術能夠只經過一個 TCP 鏈接就能夠傳輸全部的請求數據。

四、Server Push

HTTP2還在必定程度上改變了傳統的「請求-應答」工做模式,服務器再也不是徹底被動地響應請求,也能夠新建「流」主動向客戶端發送消息。好比,在瀏覽器剛請求HTML的時候就提早把可能會用到的JS、CSS文件發給客戶端,減小等待的延遲,這被稱爲"服務器推送"( Server Push,也叫 Cache push)

例以下圖所示,服務端主動把JS和CSS文件推送給客戶端,而不須要客戶端解析HTML時再發送這些請求。

image.png

另外須要補充的是,服務端能夠主動推送,客戶端也有權利選擇是否接收。若是服務端推送的資源已經被瀏覽器緩存過,瀏覽器能夠經過發送RST_STREAM幀來拒收。主動推送也遵照同源策略,換句話說,服務器不能隨便將第三方資源推送給客戶端,而必須是通過雙方確認才行。

五、提升安全性

出於兼容的考慮,HTTP/2延續了HTTP/1的「明文」特色,能夠像之前同樣使用明文傳輸數據,不強制使用加密通訊,不過格式仍是二進制,只是不須要解密。

但因爲HTTPS已是大勢所趨,並且主流的瀏覽器Chrome、Firefox等都公開宣佈只支持加密的HTTP/2,因此「事實上」的HTTP/2是加密的。也就是說,互聯網上一般所能見到的HTTP/2都是使用"https」協議名,跑在TLS上面。HTTP/2協議定義了兩個字符串標識符:「h2"表示加密的HTTP/2,「h2c」表示明文的HTTP/2。

HTTP/2 的缺點

雖然 HTTP/2 解決了不少以前舊版本的問題,可是它仍是存在一個巨大的問題,主要是底層支撐的 TCP 協議形成的。HTTP/2的缺點主要有如下幾點:

  1. TCP 以及 TCP+TLS 創建鏈接的延時
  2. TCP 的隊頭阻塞並無完全解決
  3. 多路複用致使服務器壓力上升
  4. 多路複用容易 Timeout

建連延時

HTTP/2都是使用TCP協議來傳輸的,而若是使用HTTPS的話,還須要使用TLS協議進行安全傳輸,而使用TLS也須要一個握手過程,這樣就須要有兩個握手延遲過程

①在創建TCP鏈接的時候,須要和服務器進行三次握手來確認鏈接成功,即須要消耗完 1.5 個 RTT 以後才能進行數據傳輸。

②進行TLS鏈接,TLS有兩個版本——TLS1.2和TLS1.3,每一個版本創建鏈接所花的時間不一樣,大體是須要1~2個RTT。

總之,在傳輸數據以前,咱們須要花掉 3~4 個 RTT。

RTT(Round-Trip Time):
往返時延。表示從發送端發送數據開始,到發送端收到來自接收端的確認(接收端收到數據後便當即發送確認),總共經歷的時延。

隊頭阻塞沒有完全解決

上文咱們提到在HTTP/2中,多個請求是跑在一個TCP管道中的。但當出現了丟包時,HTTP/2 的表現反倒不如 HTTP/1 了。由於TCP爲了保證可靠傳輸,有個特別的「丟包重傳」機制,丟失的包必需要等待從新傳輸確認,HTTP/2出現丟包時,整個 TCP 都要開始等待重傳,那麼就會阻塞該TCP鏈接中的全部請求(以下圖)。而對於 HTTP/1.1 來講,能夠開啓多個 TCP 鏈接,出現這種狀況反到只會影響其中一個鏈接,剩餘的 TCP 鏈接還能夠正常傳輸數據。

image.png

RTO:英文全稱是 Retransmission TimeOut,即重傳超時時間; RTO 是一個動態值,會根據網絡的改變而改變。RTO 是根據給定鏈接的往返時間 RTT 計算出來的。 接收方返回的 ack 是但願收到的下一組包的序列號。

可能就會有人考慮爲何不直接去修改 TCP 協議?其實這已是一件不可能完成的任務了。由於 TCP 存在的時間實在太長,已經充斥在各類設備中,而且這個協議是由操做系統實現的,更新起來不大現實。

多路複用致使服務器壓力上升

多路複用沒有限制同時請求數。請求的平均數量與往常相同,但實際會有許多請求的短暫爆發,致使瞬時 QPS 暴增。

多路複用容易 Timeout

大批量的請求同時發送,因爲 HTTP2 鏈接內存在多個並行的流,而網絡帶寬和服務器資源有限,每一個流的資源會被稀釋,雖然它們開始時間相差更短,但卻均可能超時。

即便是使用 Nginx 這樣的負載均衡器,想正確進行節流也可能很棘手。 其次,就算你嚮應用程序引入或調整排隊機制,但一次能處理的鏈接也是有限的。若是對請求進行排隊,還要注意在響應超時後丟棄請求,以免浪費沒必要要的資源。引用

HTTP/3 新特性

一、HTTP/3簡介

Google 在推SPDY的時候就已經意識到了這些問題,因而就另起爐竈搞了一個基於 UDP 協議的「QUIC」協議,讓HTTP跑在QUIC上而不是TCP上。而這個「HTTP over QUIC」就是HTTP協議的下一個大版本,HTTP/3。它在HTTP/2的基礎上又實現了質的飛躍,真正「完美」地解決了「隊頭阻塞」問題。

QUIC 雖然基於 UDP,可是在本來的基礎上新增了不少功能,接下來咱們重點介紹幾個QUIC新功能。不過HTTP/3目前還處於草案階段,正式發佈前可能會有變更,因此本文儘可能不涉及那些不穩定的細節。

二、QUIC新功能

上面咱們提到QUIC基於UDP,而UDP是「無鏈接」的,根本就不須要「握手」和「揮手」,因此就比TCP來得快。此外QUIC也實現了可靠傳輸,保證數據必定可以抵達目的地。它還引入了相似HTTP/2的「流」和「多路複用」,單個「流"是有序的,可能會由於丟包而阻塞,但其餘「流」不會受到影響。具體來講QUIC協議有如下特色:

  • 實現了相似TCP的流量控制、傳輸可靠性的功能

    雖然UDP不提供可靠性的傳輸,但QUIC在UDP的基礎之上增長了一層來保證數據可靠性傳輸。它提供了數據包重傳、擁塞控制以及其餘一些TCP中存在的特性。

    QUIC 協議到底改進在哪些方面呢?主要有以下幾點:

    1. 可插拔 — 應用程序層面就能實現不一樣的擁塞控制算法。
    2. 單調遞增的 Packet Number — 使用 Packet Number 代替了 TCP 的 seq。
    3. 不容許 Reneging — 一個 Packet 只要被 Ack,就認爲它必定被正確接收。
    4. 前向糾錯(FEC)
    5. 更多的 Ack 塊和增長 Ack Delay 時間。
    6. 基於 stream 和 connection 級別的流量控制。
  • 實現了快速握手功能

    因爲QUIC是基於UDP的,因此QUIC能夠實現使用0-RTT或者1-RTT來創建鏈接,這意味着QUIC能夠用最快的速度來發送和接收數據,這樣能夠大大提高首次打開頁面的速度。0RTT 建連能夠說是 QUIC 相比 HTTP2 最大的性能優點

  • 集成了TLS加密功能

    目前QUIC使用的是TLS1.3,相較於早期版本TLS1.3有更多的優勢,其中最重要的一點是減小了握手所花費的RTT個數。

    在徹底握手狀況下,須要 1-RTT 創建鏈接。 TLS1.3 恢復會話能夠直接發送加密後的應用數據,不須要額外的 TLS 握手,也就是 0-RTT。

    可是 TLS1.3 也並不完美。TLS 1.3 的 0-RTT 沒法保證前向安全性(Forward secrecy)。簡單講就是,若是當攻擊者經過某種手段獲取到了 Session Ticket Key,那麼該攻擊者能夠解密之前的加密數據。

    要緩解該問題能夠經過設置使得與 Session Ticket Key 相關的 DH 靜態參數在短期內過時(通常幾個小時)。

  • 多路複用,完全解決TCP中隊頭阻塞的問題

    和TCP不一樣,QUIC實現了在同一物理鏈接上能夠有多個獨立的邏輯數據流(以下圖)。實現了數據流的單獨傳輸,就解決了TCP中隊頭阻塞的問題。

  • 鏈接遷移

    TCP 是按照 4 要素(客戶端 IP、端口, 服務器 IP、端口)肯定一個鏈接的。而 QUIC 則是讓客戶端生成一個 Connection ID (64 位)來區別不一樣鏈接。只要 Connection ID 不變,鏈接就不須要從新創建,即使是客戶端的網絡發生變化。因爲遷移客戶端繼續使用相同的會話密鑰來加密和解密數據包,QUIC 還提供了遷移客戶端的自動加密驗證。

總結

  • HTTP/1.1有兩個主要的缺點:安全不足和性能不高。
  • HTTP/2徹底兼容HTTP/1,是「更安全的HTTP、更快的HTTPS",二進制傳輸、頭部壓縮、多路複用、服務器推送等技術能夠充分利用帶寬,下降延遲,從而大幅度提升上網體驗;
  • QUIC 基於 UDP 實現,是 HTTP/3 中的底層支撐協議,該協議基於 UDP,又取了 TCP 中的精華,實現了即快又可靠的協議。

面試題 http2 與 http1.1 區別,瞭解 http3 麼,說說;

答案嘛,既然看了本文,那就試着總結下吧,加深下記憶!!!

參考資料

  1. http2.0 原理詳細分析
  2. HPACK: HTTP/2 裏的沉默殺手
  3. QPACK:HTTP /3 的頭壓縮
  4. DH 算法
  5. 前向安全(ForwardSecrecy)
  6. TLS 1.3 VS TLS 1.2,讓你明白 TLS 1.3 的強大
  7. CaddyWeb 服務器 QUIC 部署
  8. 關於 QUIC 的各類嘗試
  9. 使用 QUIC 協議實現實時視頻直播 0 卡頓
  10. 解密 HTTP/2 與 HTTP/3 的新特性
  11. Web通訊協議,你還須要知道: SPDY 和 QUIC
  12. 如何看待 HTTP/3 ?

若是這篇文章幫到了你,記得點贊👍收藏加關注哦😊,但願點贊多多多多...

文中若有錯誤,歡迎在評論區指正

相關文章
相關標籤/搜索