http發展史(http0.九、http1.0、http1.一、http二、http3)梳理筆記

前言

對於前端開發者來講,http知識點的重要性不言而喻,不管是面試亦或工做須要。本人菜鳥一枚,試着梳理下http的知識點,從http的發展史整理以此加深印象學習,輸出知識才是真正地學習。另外文章內容若有不足還請斧正。css

提早聲明:本文主要內容參考於極客時間課程《瀏覽器工做原理與實踐》http部分。html

HTTP是瀏覽器中最重要使用最多的協議,是瀏覽器和服 務器之間的通訊語言,也是互聯網的基石。隨着瀏覽器的發展,HTTP爲了能適應新的形式也在持續進化,學習HTTP的最佳途徑就是了解其發展史, 從瀏覽器發展的視角來來了解HTTP演進: 即將完成使命的HTTP/1正在向咱們走來的HTTP/2以及將來的HTTP/3前端

超文本傳輸協議HTTP/0.9

HTTP最先誕生的版本是0.9,是於1991年提出的,主要用於學術交流,需求很簡單——用來在網絡之間傳遞HTML超文本的內容,因此被稱爲超文本傳輸協議。總體來看,它的實現也很簡單,採用了基於請求響應的模式,從客戶端發出請求,服務器返回數據。面試

下面咱們就來看看HTTP/0.9的完整的請求流程:瀏覽器

  • 由於HTTP都是基於TCP協議的,因此客戶端先要根據IP地址、端口和服務器創建TCP鏈接,而創建鏈接的過程就是TCP協議三次握手的過程。
  • 創建好鏈接以後,會發送一個GET請求行的信息,如GET /index.html用來獲取index.html。
  • 服務器接收請求信息以後,讀取對應的HTML文件,並將數據以ASCII字符流返回給客戶端。
  • HTML文檔傳輸完成後,斷開鏈接。

http/0.9請求流程

總的來講,當時的需求很簡單,就是用來傳輸體積很小的HTML文件,因此HTTP/0.9的實現有如下三個特色:緩存

  • 第一個是隻有一個請求行,並沒有HTTP請求頭和請求體,由於只須要一個請求行就能夠完整表達客戶端的需求了。
  • 第二個是服務器也沒有返回頭信息,這是由於服務器端並不須要告訴客戶端太多信息,只須要返回數據就 能夠了。
  • 第三個是返回的文件內容是以ASCII字符流來傳輸的,由於都是HTML格式的文件,因此使用ASCII字節碼 來傳輸是最合適的。

被瀏覽器推進的HTTP/1.0

雖然如今看來http/0.9版本很是簡單,只是純粹地HTML文件傳輸,但那時已經知足學術交流了;而當1994年末出現了撥號上網和網景推出一款瀏覽器後,萬維網就不侷限於學術交流了,由於在瀏覽器中展現的不單是HTML文件了,還包括了JavaScript、CSS、圖片、音頻、視頻等不一樣類型的文件。所以http/1.0呼之欲出,支持多種類型的文件下載是HTTP/1.0的一個核心訴求,並且文件格式不只僅侷限於ASCII編碼, 還有不少其餘類型編碼的文件。安全

那麼該如何實現多種類型文件的下載呢?性能優化

爲了知足傳輸多種類型文件的需求,爲了讓客戶端和服務器能更深刻地交流, HTTP/1.0引入了請求頭和響應頭,它們都是覺得Key-Value形式保存的,在HTTP發送請求時,會帶上請求 頭信息,服務器返回數據時,會先返回響應頭信息。至於HTTP/1.0具體的請求流程,你能夠參考下圖。 bash

http/1.0請求流程

那HTTP/1.0是怎麼經過請求頭和響應頭來支持多種不一樣類型的數據呢?服務器

要支持多種類型的文件,咱們就須要解決如下幾個問題。

  • 首先,瀏覽器須要知道服務器返回的數據是什麼類型的,而後瀏覽器才能根據不一樣的數據類型作針對性的 處理。
  • 其次,因爲萬維網所支持的應用變得愈來愈廣,因此單個文件的數據量也變得愈來愈大。爲了減輕傳輸性 能,服務器會對數據進行壓縮後再傳輸,因此瀏覽器須要知道服務器壓縮的方法。
  • 再次,因爲萬維網是支持全球範圍的,因此須要提供國際化的支持,服務器須要對不一樣的地區提供不一樣的語言版本,這就須要瀏覽器告訴服務器它想要什麼語言版本的⻚面。
  • 最後,因爲增長了各類不一樣類型的文件,而每種文件的編碼形式又可能不同,爲了可以準確地讀取文 件,瀏覽器須要知道文件的編碼類型。

基於以上問題,HTTP/1.0的方案是經過請求頭和響應頭來進行協商,在發起請求時候會經過HTTP請求頭告訴服務器它期待服務器返回什麼類型的文件、採起什麼形式的壓縮、提供什麼語言的文件以及文件的具體編碼。最終發送出來的請求頭內容以下:

accept: text/html
accept-encoding: gzip, deflate, br
accept-Charset: ISO-8859-1,utf-8
accept-language: zh-CN,zh
複製代碼

其中第一行表示指望服務器返回html類型的文件,第二行表示指望服務器能夠採用gzip、deflate或者br其中的一種壓縮方式,第三行表示指望返回的文件編碼是UTF-8或者ISO-8859-1,第四行是表示指望⻚面的優先語言是中文。

服務器接收到瀏覽器發送過來的請求頭信息以後,會根據請求頭的信息來準備響應數據。不過有時候會有一些意外狀況發生,好比瀏覽器請求的壓縮類型是gzip,可是服務器不支持gzip,只支持br壓縮,那麼它會經過響應頭中的content-encoding字段告訴瀏覽器最終的壓縮類型,也就是說最終瀏覽器須要根據響應頭的信息來處理數據。下面是一段響應頭的數據信息:

content-encoding: br
content-type: text/html; charset=UTF-8
複製代碼

其中第一行表示服務器採用了br的壓縮方法,第二行表示服務器返回的是html文件,而且該文件的編碼類型是UTF-8。

有了響應頭的信息,瀏覽器就會使用br方法來解壓文件,再按照UTF-8的編碼格式來處理原始文件,最後按照HTML的方式來解析該文件。這就是HTTP/1.0支持多文件的一個基本的處理流程。

HTTP/1.0除了對多文件提供良好的支持外,還依據當時實際的需求引入了不少其餘的特性,這些特性都是經過請求頭和響應頭來實現的。下面咱們來看看新增的幾個典型的特性:

  • 有的請求服務器可能沒法處理,或者處理出錯,這時候就須要告訴瀏覽器服務器最終處理該請求的狀況,這就引入了狀態碼。狀態碼是經過響應行的方式來通知瀏覽器的。
  • 爲了減輕服務器的壓力,在HTTP/1.0中提供了Cache機制,用來緩存已經下載過的數據。
  • 服務器須要統計客戶端的基礎信息,好比Windows和macOS的用戶數量分別是多少,因此HTTP/1.0的請求頭中還加入了用戶代理的字段。

縫縫補補的HTTP/1.1

不過隨着技術的繼續發展,需求也在不斷迭代更新,很快HTTP/1.0也不能知足需求了,因此HTTP/1.1又在 HTTP/1.0的基礎之上作了大量的更新。接下來咱們來看看HTTP/1.0遇到了哪些主要的問題,以及HTTP/1.1 又是如何改進的。

1. 改進持久鏈接

HTTP/1.0每進行一次HTTP通訊,都須要經歷創建TCP鏈接、傳輸HTTP數據和斷開TCP鏈接三個階段(以下圖)。

http/1.0短鏈接

在當時,因爲通訊的文件比較小,並且每一個頁面的引用也很少,因此這種傳輸形式沒什麼大問題。可是隨着瀏覽器普及,單個頁面中的圖片文件愈來愈多,有時候一個頁面可能包含了幾百個外部引用的資源文件,若是在下載每一個文件的時候,都須要經歷創建TCP鏈接、傳輸數據和斷開鏈接這樣的步驟,無疑會增長大量無謂的開銷。 爲了解決這個問題,HTTP/1.1中增長了持久鏈接的方法,它的特色是在一個TCP鏈接上能夠傳輸多個HTTP 請求,只要瀏覽器或者服務器沒有明確斷開鏈接,那麼該TCP鏈接會一直保持。

http/1.0持久鏈接

從上圖能夠看出,HTTP的持久鏈接能夠有效減小TCP創建鏈接和斷開鏈接的次數,這樣的好處是減小了服務器額外的負擔,並提高總體HTTP的請求時間。

持久鏈接在HTTP/1.1中是默認開啓的,因此你不須要專門爲了持久鏈接去HTTP請求頭設置信息,若是你不想要採用持久鏈接,能夠在HTTP請求頭中加上Connection: close。目前瀏覽器中對於同一個域名,默認容許同時創建6個TCP持久鏈接

2. 不成熟的HTTP管線化

持久鏈接雖然能減小TCP的創建和斷開次數,可是它須要等待前面的請求返回以後,才能進行下一次請求。若是TCP通道中的某個請求由於某些緣由沒有及時返回,那麼就會阻塞後面的全部請求,這就是著名的隊頭阻塞的問題。

HTTP/1.1中試圖經過管線化的技術來解決隊頭阻塞的問題。HTTP/1.1中的管線化是指將多個HTTP請求整批提交給服務器的技術,雖然能夠整批發送請求,不過服務器依然須要根據請求順序來回復瀏覽器的請求。FireFox、Chrome都作過管線化的試驗,可是因爲各類緣由,它們最終都放棄了管線化技術。

3. 提供虛擬主機的支持

在HTTP/1.0中,每一個域名綁定了一個惟一的IP地址,所以一個服務器只能支持一個域名。可是隨着虛擬主機技術的發展,須要實如今一臺物理主機上綁定多個虛擬主機,每一個虛擬主機都有本身的單獨的域名,這些單獨的域名都公用同一個IP地址。 所以,HTTP/1.1的請求頭中增長了Host字段,用來表示當前的域名地址,這樣服務器就能夠根據不一樣的Host值作不一樣的處理。

4. 對動態生成的內容提供了完美支持

在設計HTTP/1.0時,須要在響應頭中設置完整的數據大小,如Content-Length: 901,這樣瀏覽器就可 以根據設置的數據大小來接收數據。不過隨着服務器端的技術發展,不少⻚面的內容都是動態生成的,所以在傳輸數據以前並不知道最終的數據大小,這就致使了瀏覽器不知道什麼時候會接收完全部的文件數據。

HTTP/1.1經過引入Chunk transfer機制來解決這個問題,服務器會將數據分割成若干個任意大小的數據 塊,每一個數據塊發送時會附上上個數據塊的⻓度,最後使用一個零⻓度的塊做爲發送數據完成的標誌。這樣 就提供了對動態內容的支持。

5. 客戶端Cookie、安全機制
小結一下
  • HTTP是瀏覽器和服務器的通訊語言
  • 誕生之初的HTTP/0.9由於需求簡單,因此和服務器之間的通訊過程也相對簡單。
  • HTTP/1.0引入了請求頭和響應頭,主要是爲了支持多種類型的文件下載;其次,還提供了Cache機制、用戶代理、狀態碼等基礎信息。
  • 隨着技術和需求的發展,人們對文件傳輸的速度要求愈來愈高,故又基於HTTP/1.0推出了HTTP/1.1,增 加了持久鏈接方法來提高鏈接效率,同時還嘗試使用管線化技術提高效率(不過因爲各類緣由,管線化技術 最終被各大廠商放棄了)。除此以外,HTTP/1.1還引入了Cookie、虛擬主機的支持、對動態內容的支持等特性。

思考:你認爲HTTP/1.1還有哪些不足?

HTTP2:如何提高網絡速度?

咱們知道HTTP/1.1爲網絡效率作了大量的優化,最核心的有以下三種方式:

1.  增長了持久鏈接;
2.  瀏覽器爲每一個域名最多同時維護6個TCP持久鏈接; 
3.  使用CDN的實現域名分片機制。
複製代碼

經過這些方式就大大提升了頁面的下載速度,你能夠經過下圖來直觀感覺下:

HTTP/1.1的資源下載式

在該圖中,引入了CDN,並同時爲每一個域名維護6個鏈接,這樣就大大減輕了整個資源的下載時間。這裏咱們能夠簡單計算下:若是使用單個TCP的持久鏈接,下載100個資源所花費的時間爲100 * n * RTT;若經過上面的技術,就能夠把整個時間縮短爲100 * n * RTT/(6 * CDN個數)。從這個計算結果來看,咱們的頁面加載速度變快了很多。

HTTP/1.1的主要問題

雖然HTTP/1.1採起了不少優化資源加載速度的策略,也取得了必定的效果,可是HTTP/1.1對帶寬的利用率卻並不理想,這也是HTTP/1.1的一個核心問題。

帶寬是指每秒最大能發送或者接收的字節數。咱們把每秒能發送的最大字節數稱爲上行帶寬,每秒可以接收的最大字節數稱爲下行帶寬。

之因此說HTTP/1.1對帶寬的利用率不理想,是由於HTTP/1.1很難將帶寬用滿。好比咱們常說的100M帶寬, 實際的下載速度能達到12.5M/S,而採用HTTP/1.1時,也許在加載⻚面資源時最大隻能使用到2.5M/S,很難 將12.5M所有用滿。

  • 第一個緣由,TCP的慢啓動。

一旦一個TCP鏈接創建以後,就進入了發送數據狀態,剛開始TCP協議會採用一個很是慢的速度去發送數據,而後慢慢加快發送數據的速度,直到發送數據的速度達到一個理想狀態,咱們把這個過程稱爲慢啓動

你能夠把每一個TCP發送數據的過程當作是一輛車的啓動過程,當剛進入公路時,會有從0到一個穩定速度的 提速過程,TCP的慢啓動就相似於該過程。

慢啓動是TCP爲了減小網絡擁塞的一種策略,咱們是沒有辦法改變的。

而之因此說慢啓動會帶來性能問題,是由於頁面中經常使用的一些關鍵資源文件原本就不大,如HTML文件、 CSS文件和JavaScript文件,一般這些文件在TCP鏈接創建好以後就要發起請求的,但這個過程是慢啓動,因此耗費的時間比正常的時間要多不少,這樣就推遲了寶貴的首次渲染頁面的時間了。

  • 第二個緣由,同時開啓了多條TCP鏈接,那麼這些鏈接會競爭固定的帶寬。

你能夠想象一下,系統同時創建了多條TCP鏈接,當帶寬充足時,每條鏈接發送或者接收速度會慢慢向上增 加;而一旦帶寬不足時,這些TCP鏈接又會減慢發送或者接收的速度。好比一個頁面有200個文件,使用了3 個CDN,那麼加載該網頁的時候就須要創建6 * 3,也就是18個TCP鏈接來下載資源;在下載過程當中,當發現帶寬不足的時候,各個TCP鏈接就須要動態減慢接收數據的速度。這樣就會出現一個問題,由於有的TCP鏈接下載的是一些關鍵資源,如CSS文件、JavaScript文件等,而有的TCP鏈接下載的是圖片、視頻等普通的資源文件,可是多條TCP鏈接之間又不能協商讓哪些關鍵資源優先下載,這樣就有可能影響那些關鍵資源的下載速度了。

  • 第三個緣由,HTTP/1.1隊頭阻塞的問題。

咱們知道在HTTP/1.1中使用持久鏈接時,雖然能公用一個TCP管道,可是在一個管道中同 一時刻只能處理一個請求,在當前的請求沒有結束以前,其餘的請求只能處於阻塞狀態。這意味着咱們不能 隨意在一個管道中發送請求和接收內容。

這是一個很嚴重的問題,由於阻塞請求的因素有不少,而且都是一些不肯定性的因素,假若有的請求被阻塞 了5秒,那麼後續排隊的請求都要延遲等待5秒,在這個等待的過程當中,帶寬、CPU都被白白浪費了。

在瀏覽器處理生成頁面的過程當中,是很是但願能提早接收到數據的,這樣就能夠對這些數據作預處理操做,好比提早接收到了圖片,那麼就能夠提早進行編解碼操做,等到須要使用該圖片的時候,就能夠直接給出處理後的數據了,這樣能讓用戶感覺到總體速度的提高。但隊頭阻塞使得這些數據不能並行請求,因此隊頭阻塞是很不利於瀏覽器優化的。

HTTP/1.1所存在的一些主要問題: 慢啓動和TCP鏈接之間相互競爭帶寬是因爲TCP自己的機制致使的,而隊頭阻塞是因爲HTTP/1.1的機制致使的。

HTTP/2的多路複用

雖然TCP有問題,可是咱們依然沒有換掉TCP的能力,因此咱們就要想辦法去規避TCP的慢啓動和TCP鏈接之間的競爭問題。

基於此,HTTP/2的思路就是一個域名只使用一個TCP⻓鏈接來傳輸數據,這樣整個頁面資源的下載過程只 須要一次慢啓動,同時也避免了多個TCP鏈接競爭帶寬所帶來的問題。 另外,就是隊頭阻塞的問題,等待請求完成後才能去請求下一個資源,這種方式無疑是最慢的,因此 HTTP/2須要實現資源的並行請求,也就是任什麼時候候均可以將請求發送給服務器,而並不須要等待其餘請求的完成,而後服務器也能夠隨時返回處理好的請求資源給瀏覽器。

因此,HTTP/2的解決方案能夠總結爲:一個域名只使用一個TCP鏈接和消除隊頭阻塞問題。能夠參考下圖:

HTTP/2的多路複用

該圖就是HTTP/2最核心、最重要且最具顛覆性的多路複用機制。從圖中你會發現每一個請求都有一個對應的 ID,如stream1表示index.html的請求,stream2表示foo.css的請求。這樣在瀏覽器端,就能夠隨時將請求發送給服務器了。

服務器端接收到這些請求後,會根據本身的喜愛來決定優先返回哪些內容,好比服務器可能早就緩存好了 index.html和bar.js的響應頭信息,那麼當接收到請求的時候就能夠當即把index.html和bar.js的響應頭信息返回給瀏覽器,而後再將index.html和bar.js的響應體數據返回給瀏覽器。之因此能夠隨意發送,是由於每份數據都有對應的ID,瀏覽器接收到以後,會篩選出相同ID的內容,將其拼接爲完整的HTTP響應數據。

HTTP/2使用了多路複用技術,能夠將請求分紅一幀一幀的數據去傳輸,這樣帶來了一個額外的好處,就是 當收到一個優先級高的請求時,好比接收到JavaScript或者CSS關鍵資源的請求,服務器能夠暫停以前的請 求來優先處理關鍵資源的請求。

多路複用的實現

如今咱們知道爲了解決HTTP/1.1存在的問題,HTTP/2採用了多路複用機制,那HTTP/2是怎麼實現多路複用的呢?你能夠先看下面這張圖:

HTTP/2協議棧
從圖中能夠看出,HTTP/2添加了一個二進制分幀層,那咱們就結合圖來分析下HTTP/2的請求和接收過程。

  • 首先,瀏覽器準備好請求數據,包括了請求行、請求頭等信息,若是是POST方法,那麼還要有請求體。
  • 這些數據通過二進制分幀層處理以後,會被轉換爲一個個帶有請求ID編號的幀,經過協議棧將這些幀發送 給服務器。
  • 服務器接收到全部幀以後,會將全部相同ID的幀合併爲一條完整的請求信息。
  • 而後服務器處理該條請求,並將處理的響應行、響應頭和響應體分別發送至二進制分幀層。
  • 一樣,二進制分幀層會將這些響應數據轉換爲一個個帶有請求ID編號的幀,通過協議棧發送給瀏覽器。
  • 瀏覽器接收到響應幀以後,會根據ID編號將幀的數據提交給對應的請求。

從上面的流程能夠看出,經過引入二進制分幀層,就實現了HTTP的多路複用技術。

HTTP是瀏覽器和服務器通訊的語言,在這裏雖然HTTP/2引入了二進制分幀層,不 過HTTP/2的語義和HTTP/1.1依然是同樣的,也就是說它們通訊的語言並無改變,好比開發者依然能夠通 過Accept請求頭告訴服務器但願接收到什麼類型的文件,依然可使用Cookie來保持登陸狀態,依然可使用Cache來緩存本地文件,這些都沒有變,發生改變的只是傳輸方式。這一點對開發者來講尤其重要,這意味着咱們不須要爲HTTP/2去重建生態,而且HTTP/2推廣起來會也相對更輕鬆了。

HTTP/2其餘特性

經過上面的分析,咱們知道了多路複用是HTTP/2的最核心功能,它能實現資源的並行傳輸。多路複用技術 是創建在二進制分幀層的基礎之上。其實基於二進制分幀層,HTTP/2還附帶實現了不少其餘功能,下面我 們就來簡要了解下。

  1. 能夠設置請求的優先級 咱們知道瀏覽器中有些數據是很是重要的,可是在發送請求時,重要的請求可能會晚於那些不怎麼重要的請 求,若是服務器按照請求的順序來回複數據,那麼這個重要的數據就有可能推遲好久才能送達瀏覽器,這對 於用戶體驗來講是很是不友好的。 爲了解決這個問題,HTTP/2提供了請求優先級,能夠在發送請求時,標上該請求的優先級,這樣服務器接 收到請求以後,會優先處理優先級高的請求。
  2. 服務器推送 除了設置請求的優先級外,HTTP/2還能夠直接將數據提早推送到瀏覽器。你能夠想象這樣一個場景,當用 戶請求一個HTML⻚面以後,服務器知道該HTML⻚面會引用幾個重要的JavaScript文件和CSS文件,那麼在 接收到HTML請求以後,附帶將要使用的CSS文件和JavaScript文件一併發送給瀏覽器,這樣當瀏覽器解析 完HTML文件以後,就能直接拿到須要的CSS文件和JavaScript文件,這對首次打開⻚面的速度起到了相當 重要的做用。
  3. 頭部壓縮 不管是HTTP/1.1仍是HTTP/2,它們都有請求頭和響應頭,這是瀏覽器和服務器的通訊語言。HTTP/2對請求 頭和響應頭進行了壓縮,你可能以爲一個HTTP的頭文件沒有多大,壓不壓縮可能關係不大,但你這樣想一 下,在瀏覽器發送請求的時候,基本上都是發送HTTP請求頭,不多有請求體的發送,一般狀況下⻚面也有 100個左右的資源,若是將這100個請求頭的數據壓縮爲原來的20%,那麼傳輸效率確定能獲得大幅提高。
小結一下

咱們首先分析了影響HTTP/1.1效率的三個主要因素: TCP的慢啓動多條TCP鏈接競爭帶寬隊頭阻塞

接下來咱們分析了HTTP/2是如何採用多路複用機制來解決這些問題的。多路複用是經過在協議棧中添加二進制分幀層來實現的,有了二進制分幀層還可以實現請求的優先級、服務器推送、頭部壓縮等特性,從而大大提高了文件傳輸效率。

HTTP/2協議規範於2015年5月正式發佈,在那以後,該協議已在互聯網和萬維網上獲得了普遍的實現和部署。從目前的狀況來看,國內外一些排名靠前的站點基本都實現了HTTP/2的部署。使用HTTP/2能帶來20%〜60%的效率提高,至於20%仍是60%要看優化的程度。總之,咱們也應該與時俱進,放棄HTTP/1.1和其性能優化方法,去「擁抱」HTTP/2。

思考:雖然HTTP/2解決了HTTP/1.1中的隊頭阻塞問題,可是HTTP/2依然是基於TCP協議的,而TCP協議依然存在數據包級別的隊頭阻塞問題,那麼你以爲TCP的隊頭阻塞是如何影響到HTTP/2性能的呢?

HTTP3: 甩掉TCP、TLS的包袱,構建高效網絡

從目前的狀況來看,HTTP/2彷佛能夠完美取代HTTP/1了,不過HTTP/2依然存在一些缺陷。

TCP的隊頭阻塞

雖然HTTP/2解決了應用層面的隊頭阻塞問題,不過和HTTP/1.1同樣,HTTP/2依然是基於TCP協議的,而 TCP最初就是爲了單鏈接而設計的。你能夠把TCP鏈接當作是兩臺計算機以前的一個虛擬管道,計算機的一 端將要傳輸的數據按照順序放入管道,最終數據會以相同的順序出如今管道的另一頭。 接下來咱們就來分析下HTTP/1.1協議棧中TCP是如何傳輸數據的。爲直觀理解,你能夠參考下圖:

正常狀況下的TCP傳輸數據過程

經過上圖你會發現,從一端發送給另一端的數據會被拆分爲一個個按照順序排列的數據包,這些數據包通 過網絡傳輸到了接收端,接收端再按照順序將這些數據包組合成原始數據,這樣就完成了數據傳輸。

不過,若是在數據傳輸的過程當中,有一個數據由於網絡故障或者其餘緣由而丟包了,那麼整個TCP的鏈接就 會處於暫停狀態,須要等待丟失的數據包被從新傳輸過來。你能夠把TCP鏈接當作是一個按照順序傳輸數據的管道,管道中的任意一個數據丟失了,那以後的數據都須要等待該數據的從新傳輸。爲了直觀理解,你能夠參考下圖:

TCP丟包狀態
咱們就把在TCP傳輸過程當中,因爲單個數據包的丟失而形成的阻塞稱爲TCP上的隊頭阻塞。 那隊頭阻塞是怎麼影響HTTP/2傳輸的呢?首先咱們來看正常狀況下HTTP/2是怎麼傳輸多路請求的,爲了直觀理解,你能夠參考下圖:
HTTP/2多路複用
經過該圖,咱們知道在HTTP/2中,多個請求是跑在一個TCP管道中的,若是其中任意一路數據流中出現了丟包的狀況,那麼就會阻塞該TCP鏈接中的全部請求。這不一樣於HTTP/1.1,使用HTTP/1.1時,瀏覽器爲每一個域名開啓了6個TCP鏈接,若是其中的1個TCP鏈接發生了隊頭阻塞,那麼其餘的5個鏈接依然能夠繼續傳 輸數據。

因此隨着丟包率的增長,HTTP/2的傳輸效率也會愈來愈差。有測試數據代表,當系統達到了2%的丟包率 時,HTTP/1.1的傳輸效率反而比HTTP/2表現得更好。

TCP創建鏈接的延時

除了TCP隊頭阻塞以外,TCP的握手過程也是影響傳輸效率的一個重要因素。爲了搞清楚TCP協議創建鏈接的延遲問題,咱們仍是先來回顧下網絡延遲的概念,這會有助於你對後面內容的理解。網絡延遲又稱爲RTT(Round Trip Time)。咱們把從瀏覽器發送一個數據包到服務器,再從服務器返回數據包到瀏覽器的整個往返時間稱爲RTT(以下圖)。RTT是反映網絡性能的一個重要指標。

網絡延時

那創建TCP鏈接時,須要花費多少個RTT呢?下面咱們來計算下。 咱們知道HTTP/1和HTTP/2都是使用TCP協議來傳輸的,而若是使用HTTPS的話,還須要使用TLS協議進行 安全傳輸,而使用TLS也須要一個握手過程,這樣就須要有兩個握手延遲過程。

  1. 在創建TCP鏈接的時候,須要和服務器進行三次握手來確認鏈接成功,也就是說須要在消耗完1.5個RTT 以後才能進行數據傳輸。
  2. 進行TLS鏈接,TLS有兩個版本TLS1.2和TLS1.3,每一個版本創建鏈接所花的時間不一樣,大體是須要1〜2個RTT,關於HTTPS咱們到後面到安全模塊再作詳細介紹。

總之,在傳輸數據以前,咱們須要花掉3〜4個RTT。若是瀏覽器和服務器的物理距離較近,那麼1個RTT的 時間可能在10毫秒之內,也就是說總共要消耗掉30〜40毫秒。這個時間也許用戶還能夠接受,但若是服務器相隔較遠,那麼1個RTT就可能須要100毫秒以上了,這種狀況下整個握手過程須要300〜400毫秒,這時 用戶就能明顯地感覺到「慢」了。

TCP協議僵化

如今咱們知道了TCP協議存在隊頭阻塞和創建鏈接延遲等缺點,那咱們是否是能夠經過改進TCP協議來解決 這些問題呢?

答案是:很是困難。之因此這樣,主要有兩個緣由。

第一個是中間設備的僵化。要搞清楚什麼是中間設備僵化,咱們先要弄明白什麼是中間設備。咱們知道互聯 網是由多個網絡互聯的網狀結構,爲了可以保障互聯網的正常工做,咱們須要在互聯網的各處搭建各類設 備,這些設備就被稱爲中間設備。

這些中間設備有不少種類型,而且每種設備都有本身的目的,這些設備包括了路由器、防火牆、NAT、交換 機等。它們一般依賴一些不多升級的軟件,這些軟件使用了大量的TCP特性,這些功能被設置以後就不多更新了。

因此,若是咱們在客戶端升級了TCP協議,可是當新協議的數據包通過這些中間設備時,它們可能不理解包 的內容,因而這些數據就會被丟棄掉。這就是中間設備僵化,它是阻礙TCP更新的一大障礙。

除了中間設備僵化外,操做系統也是致使TCP協議僵化的另一個緣由。由於TCP協議都是經過操做系統內核來實現的,應用程序只能使用不能修改。一般操做系統的更新都滯後於軟件的更新,所以要想自由地更新內核中的TCP協議也是很是困難的。

QUIC協議(全稱Quick UDP Internet Connections,快速UDP互聯網鏈接)

HTTP/2存在一些比較嚴重的與TCP協議相關的缺陷,但因爲TCP協議僵化,咱們幾乎不可能經過修改TCP協 議自身來解決這些問題,那麼解決問題的思路是繞過TCP協議,發明一個TCP和UDP以外的新的傳輸協議。

可是這也面臨着和修改TCP同樣的挑戰,由於中間設備的僵化,這些設備只認TCP和UDP,若是採用了新的 協議,新協議在這些設備一樣不被很好地支持。

所以,HTTP/3選擇了一個折衷的方法——UDP協議,基於UDP實現了相似於 TCP的多路數據流、傳輸可靠性等功能,咱們把這套功能稱爲QUIC協議。關於HTTP/2和HTTP/3協議棧的比較,你能夠參考下圖:

HTTP/2和HTTP/3協議棧

經過上圖咱們能夠看出,HTTP/3中的QUIC協議集合瞭如下幾點功能。

  • 實現了相似TCP的流量控制、傳輸可靠性的功能。雖然UDP不提供可靠性的傳輸,但QUIC在UDP的基礎 之上增長了一層來保證數據可靠性傳輸。它提供了數據包重傳、擁塞控制以及其餘一些TCP中存在的特性。
  • 集成了TLS加密功能。目前QUIC使用的是TLS1.3,相較於早期版本,TLS1.3有更多的優勢,其中最重要的 一點是減小了握手所花費的RTT個數。
  • 實現了HTTP/2中的多路複用功能。和TCP不一樣,QUIC實現了在同一物理鏈接上能夠有多個獨立的邏輯數 據流(以下圖)。實現了數據流的單獨傳輸,就解決了TCP中隊頭阻塞的問題。
    QUIC協議的多路複用
  • 實現了快速握手功能。因爲QUIC是基於UDP的,因此QUIC能夠實現使用0-RTT或者1-RTT來創建鏈接, 這意味着QUIC能夠用最快的速度來發送和接收數據,這樣能夠大大提高首次打開⻚面的速度。
HTTP/3的挑戰

經過上面的分析,咱們相信在技術層面,HTTP/3是個完美的協議。不過要將HTTP/3應用到實際環境中依然 面臨着諸多嚴峻的挑戰,這些挑戰主要來自於如下三個方面。

第一,從目前的狀況來看,服務器和瀏覽器端都沒有對HTTP/3提供比較完整的支持。Chrome雖然在數年前 就開始支持Google版本的QUIC,可是這個版本的QUIC和官方的QUIC存在着很是大的差別。

第二,部署HTTP/3也存在着很是大的問題。由於系統內核對UDP的優化遠遠沒有達到TCP的優化程度,這 也是阻礙QUIC的一個重要緣由。 第三,中間設備僵化的問題。這些設備對UDP的優化程度遠遠低於TCP,據統計使用QUIC協議時,大約有 3%〜7%的丟包率。

小結一下

咱們首先分析了HTTP/2中所存在的一些問題,主要包括了TCP的隊頭阻塞、創建TCP鏈接的延時、TCP協議 僵化等問題。

這些問題都是TCP的內部問題,所以要解決這些問題就要優化TCP或者「另起爐竈」創造新的協議。因爲優 化TCP協議存在着諸多挑戰,因此官方選擇了建立新的QUIC協議。

HTTP/3正是基於QUIC協議的,你能夠把QUIC當作是集成了「TCP+HTTP/2的多路複用+TLS等功能」的一 套協議。這是集衆家所長的一個協議,從協議最底層對Web的文件傳輸作了比較完全的優化,因此等生態相對成熟時,能夠用來打造比如今的HTTP/2還更加高效的網絡。

雖然說這套協議解決了HTTP/2中因TCP而帶來的問題,不過因爲是改動了底層協議,因此推廣起來還會面臨 着巨大的挑戰。 關於HTTP/3的將來,做者有下面兩點判斷:

  1. 從標準制定到實踐再到協議優化還須要走很長一段路;
  2. 由於動了底層協議,因此HTTP/3的增加會比較緩慢,這和HTTP/2有着本質的區別。

思考總結:HTTP/3都作了哪些性能上的改進?它所面臨的挑戰又是什麼?

再次聲明:筆記內容文字和圖片來源於極客時間付費課程《瀏覽器工做原理與實踐》

相關文章
相關標籤/搜索