小议WebRTC拥塞控制算法:GCC介绍
網(wǎng)絡(luò)擁塞是基于IP協(xié)議的數(shù)據(jù)報(bào)交換網(wǎng)絡(luò)中常見的一種網(wǎng)絡(luò)傳輸問題,它對網(wǎng)絡(luò)傳輸?shù)馁|(zhì)量有嚴(yán)重的影響,網(wǎng)絡(luò)擁塞是導(dǎo)致網(wǎng)絡(luò)吞吐降低,網(wǎng)絡(luò)丟包等的主要原因之一,這些問題使得上層應(yīng)用無法有效的利用網(wǎng)絡(luò)帶寬獲得高質(zhì)量的網(wǎng)絡(luò)傳輸效果。特別是在通信領(lǐng)域,網(wǎng)絡(luò)擁塞導(dǎo)致的丟包,延遲,抖動等問題,嚴(yán)重的影響了通信質(zhì)量,如果不能很好的解決這些問題,一個(gè)通信產(chǎn)品就無法在現(xiàn)實(shí)環(huán)境中正常使用。在這方面WebRTC中的網(wǎng)絡(luò)擁塞控制算法給我們提供了一個(gè)可供參考的實(shí)現(xiàn),本篇文章會盡量詳細(xì)的介紹WebRTC中的擁塞控制算法---GCC的實(shí)現(xiàn)方式。
?
相關(guān)閱讀推薦
《聊聊WebRTC網(wǎng)關(guān)服務(wù)器1:如何選擇服務(wù)端端口方案?》
《聊聊WebRTC網(wǎng)關(guān)服務(wù)器2:如何選擇PeerConnection方案?》
?
WebRTC簡介
WebRTC是一個(gè)Web端的實(shí)時(shí)通信解決方案,它可以做到在不借助外部插件的情況下,在瀏覽器中實(shí)現(xiàn)點(diǎn)對點(diǎn)的實(shí)時(shí)通信。WebRTC已經(jīng)由W3C和IETF標(biāo)準(zhǔn)化,最早推出和支持這項(xiàng)技術(shù)的瀏覽器是Chrome, 其他主流瀏覽器也正在陸續(xù)支持。Chrome中集成的WebRTC代碼已全部開源,同時(shí)Chrome提供了一套LibWebRTC的代碼庫,使得這套RTC架構(gòu)可以移植到其他APP當(dāng)中,提供實(shí)時(shí)通信功能。
GCC算法概述
本文主要介紹的是WebRTC的擁塞控制算法,WebRTC的傳輸層是基于UDP協(xié)議,在此之上,使用的是標(biāo)準(zhǔn)的RTP/RTCP協(xié)議封裝媒體流。RTP/RTCP本身提供很多機(jī)制來保證傳輸?shù)目煽啃?#xff0c;比如RR/SR, NACK,PLI,FIR, FEC,REMB等,同時(shí)WebRTC還擴(kuò)展了RTP/RTCP協(xié)議,來提供一些額外的保障,比如Transport-CCFeedback, RTP Transport-wide-cc extension,RTP abs-sendtime extension等,其中一些后文會詳細(xì)介紹。
GCC算法主要分成兩個(gè)部分,一個(gè)是基于丟包的擁塞控制,一個(gè)是基于延遲的擁塞控制。在早期的實(shí)現(xiàn)當(dāng)中,這兩個(gè)擁塞控制算法分別是在發(fā)送端和接收端實(shí)現(xiàn)的,接收端的擁塞控制算法所計(jì)算出的估計(jì)帶寬,會通過RTCP的remb反饋到發(fā)送端,發(fā)送端綜合兩個(gè)控制算法的結(jié)果得到一個(gè)最終的發(fā)送碼率,并以此碼率發(fā)送數(shù)據(jù)包。下圖便是展現(xiàn)的該種實(shí)現(xiàn)方式:
從圖中可以看到,Loss-Based Controller在發(fā)送端負(fù)責(zé)基于丟包的擁塞控制,它的輸入比較簡單,只需要根據(jù)從接收端反饋的丟包率,就可以做帶寬估算;上圖右側(cè)比較復(fù)雜,做的是基于延遲的帶寬估計(jì),這也是本文后面主要介紹的部分。在最近的WebRTC實(shí)現(xiàn)中,GCC把它的兩種擁塞控制算法都移到了發(fā)送端來實(shí)現(xiàn),但是兩種算法本身并沒有改變,只是在發(fā)送端需要計(jì)算延遲,因而需要一些額外的feedback信息,為此WebRTC擴(kuò)展了RTCP協(xié)議,其中最主要的是增加了Transport-CC Feedback,該包攜帶了接收端接收到的每個(gè)媒體包的到達(dá)時(shí)間。
基于延遲的擁塞控制比較復(fù)雜,WebRTC使用延遲梯度來判斷網(wǎng)絡(luò)的擁塞程度,延遲梯段的概念后文會詳細(xì)介紹;
其算法分為幾個(gè)部分:
在獲得兩個(gè)擁塞控制算法分別結(jié)算到的發(fā)送碼率之后,GCC最終的發(fā)送碼率取的是兩種算法的最小值。下面我們詳細(xì)介紹WebRTC的擁塞控制算法GCC。
?
(一)基于丟包的帶寬估計(jì)
基于丟包的擁塞控制比較簡單,其基本思想是根據(jù)丟包的多少來判斷網(wǎng)絡(luò)的擁塞程度,丟包越多則認(rèn)為網(wǎng)絡(luò)越擁塞,那么我們就要降低發(fā)送速率來緩解網(wǎng)絡(luò)擁塞;如果沒有丟包,這說明網(wǎng)絡(luò)狀況很好,這時(shí)候就可以提高發(fā)送碼率,向上探測是否有更多的帶寬可用。實(shí)現(xiàn)該算法有兩點(diǎn):一是獲得接收端的丟包率,一是確定降低碼率和提升碼率的閾值。
WebRTC通過RTCP協(xié)議的Receive Report反饋包來獲取接收端的丟包率。Receive Report包中有一個(gè)lost fraction字段,包含了接收端的丟包率,如下圖所示。
另外,WebRTC通過以下公式來估算發(fā)送碼率,式中 As(tk)?即為?tk?時(shí)刻的帶寬估計(jì)值,fl(tk)即為?tk?時(shí)刻的丟包率:
簡單來說,當(dāng)丟包率大于10%時(shí)則認(rèn)為網(wǎng)絡(luò)有擁塞,此時(shí)根據(jù)丟包率降低帶寬,丟包率越高帶寬降的越多;當(dāng)丟包率小于2%時(shí),則認(rèn)為網(wǎng)絡(luò)狀況很好,此時(shí)向上提高5%的帶寬以探測是否有更多帶寬可用;2%到10%之間的丟包率,則會保持當(dāng)前碼率不變,這樣可以避免一些網(wǎng)絡(luò)固有的丟包被錯(cuò)判為網(wǎng)絡(luò)擁塞而導(dǎo)致降低碼率,而這部分的丟包則需要通過其他的如NACK或FEC等手段來恢復(fù)。
?
(二)基于延遲梯度的帶寬估計(jì)
WebRTC實(shí)現(xiàn)的基于延遲梯度的帶寬估計(jì)有兩種版本:
? ??
關(guān)于如何根據(jù)延遲梯度推斷當(dāng)前網(wǎng)絡(luò)狀況, 后面會分幾點(diǎn)詳細(xì)展開講, 總體來說分為以下幾個(gè)步驟:
其過程就是,到達(dá)時(shí)間濾波器根據(jù)包間的到達(dá)時(shí)延和發(fā)送間隔,計(jì)算出延遲變化,這里會用到卡爾曼濾波對延遲變化做平滑以消除網(wǎng)絡(luò)噪音帶來的誤差;延遲變化會作為過載檢測器的輸入,由過載檢測器判斷當(dāng)前網(wǎng)絡(luò)的狀態(tài),有三種網(wǎng)絡(luò)狀態(tài)返回overuse/underuse/normal,檢測的依據(jù)是比較延遲變化和一個(gè)閾值,其中該閾值非常關(guān)鍵且是動態(tài)調(diào)整的。最后根據(jù)網(wǎng)絡(luò)狀態(tài)的變化,速率控制器根據(jù)一個(gè)帶寬估計(jì)公式計(jì)算帶寬估計(jì)值。
?
(三)到達(dá)時(shí)間濾波器
前面多次提到WebRTC使用延遲梯度來判斷網(wǎng)絡(luò)擁塞狀況,那什么是延遲梯度,為什么延遲梯度可以作為判斷網(wǎng)絡(luò)擁塞的依據(jù),我們在這里詳細(xì)介紹,首先來看以下,延遲梯度是怎樣計(jì)算出來的:
1.?????延遲梯度的計(jì)算
如上圖所示,用兩個(gè)數(shù)據(jù)包的到達(dá)時(shí)間間隔減去他們的發(fā)送時(shí)間間隔,就可以得到一個(gè)延遲的變化,這里我們稱這個(gè)延遲的變化為單向延遲梯度(one way delay gradient),其公式可記為:
那么為什么延遲梯度可以用來判斷網(wǎng)絡(luò)擁塞的呢,如下面兩圖所示:
左邊這幅圖的場景是理想狀況下的網(wǎng)絡(luò)傳輸,沒有任何擁塞,按我們上面提到的公式(2)來計(jì)算,這種場景下,所計(jì)算到的延遲梯度應(yīng)該為0。而右邊這幅圖的場景則是發(fā)送擁塞時(shí)的狀況,當(dāng)包在t2時(shí)刻到達(dá)時(shí),該報(bào)在網(wǎng)絡(luò)中經(jīng)歷過一次因擁塞導(dǎo)致的排隊(duì),這導(dǎo)致他的到達(dá)時(shí)間比原本要完,此時(shí)計(jì)算出的延遲梯度就為一個(gè)較大的值,通過這個(gè)值,我們就能判斷當(dāng)前網(wǎng)絡(luò)正處在擁塞狀態(tài)。
在WebRTC的具體實(shí)現(xiàn)中,還有一些細(xì)節(jié)來保證延遲梯度計(jì)算的準(zhǔn)確性,總結(jié)如下:
?
2.?????transport-cc-feedback消息
?
具體消息格式如下:
如上圖所示,紅框之前的字段是RTCP包的通用字段,紅框中的字段為transport-cc的具體內(nèi)容,其中前四個(gè)字段分別表示:
在此之后,是兩類信息:多個(gè)packet chunk字段和多個(gè)recv delta字段。其中pcaket chunk具體含義如下:
如下兩圖所示, 表示媒體包到達(dá)狀態(tài)的結(jié)構(gòu)有兩種編碼方式, 其中 T 表示chunk type;0表示RunLength Chunk, 1表示Status Vector Chunk.
1)Run LengthChunk
這種表示方式是用于,當(dāng)我們連續(xù)收到多個(gè)數(shù)據(jù)包,他們都有相同的到達(dá)狀態(tài),就可以用這種編碼方式。其中S表示的是到達(dá)狀態(tài),Run Length表示有多少個(gè)連續(xù)的包屬于這一到達(dá)狀態(tài)。
到達(dá)狀態(tài)有三種:
? ? ?00 Packet not received
? ? ?01 Packet received, small delta?(所謂small detal是指能用一個(gè)字節(jié)表示的數(shù)值)
? ? ?10 Packet received, large ornegative delta?(large即是能用兩個(gè)字節(jié)表示的數(shù)值)
2) Status Vector Chunk
這種表示方式用于每個(gè)數(shù)據(jù)包都需要自己的狀態(tài)表示碼,當(dāng)然還是上面提到的那三種狀態(tài)。但是這里的S就不是上面的意思,這里的S指的是symbol list的編碼方式,s = 0時(shí),表示symbollist的每一個(gè)bit能表示一個(gè)數(shù)據(jù)包的到達(dá)狀態(tài),s = 1時(shí)表示每兩個(gè)bit表示一個(gè)數(shù)據(jù)包的狀態(tài)。
s = 0?時(shí)
? ? ?0 Packet not received
? ? ?1 Packet received , small detal
s = 1?時(shí)
? ? ??同 Run Length Chunk
?
最后,對于每一個(gè)狀態(tài)為Packet received 的數(shù)據(jù)包的延遲依次填入|recv delta|字段,到達(dá)狀態(tài)為1的,recv delta占用一個(gè)字節(jié),到達(dá)狀態(tài)為2的,recv delta占用兩個(gè)字節(jié)可以看出以上編碼的目的是為了盡量減少該數(shù)據(jù)包的大小,因?yàn)槊總€(gè)媒體包都需要反饋他的接受狀態(tài)。
?
(四)過載檢測器
到達(dá)時(shí)間濾波器計(jì)算出每組數(shù)據(jù)包的延遲梯度之后,就要據(jù)此判斷當(dāng)前的網(wǎng)絡(luò)擁塞狀態(tài),通過和某個(gè)閾值的比較,高過某個(gè)閾值就認(rèn)為時(shí)網(wǎng)絡(luò)擁塞,低于某個(gè)閾值就認(rèn)為網(wǎng)路狀態(tài)良好,因此如何確定閾值就至關(guān)重要。這就是過載檢測器的主要工作,它主要有兩部分,一部分是確定閾值的大小,另一部分就是依據(jù)延遲梯度和閾值的判斷,估計(jì)出當(dāng)前的網(wǎng)絡(luò)狀態(tài),一共有三種網(wǎng)絡(luò)狀態(tài):?overuse underuse normal,我們先看網(wǎng)絡(luò)狀態(tài)的判斷。
?
1. ?網(wǎng)絡(luò)狀態(tài)判斷
判斷依據(jù)入下圖所示:
其中表示的是計(jì)算出的延遲梯,表示的是一個(gè)判斷閾值,這個(gè)閾值是自適應(yīng)的, 后面還會介紹他是怎么動態(tài)調(diào)整的,這里先只看如何根據(jù)這兩個(gè)值判斷當(dāng)前網(wǎng)絡(luò)狀態(tài)。
從上圖可以看出,這里的判斷方法是:
這樣計(jì)算的依據(jù)是,網(wǎng)絡(luò)發(fā)生擁塞時(shí),數(shù)據(jù)包會在中間網(wǎng)絡(luò)設(shè)備中排隊(duì)等待轉(zhuǎn)發(fā),這會造成延遲梯度的增長,當(dāng)網(wǎng)絡(luò)流量回落時(shí),網(wǎng)絡(luò)設(shè)備快速消耗(轉(zhuǎn)發(fā))其發(fā)送隊(duì)列中的數(shù)據(jù)包,而后續(xù)的包排隊(duì)時(shí)間更短,這時(shí)延遲梯度減小或?yàn)樨?fù)值。
這里了需要說明的是:
- 在實(shí)際WebRTC的實(shí)現(xiàn)中,雖然每個(gè)數(shù)據(jù)包組(前面提到了如何分組)的到達(dá)都會觸發(fā)這個(gè)探測過程,但是使用的m(ti)這個(gè)值并不是直接使用每組數(shù)據(jù)到來時(shí)的計(jì)算值,而是將這個(gè)值放大了60倍。這么做的目的可能是m(ti)這個(gè)值通常情況下很小,理想網(wǎng)絡(luò)下基本為0,放大該值可以使該算法不會應(yīng)為太靈敏而波動太大。
- 在判斷是否overuse時(shí),不會一旦超過閾值就改變當(dāng)前狀態(tài),而是要滿足延遲梯度大于閾值至少持續(xù)100ms,才會將當(dāng)前網(wǎng)絡(luò)狀態(tài)判斷為overuse。
?
2.? 自適應(yīng)閾值
上節(jié)提到的閾值值,它是判斷當(dāng)前網(wǎng)絡(luò)狀況的依據(jù),所以如何確定它的值也就非常重要了。雖然理想狀況下,網(wǎng)絡(luò)的延遲梯度是0,但是實(shí)際的網(wǎng)絡(luò)中,不同轉(zhuǎn)發(fā)路徑其延遲梯度還是有波動的,波動的大小也是不一樣的,這就導(dǎo)致如果設(shè)置固定的?太大可能無法探測到擁塞,太小又太敏感,導(dǎo)致速率了變化很大。同時(shí),另外一個(gè)問題是,實(shí)驗(yàn)中顯示固定的值會導(dǎo)致在和TCP鏈接的競爭中,自己被餓死的現(xiàn)象(TCP是基于丟包的擁塞控制),因此WebRTC使用了一種自適應(yīng)的閾值調(diào)節(jié)算法,具體如下:
? ? ?(1) 自適應(yīng)算法
上面的公式就是GCC提出的閾值自適應(yīng)算法,其中:
,每組數(shù)據(jù)包會觸發(fā)一次探測,同時(shí)更新一次閾值,這里?的意義就是距上次更新閾值時(shí)的時(shí)間間隔。
是一個(gè)變化率,或者叫增長率,當(dāng)然也有可能是負(fù)增長,增長的基值是:當(dāng)前的延遲梯度和上一個(gè)閾值的差值---
。其具體的取值如下:
從這個(gè)式子中可以看出,當(dāng)延遲梯度減小時(shí),閾值會以一個(gè)更慢的速率減小; 延遲梯度增加時(shí),閾值也會以一個(gè)更慢的速度增加;不過相對而言,閾值的減小速度要小于增加速度。
?
(五)速率控制器
速率控制器主要實(shí)現(xiàn)了一個(gè)狀態(tài)機(jī)的變遷,并根據(jù)當(dāng)前狀態(tài)來計(jì)算當(dāng)前的可用碼率,狀態(tài)機(jī)如下圖所示:
速率控制器根據(jù)過載探測器輸出的信號(overuse underusenormal)驅(qū)動速率控制狀態(tài)機(jī), 從而估算出當(dāng)前的網(wǎng)絡(luò)速率。從上圖可以看出,當(dāng)網(wǎng)絡(luò)擁塞時(shí),會收到overuse信號,狀態(tài)機(jī)進(jìn)入“decrease”狀態(tài),發(fā)送速率降低;當(dāng)網(wǎng)絡(luò)中排隊(duì)的數(shù)據(jù)包被快速釋放時(shí),會受到underuse信號,狀態(tài)機(jī)進(jìn)入“hold”狀態(tài)。網(wǎng)絡(luò)平穩(wěn)時(shí),收到normal信號,狀態(tài)機(jī)進(jìn)入“increase”狀態(tài),開始探測是否可以增加發(fā)送速率。
在Google的paper[3]中,計(jì)算帶寬的公式如下:
其中??= 1.05,?=0.85。從該式中可以看到,當(dāng)需要Increase時(shí),以前一次的估算碼率乘以1.05作為當(dāng)前碼率;當(dāng)需要Decrease時(shí),以當(dāng)前估算的接受端碼率(Rr(ti))乘以0.85作為當(dāng)前碼率;Hold狀態(tài)不改變碼率。
最后,將基于丟包的碼率估計(jì)值和基于延遲的碼率估計(jì)值作比較,其中最小的碼率估價(jià)值將作為最終的發(fā)送碼率。
?
以上便是WebRTC中的擁塞控制算法的主要內(nèi)容,其算法也一直還在演進(jìn)當(dāng)中,每個(gè)版本都有會有一些改進(jìn)加入。其他還有一些主題這里沒有覆蓋到,比如平滑發(fā)送,可以避免突發(fā)流量; padding包等用來探測帶寬的策略。應(yīng)該說WebRTC的這套機(jī)制能覆蓋大部分的網(wǎng)絡(luò)場景,但是從我們測試來看有一些特殊場景,比如抖動或者丟包比較高的情況下,其帶寬利用率還是不夠理想,但總體來說效果還是很不錯(cuò)的。
?
另外,想要獲取更多產(chǎn)品干貨、技術(shù)干貨,記得關(guān)注網(wǎng)易云信博客。
?
總結(jié)
以上是生活随笔為你收集整理的小议WebRTC拥塞控制算法:GCC介绍的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Android短视频中如何实现720P磨
- 下一篇: 视频直播技术:最大限度保障流畅性和清晰度