HTTP/1.0 —— 無狀態無連線的應用層協議
無狀態:伺服器不跟蹤不記錄請求過的狀態
無連線:瀏覽器每次請求都需要建立tcp連線
HTTP/1.0規定瀏覽器和伺服器保持短暫的連線。瀏覽器的每次請求都需要與伺服器建立一個TCP連線,伺服器處理完成後立即斷開TCP連線(無連線),伺服器不跟蹤每個客戶端也不記錄過去的請求(無狀態)
無狀態導致的問題可以藉助cookie/session機制來做身份認證和狀態記錄解決。
然而,無連線特性將會導致以下效能缺陷:
無法複用連線。每次傳送請求的時候,都需要進行一次TCP連線,而TCP的連線釋放過程又是比較費事的。這種無連線的特性會導致網路的利用率非常低。
隊頭堵塞(head of line blocking)。由於HTTP/1.0規定下一個請求必須在前一個請求響應到達之前才能傳送。假設一個請求響應一直不到達,那麼下一個請求就不傳送,就到導致阻塞後面的請求。
為了解決這些問題,HTTP/1.1出現了。
HTTP/1.1
長連線。HTTP/1.1增加了一個Connection欄位,透過設定Keep-alive(預設已設定)可以保持連線不斷開,避免了每次客戶端與伺服器請求都要重複建立釋放TCP連線,提高了網路的利用率。如果客戶端想關閉HTTP連線,可以在請求頭中攜帶Connection:false來告知伺服器關閉請求
支援請求管道化(pipelining)。基於HTTP/1.1的長連線,使得請求管線化成為可能。管線化使得請求能夠“並行”傳輸。舉個例子來說,假如響應的主體是一個html頁面,頁面中包含了很多img,這個時候keep-alive就起了很大的作用,能夠進行“並行”傳送多個請求。(注意這裡的“並行”並不是真正意義上的並行傳輸,具體解釋如下。)
需要注意的是,伺服器必須按照客戶端請求的先後順序依次回送相應的結果,以保證客戶端能夠區分出每次請求的響應內容。
也就是說,HTTP管道化可以讓我們把先進先出佇列從客戶端(請求佇列)遷移到服務端(響應佇列)
客戶端同時發了兩個請求分別來獲取html和css,假如說伺服器的css資源先準備就緒,伺服器也會先傳送html再傳送css。
換句話來說,只有等到html響應的資源完全傳輸完畢後,css響應的資源才能開始傳輸。也就是說,不允許同時存在兩個並行的響應。
可見,HTTP/1.1還是無法解決隊頭阻塞(head of line blocking)的問題。同時“管道化”技術存在各種各樣的問題,所以很多瀏覽器要麼根本不支援它,要麼就直接預設關閉,並且開啟的條件很苛刻...而且實際上好像並沒有什麼用處。
那我們在谷歌控制檯看到的並行請求又是怎麼一回事呢?
雖然HTTP/1.1支援管道化,但是伺服器也必須進行逐個響應的送回,這個是很大的一個缺陷。實際上,現階段的瀏覽器廠商採取了另外一種做法,它允許我們開啟多個TCP的會話。也就是說,上圖我們看到的並行,其實是不同的TCP連線上的HTTP請求和響應。這也就是我們所熟悉的瀏覽器對同域下並行載入6~8個資源的限制。而這,才是真正的並行!
此外,HTTP/1.1還加入了快取處理,新的欄位如cache-control,支援斷點傳輸,以及增加了Host欄位(使得一個伺服器能夠用來建立多個Web站點)。
HTTP/2.0
幀: HTTP/2 資料通訊的最小單位訊息:指 HTTP/2 中邏輯上的 HTTP 訊息。例如請求和響應等,訊息由一個或多個幀組成。
流: 存在於連線中的一個虛擬通道。流可以承載雙向訊息,每個流都有一個唯一的整數ID。
訊息: 與邏輯訊息對應的完整的一系列資料幀。
1.二進位制分幀
HTTP/2 採用二進位制格式傳輸資料,而非 HTTP/1.x 的文字格式,二進位制協議解析起來更高效。
HTTP / 1 的請求和響應報文,都是由起始行,首部和實體正文(可選)組成,各部分之間以文字換行符分隔。
HTTP/2 將請求和響應資料分割為更小的幀,並且它們採用二進位制編碼。
2.多路複用
同域名下的所有通訊都在單個連線中完成。
單個連線可以承載任意數量的雙向資料流。
資料流以訊息的形式傳送,而訊息又由一個或多個幀組成,多個幀之間可以亂序傳送,因為根據幀首部的流標識可以重新組裝
這一特性,使效能有了很大的提升:
同個域名只需要佔用一個TCP連線,消除了因多個TCP連線而帶來的延時和記憶體消耗。
單個連線上可以並行交錯地請求和響應,之間互不干擾。
在HTTP/2中,每個請求都可以帶一個31bit的優先值,0表示最高優先順序, 數值越大優先順序越低。有了這個優先值,客戶端和伺服器就可以在處理不同的流時採取不同的策略,以最優的方式傳送流、訊息和幀。
可見,HTTP/2.0實現了真正的並行傳輸,它能夠在一個TCP上進行任意數量HTTP請求。而這個強大的功能則是基於“二進位制分幀”的特性。
3.伺服器推送
服務端可以在傳送頁面HTML時主動推送其它資源,而不用等到瀏覽器解析到相應位置,發起請求再響應。例如服務端可以主動把JS和CSS檔案推送給客戶端,而不需要客戶端解析HTML時再傳送這些請求。
服務端可以主動推送,客戶端也有權利選擇是否接收。如果服務端推送的資源已經被瀏覽器快取過,瀏覽器可以透過傳送RST_STREAM幀來拒收。主動推送也遵守同源策略,伺服器不會隨便推送第三方資源給客戶端。
4.頭部壓縮
在HTTP/1.x中,頭部後設資料都是以純文字的形式傳送的,通常會給每個請求增加500~800位元組的負荷。
比如說cookie,預設情況下,瀏覽器會在每次請求的時候,把cookie附在header上面傳送給伺服器。(由於cookie比較大且每次都重複傳送,一般不儲存資訊,只是用來做狀態記錄和身份認證)
HTTP/2.0使用encoder來減少需要傳輸的header大小,通訊雙方各自cache一份header fields表,既避免了重複header的傳輸,又減小了需要傳輸的大小。高效的壓縮演算法可以很大的壓縮header,減少傳送包的數量從而降低延遲。
各個協議的區別
HTTP/1.x keep-alive 與 HTTP/2 多路複用區別
- HTTP/1.x 是基於文字的,只能整體去傳;HTTP/2 是基於二進位制流的,可以分解為獨立的幀,交錯傳送
- HTTP/1.x keep-alive 必須按照請求傳送的順序返回響應;HTTP/2 多路複用不按序響應
- HTTP/1.x keep-alive 為了解決
隊頭阻塞
,將同一個頁面的資源分散到不同域名下,開啟了多個 TCP 連線;HTTP/2 同域名下所有通訊都在單個連線上完成 - HTTP/1.x keep-alive 單個 TCP 連線在同一時刻只能處理一個請求(兩個請求的生命週期不能重疊);HTTP/2 單個 TCP 同一時刻可以傳送多個請求和響應