QUIC(Quick UDP Internet Connection,快速UDP網(wǎng)絡(luò)連接)發(fā)音同 "quick",是 Google 公司在 2012 年提出的使用 UDP 進(jìn)行多路并發(fā)傳輸?shù)膮f(xié)議。
2016 年,互聯(lián)網(wǎng)工程任務(wù)組 IETF 開始標(biāo)準(zhǔn)化 QUIC。
2017 年,Google 開發(fā)并部署了 QUIC 協(xié)議的初始設(shè)計(jì) gQUIC。
2021 年,QUIC 協(xié)議的正式標(biāo)準(zhǔn)化版本 RFC900 發(fā)布。
QUIC協(xié)議的特性
從 QUIC 的命名中可以看到兩個(gè)關(guān)鍵詞——快速和 UDP。這個(gè)兩個(gè)關(guān)鍵詞概括了 QUIC 的特性,提供更快速、更可靠、更安全的數(shù)據(jù)傳輸方式。
QUIC協(xié)議棧
QUIC協(xié)議的原理
一個(gè) QUIC 數(shù)據(jù)包由頭部(Header)和數(shù)據(jù)(Data)組成。
QUIC
QUIC數(shù)據(jù)格式
頭部(Header)中包含以下字段:
- 標(biāo)志位(Flags):用來指示該數(shù)據(jù)包的類型、狀態(tài)等信息。
- 連接ID(Connection ID):用于唯一標(biāo)識(shí)一個(gè)連接。
- 版本號(hào)(Version):表示使用的協(xié)議版本號(hào)。
- 包編號(hào)(Packet Number):表示數(shù)據(jù)包的順序。
數(shù)據(jù)(Data)被拆分成多個(gè)小的數(shù)據(jù)幀(Frame),每個(gè)數(shù)據(jù)幀都有自己的類型、長度和負(fù)載。數(shù)據(jù)幀通過 Stream ID 進(jìn)行標(biāo)識(shí),以便于在多路復(fù)用時(shí)進(jìn)行管理。
- PING 幀:用于測試連接的可用性。
- ACK 幀:用于確認(rèn)收到數(shù)據(jù)包。
- RESET_STREAM 幀:用于重置數(shù)據(jù)流的狀態(tài)。
- STOP_SENDING 幀:用于停止向特定的數(shù)據(jù)流發(fā)送數(shù)據(jù)。
- CRYPTO 幀:用于傳輸加密數(shù)據(jù)。
- STREAM 幀:用于傳輸普通數(shù)據(jù)流。
STREAM幀結(jié)構(gòu)
下面介紹 QUIC 協(xié)議中的三個(gè)核心特性:0-RTT 連接建立、無隊(duì)頭阻塞的多路復(fù)用、無歧義重傳。
0-RTT 連接建立
QUIC 協(xié)議使用了 0-RTT(零往返時(shí)間)連接建立技術(shù),可以在客戶端發(fā)送第一個(gè)請(qǐng)求時(shí)就建立起安全連接,從而減少連接建立所需的時(shí)間。這個(gè)技術(shù)通過使用 TLS 的 Session Ticket,在服務(wù)端重啟后仍然保留連接狀態(tài),從而避免了重新握手的過程。
傳統(tǒng) HTTPs 握手包含了 TCP 和 TLS 握手,如下圖所示,總共需要 3 個(gè) RTT。
TCP和TLS握手
從中可以看出,TLS 握手需要 1 個(gè) RTT。通過 1 次 RTT,客戶端和服務(wù)端就協(xié)商好了通信密鑰。
客戶端:生成隨機(jī)數(shù) a,選擇公開的大數(shù) G 和 P,計(jì)算 A=a*G%P。發(fā)送 Client Hello 消息,將 A 和 G 傳遞給服務(wù)端。
服務(wù)端:生成隨機(jī)數(shù) b,計(jì)算 B=b*G%P。發(fā)送 Server Hello 消息。將 B 傳遞給客戶端。
客戶端:通過秘鑰加密算法生成通信密鑰 KEY = aB = ab*G%P。
服務(wù)端:通過秘鑰加密算法生成通信密鑰 KEY = bA = ba*G%P。
QUIC 的握手是基于 TLS1.3 實(shí)現(xiàn)的,建立連接時(shí)也應(yīng)該需要1次 RTT,那 QUIC 的 0-RTT 連接是如何實(shí)現(xiàn)的?
首次握手后,QUIC 的客戶端緩存了 Server Hello,那么在下次建連時(shí),可以直接使用緩存數(shù)據(jù)計(jì)算通信密鑰,如下圖所示。
0-RTT連接
客戶端:生成隨機(jī)數(shù) c,選擇公開的大數(shù) G 和 P,計(jì)算 A=c*G%P。發(fā)送 Client Hello 消息,將 A 和 G 傳遞給服務(wù)器。
客戶端:直接使用緩存的 Server Hello 計(jì)算通信密鑰 KEY = cB = cb*G%P,加密并發(fā)送應(yīng)用數(shù)據(jù)。
服務(wù)端:根據(jù) Client Hello 消息計(jì)算通信密鑰 KEY = bA = bc*G%P。
通過緩存 Server Hello,在生成 Client Hello 的同時(shí),加密了應(yīng)用數(shù)據(jù),所以客戶端不需要經(jīng)過握手就可以發(fā)送應(yīng)用數(shù)據(jù),這就是 QUIC 的 0-RTT 連接。
無隊(duì)頭阻塞的多路復(fù)用
瀏覽器限制了同一個(gè)域名下的請(qǐng)求數(shù)量。當(dāng)請(qǐng)求達(dá)到最大數(shù)量時(shí),剩余的資源需要等待其他資源請(qǐng)求完成后才能發(fā)起請(qǐng)求,這就是隊(duì)頭阻塞(Head of Line Blocking)。
在傳統(tǒng)的 HTTP/1 協(xié)議中,每個(gè) TCP 連接只能處理唯一的請(qǐng)求,因此當(dāng)需要請(qǐng)求多個(gè)資源時(shí),需要建立多個(gè) TCP 連接。為了解決 HTTP/1 的核心問題,在 HTTP/2 中引入了多路復(fù)用的技術(shù),這個(gè)技術(shù)可以只通過一個(gè) TCP 連接就可以傳輸所有的請(qǐng)求數(shù)據(jù),如下圖。
多路復(fù)用很好的解決了瀏覽器限制同一個(gè)域名下的請(qǐng)求數(shù)量的問題,從而提高網(wǎng)絡(luò)吞吐量。此外,QUIC 協(xié)議還支持?jǐn)?shù)據(jù)流級(jí)別的擁塞控制,可以更精細(xì)地控制網(wǎng)絡(luò)擁塞。
TCP連接
HTTP/2 雖然通過多路復(fù)用解決了 HTTP 層的隊(duì)頭阻塞,但仍然存在 TCP 層的隊(duì)頭阻塞問題。在 HTTP/2 中,如果 TCP 連接中出現(xiàn)了丟包的情況,那么整個(gè) TCP 都要開始等待重傳,后面的所有數(shù)據(jù)都將被阻塞。在這種情況下, HTTP/2 的表現(xiàn)情況反倒不如 HTTP/1 。
QUIC 通過為每個(gè)請(qǐng)求流都分配一個(gè)獨(dú)立的滑動(dòng)窗口,解決 TCP 層的隊(duì)頭阻塞。如下圖,A 請(qǐng)求流上的丟包不會(huì)影響 B 請(qǐng)求流上的數(shù)據(jù)發(fā)送。
QUIC連接
無歧義重傳
為了保證可靠性,TCP 使用基于序號(hào)的 Sequence Number 和 Ack 來確認(rèn)消息的有序到達(dá)。在 TCP 中,重傳包的 sequence number 和原始包的Sequence Number 是不變的,也正是因此這個(gè)特性,引發(fā)了 Tcp 重傳歧義問題。當(dāng)超時(shí)事件 RTO 發(fā)生后,客戶端發(fā)起重傳,然后接收到了 Ack 數(shù)據(jù)。但由于 Sequence Number 是一樣的,這個(gè)接收到的 Ack 到底是原始請(qǐng)求的響應(yīng)還是重傳請(qǐng)求的響應(yīng)呢?這導(dǎo)致了 RTT 計(jì)算歧義。
TCP重傳歧義性
QUIC 則是采用了單向遞增的 Packet Number 來標(biāo)識(shí)數(shù)據(jù)包,因此不會(huì)像 TCP 一樣,不會(huì)因?yàn)槌瑫r(shí)重傳了同樣序列的數(shù)據(jù)包,造成 RTT 和 RTO(Retransmission Time Out,重傳超時(shí)時(shí)間)的計(jì)算不準(zhǔn)確。每個(gè) Packet Number 都嚴(yán)格遞增,就算 Packet N 丟失了,重傳的 Packet N 的 Packet Number 已經(jīng)不是 N,而是一個(gè)比 N 大的值。
QUIC的RTT計(jì)算
QUIC 對(duì)于 RTT 的計(jì)算更為準(zhǔn)確,預(yù)估的超時(shí)時(shí)間能夠有效防止更多的重傳請(qǐng)求被錯(cuò)誤地發(fā)送回客戶端。同時(shí)也給予了 QUIC 網(wǎng)絡(luò)更為快速的反應(yīng)時(shí)間,及時(shí)通知客戶端重傳數(shù)據(jù)包。
但是單純依靠嚴(yán)格遞增的 Packet Number 肯定是無法保證數(shù)據(jù)的順序性和可靠性。
QUIC 引入了 Stream Offset 的概念,通過 Stream Offset 可以保證應(yīng)用數(shù)據(jù)的順序。假設(shè)客戶端先后發(fā)送了 Pakcet N 和 Pakcet N+1,Stream Offset 分別是 x 和 x+y。如果 Packet N 丟失,引發(fā)重傳,重傳的 Packet Number 是 N+2,但是它的 Stream Offset 依然是 x,這樣就算 Packet N + 2 是后到的,依然可以將 Stream x 和 Stream x+y 按照順序組織起來,交給應(yīng)用程序處理。
QUIC協(xié)議的應(yīng)用場景
QUIC 為各種領(lǐng)域提供了可靠、高效和安全的數(shù)據(jù)傳輸方案,其中最具潛力的應(yīng)用場景包括:
- 實(shí)時(shí) Web 和移動(dòng)應(yīng)用
這些應(yīng)用需要低延遲和可靠的數(shù)據(jù)傳輸。通過相互獨(dú)立的數(shù)據(jù)流和擁塞控制機(jī)制,QUIC 可以快速高效地發(fā)送和接收數(shù)據(jù)。在多路復(fù)用模式下,QUIC 同一連接內(nèi)不同數(shù)據(jù)流之間的數(shù)據(jù)傳輸互不干擾。
物聯(lián)網(wǎng)設(shè)備通常使用 TCP 和 MQTT 等協(xié)議進(jìn)行通信,在受限的網(wǎng)絡(luò)環(huán)境中可能存在高延遲和丟包等問題。相比之下,QUIC 可以極近實(shí)現(xiàn) 0-RTT,為高延遲和丟包的網(wǎng)絡(luò)環(huán)境,提供了更可靠和高效的替代方案。
- 支付和電子商務(wù)應(yīng)用
這些應(yīng)用需要安全可靠的數(shù)據(jù)傳輸。QUIC 通過 TLS 加密和可靠的數(shù)據(jù)流,使其成為這些應(yīng)用的理想選擇,有助于保證數(shù)據(jù)安全完整地傳輸。從用戶的角度來看,QUIC 通過保證更快、更順暢的交易,優(yōu)化了用戶體驗(yàn)。
當(dāng)前,QUIC 協(xié)議已經(jīng)成為 IETF 標(biāo)準(zhǔn)化工作組的一個(gè)項(xiàng)目,并且越來越多的互聯(lián)網(wǎng)公司開始支持 QUIC 協(xié)議。隨著 QUIC 協(xié)議的普及,我們可以期待更快、更安全、更可靠的網(wǎng)絡(luò)體驗(yàn)。