1. 程式人生 > >HTTP協議篇(一):多路複用、資料流

HTTP協議篇(一):多路複用、資料流

管道機制、多路複用

管道機制(Pipelining)

 HTTP 1.1 引入了管道機制(Pipelining),即客戶端可通過同一個TCP連線同時傳送多個請求。如果客戶端需要請求兩個資源,以前的做法是在同一個TCP連線裡面,先發送A請求,然後等待伺服器做出迴應,收到後再發出B請求;而管道機制則允許瀏覽器同時發出A請求和B請求,但是伺服器還是按照順序,先回應A請求,完成後再回應B請求。

多路複用(Multiplexing)

雖然 HTTP 1.1 預設啟用長TCP連線,但所有的請求-響應都是按序進行的(這裡的長連線可理解成半雙工協議。即便是HTTP 1.1引入了管道機制,也是如此)。複用同一個TCP連線期間,即便是通過管道同時傳送了多個請求,服務端也是按請求的順序依次給出響應的;而客戶端在未收到之前所發出所有請求的響應之前,將會阻塞後面的請求(排隊等待),這稱為"隊頭堵塞"(Head-of-line blocking)。

HTTP/2複用TCP連線則不同,雖然依然遵循請求-響應模式,但客戶端傳送多個請求和服務端給出多個響應的順序不受限制,這樣既避免了"隊頭堵塞",又能更快獲取響應。在複用同一個TCP連線時,伺服器同時(或先後)收到了A、B兩個請求,先回應A請求,但由於處理過程非常耗時,於是就傳送A請求已經處理好的部分, 接著迴應B請求,完成後,再發送A請求剩下的部分。HTTP/2長連線可以理解成全雙工的協議。

Content-Length

Content-length 宣告本次響應的資料長度。keep-alive 連線可以先後傳送多個響應,因此用Content-length來區分資料包是屬於哪一個響應。在HTTP 1.0 中,Content-Length欄位不是必需的,因為瀏覽器與伺服器通訊使用的是短連線,服務端傳送完資料關閉TCP連線,就表明收到的資料包已經全了。

分塊傳輸(Chunked)、資料流

分塊傳輸(Chunked)

使用Content-Length欄位的前提條件是,伺服器傳送響應之前,必須知道響應的資料長度。 對於一些很耗時的動態操作來說,這意味著,伺服器要等到所有操作完成,才能傳送資料,顯然這樣的效率不高。更好的處理方法是,產生一塊資料,就傳送一塊,採用"流模式"(Stream)取代"快取模式"(Buffer)。因此,HTTP 1.1 規定可以不使用Content-Length欄位,而使用"分塊傳輸編碼"(Chunked Transfer Encoding)。只要請求或響應的頭資訊有Transfer-Encoding: chunked

欄位,就表明body將可能由數量未定的多個數據塊組成。

每個資料塊之前會有一行包含一個16進位制數值,表示這個塊的長度;最後一個大小為0的塊,就表示本次響應的資料傳送完了。

HTTP/1.1 200 OK
Content-Type: text/plain
Transfer-Encoding: chunked
This is the data in the first chunk

1C
and this is the second one
con
sequence

資料流

HTTP/2 長連線中的資料包是不按請求-響應順序傳送的,一個完整的請求或響應(稱一個數據流stream,每個資料流都有一個獨一無二的編號)可能會分成非連續多次傳送。資料包傳送的時候,都必須標記所屬的資料流ID,用來區分它屬於哪個資料流。另外還規定,客戶端發出的資料流,ID一律為奇數,伺服器發出的,ID為偶數。資料流傳送到一半的時候,客戶端和伺服器都可以傳送訊號(RST_STREAM幀)取消這個資料流。HTTP 1.1 取消資料流的唯一方法,就是關閉TCP連線;HTTP/2 取消某一次請求,同時保證TCP連線還開啟著,可以被其他請求使用。客戶端還可以指定資料流的優先順序,優先順序越高,伺服器就會越早響應。