管道機制、多路復用
管道機制(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 25 This is the data in the first chunk 1C and this is the second one 3 con 8 sequence 0
數據流
HTTP/2 長連接中的數據包是不按請求-響應順序發送的,一個完整的請求或響應(稱一個數據流stream,每個數據流都有一個獨一無二的編號)可能會分成非連續多次發送。數據包發送的時候,都必須標記所屬的數據流ID,用來區分它屬於哪個數據流。另外還規定,客戶端發出的數據流,ID一律為奇數,服務器發出的,ID為偶數。數據流發送到一半的時候,客戶端和服務器都可以發送信號(RST_STREAM幀)取消這個數據流。HTTP 1.1 取消數據流的唯一方法,就是關閉TCP連接;HTTP/2 取消某一次請求,同時保證TCP連接還打開着,可以被其他請求使用。客戶端還可以指定數據流的優先級,優先級越高,服務器就會越早響應。
