本文主要介紹的是 HTTP/1.1,咱們先來學習下 HTTP/1.1 的進化史,而後再介紹在進化過程當中所遇到的各類瓶頸,以及對應的解決方法。瀏覽器
HTTP/0.9 是於 1991 年提出的,主要用於學術交流,需求很簡單——用來在網絡之間傳遞
HTML 超文本
的內容,因此被稱爲超文本傳輸協議
。
HTTP/0.9 的實現有如下三個特色:安全
- 第一個是隻有一個請求行,並無 HTTP 請求頭和請求體,由於只須要一個請求行就能夠完整表達客戶端的需求了。
- 第二個是服務器也沒有返回頭信息,這是由於服務器端並不須要告訴客戶端太多信息,只須要返回數據就能夠了。
- 第三個是返回的文件內容是以 ASCII 字符流來傳輸的,由於都是 HTML 格式的文件,因此使用 ASCII 字節碼來傳輸是最合適的。
變化是這個世界永恆不變的主旋律,1994 年末出現了撥號上網服務,同年網景又推出一款瀏覽器,今後萬維網就不侷限於學術交流了,而是進入了高速的發展階段。 萬維網的高速發展帶來了不少新的需求,而 HTTP/0.9 已經不能適用新興網絡的發展,因此這時就須要一個新的協議來支撐新興網絡,這就是 HTTP/1.0 誕生的緣由。性能優化
新興網絡帶來了新的需求:首先在瀏覽器中展現的不單是 HTML 文件了,還包括了 JavaScript、CSS、圖片、音頻、視頻等不一樣類型的文件。所以支持多種類型的文件下載是 HTTP/1.0 的一個核心訴求,並且文件格式不只僅侷限於 ASCII 編碼,還有不少其餘類型編碼的文件。服務器
爲了讓客戶端和服務器能更深刻地交流,HTTP/1.0 引入了
請求頭
和響應頭
,它們都是覺得 Key-Value 形式保存的,在 HTTP 發送請求時,會帶上請求頭信息,服務器返回數據時,會先返回響應頭信息。
HTTP/1.0 的方案是經過請求頭和響應頭來進行協商,在發起請求時候會經過 HTTP 請求頭告訴服務器它期待服務器返回什麼類型的文件、採起什麼形式的壓縮、提供什麼語言的文件以及文件的具體編碼。網絡
技術繼續發展、需求不斷迭代更新,HTTP/1.0也不能知足需求了,HTTP/1.1又在HTTP/1.0上繼續更新:性能
HTTP/1.1 中增長了持久鏈接的方法,它的特色是在一個 TCP 鏈接上能夠傳輸多個 HTTP 請求,只要瀏覽器或者服務器沒有明確斷開鏈接,那麼該 TCP 鏈接會一直保持。 HTTP 的持久鏈接能夠有效減小 TCP 創建鏈接和斷開鏈接的次數,這樣的好處是減小了服務器額外的負擔,並提高總體 HTTP 的請求時長。
持久鏈接在 HTTP/1.1 中是默認開啓的,因此你不須要專門爲了持久鏈接去 HTTP 請求頭設置信息,若是你不想要採用持久鏈接,能夠在 HTTP 請求頭中加上Connection: close。目前瀏覽器中對於同一個域名,默認容許同時創建 6 個 TCP 持久鏈接.學習
若是 TCP 通道中的某個請求由於某些緣由沒有及時返回,那麼就會阻塞後面的全部請求,這就是著名的隊頭阻塞的問題。
HTTP/1.1 中試圖經過管線化的技術來解決隊頭阻塞的問題。HTTP/1.1 中的管線化是指將多個 HTTP 請求整批提交給服務器的技術,雖然能夠整批發送請求,不過服務器依然須要根據請求順序來回復瀏覽器的請求。
FireFox、Chrome 都作過管線化的試驗,可是因爲各類緣由,它們最終都放棄了管線化技術.測試
在 HTTP/1.0 中,每一個域名綁定了一個惟一的 IP 地址,所以一個服務器只能支持一個域名。
可是隨着虛擬主機技術的發展,須要實如今一臺物理主機上綁定多個虛擬主機,每一個虛擬主機都有本身的單獨的域名,這些單獨的域名都公用同一個 IP 地址。
所以,HTTP/1.1 的請求頭中增長了 Host 字段,用來表示當前的域名地址,這樣服務器就能夠根據不一樣的 Host 值作不一樣的處理。優化
在設計 HTTP/1.0 時,須要在響應頭中設置完整的數據大小,如Content-Length: 901,這樣瀏覽器就能夠根據設置的數據大小來接收數據。
不過隨着服務器端的技術發展,不少頁面的內容都是動態生成的,所以在傳輸數據以前並不知道最終的數據大小,這就致使了瀏覽器不知道什麼時候會接收完全部的文件數據。 HTTP/1.1 經過引入 Chunk transfer 機制來解決這個問題,服務器會將數據分割成若干個任意大小的數據塊,每一個數據塊發送時會附上上個數據塊的長度,最後使用一個零長度的塊做爲發送數據完成的標誌。這樣就提供了對動態內容的支持。編碼
除此以外,HTTP/1.1 還引入了客戶端 Cookie 機制和安全機制。
HTTP/1.1爲網絡效率作了大量的優化,最核心的三種方式爲:
- 增長了持久鏈接。
- 瀏覽器爲每一個域名最多同時支持6個TCP持久鏈接。
- 使用CDN的實現域名分片機制。
HTTP/1.1對帶寬的利用率卻並不理想,這也是 HTTP/1.1 的一個核心問題. 帶寬是指每秒最大能發送或者接收的字節數。咱們把每秒能發送的最大字節數稱爲上行帶寬,每秒可以接收的最大字節數稱爲下行帶寬。
出現寬帶利用率不理想的緣由,主要爲:
- 第一個緣由,TCP的慢啓動。
- 第二個緣由,同時開啓了多條TCP鏈接,那麼這些鏈接會競爭固定的寬帶。
- 第三個緣由,HTTP/1.1隊頭阻塞的問題。
HTTP/2 的解決方案能夠總結爲:一個域名只使用一個 TCP 長鏈接和消除隊頭阻塞問題.
具體實現就是:經過引入二進制分幀層,實現 HTTP 的多路複用技術。
- 能夠設置請求的優先級。
- 服務器推送。
- 頭部壓縮。
HTTP/2 協議規範於 2015 年 5 月正式發佈,在那以後,該協議已在互聯網和萬維網上獲得了普遍的實現和部署。從目前的狀況來看,國內外一些排名靠前的站點基本都實現了 HTTP/2 的部署。使用 HTTP/2 能帶來 20%~60% 的效率提高,至於 20% 仍是 60% 要看優化的程度。總之,咱們也應該與時俱進,放棄 HTTP/1.1 和其性能優化方法,去「擁抱」HTTP/2
和一般同樣,介紹 HTTP/3 以前,咱們先來看看 HTTP/2 到底有什麼缺陷。
在 TCP 傳輸過程當中,因爲單個數據包的丟失而形成的阻塞稱爲 TCP 上的隊頭阻塞。
有測試數據代表,當系統達到了 2% 的丟包率時,HTTP/1.1 的傳輸效率反而比 HTTP/2 表現得更好。
網絡延遲又稱爲 RTT(Round Trip Time)。咱們把從瀏覽器發送一個數據包到服務器,再從服務器返回數據包到瀏覽器的整個往返時間稱爲 RTT。RTT 是反映網絡性能的一個重要指標。
雖然咱們知道了TCP的隊頭阻塞和創建鏈接延時等缺點,可是經過改進TCP協議來解決這些問題很是困難,這裏說的很是困難就是指TCP協議僵化。
TCP協議僵化體如今兩個方面:第一個是中間設備的僵化;除中間設備的僵化外,操做系統也是致使TCP協議僵化的另一個緣由。
HTTP/3 選擇了一個折衷的方法——UDP 協議,基於 UDP 實現了相似於 TCP 的多路數據流、傳輸可靠性等功能,咱們把這套功能稱爲 QUIC 協議。 HTTP/3 中的 QUIC 協議集合瞭如下幾點功能:
- 實現了相似 TCP 的流量控制、傳輸可靠性的功能。雖然 UDP 不提供可靠性的傳輸,但 QUIC 在 UDP 的基礎之上增長了一層來保證數據可靠性傳輸。它提供了數據包重傳、擁塞控制以及其餘一些 TCP 中存在的特性。
- 集成了 TLS 加密功能。
- 實現了 HTTP/2 中的多路複用功能。
- 實現了快速握手功能。
經過上面的分析,咱們相信在技術層面,HTTP/3 是個完美的協議。不過要將 HTTP/3 應用到實際環境中依然面臨着諸多嚴峻的挑戰,這些挑戰主要來自於如下三個方面:
- 第一,從目前的狀況來看,服務器和瀏覽器端都沒有對 HTTP/3 提供比較完整的支持。Chrome 雖然在數年前就開始支持 Google 版本的 QUIC,可是這個版本的 QUIC 和官方的 QUIC 存在着很是大的差別。
- 第二,部署 HTTP/3 也存在着很是大的問題。由於系統內核對 UDP 的優化遠遠沒有達到 TCP 的優化程度,這也是阻礙 QUIC 的一個重要緣由。
- 第三,中間設備僵化的問題。這些設備對 UDP 的優化程度遠遠低於 TCP,據統計使用 QUIC 協議時,大約有 3%~7% 的丟包率。