HTTP1.0 HTTP1.1 HTTP2.0 主要特性對比

本篇是對 HTTP不一樣版本主要特性的一個概述和總結。

HTTP1.0

早先1.0HTTP版本,是一種無狀態、無鏈接的應用層協議。css

HTTP1.0規定瀏覽器和服務器保持短暫的鏈接,瀏覽器的每次請求都須要與服務器創建一個TCP鏈接,服務器處理完成後當即斷開TCP鏈接(無鏈接),服務器不跟蹤每一個客戶端也不記錄過去的請求(無狀態)。html

這種無狀態性能夠藉助cookie/session機制來作身份認證和狀態記錄。而下面兩個問題就比較麻煩了。web

首先,無鏈接的特性致使最大的性能缺陷就是沒法複用鏈接。每次發送請求的時候,都須要進行一次TCP的鏈接,而TCP的鏈接釋放過程又是比較費事的。這種無鏈接的特性會使得網絡的利用率很是低。算法

其次就是隊頭阻塞(head of line blocking)。因爲HTTP1.0規定下一個請求必須在前一個請求響應到達以前才能發送。假設前一個請求響應一直不到達,那麼下一個請求就不發送,一樣的後面的請求也給阻塞了。segmentfault

爲了解決這些問題,HTTP1.1出現了。瀏覽器

HTTP1.1

對於HTTP1.1,不只繼承了HTTP1.0簡單的特色,還克服了諸多HTTP1.0性能上的問題。緩存

首先是長鏈接HTTP1.1增長了一個Connection字段,經過設置Keep-Alive能夠保持HTTP鏈接不斷開,避免了每次客戶端與服務器請求都要重複創建釋放創建TCP鏈接,提升了網絡的利用率。若是客戶端想關閉HTTP鏈接,能夠在請求頭中攜帶Connection: false來告知服務器關閉請求。服務器

其次,是HTTP1.1支持請求管道化pipelining)。基於HTTP1.1的長鏈接,使得請求管線化成爲可能。管線化使得請求可以「並行」傳輸。舉個例子來講,假如響應的主體是一個html頁面,頁面中包含了不少img,這個時候keep-alive就起了很大的做用,可以進行「並行」發送多個請求。(注意這裏的「並行」並非真正意義上的並行傳輸,具體解釋以下。)cookie

須要注意的是,服務器必須按照客戶端請求的前後順序依次回送相應的結果,以保證客戶端可以區分出每次請求的響應內容。網絡

也就是說,HTTP管道化可讓咱們把先進先出隊列從客戶端(請求隊列)遷移到服務端(響應隊列)。

如圖所示,客戶端同時發了兩個請求分別來獲取htmlcss,假如說服務器的css資源先準備就緒,服務器也會先發送html再發送css

換句話來講,只有等到html響應的資源徹底傳輸完畢後,css響應的資源才能開始傳輸。也就是說,不容許同時存在兩個並行的響應

可見,HTTP1.1仍是沒法解決隊頭阻塞(head of line blocking)的問題。同時「管道化」技術存在各類各樣的問題,因此不少瀏覽器要麼根本不支持它,要麼就直接默認關閉,而且開啓的條件很苛刻...並且實際上好像並無什麼用處。

那咱們在谷歌控制檯看到的並行請求又是怎麼一回事呢?

如圖所示,綠色部分表明請求發起到服務器響應的一個等待時間,而藍色部分表示資源的下載時間。按照理論來講,HTTP響應理應當是前一個響應的資源下載完了,下一個響應的資源才能開始下載。而這裏卻出現了響應資源下載並行的狀況。這又是爲何呢?

其實,雖然HTTP1.1支持管道化,可是服務器也必須進行逐個響應的送回,這個是很大的一個缺陷。實際上,現階段的瀏覽器廠商採起了另一種作法,它容許咱們打開多個TCP的會話。也就是說,上圖咱們看到的並行,實際上是不一樣的TCP鏈接上的HTTP請求和響應。這也就是咱們所熟悉的瀏覽器對同域下並行加載6~8個資源的限制。而這,纔是真正的並行

此外,HTTP1.1還加入了緩存處理(強緩存和協商緩存[傳送門])新的字段如cache-control,支持斷點傳輸,以及增長了Host字段(使得一個服務器可以用來建立多個Web站點)。

HTTP2.0

HTTP2.0的新特性大體以下:

二進制分幀

HTTP2.0經過在應用層和傳輸層之間增長一個二進制分幀層,突破了HTTP1.1的性能限制、改進傳輸性能。

可見,雖然HTTP2.0的協議和HTTP1.x協議之間的規範徹底不一樣了,可是實際上HTTP2.0並無改變HTTP1.x的語義。
簡單來講,HTTP2.0只是把原來HTTP1.xheaderbody部分用frame從新封裝了一層而已。

多路複用(鏈接共享)

下面是幾個概念:

  • 流(stream):已創建鏈接上的雙向字節流。
  • 消息:與邏輯消息對應的完整的一系列數據幀。
  • 幀(frame):HTTP2.0通訊的最小單位,每一個幀包含幀頭部,至少也會標識出當前幀所屬的流(stream id)。

從圖中可見,全部的HTTP2.0通訊都在一個TCP鏈接上完成,這個鏈接能夠承載任意數量的雙向數據流。

每一個數據流以消息的形式發送,而消息由一或多個幀組成。這些幀能夠亂序發送,而後再根據每一個幀頭部的流標識符(stream id)從新組裝。

舉個例子,每一個請求是一個數據流,數據流以消息的方式發送,而消息又分爲多個幀,幀頭部記錄着stream id用來標識所屬的數據流,不一樣屬的幀能夠在鏈接中隨機混雜在一塊兒。接收方能夠根據stream id將幀再歸屬到各自不一樣的請求當中去。

另外,多路複用(鏈接共享)可能會致使關鍵請求被阻塞。HTTP2.0裏每一個數據流均可以設置優先級和依賴,優先級高的數據流會被服務器優先處理和返回給客戶端,數據流還能夠依賴其餘的子數據流。

可見,HTTP2.0實現了真正的並行傳輸,它可以在一個TCP上進行任意數量HTTP請求。而這個強大的功能則是基於「二進制分幀」的特性。

頭部壓縮

HTTP1.x中,頭部元數據都是以純文本的形式發送的,一般會給每一個請求增長500~800字節的負荷。

好比說cookie,默認狀況下,瀏覽器會在每次請求的時候,把cookie附在header上面發送給服務器。(因爲cookie比較大且每次都重複發送,通常不存儲信息,只是用來作狀態記錄和身份認證)

HTTP2.0使用encoder來減小須要傳輸的header大小,通信雙方各自cache一份header fields表,既避免了重複header的傳輸,又減少了須要傳輸的大小。高效的壓縮算法能夠很大的壓縮header,減小發送包的數量從而下降延遲。

服務器推送

服務器除了對最初請求的響應外,服務器還能夠額外的向客戶端推送資源,而無需客戶端明確的請求。

HTTP1.1的合併請求是否適用於HTTP2.0

首先,答案是「沒有必要」。之因此沒有必要,是由於這跟HTTP2.0的頭部壓縮有很大的關係。

在頭部壓縮技術中,客戶端和服務器均會維護兩份相同的靜態字典和動態字典。

在靜態字典中,包含了常見的頭部名稱以及頭部名稱與值的組合。靜態字典在首次請求時就可使用。那麼如今頭部的字段就能夠被簡寫成靜態字典中相應字段對應的index

而動態字典跟鏈接的上下文相關,每一個HTTP/2鏈接維護的動態字典是不盡相同的。動態字典能夠在鏈接中不聽的進行更新。

也就是說,本來完整的HTTP報文頭部的鍵值對或字段,因爲字典的存在,如今能夠轉換成索引index,在相應的端再進行查找還原,也就起到了壓縮的做用。

因此,同一個鏈接上產生的請求和響應越多,動態字典累積得越全,頭部壓縮的效果也就越好,因此針對HTTP/2網站,最佳實踐是不要合併資源。

另外,HTTP2.0多路複用使得請求能夠並行傳輸,而HTTP1.1合併請求的一個緣由也是爲了防止過多的HTTP請求帶來的阻塞問題。而如今HTTP2.0已經可以並行傳輸了,因此合併請求也就沒有必要了。

總結

HTTP1.0

  • 無狀態、無鏈接

HTTP1.1

  • 持久鏈接
  • 請求管道化
  • 增長緩存處理(新的字段如cache-control
  • 增長Host字段、支持斷點傳輸等

HTTP2.0

  • 二進制分幀
  • 多路複用(或鏈接共享)
  • 頭部壓縮
  • 服務器推送

參考:
https://www.zhihu.com/questio...
https://segmentfault.com/q/10...
http://imweb.io/topic/554c587...
http://web.jobbole.com/85635/

相關文章
相關標籤/搜索