作者:流云IoT
鏈接:https://blog.csdn.net/m0_37621078/article/details/106506532
文章目錄
一、QUIC 如何解決TCP的隊(duì)頭阻塞問題?
1.1 TCP 為何會(huì)有隊(duì)頭阻塞問題
1.2 QUIC 如何解決隊(duì)頭阻塞問題
1.3 QUIC 沒有隊(duì)頭阻塞的多路復(fù)用
二、QUIC 如何優(yōu)化TCP 的連接管理機(jī)制?
2.1 TCP連接的本質(zhì)是什么
2.2 QUIC 如何減少TCP 建立連接的開銷
2.3 QUIC 如何實(shí)現(xiàn)連接的無感遷移
三、QUIC 如何改進(jìn)TCP 的擁塞控制機(jī)制?
3.1 TCP 擁塞控制機(jī)制的瓶頸在哪?
3.2 QUIC 如何降低重傳概率
3.3 QUIC 如何改進(jìn)擁塞控制機(jī)制
HTTP/2 相比HTTP/1.1 設(shè)計(jì)出的一些優(yōu)秀的改進(jìn)方案,大幅提高了HTTP 的網(wǎng)絡(luò)利用效率。HTTP/2 在應(yīng)用協(xié)議層通過多路復(fù)用同一個(gè)TCP連接解決了隊(duì)頭阻塞問題,但這是以下層協(xié)議比如TCP 協(xié)議不出現(xiàn)任何數(shù)據(jù)包阻塞為前提的。TCP 在實(shí)際運(yùn)行中,特別是遇到網(wǎng)絡(luò)環(huán)境不好時(shí),數(shù)據(jù)包超時(shí)確認(rèn)或丟失是常有的事,假如某個(gè)數(shù)據(jù)包丟失需要重傳時(shí)會(huì)發(fā)生什么呢?
TCP 采用正面確認(rèn)和超時(shí)重傳機(jī)制來保證數(shù)據(jù)包的可靠交付。比如主機(jī)A 向 主機(jī)B 發(fā)送數(shù)據(jù)包,主機(jī)B 收到該數(shù)據(jù)包后會(huì)向主機(jī)A 返回確認(rèn)應(yīng)答報(bào)文,表示自己確實(shí)收到了該數(shù)據(jù)包,主機(jī)A 收到確認(rèn)應(yīng)答報(bào)文后才確定上一個(gè)數(shù)據(jù)包已經(jīng)發(fā)送成功,開始發(fā)送下一個(gè)數(shù)據(jù)包。如果超過一定時(shí)間(根據(jù)每次測量的往返時(shí)間RTT估算出的動(dòng)態(tài)閾值)未收到確認(rèn)應(yīng)答,則主機(jī)A 判斷上一個(gè)數(shù)據(jù)包丟失了,重新發(fā)送上一個(gè)數(shù)據(jù)包,這就相當(dāng)于阻塞了下一個(gè)數(shù)據(jù)包的發(fā)送。
TCP 因?yàn)槌瑫r(shí)確認(rèn)或丟包引起的滑動(dòng)窗口阻塞問題,是不是有點(diǎn)像HTTP/1.1 管道化機(jī)制中出現(xiàn)的隊(duì)頭阻塞問題?HTTP/2 在應(yīng)用協(xié)議層通過多路復(fù)用解決了隊(duì)頭阻塞問題,但TCP 在傳輸層依然存在隊(duì)頭阻塞問題,這是TCP 協(xié)議的一個(gè)主要性能瓶頸。該怎么解決TCP 的隊(duì)頭阻塞問題呢?
TCP 隊(duì)頭阻塞的主要原因是數(shù)據(jù)包超時(shí)確認(rèn)或丟失阻塞了當(dāng)前窗口向右滑動(dòng),我們最容易想到的解決隊(duì)頭阻塞的方案是不讓超時(shí)確認(rèn)或丟失的數(shù)據(jù)包將當(dāng)前窗口阻塞在原地。QUIC (Quick UDP Internet Connections)也正是采用上述方案來解決TCP 隊(duì)頭阻塞問題的。
TCP 為了保證可靠性,使用了基于字節(jié)序號(hào)的 Sequence Number 及 Ack 來確認(rèn)消息的有序到達(dá)。QUIC 同樣是一個(gè)可靠的協(xié)議,它使用 Packet Number 代替了 TCP 的 Sequence Number,并且每個(gè) Packet Number 都嚴(yán)格遞增,也就是說就算 Packet N 丟失了,重傳的 Packet N 的 Packet Number 已經(jīng)不是 N,而是一個(gè)比 N 大的值,比如Packet N+M。
QUIC 使用的Packet Number 單調(diào)遞增的設(shè)計(jì),可以讓數(shù)據(jù)包不再像TCP 那樣必須有序確認(rèn),QUIC 支持亂序確認(rèn),當(dāng)數(shù)據(jù)包Packet N 丟失后,只要有新的已接收數(shù)據(jù)包確認(rèn),當(dāng)前窗口就會(huì)繼續(xù)向右滑動(dòng)。待發(fā)送端獲知數(shù)據(jù)包Packet N 丟失后,會(huì)將需要重傳的數(shù)據(jù)包放到待發(fā)送隊(duì)列,重新編號(hào)比如數(shù)據(jù)包Packet N+M 后重新發(fā)送給接收端,對(duì)重傳數(shù)據(jù)包的處理跟發(fā)送新的數(shù)據(jù)包類似,這樣就不會(huì)因?yàn)閬G包重傳將當(dāng)前窗口阻塞在原地,從而解決了隊(duì)頭阻塞問題。那么,既然重傳數(shù)據(jù)包的Packet N+M 與丟失數(shù)據(jù)包的Packet N 編號(hào)并不一致,我們怎么確定這兩個(gè)數(shù)據(jù)包的內(nèi)容一樣呢?
還記得前篇博文:HTTP/2 是如何解決HTTP/1.1 性能瓶頸的?使用Stream ID 來標(biāo)識(shí)當(dāng)前數(shù)據(jù)流屬于哪個(gè)資源請求,這同時(shí)也是數(shù)據(jù)包多路復(fù)用傳輸?shù)浇邮斩撕竽苷=M裝的依據(jù)。重傳的數(shù)據(jù)包Packet N+M 和丟失的數(shù)據(jù)包Packet N 單靠Stream ID 的比對(duì)一致仍然不能判斷兩個(gè)數(shù)據(jù)包內(nèi)容一致,還需要再新增一個(gè)字段Stream Offset,標(biāo)識(shí)當(dāng)前數(shù)據(jù)包在當(dāng)前Stream ID 中的字節(jié)偏移量。
有了Stream Offset 字段信息,屬于同一個(gè)Stream ID 的數(shù)據(jù)包也可以亂序傳輸了(HTTP/2 中僅靠Stream ID 標(biāo)識(shí),要求同屬于一個(gè)Stream ID 的數(shù)據(jù)幀必須有序傳輸),通過兩個(gè)數(shù)據(jù)包的Stream ID 與 Stream Offset 都一致,就說明這兩個(gè)數(shù)據(jù)包的內(nèi)容一致。
QUIC 通過單向遞增的Packet Number,配合Stream ID 與 Offset 字段信息,可以支持非連續(xù)確認(rèn)應(yīng)答Ack而不影響數(shù)據(jù)包的正確組裝,擺脫了TCP 必須按順序確認(rèn)應(yīng)答Ack 的限制(也即不能出現(xiàn)非連續(xù)的空位),解決了TCP 因某個(gè)數(shù)據(jù)包重傳而阻塞后續(xù)所有待發(fā)送數(shù)據(jù)包的問題(也即隊(duì)頭阻塞問題)。
QUIC 可以支持非連續(xù)的數(shù)據(jù)包確認(rèn)應(yīng)答Ack,自然也就要求每個(gè)數(shù)據(jù)包的確認(rèn)應(yīng)答Ack 都能返回給發(fā)送端(TCP 中間丟失幾個(gè)Ack 對(duì)數(shù)據(jù)包的確認(rèn)應(yīng)答影響不大),發(fā)送端收到該數(shù)據(jù)包的確認(rèn)應(yīng)答后才會(huì)釋放該數(shù)據(jù)包所占用的緩存資源,已發(fā)送但未收到確認(rèn)應(yīng)答的數(shù)據(jù)包會(huì)保存在緩存鏈表中等待可能的重傳。QUIC 對(duì)確認(rèn)應(yīng)答Ack 丟失的容忍度比較低,自然對(duì)Ack 的傳輸能力進(jìn)行了增強(qiáng),Quic Ack Frame 可以同時(shí)提供 256 個(gè) Ack Block,在丟包率比較高的網(wǎng)絡(luò)下,更多的 Ack Block 可以提高Ack 送達(dá)的成功率,減少重傳量。
QUIC 解決了TCP 的隊(duì)頭阻塞問題,同時(shí)繼承了HTTP/2 的多路復(fù)用優(yōu)點(diǎn),因?yàn)镾tream Offset 字段的引入,QUIC 中同一Stream ID 的數(shù)據(jù)幀也支持亂序傳輸,不再像HTTP/2 要求的同一Stream ID 的數(shù)據(jù)幀必須有序傳輸那么嚴(yán)格。
值得一提的是,TLS 協(xié)議加解密前需要對(duì)數(shù)據(jù)進(jìn)行完整性校驗(yàn),HTTP/2 中如果TCP 出現(xiàn)丟包,TLS 也會(huì)因接收到的數(shù)據(jù)不完整而無法對(duì)其進(jìn)行處理,也即HTTP/2 中的TLS 協(xié)議層也存在隊(duì)頭阻塞問題,該問題如何解決呢?既然TLS 協(xié)議是因?yàn)榻邮諗?shù)據(jù)不完整引起的阻塞,我們只需要讓TLS 加密認(rèn)證過程基于一個(gè)獨(dú)立的Packet,不對(duì)多個(gè)Packet 同時(shí)進(jìn)行加密認(rèn)證,就能解決TLS 協(xié)議層出現(xiàn)的隊(duì)頭阻塞問題,某一個(gè)Packet 丟失只會(huì)影響封裝該P(yáng)acket 的Record,不會(huì)讓其它Record 陷入阻塞等待的情況。
你可能熟悉TCP 建立連接的三次握手和四次揮手過程,但你知道TCP 建立的連接本質(zhì)上是什么嗎?這里的連接跟我們熟悉的物理介質(zhì)連接(比如電路連接)不同,主要是用來說明如何在物理介質(zhì)上傳輸數(shù)據(jù)的。
為了更直觀了解網(wǎng)絡(luò)連接概念,我們拿面向連接的TCP 與無連接的UDP 做對(duì)比,網(wǎng)絡(luò)傳輸層的兩個(gè)主流協(xié)議,他們的主要區(qū)別是什么呢?UDP 每個(gè)分組的處理都獨(dú)立于所有其他分組,TCP 每個(gè)分組的傳輸都有確認(rèn)應(yīng)答過程和可能的丟包重傳過程,需要為每個(gè)分組數(shù)據(jù)進(jìn)行狀態(tài)信息記錄和管理(比如未發(fā)送、已發(fā)送、未確認(rèn)、已確認(rèn)等狀態(tài))。
TCP 建立連接的三次握手過程都做了哪些工作呢?首先確認(rèn)雙方是否能正常收發(fā)數(shù)據(jù),通信雙方交換待發(fā)送數(shù)據(jù)的初始序列編號(hào)并作為有序確認(rèn)應(yīng)答的基點(diǎn),通信雙方根據(jù)預(yù)設(shè)的狀態(tài)轉(zhuǎn)換圖完成各自的狀態(tài)遷移過程,通信雙方為分組數(shù)據(jù)的可靠傳輸和狀態(tài)信息的記錄管理分配控制塊緩存資源等。下面給出TCP 連接建立、數(shù)據(jù)傳輸、連接釋放三個(gè)階段的報(bào)文交互過程和狀態(tài)遷移圖示(詳見博文:TCP協(xié)議與Transmission Control Protocol):
TCP 的狀態(tài)管理可以分為連接狀態(tài)管理和分組數(shù)據(jù)狀態(tài)管理兩種,連接狀態(tài)管理用于雙方同步數(shù)據(jù)發(fā)送與接收狀態(tài),分組數(shù)據(jù)狀態(tài)管理用于保證數(shù)據(jù)的可靠傳輸。涉及到狀態(tài)管理一般都有狀態(tài)轉(zhuǎn)換圖,TCP 連接管理的狀態(tài)轉(zhuǎn)換圖上面已經(jīng)給出了,HTTP/2 的Stream 實(shí)際上也記錄并維護(hù)了每個(gè)Stream Frame 的狀態(tài)信息,Stream 的狀態(tài)轉(zhuǎn)換圖如下:
TCP 建立連接需要三次握手過程,第三次握手報(bào)文發(fā)出后不需要等待應(yīng)答回復(fù)就可以發(fā)送數(shù)據(jù)報(bào)文了,所以TCP 建立連接的開銷為 1-RTT。既然TCP 連接主要是由雙方記錄并同步維護(hù)的狀態(tài)組成的,我們能否借鑒TLS 快速恢復(fù)簡短握手相比完整握手的優(yōu)化方案呢?
TLS 簡短握手過程是將之前完整握手過程協(xié)商的信息記錄下來,以Session Ticket 的形式傳輸給客戶端,如果想恢復(fù)之前的會(huì)話連接,可以將Session Ticket 發(fā)送給服務(wù)器,就能通過簡短的握手過程重建或者恢復(fù)之前的連接,通過復(fù)用之前的握手信息可以節(jié)省 1-RTT 的連接建立開銷。
TCP 也提供了快速建立連接的方案 TFO (TCP Fast Open),原理跟TLS 類似,也是將首次建立連接的狀態(tài)信息記錄下來,以Cookie 的形式傳輸給客戶端,如果想復(fù)用之前的連接,可以將Cookie 發(fā)送給服務(wù)器,如果服務(wù)器通過驗(yàn)證就能快速恢復(fù)之前的連接,TFO 技術(shù)可以通過復(fù)用之前的連接將連接建立開銷縮短為 0-RTT。因?yàn)門CP 協(xié)議內(nèi)置于操作系統(tǒng)中,操作系統(tǒng)的升級(jí)普及過程較慢,因此TFO 技術(shù)至今仍未普及(TFO 在2014年發(fā)布于RFC 7413)。
從上圖可知,TCP 首次建立連接的開銷為 1-RTT,快速復(fù)用/打開連接的開銷為 0-RTT,這與TLS 1.3 協(xié)議首次完整握手與快速恢復(fù)簡短握手的開銷一致。
客戶端發(fā)送的第一個(gè)SYN 握手包是可以攜帶數(shù)據(jù)的,但為了防止TCP 泛洪攻擊,TCP 的實(shí)現(xiàn)者不允許將SYN 攜帶的數(shù)據(jù)包上傳給應(yīng)用層。HTTP 協(xié)議中TCP 與TLS 常常配合使用,這里TCP 的第一個(gè)SYN 握手包可以攜帶TLS 1.3 的握手包,這就可以將TCP + TLS 總的握手開銷進(jìn)一步降低。
首次建立連接時(shí),TCP 和TLS 1.3 都只需要 1-RTT 就可以完成握手過程,由于TCP 第一個(gè)SYN 握手包可以攜帶TLS 的握手包,因此TCP + TLS 1.3 總的首次建立連接開銷為 1-RTT。當(dāng)要快速恢復(fù)之前的連接時(shí),TFO 和TLS 1.3 都只需要 0-RTT 就可以完成握手過程,因此TCP + TLS 1.3 總的連接恢復(fù)開銷為 0-RTT。
QUIC 可以理解為”TCP + TLS 1.3“(QUIC 是基于UDP的,可能使用的是DTLS 1.3),QUIC 自然也實(shí)現(xiàn)了首次建立連接的開銷為 1-RTT,快速恢復(fù)先前連接的開銷為 0-RTT 的效率。QUIC 作為HTTP/2 的改進(jìn)版,建立連接的開銷也有明顯降低,下面給出HTTP/2 和QUIC 首次連接和會(huì)話恢復(fù)過程中,HTTP 請求首個(gè)資源的RTT 開銷對(duì)比:
HTTP/2 + TLS 1.2 首次連接 | HTTP/2 + TLS 1.2 會(huì)話恢復(fù) | HTTP/2 + TLS 1.3 首次連接 | HTTP/2 + TLS 1.3 會(huì)話恢復(fù) | HTTP/2 + TLS 1.3 會(huì)話恢復(fù) + TFO | QUIC 首次連接 | QUIC 會(huì)話恢復(fù) | |
---|---|---|---|---|---|---|---|
DNS 解析 | 1-RTT | 0-RTT | 1-RTT | 0-RTT | 0-RTT | 1-RTT | 0-RTT |
TCP 握手 | 1-RTT | 1-RTT | 1-RTT | 1-RTT | 0-RTT (TCP Fast Open) | - | - |
TLS 握手 | 2-RTT | 1-RTT | 1-RTT | 0-RTT | 0-RTT | - | - |
QUIC 握手 | - | - | - | - | - | 1-RTT | 0-RTT |
HTTP 請求 | 1-RTT | 1-RTT | 1-RTT | 1-RTT | 1-RTT | 1-RTT | 1-RTT |
總計(jì) | 5-RTT | 3-RTT | 4-RTT | 2-RTT | 1-RTT | 3-RTT | 1-RTT |
從上表可以看出,QUIC 首次建立連接的開銷比'HTTP/2 + TLS 1.3'減少了 1-RTT,會(huì)話/連接恢復(fù)的開銷降低到了 0-RTT(除去HTTP 自身請求資源的開銷),顯著降低了網(wǎng)頁請求延遲。
值得一提的是,TCP 因?yàn)閳?bào)文首部是透明傳輸?shù)?,在安全防護(hù)方便比較脆弱,容易受到網(wǎng)絡(luò)攻擊。QUIC 因?yàn)橛蠺LS 對(duì)數(shù)據(jù)包首部進(jìn)行加密和驗(yàn)證,增加了安全防護(hù)強(qiáng)度,更不容易受到網(wǎng)絡(luò)攻擊。
每個(gè)網(wǎng)絡(luò)連接都應(yīng)該有一個(gè)唯一的標(biāo)識(shí),用來辨識(shí)并區(qū)分特定的連接。TCP 連接使用<Source IP, Source Port, Target IP, Target Port> 這四個(gè)信息共同標(biāo)識(shí),在早期PC 時(shí)代,這四個(gè)元素信息可以唯一標(biāo)識(shí)通信雙方的主機(jī)及端口,報(bào)文中也不需要一個(gè)專門的字段來標(biāo)識(shí)連接,減少了傳輸開銷。
到了移動(dòng)互聯(lián)網(wǎng)時(shí)代,客戶端(比如手機(jī))的位置可能一直在變,接入不同的基站可能就會(huì)被分配不同的Source IP 和Source Port。即便在家里,客戶端可能也需要在LTE 和WIFI 之間切換,這兩個(gè)網(wǎng)絡(luò)分配給客戶端的Source IP 和Source Port 可能也是不同的。TCP 用來標(biāo)識(shí)連接的四個(gè)信息中的任何一個(gè)改變,都相當(dāng)于TCP 連接標(biāo)識(shí)改變了,也就變成了不同的連接,TCP 需要先斷開舊的連接再建立新的連接,很顯然連接切換或遷移過程不夠順暢高效。
未來移動(dòng)設(shè)備越來越多,在通話或者玩游戲等對(duì)實(shí)時(shí)性要求較高的場景中,因?yàn)榫W(wǎng)絡(luò)遷移或切換導(dǎo)致TCP 斷開連接會(huì)大大降低網(wǎng)絡(luò)服務(wù)體驗(yàn),怎么解決TCP 因?yàn)榫W(wǎng)絡(luò)遷移或切換導(dǎo)致斷線重連的問題呢?早期移動(dòng)電話使用Mobile IP 技術(shù)來解決網(wǎng)絡(luò)遷移或切換過程引起的斷連問題,Mobile IP 主要是通過新建IP 隧道的方式(也即建立一個(gè)新連接來轉(zhuǎn)發(fā)數(shù)據(jù)包)保持原來的連接不斷開,但這種方式增加了數(shù)據(jù)包的傳輸路徑,也就增大了數(shù)據(jù)包的往返時(shí)間,降低了數(shù)據(jù)包的傳輸效率。Mobile IP 的工作原理如下(移動(dòng)主機(jī)遷移到外部代理后,為了保持原連接不斷開,新建了一條到歸屬代理的IP 隧道,讓歸屬代理以原主機(jī)IP 轉(zhuǎn)發(fā)數(shù)據(jù)包):
TCP 為保持前向兼容性,沒法重新設(shè)計(jì)連接標(biāo)識(shí),但為了解決移動(dòng)主機(jī)連接切換問題還是推出了一套解決方案MPTCP (Multipath TCP,在2013年發(fā)布于RFC 6824) 。針對(duì)移動(dòng)主機(jī)同時(shí)支持LTE 和WIFI 等多條連接鏈路的情況,設(shè)計(jì)的多路徑TCP 技術(shù)(MPTCP) 允許在一條TCP 鏈路中建立多個(gè)子通道,每個(gè)子通道都可以按照三次握手的方式建立連接,每個(gè)子通道的連接允許IP 不一致,這些子通道都會(huì)綁定到MPTCP Session(比如通過LTE 和WIFI 各建立一個(gè)子通道),發(fā)送端的數(shù)據(jù)可以選擇其中一條通道進(jìn)行傳輸。MPTCP 可以讓移動(dòng)主機(jī)在多個(gè)連接鏈路間順暢切換,切換過程不斷開連接。對(duì)于移動(dòng)主機(jī)跨基站連接遷移的問題,也可以在原基站與目標(biāo)遷移基站之間各建立一個(gè)連接鏈路/子通道,當(dāng)移動(dòng)主機(jī)從一個(gè)基站遷移到另一個(gè)基站時(shí),只是從一個(gè)鏈路子通道切換到另一個(gè)鏈路子通道,同樣能讓連接鏈路順暢遷移而不斷開連接。MPTCP 跟TFO 技術(shù)類似,需要操作系統(tǒng)及網(wǎng)絡(luò)協(xié)議棧支持,更新和部署阻力較大,目前并不適用。
QUIC 擺脫了TCP 的諸多限制,可以重新設(shè)計(jì)連接標(biāo)識(shí),還記得前面給出的QUIC 數(shù)據(jù)包結(jié)構(gòu)嗎?QUIC 數(shù)據(jù)包結(jié)構(gòu)中有一個(gè)Connection ID 字段專門標(biāo)識(shí)連接,Connection ID 是一個(gè)64位的通用唯一標(biāo)識(shí)UUID (Universally Unique IDentifier)。借助Connection ID,QUIC 的連接不再綁定IP 與 Port 信息,即便因?yàn)榫W(wǎng)絡(luò)遷移或切換導(dǎo)致Source IP 和Source Port 發(fā)生變化,只要Connection ID 不變就仍是同一個(gè)連接,協(xié)議層只需要將控制塊中記錄的Source IP 和Source Port 信息更新即可,不需要像TCP 那樣先斷開連接,這就可以保證連接的順暢遷移或切換,用戶基本不會(huì)感知到連接切換過程。
計(jì)算機(jī)網(wǎng)絡(luò)都處于一個(gè)共享環(huán)境中,可能會(huì)因?yàn)槠渌鳈C(jī)之間的通信使得網(wǎng)絡(luò)擁堵,如果在通信剛開始時(shí)就突然發(fā)送大量數(shù)據(jù),可能會(huì)導(dǎo)致整個(gè)網(wǎng)絡(luò)的擁堵阻塞。TCP為了防止該問題的出現(xiàn),設(shè)計(jì)了擁塞控制機(jī)制來限制數(shù)據(jù)包的發(fā)送帶寬,實(shí)際就是控制發(fā)送窗口的大小。TCP 發(fā)送數(shù)據(jù)的速率受到兩個(gè)因素限制:一個(gè)是目前接收窗口的大小,通過接收端的實(shí)際接收能力來控制發(fā)送速率的機(jī)制稱為流量控制機(jī)制;另一個(gè)是目前擁塞窗口的大小,通過慢啟動(dòng)和擁塞避免算法來控制發(fā)送速率的機(jī)制稱為擁塞控制機(jī)制,TCP 發(fā)送窗口大小被限制為不超過接收窗口和擁塞窗口的較小值。
TCP 通信開始時(shí),會(huì)通過慢啟動(dòng)算法得出的擁塞窗口大小對(duì)發(fā)送數(shù)據(jù)速率進(jìn)行控制,慢啟動(dòng)階段擁塞窗口大小從1 開始按指數(shù)增大(每收到一次確認(rèn)應(yīng)答擁塞窗口值加1,收到一個(gè)窗口大小數(shù)量的確認(rèn)應(yīng)答則擁塞窗口大小翻倍),雖然擁塞窗口增長率較快,但由于初始值較小,增長到慢啟動(dòng)閾值仍然需要花費(fèi)不少時(shí)間。為了防止擁塞窗口后期增長過快,當(dāng)擁塞窗口大小超過慢啟動(dòng)閾值(一般為發(fā)生超時(shí)重傳或重復(fù)確認(rèn)應(yīng)答時(shí),擁塞窗口一半的大?。┖?,就變更為線性增長(每收到一個(gè)窗口大小數(shù)量的確認(rèn)應(yīng)答則擁塞窗口大小增加一個(gè)數(shù)據(jù)段),直到發(fā)生超時(shí)重傳或重復(fù)確認(rèn)應(yīng)答,擁塞窗口向下調(diào)整,擁塞窗口大小變化過程如下圖示:
從上圖可以看出,TCP 發(fā)生超時(shí)重傳時(shí),擁塞窗口直接下調(diào)為 1,并從慢啟動(dòng)階段開始逐漸增大擁塞窗口,當(dāng)超過慢啟動(dòng)閾值后進(jìn)入擁塞避免階段,這個(gè)過程對(duì)網(wǎng)絡(luò)傳輸效率影響較大。TCP 發(fā)生重復(fù)確認(rèn)應(yīng)答而觸發(fā)快速重傳時(shí),判斷網(wǎng)絡(luò)擁堵情況更輕些,因此擁塞窗口下調(diào)為慢啟動(dòng)閾值 + 3個(gè)數(shù)據(jù)段的大小,相當(dāng)于直接跨過慢啟動(dòng)階段進(jìn)入擁塞避免階段,這個(gè)過程對(duì)網(wǎng)絡(luò)傳輸效率影響相對(duì)較小,這種機(jī)制稱為快速恢復(fù)機(jī)制。
現(xiàn)在網(wǎng)絡(luò)帶寬相比TCP協(xié)議剛誕生時(shí)有了明顯的改善,TCP 的擁塞控制算法也成為影響網(wǎng)絡(luò)傳輸效率的一個(gè)瓶頸,如果觸發(fā)超時(shí)重傳的次數(shù)比較多,對(duì)網(wǎng)絡(luò)傳輸效率的影響相當(dāng)大。
TCP 的擁塞控制機(jī)制是被超時(shí)重傳或者快速重傳觸發(fā)的,想要提高網(wǎng)絡(luò)傳輸效率,容易想到兩個(gè)方案:一個(gè)是改進(jìn)擁塞控制算法;另一個(gè)是降低重傳次數(shù)。這里先介紹如何降低重傳次數(shù)/概率?
降低TCP 的重傳概率有兩個(gè)方向:
降低超時(shí)重傳概率:可以通過改善網(wǎng)絡(luò)環(huán)境,提高重發(fā)超時(shí)閾值的計(jì)算準(zhǔn)確度,也就是提高往返時(shí)間RTT 的測量準(zhǔn)確度,來降低超時(shí)重傳概率;
降低丟包重傳概率:可以增加傳輸一定的冗余數(shù)據(jù)比如糾錯(cuò)碼,當(dāng)丟失部分?jǐn)?shù)據(jù)時(shí)可以通過糾錯(cuò)碼恢復(fù)丟失的數(shù)據(jù),降低丟包重傳的概率。
由于TCP 重傳 segment 的 Sequence Number 和原始的 segment 的 Sequence Number 保持不變,當(dāng)發(fā)送端觸發(fā)重傳數(shù)據(jù)包Sequence N后,接收到了該數(shù)據(jù)包,發(fā)送端無法判斷接收到的數(shù)據(jù)包是來自原始請求的響應(yīng),還是來自重傳請求的響應(yīng),這就帶來了TCP 重傳的歧義性,該問題肯定會(huì)影響采樣RTT 測量值的準(zhǔn)確性,進(jìn)而影響重發(fā)超時(shí)閾值計(jì)算的準(zhǔn)確度,可能會(huì)增大數(shù)據(jù)包超時(shí)重傳的概率。
QUIC 采用單向遞增的Packet Number 來標(biāo)識(shí)數(shù)據(jù)包,原始請求的數(shù)據(jù)包與重傳請求的數(shù)據(jù)包編號(hào)并不一樣,自然也就不會(huì)引起重傳的歧義性,采樣RTT 的測量更準(zhǔn)確。除此之外,QUIC 計(jì)算RTT 時(shí)除去了接收端的應(yīng)答延遲時(shí)間,更準(zhǔn)確的反映了網(wǎng)絡(luò)往返時(shí)間,進(jìn)一步提高了RTT 測量的準(zhǔn)確性,降低了數(shù)據(jù)包超時(shí)重傳的概率。
QUIC 引入了前向冗余糾錯(cuò)碼(FEC: Fowrard Error Correcting),如果接收端出現(xiàn)少量(不超過FEC的糾錯(cuò)能力)的丟包或錯(cuò)包,可以借助冗余糾錯(cuò)碼恢復(fù)丟失或損壞的數(shù)據(jù)包,這就不需要再重傳該數(shù)據(jù)包了,降低了丟包重傳概率,自然就減少了擁塞控制機(jī)制的觸發(fā)次數(shù),可以維持較高的網(wǎng)絡(luò)利用效率。
糾錯(cuò)碼的原理比較復(fù)雜,如果想對(duì)糾錯(cuò)碼有更多的了解,可以參考文章:二維碼的秘密,文中簡單介紹了二維碼中的糾錯(cuò)碼是如何實(shí)現(xiàn)信息糾錯(cuò)和補(bǔ)全的。
TCP 的擁塞控制實(shí)際上包含了四個(gè)算法:慢啟動(dòng)、擁塞避免、快速重傳、快速恢復(fù)。現(xiàn)在網(wǎng)絡(luò)環(huán)境改善速度較快,TCP 的慢啟動(dòng)與擁塞避免過程需要的時(shí)間較長,雖然TCP 也在不斷更新改進(jìn)擁塞控制算法,但由于TCP 內(nèi)置于操作系統(tǒng),擁塞控制算法的更新速度太過緩慢,跟不上網(wǎng)絡(luò)環(huán)境改善速度,TCP 落后的擁塞控制算法自然會(huì)降低網(wǎng)絡(luò)利用效率。
QUIC 直接照搬TCP 的擁塞控制算法只是借鑒了TCP 經(jīng)過驗(yàn)證的成熟方案,由于QUIC 是處于應(yīng)用層的,可以隨瀏覽器更新,QUIC 的擁塞控制算法就可以有較快的迭代速度,在TCP 的擁塞控制算法基礎(chǔ)上快速迭代,可以跟上網(wǎng)絡(luò)環(huán)境改善的速度,盡快提高擁塞恢復(fù)的效率。
QUIC 還將擁塞控制算法設(shè)計(jì)為可插拔模塊,可以根據(jù)需要為不同的連接配置不同的擁塞控制算法,這樣可以為每個(gè)連接根據(jù)其網(wǎng)絡(luò)環(huán)境配置最適合的擁塞控制算法(可以根據(jù)大數(shù)據(jù)和人工智能計(jì)算結(jié)果自動(dòng)精準(zhǔn)配置),盡可能讓每個(gè)連接的網(wǎng)絡(luò)帶寬得到最高效的利用。
聯(lián)系客服