不管哪類場(chǎng)景,都是要保證可靠性,也就是質(zhì)量,那么在UDP之上怎么實(shí)現(xiàn)可靠呢?答案就是重傳。
重傳模式
IP協(xié)議在設(shè)計(jì)的時(shí)候就不是為了數(shù)據(jù)可靠到達(dá)而設(shè)計(jì)的,所以UDP要保證可靠,就依賴于重傳,這也就是我們通常意義上的RUDP行為,在描述RUDP重傳之前先來了解下RUDP基本框架,如圖:
圖2
RUDP在分為發(fā)送端和接收端,每一種RUDP在設(shè)計(jì)的時(shí)候會(huì)做不一樣的選擇和精簡(jiǎn),概括起來就是圖中的單元。RUDP的重傳是發(fā)送端通過接收端ACK的丟包信息反饋來進(jìn)行數(shù)據(jù)重傳,發(fā)送端會(huì)根據(jù)場(chǎng)景來設(shè)計(jì)自己的重傳方式,重傳方式分為三類:定時(shí)重傳,請(qǐng)求重傳和FEC選擇重傳。
定時(shí)重傳
定時(shí)重傳很好理解,就是發(fā)送端如果在發(fā)出數(shù)據(jù)包(T1)時(shí)刻一個(gè)RTO之后還未收到這個(gè)數(shù)據(jù)包的ACK消息,那么發(fā)送就重傳這個(gè)數(shù)據(jù)包。這種方式依賴于接收端的ACK和RTO,容易產(chǎn)生誤判,主要有兩種情況:
對(duì)方收到了數(shù)據(jù)包,但是ACK發(fā)送途中丟失。
ACK在途中,但是發(fā)送端的時(shí)間已經(jīng)超過了一個(gè)RTO。
所以超時(shí)重傳的方式主要集中在RTO的計(jì)算上,如果你的場(chǎng)景是一個(gè)對(duì)延遲敏感但對(duì)流量成本要求不高的場(chǎng)景,就可以將RTO的計(jì)算設(shè)計(jì)比較小,這樣能盡最大可能保證你的延時(shí)足夠小。例如:實(shí)時(shí)操作類網(wǎng)游、教育領(lǐng)域的書寫同步,是典型的用expense換latency和Quality的場(chǎng)景,適合用于小帶寬低延遲傳輸。如果是大帶寬實(shí)時(shí)傳輸,定時(shí)重傳對(duì)帶寬的消耗是很大的,極端情況會(huì)用20%的重復(fù)重傳率,所以在大帶寬模式下一般會(huì)采用請(qǐng)求重傳模式。
請(qǐng)求重傳
請(qǐng)求重傳就是接收端在發(fā)送ACK的時(shí)候攜帶自己丟失報(bào)文的信息反饋,發(fā)送端接收到ACK信息時(shí)根據(jù)丟包反饋進(jìn)行報(bào)文重傳。如下圖:
圖3
這個(gè)反饋過程最關(guān)鍵的步驟就是回送ACK的時(shí)候應(yīng)該攜帶哪些丟失報(bào)文的信息,因?yàn)閁DP在網(wǎng)絡(luò)傳輸過程中會(huì)亂序會(huì)抖動(dòng),接收端在通信的過程中要評(píng)估網(wǎng)絡(luò)的jitter time,也就是rtt_var(RTT方差值),當(dāng)發(fā)現(xiàn)丟包的時(shí)候記錄一個(gè)時(shí)刻t1,當(dāng)t1 + rtt_var < curr_t(當(dāng)前時(shí)刻),我們就認(rèn)為它丟失了,這個(gè)時(shí)候后續(xù)的ACK就需要攜帶這個(gè)丟包信息并更新丟包時(shí)刻t2,后續(xù)持續(xù)掃描丟包隊(duì)列,如果他t2 + RTO <curr_t,再次在ACK攜帶這個(gè)丟包信息,以此類推,直到收到報(bào)文為止。這種方式是由丟包請(qǐng)求引起的重發(fā),如果網(wǎng)絡(luò)很不好,接收端會(huì)不斷發(fā)起重傳請(qǐng)求,造成發(fā)送端不停的重傳,引起網(wǎng)絡(luò)風(fēng)暴,通信質(zhì)量會(huì)下降,所以我們?cè)诎l(fā)送端設(shè)計(jì)一個(gè)擁塞控制模塊來限流,這個(gè)后面我們重點(diǎn)分析。除了網(wǎng)絡(luò)風(fēng)暴以外,整個(gè)請(qǐng)求重傳機(jī)制也依賴于jitter time和RTO這個(gè)兩個(gè)時(shí)間參數(shù),評(píng)估和調(diào)整這兩個(gè)參數(shù)和對(duì)應(yīng)的傳輸場(chǎng)景也息息相關(guān)。請(qǐng)求重傳這種方式比定時(shí)重傳方式的延遲會(huì)大,一般適合于帶寬較大的傳輸場(chǎng)景,例如:視頻、文件傳輸、數(shù)據(jù)同步等。
FEC選擇重傳
除了定時(shí)重傳和請(qǐng)求重傳模式以外,還有一種方式就是以FEC分組方式選擇重傳,F(xiàn)EC(Forward Error Correction)是一種前向糾錯(cuò)技術(shù),一般是通過XOR類似的算法來實(shí)現(xiàn),也有多層的EC算法和raptor涌泉碼技術(shù),其實(shí)是一個(gè)解方程的過程。應(yīng)用到RUDP上示意圖如下:
圖4
在發(fā)送方發(fā)送報(bào)文的時(shí)候,會(huì)根據(jù)FEC方式把幾個(gè)報(bào)文進(jìn)行FEC分組,通過XOR的方式得到若干個(gè)冗余包,然后一起發(fā)往接收端,如果接收端發(fā)現(xiàn)丟包但能通過FEC分組算法還原,就不向發(fā)送端請(qǐng)求重傳,如果分組內(nèi)包是不能進(jìn)行FEC恢復(fù)的,就請(qǐng)求想發(fā)送端請(qǐng)求原始的數(shù)據(jù)包。FEC分組方式適合解決要求延時(shí)敏感且隨機(jī)丟包的傳輸場(chǎng)景,在一個(gè)帶寬不是很充裕的傳輸條件下,F(xiàn)EC會(huì)增加多余的冗余包,可能會(huì)使得網(wǎng)絡(luò)更加不好。FEC方式不僅可以配合請(qǐng)求重傳模式,也可以配合定時(shí)重傳模式。