HTTP長(zhǎng)連接和流水線原理是什么?什么是隊(duì)頭阻塞?HTTP/2多路復(fù)用如何解決隊(duì)頭阻塞?HTTP/3的QUIC協(xié)議做出了哪些優(yōu)化
一、面試官:請(qǐng)說說看HTTP1.1與HTTP1.0的主要區(qū)別是什么?
1. 連接管理:長(zhǎng)連接與流水線處理
HTTP/1.0:默認(rèn)使用短連接,每次請(qǐng)求需建立新TCP連接,請(qǐng)求完成后立即關(guān)閉。若需長(zhǎng)連接,需顯式設(shè)置 Connection: Keep-Alive,但兼容性差(部分代理不支持)。
HTTP/1.1:默認(rèn)啟用長(zhǎng)連接(持久連接),允許在一個(gè)TCP連接上傳輸多個(gè)請(qǐng)求/響應(yīng),減少握手開銷。支持流水線(Pipelining)技術(shù),客戶端可連續(xù)發(fā)送多個(gè)請(qǐng)求(無需等待響應(yīng)),但服務(wù)器需按請(qǐng)求順序返回響應(yīng),避免隊(duì)頭阻塞。
2. Host頭域支持虛擬主機(jī)
HTTP/1.0:假設(shè)一個(gè)IP對(duì)應(yīng)唯一服務(wù)器,請(qǐng)求頭中無Host字段,無法支持虛擬主機(jī)技術(shù)(如多個(gè)域名共享同一IP)。
HTTP/1.1:強(qiáng)制要求請(qǐng)求頭包含 Host 字段,用于標(biāo)識(shí)目標(biāo)服務(wù)器域名。若缺失,服務(wù)器返回 400 Bad Request,解決了虛擬主機(jī)場(chǎng)景下的資源定位問題。
3. 緩存機(jī)制增強(qiáng)
HTTP/1.0:依賴 Expires(絕對(duì)時(shí)間)和 Last-Modified(最后修改時(shí)間)控制緩存,存在時(shí)鐘同步問題。緩存驗(yàn)證通過 If-Modified-Since 實(shí)現(xiàn)。
HTTP/1.1:
- 引入 Cache-Control 頭(如 max-age、no-cache),支持相對(duì)時(shí)間緩存策略。
- 新增 ETag(實(shí)體標(biāo)簽)機(jī)制,通過 If-None-Match 驗(yàn)證資源是否變更。
- 支持 Vary 頭,根據(jù)請(qǐng)求頭(如 Accept-Language)區(qū)分不同緩存版本。
4. 帶寬優(yōu)化與分塊傳輸
范圍請(qǐng)求:HTTP/1.1 支持 Range 頭,允許請(qǐng)求資源部分內(nèi)容(如斷點(diǎn)續(xù)傳),響應(yīng)狀態(tài)碼為 206 Partial Content。
分塊傳輸編碼(Chunked Encoding):動(dòng)態(tài)生成內(nèi)容時(shí),通過 Transfer-Encoding: chunked 分塊傳輸,無需預(yù)知完整數(shù)據(jù)大小,提升傳輸效率。
100 Continue 狀態(tài)碼:客戶端發(fā)送大請(qǐng)求前,先通過 Expect: 100-continue 頭詢問服務(wù)器是否接受,避免帶寬浪費(fèi)。
5. 錯(cuò)誤狀態(tài)碼與內(nèi)容協(xié)商
錯(cuò)誤狀態(tài)碼:HTTP/1.1 新增24個(gè)狀態(tài)碼,如
- 100 Continue:(繼續(xù)請(qǐng)求)
- 206 Partial Content:(部分內(nèi)容)
- 409 Conflict:(資源狀態(tài)沖突)
- 410 Gone:(資源永久刪除)。
內(nèi)容協(xié)商:通過 Accept-* 系列頭(如 Accept-Language、Accept-Encoding)支持多語(yǔ)言/壓縮格式,服務(wù)器返回最適配版本,并通過 Vary 頭記錄協(xié)商依據(jù)。
6. 其他改進(jìn)
請(qǐng)求方法擴(kuò)展:HTTP/1.1 新增 OPTIONS、PUT、DELETE、TRACE 等方法,支持 RESTful API 設(shè)計(jì)。
消息傳遞優(yōu)化:支持 Trailer 頭傳遞分塊傳輸后的元數(shù)據(jù)(如校驗(yàn)和),提升大文件傳輸?shù)耐暾浴?/p>
總結(jié)對(duì)比表:
特性 | HTTP/1.0 | HTTP/1.1 |
連接管理 | 短連接,需手動(dòng)啟用長(zhǎng)連接 | 默認(rèn)長(zhǎng)連接,支持流水線 |
Host頭域 | 不支持 | 強(qiáng)制要求,支持虛擬主機(jī) |
緩存機(jī)制 | 僅Expires/Last-Modified | Cache-Control/ETag/Vary |
帶寬優(yōu)化 | 不支持范圍請(qǐng)求 | 支持Range請(qǐng)求與分塊傳輸 |
狀態(tài)碼 | 16種基本狀態(tài)碼 | 新增24種,如100、206、409等 |
內(nèi)容協(xié)商 | 有限支持 | 通過Accept頭與Vary靈活適配 |
二、面試官:不錯(cuò),能不能展開聊聊HTTP長(zhǎng)連接怎么實(shí)現(xiàn)的,它的優(yōu)點(diǎn)是什么,有什么不足?
1. HTTP持久連接(長(zhǎng)連接)的詳細(xì)解析
(1) 原理
HTTP持久連接(Persistent Connection),也稱為長(zhǎng)連接(Keep-Alive),允許客戶端和服務(wù)器在單個(gè)TCP連接上發(fā)送和接收多個(gè)HTTP請(qǐng)求/響應(yīng),而無需為每個(gè)請(qǐng)求重新建立新的連接。
① 工作流程
HTTP/1.0:默認(rèn)短連接,每個(gè)請(qǐng)求需建立新TCP連接,響應(yīng)后立即關(guān)閉。 如需啟用長(zhǎng)連接,需顯式設(shè)置頭部:Connection: keep-alive。
HTTP/1.1:默認(rèn)啟用長(zhǎng)連接,除非顯式設(shè)置Connection: close。 客戶端和服務(wù)器可復(fù)用同一TCP連接處理多個(gè)請(qǐng)求。
② 連接管理
?;顧C(jī)制:通過Keep-Alive頭部字段協(xié)商參數(shù)(如超時(shí)時(shí)間、最大請(qǐng)求數(shù))。 示例:Keep-Alive: timeout=5, max=100(連接空閑5秒后關(guān)閉,最多處理100個(gè)請(qǐng)求)。
關(guān)閉條件:
- 客戶端/服務(wù)器發(fā)送`Connection: close`頭部。
- 達(dá)到保活參數(shù)限制(如超時(shí)或最大請(qǐng)求數(shù))。
(2) 優(yōu)點(diǎn)
① 減少TCP握手開銷
- 每個(gè)TCP連接的建立需三次握手,關(guān)閉需四次揮手。
- 復(fù)用連接避免了重復(fù)握手,降低延遲(尤其對(duì)高延遲網(wǎng)絡(luò)顯著)。
② 提升資源加載效率
- 網(wǎng)頁(yè)通常需加載多個(gè)資源(HTML、CSS、JS、圖片等)。
- 長(zhǎng)連接允許并行或串行復(fù)用同一連接,減少總加載時(shí)間。
③ 減輕服務(wù)器壓力
減少頻繁創(chuàng)建/銷毀連接的系統(tǒng)調(diào)用和內(nèi)存消耗。
④ 支持管道化(Pipelining)
HTTP/1.1允許在未收到響應(yīng)時(shí)發(fā)送多個(gè)請(qǐng)求(理論優(yōu)化)。
因?qū)崿F(xiàn)復(fù)雜和隊(duì)頭阻塞問題,實(shí)際使用較少,但在長(zhǎng)連接基礎(chǔ)上提出。
(3) 局限性
① 隊(duì)頭阻塞(Head-of-Line Blocking)
- HTTP/1.1的串行請(qǐng)求:同一連接中的請(qǐng)求必須按順序處理。若前一個(gè)請(qǐng)求處理慢(如大文件上傳),后續(xù)請(qǐng)求被阻塞。
- HTTP/2的解決方案:引入多路復(fù)用(Multiplexing),允許并行處理請(qǐng)求。
② 資源占用問題
- 長(zhǎng)連接占用服務(wù)器和客戶端的TCP端口和內(nèi)存資源。
- 高并發(fā)場(chǎng)景下,可能導(dǎo)致服務(wù)器連接數(shù)達(dá)到上限(如Linux默認(rèn)ulimit -n為1024)。
③ 連接空閑浪費(fèi)
- 若連接長(zhǎng)時(shí)間無請(qǐng)求,仍占用資源直到超時(shí)關(guān)閉。
- 需合理配置超時(shí)時(shí)間(如Nginx默認(rèn)keepalive_timeout 75s)。
(4) 對(duì)比不同HTTP版本
特性 | HTTP/1.0 | HTTP/1.1 | HTTP/2 |
默認(rèn)連接 | 短連接 | 長(zhǎng)連接 | 長(zhǎng)連接 + 多路復(fù)用 |
管道化支持 | 不支持 | 支持(但實(shí)際受限) | 支持(并行無阻塞) |
頭部壓縮 | 無 | 無 | HPACK壓縮 |
資源優(yōu)先級(jí) | 無 | 無 | 支持優(yōu)先級(jí)流 |
2. 總結(jié)
- 核心價(jià)值:HTTP持久連接通過復(fù)用TCP連接,顯著降低延遲和服務(wù)器開銷,是Web性能優(yōu)化的基石。
- 適用場(chǎng)景:資源密集型頁(yè)面、API高頻調(diào)用、高并發(fā)服務(wù)。
- 權(quán)衡取舍:需平衡連接復(fù)用效率與資源占用,結(jié)合HTTP/2或HTTP/3進(jìn)一步優(yōu)化。
三、面試官:剛剛你有提到HTTP的管道化(流水線)和隊(duì)頭阻塞,能說說看是怎么回事嗎?有什么方法可以徹底解決隊(duì)頭阻塞問題?
HTTP的流水線處理(HTTP Pipelining)是HTTP/1.1引入的一種優(yōu)化技術(shù),允許客戶端通過同一TCP連接連續(xù)發(fā)送多個(gè)請(qǐng)求,而無需等待前一個(gè)請(qǐng)求的響應(yīng)返回。
1. 流水線處理的原理
(1) 與非流水線的對(duì)比
- 非流水線方式(如HTTP/1.0):客戶端需等待前一個(gè)請(qǐng)求的響應(yīng)完全返回后,才能發(fā)送下一個(gè)請(qǐng)求。例如,請(qǐng)求A完成后才能發(fā)送請(qǐng)求B,導(dǎo)致延遲疊加。
- 流水線方式(HTTP/1.1):客戶端可在未收到響應(yīng)時(shí)連續(xù)發(fā)送多個(gè)請(qǐng)求,服務(wù)器按接收順序依次處理并返回響應(yīng)。例如,客戶端可一次性發(fā)送請(qǐng)求A、B、C,服務(wù)器依次返回A、B、C的響應(yīng)。
(2) 實(shí)現(xiàn)條件
- 依賴長(zhǎng)連接(Persistent Connection),即通過Connection: keep-alive保持TCP連接活躍。
- 服務(wù)器需支持按請(qǐng)求順序響應(yīng),且客戶端需能處理亂序到達(dá)的響應(yīng)(實(shí)際中較少見,多數(shù)實(shí)現(xiàn)仍按順序返回)。
HTTP1.1請(qǐng)求報(bào)文之間沒有記錄請(qǐng)求順序(如請(qǐng)求編號(hào)、序號(hào))的信息,因此無法保證多個(gè)響應(yīng)之間的返回順序與發(fā)送的多個(gè)請(qǐng)求順序相對(duì)應(yīng),也就是說發(fā)送順序是請(qǐng)求1、請(qǐng)求2 和請(qǐng)求3,但由于服務(wù)端響應(yīng)速度上是請(qǐng)求3、請(qǐng)求2和請(qǐng)求1,因此HTTP1.1依舊要等請(qǐng)求1的響應(yīng)內(nèi)容準(zhǔn)備好之后才能依照 響應(yīng)1、響應(yīng)2和響應(yīng)3的順序返回。否則亂序到達(dá)的響應(yīng)就可能會(huì)交付給錯(cuò)誤的請(qǐng)求(如將響應(yīng)3交付給了請(qǐng)求1)。
而上述過程中,響應(yīng)3和響應(yīng)2就被響應(yīng)1阻塞住了,這就是所謂的隊(duì)頭阻塞。HTTP的隊(duì)頭阻塞(Head-of-Line Blocking) 是指在數(shù)據(jù)傳輸過程中,某個(gè)請(qǐng)求或數(shù)據(jù)包的延遲或丟失導(dǎo)致后續(xù)請(qǐng)求/數(shù)據(jù)被阻塞的問題。
雖然理論上HTTP1.1的流水線支持一個(gè)連接并發(fā)傳輸多個(gè)請(qǐng)求和響應(yīng),但由于隊(duì)頭阻塞問題無法解決,因此HTTP1.1在實(shí)際應(yīng)用中不會(huì)開啟流水線,依舊是一個(gè)連接只能串行傳輸請(qǐng)求和響應(yīng),要等上一個(gè)請(qǐng)求的響應(yīng)返回了才發(fā)送下一個(gè)請(qǐng)求,如果要并發(fā)發(fā)送請(qǐng)求只能通過建立多個(gè)連接實(shí)現(xiàn)較為有限的并發(fā)。
隊(duì)頭阻塞問題在不同協(xié)議層(如HTTP/1.1、TCP)中表現(xiàn)不同,以下是詳細(xì)說明。
2. HTTP/1.1中的隊(duì)頭阻塞
HTTP/1.1即使啟用了流水線(Pipelining),客戶端可以并發(fā)的發(fā)送請(qǐng)求,但服務(wù)器仍需按請(qǐng)求順序串行的返回響應(yīng)。若第一個(gè)請(qǐng)求的響應(yīng)因服務(wù)器處理緩慢被阻塞,后續(xù)請(qǐng)求即使已處理完成,也需等待前一個(gè)響應(yīng)返回后才能被客戶端接收。
示例:請(qǐng)求A、B、C依次發(fā)送,若A的響應(yīng)延遲1秒,B和C的響應(yīng)即使已生成,也必須在A的響應(yīng)返回后才能被客戶端處理。
影響 :
- 頁(yè)面加載延遲:資源(如圖片、CSS)需排隊(duì)等待,拖慢整體加載速度。
- 資源利用率低:TCP連接無法被其他請(qǐng)求充分利用,浪費(fèi)帶寬。
采用HTTP2的多路復(fù)用機(jī)制可以解決應(yīng)用層的隊(duì)頭阻塞問題。
要介紹HTTP2如何解決應(yīng)用層的隊(duì)頭阻塞,就需要介紹流(Stream)、消息(Message)和幀(Frame)的概念和他們之間的關(guān)系。
在HTTP/2中,一個(gè)流代表一個(gè)獨(dú)立的請(qǐng)求-響應(yīng)交互,可以包含多個(gè)消息,每個(gè)消息由多個(gè)幀組成。流具有唯一的標(biāo)識(shí)符,可以在同一個(gè)連接上并行傳輸多個(gè)流的幀,從而實(shí)現(xiàn)多路復(fù)用。
從上圖中看到:
- 1 個(gè) TCP 連接包含一個(gè)或者多個(gè) Stream;
- Stream 里可以包含 1 個(gè)或多個(gè) Message,Message 對(duì)應(yīng)請(qǐng)求或響應(yīng),由 HTTP 頭部和包體構(gòu)成;
- Message 里包含一條或者多個(gè) Frame,F(xiàn)rame 是 HTTP/2 的最小傳輸單位,以二進(jìn)制壓縮格式存放請(qǐng)求Message;
一個(gè)Message消息是由 Headers 幀和DATA 幀組成的。
在 HTTP/2 連接上,不同 Stream 的幀是可以亂序發(fā)送的(因此可以并發(fā)不同的 Stream ),因?yàn)槊總€(gè)幀的頭部會(huì)攜帶 Stream ID 信息,所以接收端可以通過 Stream ID 有序組裝成 HTTP 消息,而同一 Stream 內(nèi)部的幀和消息必須是嚴(yán)格有序的。
比如下圖,服務(wù)端并行交錯(cuò)地發(fā)送了兩個(gè)響應(yīng): Stream 1 的響應(yīng)Message 和 Stream 3 的響應(yīng)Message,這兩個(gè) Stream 都是跑在一個(gè) TCP 連接上,客戶端收到后,會(huì)根據(jù)相同的 Stream ID 有序組裝成 HTTP 消息。
這樣一來,假設(shè)stream1的請(qǐng)求Message比stream3的請(qǐng)求Message先到達(dá)服務(wù)端,而stream3的響應(yīng)Message先準(zhǔn)備好,不需要等待stream1的響應(yīng)Message準(zhǔn)備好就可以發(fā)送。客戶端可以通過消息上唯一的流標(biāo)識(shí)符準(zhǔn)確的拼裝好 Stream1 和 Stream3 的響應(yīng)Message并通過唯一的流標(biāo)識(shí)符交付給對(duì)應(yīng)的請(qǐng)求從而解決隊(duì)頭阻塞問題,提高并發(fā)。
四、面試官:能不能說說看HTTP/2相比HTTP/1.1還有哪些地方做了提升?
HTTP/2 在 HTTP/1.1 的基礎(chǔ)上通過多項(xiàng)技術(shù)改進(jìn)顯著提升了性能,主要優(yōu)化點(diǎn)如下:
1. 多路復(fù)用
HTTP/2 的多路復(fù)用(Multiplexing) 是其核心特性之一,通過在一個(gè) TCP 連接上并行傳輸多個(gè)請(qǐng)求和響應(yīng),徹底解決了 HTTP/1.1 的隊(duì)頭阻塞問題。以下是其原理及性能提升的詳細(xì)分析:
(1) 流(Stream)與幀(Frame)
- 流:HTTP/2 連接中的邏輯通道,每個(gè)流獨(dú)立傳輸雙向的幀序列(請(qǐng)求或響應(yīng))。
- 幀:數(shù)據(jù)傳輸?shù)淖钚挝?,包含流?biāo)識(shí)符(Stream ID)和類型(如 HEADERS、DATA)。
- 實(shí)現(xiàn)方式:多個(gè)流的幀可交錯(cuò)傳輸,客戶端和服務(wù)器按流 ID 重組數(shù)據(jù),無需按順序等待。
(2) 與 HTTP/1.1 的對(duì)比
- HTTP/1.1請(qǐng)求/響應(yīng)需嚴(yán)格串行化,一個(gè)請(qǐng)求延遲會(huì)導(dǎo)致后續(xù)請(qǐng)求阻塞(隊(duì)頭阻塞)。
- HTTP/2同一 TCP 連接上可并行處理多個(gè)請(qǐng)求,流之間相互獨(dú)立,互不干擾。
HTTP2的多路復(fù)用帶來了如下提升。
① 消除隊(duì)頭阻塞
- 問題場(chǎng)景:在 HTTP/1.1 中,若請(qǐng)求 A 的響應(yīng)延遲,后續(xù)請(qǐng)求 B、C 需排隊(duì)等待。
- 解決方案:HTTP/2 的多路復(fù)用允許請(qǐng)求 B、C 的幀與請(qǐng)求 A 的幀交錯(cuò)傳輸,即使 A 延遲,B 和 C 的響應(yīng)仍可被優(yōu)先處理。
② 減少 TCP 連接數(shù)
- HTTP/1.1:瀏覽器通常為每個(gè)域名建立 6-8 個(gè) TCP 連接以并行請(qǐng)求資源。
- HTTP/2:僅需一個(gè)連接即可并行傳輸所有請(qǐng)求,降低連接建立和維護(hù)的開銷(如三次握手、TLS 握手)。
③ 提升傳輸效率
- 資源利用率:TCP 連接的帶寬被多個(gè)流共享,避免單個(gè)請(qǐng)求占用TCP連接內(nèi)的全部資源。
- 延遲優(yōu)化:在弱網(wǎng)環(huán)境下,多路復(fù)用可減少 30%-50% 的頁(yè)面加載時(shí)間。例如,請(qǐng)求一個(gè)大 JS 文件和一個(gè)小 CSS 文件時(shí),HTTP/2 可并行傳輸,而 HTTP/1.1 需串行等待。
④ 節(jié)省服務(wù)器資源
減少并發(fā)連接數(shù)可降低服務(wù)器內(nèi)存和 CPU 的消耗,提升高負(fù)載場(chǎng)景下的穩(wěn)定性。
2. 頭部壓縮
HTTP/2 的頭部壓縮是通過 HPACK 算法實(shí)現(xiàn)的核心優(yōu)化技術(shù),旨在減少 HTTP 頭部的冗余數(shù)據(jù),提升傳輸效率。以下是其原理及優(yōu)點(diǎn)的詳細(xì)說明:
(1) HPACK 算法
核心思想:通過靜態(tài)表、動(dòng)態(tài)表和哈夫曼編碼,消除重復(fù)的頭部字段,減少傳輸體積。
實(shí)現(xiàn)方式:
- 靜態(tài)表(Static Table):預(yù)定義 61 個(gè)常用頭部字段(如 `:method`、`:path`、`content-type`),直接用索引號(hào)代替完整字段名。例如,`:method: GET` 可編碼為索引 `2`,僅需傳輸 1 字節(jié)。
- 動(dòng)態(tài)表(Dynamic Table):在會(huì)話過程中動(dòng)態(tài)存儲(chǔ)客戶端與服務(wù)器交換的自定義頭部字段,后續(xù)請(qǐng)求直接引用索引。
例如,首次發(fā)送 `user-agent: Mozilla/5.0` 后,后續(xù)請(qǐng)求只需發(fā)送其動(dòng)態(tài)表索引。
- 哈夫曼編碼(Huffman Coding):對(duì)頭部字段的鍵和值進(jìn)行字符級(jí)壓縮,高頻字符用短編碼,低頻字符用長(zhǎng)編碼。例如,字母 `e` 出現(xiàn)頻率高,編碼為 `010`,而 `z` 編碼為 `111111`。
頭部壓縮的總和效果如下圖所示:
(2) 頭部壓縮的優(yōu)點(diǎn)
① 顯著減少帶寬消耗
- 通過消除冗余頭部字段(如重復(fù)的 Cookie、User-Agent),降低傳輸數(shù)據(jù)量,尤其適用于移動(dòng)端或低帶寬環(huán)境。
- 例如,一個(gè)包含 20 個(gè)請(qǐng)求的頁(yè)面,HTTP/1.1 的頭部總大小可能達(dá) 10KB,而 HTTP/2 壓縮后可降至 1KB 以下。
② 降低延遲,提升并發(fā)性能
- 減少 TCP 連接數(shù):頭部壓縮允許單個(gè)連接承載更多請(qǐng)求。
- 加速首屏加載:關(guān)鍵資源(如 HTML、CSS)的頭部壓縮后,傳輸時(shí)間縮短,頁(yè)面渲染更快。
3. 服務(wù)器推送
HTTP/2 的服務(wù)器推送(Server Push) 是一種允許服務(wù)器主動(dòng)向客戶端發(fā)送資源的技術(shù),無需等待客戶端顯式請(qǐng)求。以下是其特性與優(yōu)點(diǎn)的詳細(xì)說明:
(1) 主動(dòng)推送機(jī)制
服務(wù)器在客戶端請(qǐng)求一個(gè)資源(如 HTML 頁(yè)面)時(shí),可主動(dòng)推送與之關(guān)聯(lián)的其他資源(如 CSS、JS、圖片)。
示例:客戶端請(qǐng)求 index.html,服務(wù)器同時(shí)推送 style.css 和 script.js,減少后續(xù)請(qǐng)求的往返時(shí)間(RTT)。
(2) 資源預(yù)判與優(yōu)先級(jí)
- 服務(wù)器可根據(jù)業(yè)務(wù)邏輯預(yù)判客戶端需要的資源(如通過 Link 頭部聲明推送列表)。
- 支持設(shè)置推送資源的優(yōu)先級(jí),確保關(guān)鍵資源(如首屏 CSS)優(yōu)先傳輸。
(3) 服務(wù)器推送的優(yōu)點(diǎn)與局限性
① 顯著減少延遲(優(yōu)點(diǎn))
- 減少往返次數(shù):通過提前推送資源,客戶端無需額外發(fā)起請(qǐng)求,降低頁(yè)面加載時(shí)間。
- 加速首屏渲染:關(guān)鍵資源(如 CSS、JS)的提前到達(dá)可更快完成頁(yè)面渲染。
② 僅支持靜態(tài)資源(局限)
服務(wù)器推送無法傳輸動(dòng)態(tài)生成的內(nèi)容(如實(shí)時(shí)數(shù)據(jù)),需結(jié)合 WebSocket 或 SSE 實(shí)現(xiàn)實(shí)時(shí)通信。
4. 安全機(jī)制提升
- 協(xié)議要求:HTTP/2 規(guī)范(RFC 7540)建議與 TLS 1.2 或更高版本 結(jié)合使用,且必須支持 前向安全(Forward Secrecy) 和 服務(wù)器名稱指示(SNI)。
- TLS 1.3 支持:HTTP/2 結(jié)合 TLS 1.3 時(shí),握手僅需 1 個(gè)往返時(shí)間(RTT),且通過臨時(shí)密鑰(Ephemeral Key)實(shí)現(xiàn)前向安全,即使長(zhǎng)期密鑰泄露,歷史通信也無法被解密。
- 會(huì)話復(fù)用:支持基于會(huì)話 ID 或票據(jù)(Session Ticket)的快速握手,減少重復(fù)連接的加密開銷。
- 二進(jìn)制分幀:HTTP/2 使用二進(jìn)制格式而非明文傳輸,降低中間設(shè)備(如代理、防火墻)因解析文本協(xié)議導(dǎo)致的注入攻擊或篡改風(fēng)險(xiǎn)。
- 頭部壓縮安全:HPACK 算法通過動(dòng)態(tài)表和哈夫曼編碼壓縮頭部,避免明文頭部字段被竊取或篡改。
五、面試官:HTTP/2有什么局限性?HTTP/3基于UPD的QUIC協(xié)議如何提升連接效率??
1. HTTP/2 的缺陷
(1) TCP層面的隊(duì)頭阻塞
HTTP/2 通過 Stream 的并發(fā)能力,解決了 HTTP/1 隊(duì)頭阻塞的問題,看似很完美了,但是 HTTP/2 還是存在“隊(duì)頭阻塞”的問題,只不過問題不是在 HTTP 這一層面,而是在 TCP 這一層。
HTTP/2 是基于 TCP 協(xié)議來傳輸數(shù)據(jù)的,TCP 是字節(jié)流協(xié)議,TCP 層必須保證收到的字節(jié)數(shù)據(jù)是完整且連續(xù)的,這樣內(nèi)核才會(huì)將緩沖區(qū)里的數(shù)據(jù)返回給 HTTP 應(yīng)用,那么當(dāng)「前 1 個(gè)字節(jié)數(shù)據(jù)」沒有到達(dá)時(shí),后收到的字節(jié)數(shù)據(jù)只能存放在內(nèi)核緩沖區(qū)里,只有等到這 1 個(gè)字節(jié)數(shù)據(jù)到達(dá)時(shí),HTTP/2 應(yīng)用層才能從內(nèi)核中拿到數(shù)據(jù),這就是 HTTP/2 隊(duì)頭阻塞問題。
圖片
因?yàn)?TCP 是字節(jié)流協(xié)議,TCP 層必須保證收到的字節(jié)數(shù)據(jù)是完整且有序的,如果序列號(hào)較低的 TCP 段在網(wǎng)絡(luò)傳輸中丟失了,即使序列號(hào)較高的 TCP 段已經(jīng)被接收了,應(yīng)用層也無法從內(nèi)核中讀取到這部分?jǐn)?shù)據(jù)。從 HTTP 視角看,就是請(qǐng)求被阻塞了。
舉個(gè)例子,如下圖:
圖中發(fā)送方發(fā)送了很多個(gè) Packet,每個(gè) Packet 都有自己的序號(hào),你可以認(rèn)為是 TCP 的序列號(hào),其中 Packet 3 在網(wǎng)絡(luò)中丟失了,即使 Packet 4~6 被接收方收到后,由于內(nèi)核中的 TCP 數(shù)據(jù)不是連續(xù)的,于是接收方的應(yīng)用層就無法從內(nèi)核中讀取到,只有等到 Packet 3 重傳后,接收方的應(yīng)用層才可以從內(nèi)核中讀取到數(shù)據(jù),這就是 HTTP/2 的隊(duì)頭阻塞問題,是在 TCP 層面發(fā)生的。
所以,一旦發(fā)生了丟包現(xiàn)象,就會(huì)觸發(fā) TCP 的重傳機(jī)制,這樣在一個(gè) TCP 連接中的所有的 HTTP 請(qǐng)求都必須等待這個(gè)丟了的包被重傳回來。
(2) TCP 與 TLS 的握手時(shí)延遲
發(fā)起 HTTP 請(qǐng)求時(shí),需要經(jīng)過 TCP 三次握手和 TLS 四次握手(TLS 1.2)的過程,因此共需要 3 個(gè) RTT 的時(shí)延才能發(fā)出請(qǐng)求數(shù)據(jù)。
另外,TCP 由于具有「擁塞控制」的特性,所以剛建立連接的 TCP 會(huì)有個(gè)「慢啟動(dòng)」的過程,它會(huì)對(duì) TCP 連接產(chǎn)生“減速”效果。
(3) 網(wǎng)絡(luò)遷移需要重新連接
一個(gè) TCP 連接是由四元組(源 IP 地址,源端口,目標(biāo) IP 地址,目標(biāo)端口)確定的,這意味著如果 IP 地址或者端口變動(dòng)了,就會(huì)導(dǎo)致需要 TCP 與 TLS 重新握手,這不利于移動(dòng)設(shè)備切換網(wǎng)絡(luò)的場(chǎng)景,比如 4G 網(wǎng)絡(luò)環(huán)境切換成 WiFi。
這些問題都是 TCP 協(xié)議固有的問題,無論應(yīng)用層的 HTTP/2 在怎么設(shè)計(jì)都無法避免。
HTTP3把傳輸層協(xié)議替換成 UDP,從傳輸層徹底進(jìn)行優(yōu)化。
2. HTTP/3 的優(yōu)化
(1) 無隊(duì)頭阻塞
QUIC 協(xié)議也有類似 HTTP/2 Stream 與多路復(fù)用的概念,也是可以在同一條連接上并發(fā)傳輸多個(gè) Stream,Stream 可以認(rèn)為就是一條 HTTP 請(qǐng)求。
由于 QUIC 使用的傳輸協(xié)議是 UDP,UDP 不關(guān)心數(shù)據(jù)包的順序,如果數(shù)據(jù)包丟失,UDP 也不關(guān)心。
不過 QUIC 協(xié)議會(huì)保證數(shù)據(jù)包的可靠性,每個(gè)數(shù)據(jù)包都有一個(gè)序號(hào)唯一標(biāo)識(shí)。當(dāng)某個(gè)流中的一個(gè)數(shù)據(jù)包丟失了,即使該流的其他數(shù)據(jù)包到達(dá)了,數(shù)據(jù)也無法被 HTTP/3 讀取,直到 QUIC 重傳丟失的報(bào)文,數(shù)據(jù)才會(huì)交給 HTTP/3。
而其他流的數(shù)據(jù)報(bào)文只要被完整接收,HTTP/3 就可以讀取到數(shù)據(jù)??梢哉J(rèn)為HTTP/3 把 HTTP/2 在應(yīng)用層上的多個(gè)流的概念轉(zhuǎn)移到了傳輸層上,解決了傳輸層的隊(duì)頭阻塞問題。
(2) 更快的連接建立
對(duì)于 HTTP/1 和 HTTP/2 協(xié)議,TCP 和 TLS 是分層的,分別屬于內(nèi)核實(shí)現(xiàn)的傳輸層、OpenSSL 庫(kù)實(shí)現(xiàn)的表示層,因此它們難以合并在一起,需要分批次來握手,先 TCP 握手,再 TLS 握手。
HTTP/3 在傳輸數(shù)據(jù)前雖然需要 QUIC 協(xié)議握手,這個(gè)握手過程只需要 1 RTT,握手的目的是為確認(rèn)雙方的「連接 ID」,連接遷移就是基于連接 ID 實(shí)現(xiàn)的。
但是 HTTP/3 的 QUIC 協(xié)議并不是與 TLS 分層,而是 QUIC 內(nèi)部包含了 TLS,它在自己的幀會(huì)攜帶 TLS 里的“記錄”,再加上 QUIC 使用的是 TLS/1.3,因此僅需 1 個(gè) RTT 就可以「同時(shí)」完成建立連接與密鑰協(xié)商,如下圖:
甚至,在第二次連接的時(shí)候,應(yīng)用數(shù)據(jù)包可以和 QUIC 握手信息(連接信息 + TLS 信息)一起發(fā)送,達(dá)到 0-RTT 的效果。
如下圖右邊部分,HTTP/3 當(dāng)會(huì)話恢復(fù)時(shí),有效負(fù)載數(shù)據(jù)與第一個(gè)數(shù)據(jù)包一起發(fā)送,可以做到 0-RTT(下圖的右下角):
(3) 連接遷移
基于 TCP 傳輸協(xié)議的 HTTP 協(xié)議,由于是通過四元組(源 IP、源端口、目的 IP、目的端口)確定一條 TCP 連接。
那么當(dāng)移動(dòng)設(shè)備的網(wǎng)絡(luò)從 4G 切換到 WIFI 時(shí),意味著 IP 地址變化了,那么就必須要斷開連接,然后重新建立連接。而建立連接的過程包含 TCP 三次握手和 TLS 四次握手的時(shí)延,以及 TCP 慢啟動(dòng)的減速過程,給用戶的感覺就是網(wǎng)絡(luò)突然卡頓了一下,因此連接的遷移成本是很高的。
而 QUIC 協(xié)議沒有用四元組的方式來“綁定”連接,而是通過連接 ID 來標(biāo)記通信的兩個(gè)端點(diǎn),客戶端和服務(wù)器可以各自選擇一組 ID 來標(biāo)記自己,因此即使移動(dòng)設(shè)備的網(wǎng)絡(luò)變化后,導(dǎo)致 IP 地址變化了,只要仍保有上下文信息(比如連接 ID、TLS 密鑰等),就可以“無縫”地復(fù)用原連接,消除重連的成本,沒有絲毫卡頓感,達(dá)到了連接遷移的功能。