來源:https://zhuanlan.zhihu.com/p/143464334
2015 年 HTTP/2 標(biāo)準(zhǔn)發(fā)表后拄显,大多數(shù)主流瀏覽器也于當(dāng)年年底支持該標(biāo)準(zhǔn)崖面。此后,憑借著多路復(fù)用共啃、頭部壓縮居扒、服務(wù)器推送等優(yōu)勢(shì)概漱,HTTP/2 得到了越來越多開發(fā)者的青睞。不知不覺的 HTTP 已經(jīng)發(fā)展到了第三代喜喂,鵝廠也緊跟技術(shù)潮流犀概,很多項(xiàng)目也在逐漸使用 HTTP/3。本文基于興趣部落接入 HTTP/3 的實(shí)踐夜惭,聊一聊 HTTP/3 的原理以及業(yè)務(wù)接入的方式。
1. HTTP/3 原理
1.1 HTTP 歷史
在介紹 HTTP/3 之前铛绰,我們先簡(jiǎn)單看下 HTTP 的歷史诈茧,了解下 HTTP/3 出現(xiàn)的背景。
隨著網(wǎng)絡(luò)技術(shù)的發(fā)展捂掰,1999 年設(shè)計(jì)的 HTTP/1.1 已經(jīng)不能滿足需求敢会,所以 Google 在 2009 年設(shè)計(jì)了基于 TCP 的 SPDY,后來 SPDY 的開發(fā)組推動(dòng) SPDY 成為正式標(biāo)準(zhǔn)这嚣,不過最終沒能通過鸥昏。不過 SPDY 的開發(fā)組全程參與了 HTTP/2 的制定過程,參考了 SPDY 的很多設(shè)計(jì)姐帚,所以我們一般認(rèn)為 SPDY 就是 HTTP/2 的前身吏垮。無(wú)論 SPDY 還是 HTTP/2,都是基于 TCP 的,TCP 與 UDP 相比效率上存在天然的劣勢(shì)膳汪,所以 2013 年 Google 開發(fā)了基于 UDP 的名為 QUIC 的傳輸層協(xié)議唯蝶,QUIC 全稱 Quick UDP Internet Connections,希望它能替代 TCP遗嗽,使得網(wǎng)頁(yè)傳輸更加高效粘我。后經(jīng)提議,互聯(lián)網(wǎng)工程任務(wù)組正式將基于 QUIC 協(xié)議的 HTTP (HTTP over QUIC)重命名為 HTTP/3痹换。
1.2 QUIC 協(xié)議概覽
TCP 一直是傳輸層中舉足輕重的協(xié)議征字,而 UDP 則默默無(wú)聞,在面試中問到 TCP 和 UDP 的區(qū)別時(shí)娇豫,有關(guān) UDP 的回答常常寥寥幾語(yǔ)匙姜,長(zhǎng)期以來 UDP 給人的印象就是一個(gè)很快但不可靠的傳輸層協(xié)議。但有時(shí)候從另一個(gè)角度看锤躁,缺點(diǎn)可能也是優(yōu)點(diǎn)搁料。QUIC(Quick UDP Internet Connections,快速 UDP 網(wǎng)絡(luò)連接) 基于 UDP系羞,正是看中了 UDP 的速度與效率郭计。同時(shí) QUIC 也整合了 TCP、TLS 和 HTTP/2 的優(yōu)點(diǎn)椒振,并加以優(yōu)化昭伸。用一張圖可以清晰地表示他們之間的關(guān)系。
那 QUIC 和 HTTP/3 什么關(guān)系呢澎迎?QUIC 是用來替代 TCP庐杨、SSL/TLS 的傳輸層協(xié)議,在傳輸層之上還有應(yīng)用層夹供,我們熟知的應(yīng)用層協(xié)議有 HTTP灵份、FTP、IMAP 等哮洽,這些協(xié)議理論上都可以運(yùn)行在 QUIC 之上填渠,其中運(yùn)行在 QUIC 之上的 HTTP 協(xié)議被稱為 HTTP/3,這就是”HTTP over QUIC 即 HTTP/3“的含義鸟辅。
因此想要了解 HTTP/3氛什,QUIC 是繞不過去的,下面主要通過幾個(gè)重要的特性讓大家對(duì) QUIC 有更深的理解匪凉。
1.3 零 RTT 建立連接
用一張圖可以形象地看出 HTTP/2 和 HTTP/3 建立連接的差別枪眉。
HTTP/2 的連接需要 3 RTT,如果考慮會(huì)話復(fù)用再层,即把第一次握手算出來的對(duì)稱密鑰緩存起來贸铜,那么也需要 2 RTT堡纬,更進(jìn)一步的,如果 TLS 升級(jí)到 1.3萨脑,那么 HTTP/2 連接需要 2 RTT隐轩,考慮會(huì)話復(fù)用則需要 1 RTT。有人會(huì)說 HTTP/2 不一定需要 HTTPS渤早,握手過程還可以簡(jiǎn)化职车。這沒毛病,HTTP/2 的標(biāo)準(zhǔn)的確不需要基于 HTTPS鹊杖,但實(shí)際上所有瀏覽器的實(shí)現(xiàn)都要求 HTTP/2 必須基于 HTTPS悴灵,所以 HTTP/2 的加密連接必不可少。而 HTTP/3 首次連接只需要 1 RTT骂蓖,后面的連接更是只需 0 RTT积瞒,意味著客戶端發(fā)給服務(wù)端的第一個(gè)包就帶有請(qǐng)求數(shù)據(jù),這一點(diǎn) HTTP/2 難以望其項(xiàng)背登下。那這背后是什么原理呢茫孔?我們具體看下 QUIC 的連接過程。
Step1:首次連接時(shí)被芳,客戶端發(fā)送 Inchoate Client Hello 給服務(wù)端缰贝,用于請(qǐng)求連接;
Step2:服務(wù)端生成 g畔濒、p剩晴、a,根據(jù) g侵状、p 和 a 算出 A赞弥,然后將 g、p趣兄、A 放到 Server Config 中再發(fā)送 Rejection 消息給客戶端绽左;
Step3:客戶端接收到 g、p艇潭、A 后妇菱,自己再生成 b,根據(jù) g暴区、p、b 算出 B辛臊,根據(jù) A仙粱、p、b 算出初始密鑰 K彻舰。B 和 K 算好后伐割,客戶端會(huì)用 K 加密 HTTP 數(shù)據(jù)候味,連同 B 一起發(fā)送給服務(wù)端;
Step4:服務(wù)端接收到 B 后隔心,根據(jù) a白群、p、B 生成與客戶端同樣的密鑰硬霍,再用這密鑰解密收到的 HTTP 數(shù)據(jù)帜慢。為了進(jìn)一步的安全(前向安全性),服務(wù)端會(huì)更新自己的隨機(jī)數(shù) a 和公鑰唯卖,再生成新的密鑰 S粱玲,然后把公鑰通過 Server Hello 發(fā)送給客戶端。連同 Server Hello 消息拜轨,還有 HTTP 返回?cái)?shù)據(jù)抽减;
Step5:客戶端收到 Server Hello 后,生成與服務(wù)端一致的新密鑰 S橄碾,后面的傳輸都使用 S 加密卵沉。
這樣,QUIC 從請(qǐng)求連接到正式接發(fā) HTTP 數(shù)據(jù)一共花了 1 RTT法牲,這 1 個(gè) RTT 主要是為了獲取 Server Config史汗,后面的連接如果客戶端緩存了 Server Config,那么就可以直接發(fā)送 HTTP 數(shù)據(jù)皆串,實(shí)現(xiàn) 0 RTT 建立連接淹办。
這里使用的是 DH 密鑰交換算法,DH 算法的核心就是服務(wù)端生成 a恶复、g怜森、p 3 個(gè)隨機(jī)數(shù),a 自己持有谤牡,g 和 p 要傳輸給客戶端副硅,而客戶端會(huì)生成 b 這 1 個(gè)隨機(jī)數(shù),通過 DH 算法客戶端和服務(wù)端可以算出同樣的密鑰翅萤。在這過程中 a 和 b 并不參與網(wǎng)絡(luò)傳輸恐疲,安全性大大提高。因?yàn)?p 和 g 是大數(shù)套么,所以即使在網(wǎng)絡(luò)中傳輸?shù)?p培己、g、A胚泌、B 都被劫持省咨,那么靠現(xiàn)在的計(jì)算機(jī)算力也沒法破解密鑰。
1.4 連接遷移
TCP 連接基于四元組(源 IP玷室、源端口零蓉、目的 IP笤受、目的端口),切換網(wǎng)絡(luò)時(shí)至少會(huì)有一個(gè)因素發(fā)生變化敌蜂,導(dǎo)致連接發(fā)生變化箩兽。當(dāng)連接發(fā)生變化時(shí),如果還使用原來的 TCP 連接章喉,則會(huì)導(dǎo)致連接失敗汗贫,就得等原來的連接超時(shí)后重新建立連接,所以我們有時(shí)候發(fā)現(xiàn)切換到一個(gè)新網(wǎng)絡(luò)時(shí)囊陡,即使新網(wǎng)絡(luò)狀況良好芳绩,但內(nèi)容還是需要加載很久。如果實(shí)現(xiàn)得好撞反,當(dāng)檢測(cè)到網(wǎng)絡(luò)變化時(shí)立刻建立新的 TCP 連接妥色,即使這樣,建立新的連接還是需要幾百毫秒的時(shí)間遏片。
QUIC 的連接不受四元組的影響嘹害,當(dāng)這四個(gè)元素發(fā)生變化時(shí),原連接依然維持吮便。那這是怎么做到的呢笔呀?道理很簡(jiǎn)單,QUIC 連接不以四元組作為標(biāo)識(shí)髓需,而是使用一個(gè) 64 位的隨機(jī)數(shù)许师,這個(gè)隨機(jī)數(shù)被稱為 Connection ID,即使 IP 或者端口發(fā)生變化僚匆,只要 Connection ID 沒有變化微渠,那么連接依然可以維持。
1.5 隊(duì)頭阻塞/多路復(fù)用
HTTP/1.1 和 HTTP/2 都存在隊(duì)頭阻塞問題(Head of line blocking)咧擂,那什么是隊(duì)頭阻塞呢逞盆?
TCP 是個(gè)面向連接的協(xié)議,即發(fā)送請(qǐng)求后需要收到 ACK 消息松申,以確認(rèn)對(duì)方已接收到數(shù)據(jù)云芦。如果每次請(qǐng)求都要在收到上次請(qǐng)求的 ACK 消息后再請(qǐng)求,那么效率無(wú)疑很低贸桶。后來 HTTP/1.1 提出了 Pipelining 技術(shù)舅逸,允許一個(gè) TCP 連接同時(shí)發(fā)送多個(gè)請(qǐng)求,這樣就大大提升了傳輸效率皇筛。
在這個(gè)背景下堡赔,下面就來談 HTTP/1.1 的隊(duì)頭阻塞。下圖中设联,一個(gè) TCP 連接同時(shí)傳輸 10 個(gè)請(qǐng)求善已,其中第 1、2离例、3 個(gè)請(qǐng)求已被客戶端接收换团,但第 4 個(gè)請(qǐng)求丟失,那么后面第 5 - 10 個(gè)請(qǐng)求都被阻塞宫蛆,需要等第 4 個(gè)請(qǐng)求處理完畢才能被處理艘包,這樣就浪費(fèi)了帶寬資源。
因此耀盗,HTTP 一般又允許每個(gè)主機(jī)建立 6 個(gè) TCP 連接想虎,這樣可以更加充分地利用帶寬資源,但每個(gè)連接中隊(duì)頭阻塞的問題還是存在叛拷。
HTTP/2 的多路復(fù)用解決了上述的隊(duì)頭阻塞問題舌厨。不像 HTTP/1.1 中只有上一個(gè)請(qǐng)求的所有數(shù)據(jù)包被傳輸完畢下一個(gè)請(qǐng)求的數(shù)據(jù)包才可以被傳輸,HTTP/2 中每個(gè)請(qǐng)求都被拆分成多個(gè) Frame 通過一條 TCP 連接同時(shí)被傳輸忿薇,這樣即使一個(gè)請(qǐng)求被阻塞裙椭,也不會(huì)影響其他的請(qǐng)求。如下圖所示署浩,不同顏色代表不同的請(qǐng)求揉燃,相同顏色的色塊代表請(qǐng)求被切分的 Frame。
事情還沒完筋栋,HTTP/2 雖然可以解決“請(qǐng)求”這個(gè)粒度的阻塞炊汤,但 HTTP/2 的基礎(chǔ) TCP 協(xié)議本身卻也存在著隊(duì)頭阻塞的問題。HTTP/2 的每個(gè)請(qǐng)求都會(huì)被拆分成多個(gè) Frame弊攘,不同請(qǐng)求的 Frame 組合成 Stream抢腐,Stream 是 TCP 上的邏輯傳輸單元,這樣 HTTP/2 就達(dá)到了一條連接同時(shí)發(fā)送多條請(qǐng)求的目標(biāo)肴颊,這就是多路復(fù)用的原理氓栈。我們看一個(gè)例子,在一條 TCP 連接上同時(shí)發(fā)送 4 個(gè) Stream婿着,其中 Stream1 已正確送達(dá)授瘦,Stream2 中的第 3 個(gè) Frame 丟失,TCP 處理數(shù)據(jù)時(shí)有嚴(yán)格的前后順序竟宋,先發(fā)送的 Frame 要先被處理提完,這樣就會(huì)要求發(fā)送方重新發(fā)送第 3 個(gè) Frame,Stream3 和 Stream4 雖然已到達(dá)但卻不能被處理丘侠,那么這時(shí)整條連接都被阻塞徒欣。
不僅如此,由于 HTTP/2 必須使用 HTTPS蜗字,而 HTTPS 使用的 TLS 協(xié)議也存在隊(duì)頭阻塞問題打肝。TLS 基于 Record 組織數(shù)據(jù)脂新,將一堆數(shù)據(jù)放在一起(即一個(gè) Record)加密,加密完后又拆分成多個(gè) TCP 包傳輸粗梭。一般每個(gè) Record 16K争便,包含 12 個(gè) TCP 包,這樣如果 12 個(gè) TCP 包中有任何一個(gè)包丟失断医,那么整個(gè) Record 都無(wú)法解密滞乙。
隊(duì)頭阻塞會(huì)導(dǎo)致 HTTP/2 在更容易丟包的弱網(wǎng)絡(luò)環(huán)境下比 HTTP/1.1 更慢!
那 QUIC 是如何解決隊(duì)頭阻塞問題的呢鉴嗤?主要有兩點(diǎn)斩启。
QUIC 的傳輸單元是 Packet,加密單元也是 Packet醉锅,整個(gè)加密兔簇、傳輸、解密都基于 Packet荣挨,這樣就能避免 TLS 的隊(duì)頭阻塞問題男韧;
QUIC 基于 UDP,UDP 的數(shù)據(jù)包在接收端沒有處理順序默垄,即使中間丟失一個(gè)包此虑,也不會(huì)阻塞整條連接,其他的資源會(huì)被正常處理口锭。
1.6 擁塞控制
擁塞控制的目的是避免過多的數(shù)據(jù)一下子涌入網(wǎng)絡(luò)朦前,導(dǎo)致網(wǎng)絡(luò)超出最大負(fù)荷。QUIC 的擁塞控制與 TCP 類似鹃操,并在此基礎(chǔ)上做了改進(jìn)韭寸。所以我們先簡(jiǎn)單介紹下 TCP 的擁塞控制。
TCP 擁塞控制由 4 個(gè)核心算法組成:慢啟動(dòng)荆隘、擁塞避免恩伺、快速重傳和快速恢復(fù),理解了這 4 個(gè)算法椰拒,對(duì) TCP 的擁塞控制也就有了大概了解晶渠。
慢啟動(dòng):發(fā)送方向接收方發(fā)送 1 個(gè)單位的數(shù)據(jù),收到對(duì)方確認(rèn)后會(huì)發(fā)送 2 個(gè)單位的數(shù)據(jù)燃观,然后依次是 4 個(gè)褒脯、8 個(gè)……呈指數(shù)級(jí)增長(zhǎng),這個(gè)過程就是在不斷試探網(wǎng)絡(luò)的擁塞程度缆毁,超出閾值則會(huì)導(dǎo)致網(wǎng)絡(luò)擁塞番川;
擁塞避免:指數(shù)增長(zhǎng)不可能是無(wú)限的,到達(dá)某個(gè)限制(慢啟動(dòng)閾值)之后,指數(shù)增長(zhǎng)變?yōu)榫€性增長(zhǎng)颁督;
快速重傳:發(fā)送方每一次發(fā)送時(shí)都會(huì)設(shè)置一個(gè)超時(shí)計(jì)時(shí)器践啄,超時(shí)后即認(rèn)為丟失,需要重發(fā)沉御;
快速恢復(fù):在上面快速重傳的基礎(chǔ)上往核,發(fā)送方重新發(fā)送數(shù)據(jù)時(shí),也會(huì)啟動(dòng)一個(gè)超時(shí)定時(shí)器嚷节,如果收到確認(rèn)消息則進(jìn)入擁塞避免階段,如果仍然超時(shí)虎锚,則回到慢啟動(dòng)階段硫痰。
QUIC 重新實(shí)現(xiàn)了 TCP 協(xié)議的 Cubic 算法進(jìn)行擁塞控制,并在此基礎(chǔ)上做了不少改進(jìn)窜护。下面介紹一些 QUIC 改進(jìn)的擁塞控制的特性效斑。
1.6.1 熱插拔
TCP 中如果要修改擁塞控制策略,需要在系統(tǒng)層面進(jìn)行操作柱徙。QUIC 修改擁塞控制策略只需要在應(yīng)用層操作缓屠,并且 QUIC 會(huì)根據(jù)不同的網(wǎng)絡(luò)環(huán)境、用戶來動(dòng)態(tài)選擇擁塞控制算法护侮。
1.6.2 前向糾錯(cuò) FEC
QUIC 使用前向糾錯(cuò)(FEC敌完,F(xiàn)orward Error Correction)技術(shù)增加協(xié)議的容錯(cuò)性。一段數(shù)據(jù)被切分為 10 個(gè)包后羊初,依次對(duì)每個(gè)包進(jìn)行異或運(yùn)算滨溉,運(yùn)算結(jié)果會(huì)作為 FEC 包與數(shù)據(jù)包一起被傳輸,如果不幸在傳輸過程中有一個(gè)數(shù)據(jù)包丟失长赞,那么就可以根據(jù)剩余 9 個(gè)包以及 FEC 包推算出丟失的那個(gè)包的數(shù)據(jù)晦攒,這樣就大大增加了協(xié)議的容錯(cuò)性。
這是符合現(xiàn)階段網(wǎng)絡(luò)技術(shù)的一種方案得哆,現(xiàn)階段帶寬已經(jīng)不是網(wǎng)絡(luò)傳輸?shù)钠款i脯颜,往返時(shí)間才是,所以新的網(wǎng)絡(luò)傳輸協(xié)議可以適當(dāng)增加數(shù)據(jù)冗余贩据,減少重傳操作栋操。
1.6.3 單調(diào)遞增的 Packet Number
TCP 為了保證可靠性,使用 Sequence Number 和 ACK 來確認(rèn)消息是否有序到達(dá)乐设,但這樣的設(shè)計(jì)存在缺陷讼庇。
超時(shí)發(fā)生后客戶端發(fā)起重傳,后來接收到了 ACK 確認(rèn)消息近尚,但因?yàn)樵颊?qǐng)求和重傳請(qǐng)求接收到的 ACK 消息一樣蠕啄,所以客戶端就郁悶了,不知道這個(gè) ACK 對(duì)應(yīng)的是原始請(qǐng)求還是重傳請(qǐng)求。如果客戶端認(rèn)為是原始請(qǐng)求的 ACK歼跟,但實(shí)際上是左圖的情形和媳,則計(jì)算的采樣 RTT 偏大;如果客戶端認(rèn)為是重傳請(qǐng)求的 ACK哈街,但實(shí)際上是右圖的情形留瞳,又會(huì)導(dǎo)致采樣 RTT 偏小。圖中有幾個(gè)術(shù)語(yǔ)骚秦,RTO 是指超時(shí)重傳時(shí)間(Retransmission TimeOut)她倘,跟我們熟悉的 RTT(Round Trip Time,往返時(shí)間)很長(zhǎng)得很像作箍。采樣 RTT 會(huì)影響 RTO 計(jì)算硬梁,超時(shí)時(shí)間的準(zhǔn)確把握很重要,長(zhǎng)了短了都不合適胞得。
QUIC 解決了上面的歧義問題荧止。與 Sequence Number 不同的是,Packet Number 嚴(yán)格單調(diào)遞增阶剑,如果 Packet N 丟失了跃巡,那么重傳時(shí) Packet 的標(biāo)識(shí)不會(huì)是 N,而是比 N 大的數(shù)字牧愁,比如 N + M素邪,這樣發(fā)送方接收到確認(rèn)消息時(shí)就能方便地知道 ACK 對(duì)應(yīng)的是原始請(qǐng)求還是重傳請(qǐng)求。
1.6.4 ACK Delay
TCP 計(jì)算 RTT 時(shí)沒有考慮接收方接收到數(shù)據(jù)到發(fā)送確認(rèn)消息之間的延遲递宅,如下圖所示娘香,這段延遲即 ACK Delay。QUIC 考慮了這段延遲办龄,使得 RTT 的計(jì)算更加準(zhǔn)確烘绽。
1.6.5 更多的 ACK 塊
一般來說,接收方收到發(fā)送方的消息后都應(yīng)該發(fā)送一個(gè) ACK 回復(fù)俐填,表示收到了數(shù)據(jù)安接。但每收到一個(gè)數(shù)據(jù)就返回一個(gè) ACK 回復(fù)太麻煩,所以一般不會(huì)立即回復(fù)英融,而是接收到多個(gè)數(shù)據(jù)后再回復(fù)盏檐,TCP SACK 最多提供 3 個(gè) ACK block。但有些場(chǎng)景下驶悟,比如下載胡野,只需要服務(wù)器返回?cái)?shù)據(jù)就好,但按照 TCP 的設(shè)計(jì)痕鳍,每收到 3 個(gè)數(shù)據(jù)包就要“禮貌性”地返回一個(gè) ACK硫豆。而 QUIC 最多可以捎帶 256 個(gè) ACK block龙巨。在丟包率比較嚴(yán)重的網(wǎng)絡(luò)下,更多的 ACK block 可以減少重傳量熊响,提升網(wǎng)絡(luò)效率旨别。
1.7 流量控制
TCP 會(huì)對(duì)每個(gè) TCP 連接進(jìn)行流量控制,流量控制的意思是讓發(fā)送方不要發(fā)送太快汗茄,要讓接收方來得及接收秸弛,不然會(huì)導(dǎo)致數(shù)據(jù)溢出而丟失,TCP 的流量控制主要通過滑動(dòng)窗口來實(shí)現(xiàn)的洪碳〉堇溃可以看出,擁塞控制主要是控制發(fā)送方的發(fā)送策略瞳腌,但沒有考慮到接收方的接收能力非迹,流量控制是對(duì)這部分能力的補(bǔ)齊。
QUIC 只需要建立一條連接纯趋,在這條連接上同時(shí)傳輸多條 Stream,好比有一條道路冷离,兩頭分別有一個(gè)倉(cāng)庫(kù)吵冒,道路中有很多車輛運(yùn)送物資。QUIC 的流量控制有兩個(gè)級(jí)別:連接級(jí)別(Connection Level)和 Stream 級(jí)別(Stream Level)西剥,好比既要控制這條路的總流量痹栖,不要一下子很多車輛涌進(jìn)來,貨物來不及處理瞭空,也不能一個(gè)車輛一下子運(yùn)送很多貨物揪阿,這樣貨物也來不及處理。
那 QUIC 是怎么實(shí)現(xiàn)流量控制的呢咆畏?我們先看單條 Stream 的流量控制南捂。Stream 還沒傳輸數(shù)據(jù)時(shí),接收窗口(flow control receive window)就是最大接收窗口(flow control receive window)旧找,隨著接收方接收到數(shù)據(jù)后溺健,接收窗口不斷縮小。在接收到的數(shù)據(jù)中钮蛛,有的數(shù)據(jù)已被處理鞭缭,而有的數(shù)據(jù)還沒來得及被處理。如下圖所示魏颓,藍(lán)色塊表示已處理數(shù)據(jù)岭辣,黃色塊表示未處理數(shù)據(jù),這部分?jǐn)?shù)據(jù)的到來甸饱,使得 Stream 的接收窗口縮小沦童。
隨著數(shù)據(jù)不斷被處理,接收方就有能力處理更多數(shù)據(jù)。當(dāng)滿足 (flow control receive offset - consumed bytes) < (max receive window / 2) 時(shí)搞动,接收方會(huì)發(fā)送 WINDOW_UPDATE frame 告訴發(fā)送方你可以再多發(fā)送些數(shù)據(jù)過來躏精。這時(shí) flow control receive offset 就會(huì)偏移,接收窗口增大鹦肿,發(fā)送方可以發(fā)送更多數(shù)據(jù)到接收方矗烛。
Stream 級(jí)別對(duì)防止接收端接收過多數(shù)據(jù)作用有限,更需要借助 Connection 級(jí)別的流量控制箩溃。理解了 Stream 流量那么也很好理解 Connection 流控瞭吃。Stream 中,接收窗口(flow control receive window) = 最大接收窗口(max receive window) - 已接收數(shù)據(jù)(highest received byte offset) 涣旨,而對(duì) Connection 來說:接收窗口 = Stream1 接收窗口 + Stream2 接收窗口 + ... + StreamN 接收窗口 歪架。
2. HTTP/3 實(shí)踐
2.1 X5 內(nèi)核與 STGW
X5 內(nèi)核是騰訊開發(fā)的適用于安卓系統(tǒng)的瀏覽器內(nèi)核,為了解決傳統(tǒng)安卓系統(tǒng)瀏覽器內(nèi)核適配成本高霹陡、不安全和蚪、不穩(wěn)定等問題而開發(fā)的統(tǒng)一的瀏覽器內(nèi)核。STGW 是 Secure Tencent Gateway 的縮寫烹棉,意思是騰訊安全云網(wǎng)關(guān)攒霹。兩者早在前兩年便支持了 QUIC 協(xié)議。
那作為運(yùn)行在 X5 上的業(yè)務(wù)浆洗,我們?cè)撊绾谓尤?QUIC 呢催束?得益于 X5 和 STGW,業(yè)務(wù)在接入 QUIC 時(shí)所需要做的改動(dòng)非常小伏社,只需要兩步抠刺。
Step 1.?在 STGW 上開啟白名單,允許業(yè)務(wù)域名接入 QUIC 協(xié)議摘昌;
Step 2.?業(yè)務(wù)資源的 Response Header 添加 alt-svc 屬性速妖,示例:alt-svc: quic=":443"; ma=2592000; v="44,43,39"。
接入 QUIC 時(shí)聪黎,STGW 的優(yōu)勢(shì)非常明顯买优,由 STGW 與支持 QUIC 的客戶端(這里是 X5)進(jìn)行通信,而業(yè)務(wù)后臺(tái)與 STGW 仍然使用 HTTP/1.1 通信挺举,QUIC 所需要的 Server Config 等緩存信息也都是由 STGW 維護(hù)杀赢。
2.2 協(xié)商升級(jí)與競(jìng)速
業(yè)務(wù)域名加入了 STGW 的白名單丐吓,業(yè)務(wù)資源的 Response Header 也添加了 alt-svc 屬性蚜退,那 QUIC 是如何建立連接的呢帮寻?這里有個(gè)關(guān)鍵的步驟:協(xié)商升級(jí)逛拱≡禄希客戶端不確定服務(wù)器是否支持 QUIC芹壕,如果貿(mào)然地請(qǐng)求建立 QUIC 連接可能會(huì)失敗淆两,所以需要經(jīng)歷協(xié)商升級(jí)過程才能決定是否使用 QUIC师崎。
首次請(qǐng)求時(shí),客戶端會(huì)使用 HTTP/1.1 或者 HTTP/2汇歹,如果服務(wù)器支持 QUIC屁擅,則在響應(yīng)的數(shù)據(jù)中返回 alt-svc 頭部,告訴客戶端下次請(qǐng)求可以走 QUIC产弹。alt-svc 主要包含以下信息:
quic:監(jiān)聽的端口派歌;
ma:有效時(shí)間,單位是秒痰哨,承諾在這段時(shí)間內(nèi)都支持 QUIC胶果;
版本號(hào):QUIC 的迭代很快,這里列出所有支持的版本號(hào)斤斧。
確認(rèn)服務(wù)器支持 QUIC 之后早抠,客戶端向服務(wù)端同時(shí)發(fā)起 QUIC 連接和 TCP 連接,比較兩個(gè)連接的速度撬讽,然后選擇較快的協(xié)議蕊连,這個(gè)過程叫“競(jìng)速”,一般都是 QUIC 獲勝游昼。
2.3 QUIC 性能表現(xiàn)
QUIC 建立連接的成功率在 90% 以上咪奖,競(jìng)速成功率也接近 90%,0 RTT 率在 55% 左右酱床。
使用 QUIC 協(xié)議時(shí)頁(yè)面首屏耗時(shí)要比非 QUIC 協(xié)議減少 10%。
從資源獲取的不同階段看趟佃,QUIC 協(xié)議在連接階段節(jié)省的時(shí)間比較明顯扇谣。
從頁(yè)面首屏區(qū)間占比圖中可以看出,使用了 QUIC 協(xié)議后闲昭,首屏耗時(shí)在 1 秒內(nèi)的占比提升明顯罐寨,大約在 12% 左右。
3. 總結(jié)
QUIC 丟掉了 TCP序矩、TLS 的包袱鸯绿,基于 UDP,并對(duì) TCP簸淀、TLS瓶蝴、HTTP/2 的經(jīng)驗(yàn)加以借鑒、改進(jìn)租幕,實(shí)現(xiàn)了一個(gè)安全高效可靠的 HTTP 通信協(xié)議舷手。憑借著 0 RTT 建立連接、平滑的連接遷移劲绪、基本消除了隊(duì)頭阻塞男窟、改進(jìn)的擁塞控制和流量控制等優(yōu)秀的特性盆赤,QUIC 在絕大多數(shù)場(chǎng)景下獲得了比 HTTP/2 更好的效果。
一周前歉眷,微軟宣布開源自己的內(nèi)部 QUIC 庫(kù) -- MsQuic牺六,將全面推薦 QUIC 協(xié)議替換 TCP/IP 協(xié)議。
HTTP/3 未來可期汗捡。
作者:billpchen淑际,騰訊看點(diǎn)前端開發(fā)工程師