聊聊QUIC


一、QUIC是什么南用?

????????QUIC是快速UDP網(wǎng)絡(luò)連接(Quick UDP Internet Connections)的縮寫,? 是Google公司研發(fā)的一種基于? UDP? 協(xié)議的低時延互聯(lián)網(wǎng)傳輸協(xié)議。在過去,QUIC用在HTTP上苹粟,后來IETF(國際互聯(lián)網(wǎng)工程任務(wù)組)發(fā)現(xiàn)QUIC是個好東西,于是希望把QUIC從HTTP中分離出來(如 : IP / UDP / QUIC / HTTP)跃闹。在2016年IETF會議中嵌削,HTTP-over-QUIC協(xié)議被重命名為HTTP/3,并成為? HTTP? 協(xié)議的第三個正式版本望艺。

????????社區(qū)中的人們已經(jīng)使用非正式名稱如iQUIC和gQUIC來指代這些不同版本的協(xié)議苛秕,以將QUIC協(xié)議與IETF和Google分開,在wireshark中可以通過輸入gquic或quic過濾quic報文荣茫。

QUIC是個很大的協(xié)議想帅,位于傳輸層,使用TLS 1.3(RFC 8446)啡莉,在UDP之上實現(xiàn)類似于TCP + TLS + HTTP/2港准。

QUIC位于傳輸層


QUIC相關(guān)時間:

2013 年由Google提出

2015 年被提議作為 IETF 的標(biāo)準(zhǔn)草案

2016年11月IETF召開了第一次QUIC工作組會議

二、為什么是UDP咧欣,而不是TCP浅缸?

吐槽歷代HTTP

1、HTTP0.9 只有Get方法

2魄咕、HTTP1.0 使用短連接衩椒,每次請求都要經(jīng)過三次握手,四次揮手。需要使用keep-alive參數(shù)來告知服務(wù)器端要建立一個長連接毛萌,而HTTP1.1默認(rèn)支持長連接苟弛。

3、HTTP 1.1 隊頭阻塞阁将。

4膏秫、HTTP2.0? IETF借鑒了SPDY,雖然消除了以請求為單元的隊頭阻塞做盅,但是請求內(nèi)是以TCP同步發(fā)送缤削,沒能根治隊頭阻塞。

對比各個版本的HTTP


2吹榴、吐槽TCP:

? ? ? ? a. TCP由操作系統(tǒng)內(nèi)核實現(xiàn)亭敢,如果要改變,那么所有操作系統(tǒng)都得改變图筹,不現(xiàn)實帅刀。

????????b. TCP對報文控制太精細(xì),很難有改進(jìn)的空間远剩,數(shù)據(jù)包經(jīng)過嚴(yán)格控制劝篷,不能來一場說走就走的旅行。曾經(jīng)Google有人提出TFO (tcp fast open)對TCP擴(kuò)展民宿,也提交了RFC,但是沒普及像鸡。

? ? ? ? c. UDP報文結(jié)構(gòu)簡單活鹰,在此基礎(chǔ)上做文章很方便。而且QUIC并非基于系統(tǒng)內(nèi)核修改只估,可以進(jìn)行快速迭代更新志群。

3、吐槽完:

UDP是不可靠傳輸蛔钙,IP也是不可靠傳輸锌云。為啥QUIC不直接建立在IP上呢?

世界上有很多終端設(shè)備通過NAT通信吁脱,所有的NAT產(chǎn)品都支持TCP/UDP桑涎,根據(jù)IP+PORT與終端的會話一一對應(yīng)。如果QUIC建立在IP之上兼贡,并沒有端口號攻冷,意味著每一個NAT設(shè)備只能記憶一個終端的會話,一個全球IP 與一個私有IP的一一映射遍希。那將意味著NAT設(shè)備后只能有一個會話可以訪問同一個服務(wù)器的頁面等曼。那還不如趕緊普及IPv6。

再退一步,即使在IP層之上給到QUIC端口號禁谦,那也得所有的NAT設(shè)備都得修改可以兼容QUIC的規(guī)則胁黑。所以QUIC建立在UDP上是唯一出路翰灾。

4虑绵、QUIC相比現(xiàn)在廣泛應(yīng)用的TCP + TLS + HTTP/2協(xié)議有如下優(yōu)勢:

(1)通過減少往返次數(shù),以縮短連接建立時間

HTTPS 及 QUIC 建連過程??


(2)多路復(fù)用哩俭,解決HTTP/2隊頭阻塞問題

????????QUIC 最基本的傳輸單元是 Packet拥诡,不會超過 MTU 的大小触趴,整個加密和認(rèn)證過程都是基于 Packet 的,不會跨越多個 Packet渴肉。這樣就能避免 TLS 協(xié)議存在的隊頭阻塞冗懦。Stream 之間相互獨立,比如 Stream2 丟了一個 Pakcet仇祭,不會影響 Stream3 和 Stream4披蕉。不存在 TCP 隊頭阻塞。

????????QUIC? 的流量控制類似? HTTP2乌奇,即在? Connection? 和? Stream? 級別提供了兩種流量控制没讲。為什么需要兩類流量控制呢?主要是因為? QUIC? 支持多路復(fù)用礁苗。Stream? 可以認(rèn)為就是一條? HTTP? 請求爬凑。Connection? 可以類比一條? TCP? 連接。多路復(fù)用意味著在一條? Connetion? 上會同時存在多條? Stream试伙。既需要對單個? Stream? 進(jìn)行控制嘁信,又需要針對所有? Stream? 進(jìn)行總體控制。相當(dāng)于rabbitmq的channel和Connection的關(guān)系疏叨。

????????簡單來說潘靖,http2解決http1.1在應(yīng)用層中隊頭阻塞的問題,但是沒有解決傳輸層TCP的單個報文的重傳阻塞(傳輸層的隊頭阻塞沒有解決)蚤蔓。而UDP沒有報文阻塞這個問題卦溢,所以基于UDP的quic協(xié)議,可以更深一層的解決阻塞問題秀又。

QUIC 多路復(fù)用時沒有隊頭阻塞的問題


(3)使用FEC(前向糾錯)恢復(fù)丟失的包单寂,以減少超時重傳

????????前向糾錯是一種差錯控制方式,它是指信號在被送入傳輸信道之前預(yù)先按一定的算法進(jìn)行編碼處理吐辙,加入帶有信號本身特征的冗碼凄贩,在接收端按照相應(yīng)算法對接收到的信號進(jìn)行解碼,從而找出在傳輸過程中產(chǎn)生的錯誤碼并將其糾正的技術(shù)袱讹。QUIC用的是一階冗余疲扎,如果有一個Group內(nèi)有其中一條QUIC報文出錯可以修正昵时。如果有超過一個QUIC報文出錯,則NACK椒丧。

(4)使用一個隨機(jī)數(shù)(CID)標(biāo)志一個連接壹甥,取代傳統(tǒng)IP + PORT的方式,使得切換網(wǎng)絡(luò)環(huán)境如從4G到wifi仍然能使用之前的連接壶熏。

? ? ? ? 當(dāng)使用手機(jī)在 WIFI 和 4G 移動網(wǎng)絡(luò)切換時句柠,客戶端的 IP 肯定會發(fā)生變化,需要重新建立和服務(wù)端的 TCP 連接棒假。而任何一條 QUIC 連接不再以 IP 及端口四元組標(biāo)識溯职,而是以一個 64 位的隨機(jī)數(shù)作為 ID 來標(biāo)識(?由于這個 ID 是客戶端隨機(jī)產(chǎn)生的,并且長度有 64 位帽哑,所以沖突概率非常低)谜酒,這樣就算 IP 或者端口發(fā)生變化時,只要 ID 不變妻枕,這條連接依然維持著僻族,上層業(yè)務(wù)邏輯感知不到變化,不會中斷屡谐,也就不需要重連述么。

三、QUIC報文

參考?https://tools.ietf.org/html/draft-tsvwg-quic-protocol-02#ref-3

紅色為QUIC公共報文頭


第一字節(jié)為:Public ?Flags:

Public Flag的8位如下所示愕掏,左邊為高位度秘,右邊為低位

public flags

如果Bit0被置上(0x01 = PUBLIC_FLAG_VERSION = 0x01),該字段的含義取決于報文是客戶端還是服務(wù)端發(fā)送饵撑。如果是客戶端發(fā)送敷钾,這一位被置上表示QUIC Version字段不為空,且QUIC Version字段被填充為客戶端的QUIC版本信息肄梨。在客戶端收到服務(wù)端同意建立該版本的連接報文抵達(dá)之前,客戶端發(fā)送的所有報文的這一位必須都要被設(shè)置挠锥。如果服務(wù)端同意建立該版本的連接众羡,那么這一位不用設(shè)置。如果這一位被服務(wù)端置上蓖租,那么表示該報文是版本協(xié)商報文(Version Negotiation Packet)粱侣。

如果Bit1被置上(0x02 = PUBLIC_FLAG_RESET),表明該報文是公共重置報文(Public Reset packet)

Bit2蓖宦、Bit3兩位表示報文中的Connection ID的長度齐婴。直至協(xié)商另外一個值之前,在所有的報文中稠茂,這兩位必須設(shè)置被設(shè)置為相同(客戶端可能請求更少的數(shù)據(jù)柠偶,所以ConnectID的長度需要變化)

0x0C(Bit3及Bit2均為1)表示Connection ID長度是8字節(jié)

0x08(Bit3位1情妖,Bit2為0)表示Connection ID長度是4字節(jié)

0x04(Bit3位0,Bit2為1)表示Connection ID長度是1字節(jié)

0x00(Bit3及Bit2均為0)表示無Connection ID

Bit4诱担、Bit5兩位表示每個數(shù)據(jù)包中存在的數(shù)據(jù)包編號的字節(jié)數(shù)毡证。對于幀數(shù)據(jù),這兩位才使用蔫仙,對于Public Reset報文及Version Negotiation報文料睛,這兩位必須為0

0x30(Bit5及Bit4均為1)表示:包序號是6個字節(jié)

0x20(Bit5為1,Bit4為0)表示:包序號是4個字節(jié)

0x10(Bit5為0摇邦,Bit4為1)表示:包序號是2個字節(jié)

0x00(Bit5及Bit4均為0)表示:包序號是1個字節(jié)

Bit6:預(yù)留給多路徑使用

Bit7:未使用恤煞,必須為0

Connection ID:客戶端隨機(jī)選擇的最大長度為64位的無符號整數(shù)。但是施籍,長度可以協(xié)商居扒。

QUIC Version:QUIC協(xié)議的版本號,32位的可選字段法梯。如果Public Flag & FLAG_VERSION != 0苔货,這個字段必填×⒀疲客戶端設(shè)置Public Flag中的Bit0為1夜惭,并且填寫期望的版本號。如果客戶端期望的版本號服務(wù)端不支持铛绰,服務(wù)端設(shè)置Public Flag中的Bit0為1诈茧,并且在該字段中列出服務(wù)端支持的協(xié)議版本(0或者多個),并且該字段后不能有任何報文捂掰。

Packet Number:長度取決于Public Flag中Bit4及Bit5兩位的值敢会,最大長度6字節(jié)。發(fā)送端在每個普通報文中設(shè)置Packet Number这嚣。發(fā)送端發(fā)送的第一個包的序列號是1鸥昏,隨后的數(shù)據(jù)包中的序列號的都大于前一個包中的序列號。

QUIC報文分為:

1姐帚、特殊報文

版本協(xié)商報文(Version Negotiation Packets)

只由服務(wù)端發(fā)送吏垮。版本協(xié)議報文以1字節(jié)的Public Flag及8字節(jié)的Connection ID開始。必須設(shè)置PUBLIC_FLAG_VERSION且標(biāo)識Connection ID長度為8字節(jié)罐旗,最后面就是服務(wù)端支持的協(xié)議版本(4字節(jié))膳汪。

版本協(xié)商報文


公共重置報文(Public Reset Packets)

Public Reset報文以1字節(jié)的Public Flag及8字節(jié)的Connection ID開始。必須設(shè)置PUBLIC_FLAG_RESET且標(biāo)識Connection ID長度為8字節(jié)九秀,剩余的部分是QUIC Tag遗嗽。

公共重置報文


2、普通報文

普通的報文被驗證(authenticated)且被加密鼓蜒。公有頭被驗證但是沒有加密痹换,從Private Flags字段開始的報文被加密征字。普通的報文包含AEAD(authenticated encryption and associated data)報文。普通報文必須被解密晴音,并且密文被解密后柔纵,明文以Private Header開始。

普通報文中私有頭格式


幀報文

除了私有頭外锤躁,幀包有一系列的基于類型的幀數(shù)據(jù)的負(fù)載搁料,通用的幀包的格式

幀報文

FEC(Forward Error Correction)報文

FEC包(FLAG_FEC標(biāo)志被置為1)的負(fù)載只包含位于FEC組中的每個數(shù)據(jù)包的空填充負(fù)載的XOR值。每個FEC包的FLAG_FEC_GROUP標(biāo)志也必須被置為1

FEC包


四系羞、瀏覽器中查看QUIC

有豆瓣郭计,google,F(xiàn)acebook椒振,YouTube昭伸,QQ空間。以下是F12豆瓣網(wǎng)的澎迎,可以發(fā)現(xiàn)豆瓣有在用HTTP1.1庐杨,HTTP2.0(h2),QUIC夹供。

在Google新版的Chrome瀏覽器中灵份,支持QUIC協(xié)議,在Chrome瀏覽器中打開“實驗性功能”頁面(chrome://flags/)哮洽,把Experimental QUIC protocol設(shè)置enabled填渠。

豆瓣使用QUIC


服務(wù)器返回可用的QUIC版本


五、抓包驗證

抓不到正常通信的包鸟辅。將就看個版本匹配失敗的例子? - -

客戶端發(fā)送一個CHLO報文氛什,報文里Public Flags的bit0(Version)設(shè)置1,而且設(shè)置Version值Q039匪凉。創(chuàng)建CID連接號枪眉。

客戶端發(fā)送hello報文


服務(wù)端收到客戶端的連接請求,返回協(xié)商報文再层,Public Flags的bit0(Version)設(shè)置1贸铜,并返回可支持的QUIC Version版本列表。

服務(wù)端應(yīng)答可用version


客戶端發(fā)現(xiàn)服務(wù)端返回的版本列表里树绩,并沒有符合的,于是發(fā)送CONNECTION_CLOSE消息隐轩,關(guān)閉通信饺饭。雖然看到連接關(guān)閉的字樣,但實際上我是可以訪問到豆瓣的职车,因為此時TCP會有替補(bǔ)瘫俊,走基于TCP的HTTP通信鹊杖。

客戶端應(yīng)答版本不一致并關(guān)閉


六、支持QUIC的開源項目

Caddy:Go 寫的 Web 服務(wù)器 扛芽,QUIC只是附屬功能骂蓖,但用它的人更多是用來做QUIC實驗 :D, 勉強(qiáng)能用在生產(chǎn)環(huán)境川尖。

quic-go :是完全用 go 寫的 QUIC 協(xié)議棧登下,開發(fā)很活躍,已在 Caddy 中使用叮喳,MIT 許可被芳。

Chromium :Google 官方維護(hù)基本沒有坑,隨時可以跟隨 chrome 更新到最新版本馍悟。不過編譯 Chromium 比較麻煩畔濒。

七、附錄:

1锣咒、header壓縮

????????在HTTP1.x中侵状,頭部元數(shù)據(jù)都是以純文本的形式發(fā)送的,通常會給每個請求增加500~800字節(jié)的負(fù)荷毅整。

????????HTTP2.0使用HPACK算法來減少需要傳輸?shù)膆eader大小趣兄,通訊雙方各自cache一份header fields表,既避免了重復(fù)header的傳輸毛嫉,又減小了需要傳輸?shù)拇笮》谈8咝У膲嚎s算法可以很大的壓縮header,減少發(fā)送包的數(shù)量從而降低延遲承粤。

2暴区、參考文檔 https://tools.ietf.org/html/draft-ietf-quic-http-17

3、FEC算法? https://blog.csdn.net/u010178611/article/details/82656838?

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末辛臊,一起剝皮案震驚了整個濱河市仙粱,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌彻舰,老刑警劉巖伐割,帶你破解...
    沈念sama閱讀 216,744評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異刃唤,居然都是意外死亡隔心,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,505評論 3 392
  • 文/潘曉璐 我一進(jìn)店門尚胞,熙熙樓的掌柜王于貴愁眉苦臉地迎上來硬霍,“玉大人,你說我怎么就攤上這事笼裳∥簦” “怎么了粱玲?”我有些...
    開封第一講書人閱讀 163,105評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長拜轨。 經(jīng)常有香客問我抽减,道長,這世上最難降的妖魔是什么橄碾? 我笑而不...
    開封第一講書人閱讀 58,242評論 1 292
  • 正文 為了忘掉前任卵沉,我火速辦了婚禮,結(jié)果婚禮上堪嫂,老公的妹妹穿的比我還像新娘偎箫。我一直安慰自己,他們只是感情好皆串,可當(dāng)我...
    茶點故事閱讀 67,269評論 6 389
  • 文/花漫 我一把揭開白布淹办。 她就那樣靜靜地躺著,像睡著了一般恶复。 火紅的嫁衣襯著肌膚如雪怜森。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,215評論 1 299
  • 那天谤牡,我揣著相機(jī)與錄音副硅,去河邊找鬼。 笑死翅萤,一個胖子當(dāng)著我的面吹牛恐疲,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播套么,決...
    沈念sama閱讀 40,096評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼培己,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了胚泌?” 一聲冷哼從身側(cè)響起省咨,我...
    開封第一講書人閱讀 38,939評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎玷室,沒想到半個月后零蓉,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,354評論 1 311
  • 正文 獨居荒郊野嶺守林人離奇死亡穷缤,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,573評論 2 333
  • 正文 我和宋清朗相戀三年敌蜂,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片津肛。...
    茶點故事閱讀 39,745評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡章喉,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情囊陡,我是刑警寧澤,帶...
    沈念sama閱讀 35,448評論 5 344
  • 正文 年R本政府宣布掀亥,位于F島的核電站撞反,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏搪花。R本人自食惡果不足惜遏片,卻給世界環(huán)境...
    茶點故事閱讀 41,048評論 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望撮竿。 院中可真熱鬧吮便,春花似錦、人聲如沸幢踏。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,683評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽房蝉。三九已至僚匆,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間搭幻,已是汗流浹背咧擂。 一陣腳步聲響...
    開封第一講書人閱讀 32,838評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留檀蹋,地道東北人松申。 一個月前我還...
    沈念sama閱讀 47,776評論 2 369
  • 正文 我出身青樓,卻偏偏與公主長得像俯逾,于是被迫代替她去往敵國和親贸桶。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,652評論 2 354

推薦閱讀更多精彩內(nèi)容

  • 科普:QUIC 協(xié)議原理分析 作者介紹:lancelot纱昧,騰訊資深研發(fā)工程師刨啸。目前主要負(fù)責(zé)騰訊 stgw(騰訊安全...
    吸霾少年閱讀 9,759評論 0 19
  • 茫茫人海兩相遇,初相知识脆,共相望设联。縱使?fàn)幊硿I不斷灼捂。 攜手相伴共風(fēng)雨离例,愛之深,恨之切悉稠,只因我們最相顧宫蛆。
    我很簡單一介俗人閱讀 164評論 1 3
  • 風(fēng)吹起我的發(fā) 絲絲縷縷將歲月結(jié)扣相加 發(fā)絲飄過曾經(jīng)的期待 又在天空中揚起幻想的沙 偷偷織就一城縹緲的線 在錯中復(fù)雜...
    我是深海精靈閱讀 330評論 0 0
  • 晚飯后散步,走得有點遠(yuǎn)∫粒回去的時候想虎,一想到還要走三、四十分鐘的路程回去叛拷,腿就軟了起來舌厨。無奈,不爭氣地掏出手機(jī)忿薇,...
    Banagher閱讀 240評論 0 0
  • 一群有夢想的青年,最后一個晚上筋栋,在KTV炊汤,激情慷慨,唱浮夸弊攘,死了都要愛婿崭,燈紅酒綠的包廂里,有煙味肴颊,有酒氣氓栈,有美...
    藕吟詩語閱讀 446評論 0 2