低延時直播與RTC融合架構設計②:直播與RTC低延時方案

本文整理自網易雲信多媒體資深技術架構師吳桐在 QCon 全球軟件開發大會上海站的演講內容《超高清4K視頻低延時直播與RTC融合架構設計》,爲該系列的第二篇文章。

回顧該系列第一篇文章《超高清4K視頻低延時直播與RTC融合架構設計①:5G與未來的網絡格局》。

在本篇文章中,吳桐從傳輸協議、擁塞控制算法的選擇說起,分享了網易雲信對於BBR算法在低延時直播與RTC場景下的優化實踐,以及網易雲信低延時拓撲的設計方案。

 

直播火了,這是近幾年大家最直觀的感受。從2015年開始,各個平臺風起雲湧、百家齊放,到2016、2017年,大家開始尋求互動連麥直播的差異化體驗。如今,直播已經進入下半場,低延時直播成爲了新的突破口。

相信很多人都看過《瘋狂動物城》,閃電雖然非常可愛,但是誰都不希望直播裏的女主播,反應像他這麼慢吧。

那麼低延時由哪些因素決定呢?

  1. 傳輸維度
  • 傳輸協議
  • 擁塞控制算法
  • 服務器分發網絡
  • 第1公里:分配與選路
  1. 其它維度
  • 發送端採集、編碼、前處理延時
  • 接收端Jitterbuffer處理延時
  • 接收端解碼、後處理、渲染與播放延時

今天由於時間關係,我們主要來探討一下傳輸維度的決定因素。

 

傳輸協議的選擇

首先我們來看看傳輸協議的選擇。

  1. RTMP協議

RTMP協議是當前應用最廣泛的直播推拉流協議,標準的RTMP協議傳輸層使用的是TCP,所以它的缺陷也是顯而易見的:

  1. 抗丟包能力差,丟包時發送窗口直接退避導致發送速率很慢;
  2. 整體延時不可控,主要依賴於接收端的ACK的可靠傳輸;
  3. 擁塞控制優化成本高,TCP算法擁塞控制策略是在操作系統內核層實現的,想要優化的成本很高,一般只有在服務端做內核層面TCP擁塞控制的相關優化,而客戶端只能依賴各平臺的操作系統自己做的擁塞控制優化。

綜上,標準的RTMP不適用於低延時場景。

  1. QUIC協議

想必大家對QUIC(Quick UDP Internet Connection)也不陌生,這兩年隨着大家對Google QUIC協議研究的深入,不少友商和項目開始用RTMP over QUIC替代傳統的RTMP over TCP。

QUIC是一個非常優秀的協議,現在它已經成爲HTTP3的標準協議。它的優勢大家應該也都有所瞭解:

(1)0 RTT連接。QUIC底層使用了UDP,所以它可以非常靈活的重新設計一些協議特性,包括可以在首次以1RTT握手建連後,後續握手重連只需0RTT;

(2)支持HTTP2一樣的多路複用,同時由於使用UDP協議,所以也解決了隊頭阻塞問題;

(3)支持FEC,所以相比於TCP抗丟包能力也有所提升;

(4)因爲是應用層協議,它可以很靈活的改進擁塞控制,各類擁塞控制算法都可以以可插拔的模式在QUIC中使用。

綜上,QUIC很優秀,但是我認爲,QUIC作爲低延時直播協議也有幾點缺陷:(1)本質上是一個可靠協議,我們沒辦法方便的主動控制協議延時

(2)作爲一種通用協議,對音視頻媒體不友好,沒辦法理解音視頻媒體數據的具體含義,它以一視同仁的角度來對待這些媒體數據。

  1. SRT協議

這兩年還有一個傳輸協議進入大家視野,那就是SRT(Secure Reliable Transport)。它由Haivision 和 Wowza共同創建,並於2017開源。它具備以下特點:

  • 安全方面:SRT支持AES加密,保障端到端的視頻傳輸安全;
  • 可靠性方面:SRT通過前向糾正技術(FEC)保證傳輸的穩定性;
  • 低延遲方面:SRT底層使用UDT協議,UDT協議是一個老牌的基於UDP的可靠傳輸協議,當然原生的UDT傳輸延遲是比較高的,SRT在此基礎上做了不少的擁塞控制策略的相關優化以降低傳輸延時。

SRT協議當前還相對小衆,我們沒有選擇它作爲我們的傳輸協議主要原因有兩個:

(1)協議複雜度較高;

(2)丟包場景下速度退避較大。

 

4. 自研低延時傳輸協議

其實無論是QUIC還是SRT,他們的設計有很多共性:

  1. 他們都採用了基於UDP的底層傳輸協議,我認爲這是一個非常正確的方向;
  2. 他們都採用了FEC來提高抗丟包能力;
  3. 他們都重新設計了擁塞算法來實現更準確的帶寬估計、擁塞判斷以降低傳輸延時。

因此我們的選擇是:基於UDP協議,自研低延時傳輸協議,同時應用在低延時直播和RTC場景。

在這裏和大家分享我們設計這個協議的主要特徵:

  1. 協議中支持描述每個包對可靠性以及優先級的不同要求,這樣我們在傳輸的全鏈路上就可以區分不同可靠性和優先級的數據包做差異化處理;
  2. 協議完全面向音視頻媒體,可以方便描述各類音視頻媒體類型,無論是H.264、H.265、VP8、VP9或者是AV1、VVC都可以直接在協議中描述;
  3. 協議支持描述視頻分片信息、視頻時域分層信息及多流信息,這些信息用於服務器做相關分段QoS策略,以及在接收端更方便的完成視頻組包;
  4. 支持傳輸層全局統一序,簡化feedback的處理,同時對丟包計算,抖動計算都非常有意義;
  5. 支持FEC,特別在高RTT的場景下(如:跨國傳輸),FEC的合理使用對於抗擊隨機丟包的意義十分巨大;
  6. 協議包在應用層小於MTU切片,這對於對抗丟包以及中間路由非常有意義;
  7. 支持擴展豐富的媒體信息,無論是時間戳,視頻旋轉角度,音頻音量等等,這些信息我們部分參考了RTP的設計,當然也簡化了RTP的設計;
  8. 協議支持攜帶應用層路由信息,這個對於實現方便的服務器級聯以及邊緣加速很有意義。

其實RTP已經是一個非常優秀的媒體傳輸協議了,我們設計協議的目的是在雲信的場景及服務器架構下可以更方便地使用,如果大家沒有特殊的需求,可以直接使用RTP協議,使用RTP Extension來實現其它相對複雜功能。

在談好了協議後,我們進入下一步,就是如何選擇一個擁塞控制算法。

 

擁塞控制算法選擇

擁塞控制算法在音視頻領域一直都是一個熱門話題,而且也是業界一直在不停探索的一個方向。

  1. TCP擁塞控制算法

TCP協議裏,從最早的Reno、BIO到現在廣泛使用的Cubic算法,都有非常巧妙的算法和數學原理,由於他們是基於丟包的,所以此類擁塞控制算法對於丟包過於敏感,同時延時不可控,因此無法用於低延時傳輸。

  1. GCC

GCC算法是大家普遍使用的一個RTC裏的擁塞控制算法,它也是開源WebRTC當前默認使用的,算法是主要基於時延+丟包,核心模塊有三個:

  1. 到達時間濾波器;
  2. 過載檢查器;
  3. 速率控制器。

GCC算法這幾年也在不斷的更新迭代,早期帶寬在接收端估計,發送端在媒體包頭上需要攜帶abs-sendtime,接收端採用的是卡爾曼濾波器,估算出帶寬後用REMB協議帶回發送端;後來帶寬估計在發送端來做,發送端在媒體包頭上需要攜帶統一序transport-sequence-number,然後接收端將收包信息,主要包括收包時間等使用transportCC報文帶回發送端,在發送端採用線性濾波器進行相關帶寬估計。

因爲GCC算法在業界比較成熟,這裏我就不多做介紹,簡單分享一下我們在實踐的過程中發現的幾個問題:

  1. 帶寬估計不夠準確,特別是低帶寬時會過降;
  2. 與TCP競爭會過度退避;
  3. 在時延抖動場景,帶寬波動大。

當然這些問題,隨着GCC的持續優化有些會逐漸被優化,但是有些問題卻是在GCC框架下無法解決的。後來,我們關注到了BBR。

  1. BBR

BBR(Bottleneck Bandwidth and Round-trip propagation time)是2016年由谷歌提出並推廣的,BBR算法是基於帶寬和延遲反饋的算法。BBR算法有很多優點,我認爲其中最核心的三點是:

  1. 算法思想是儘量不排隊,保持低延遲;
  2. 帶寬估計準確;
  3. 在多數場景下與傳統TCP基於丟包的擁塞控制算法競爭,不喫虧。

網易雲信從2018年開始,在項目中使用BBR,並進行了BBR在低延時領域的相關優化,今天想和大家簡單談談BBR算法在低延時直播與RTC領域的一些使用心得。

 

BBR在低延時直播與RTC場景下的應用

BBR算法的核心就是找到當前鏈路的最大帶寬最小延時。最大帶寬和最小延時的乘積就是BDP, BDP就是網絡鏈路中可以存放數據的最大容量。知道了BDP就可以解決應該發送多少數據的問題,而網絡最大帶寬可以解決用多大速度發送的問題。因此BBR也就是解決了該不該發,以及發多快這兩件事。

我們來看一張很經典的圖,圖片來自BBR作者的分享內容,圖中橫軸是網絡鏈路中的數據量,縱軸分別是RTT和帶寬。可以發現在RTT不變的時候,帶寬一直在上升,因爲這個時候網絡沒有擁塞,而帶寬停止上漲的時候RTT持續變大,一直到發生丟包。因爲這個時候,網絡開始擁塞,報文累積在路由器的buffer中,這樣RTT持續變大,而帶寬不會變大。

圖中紅色虛線框所標識的就是理想情況下最大帶寬和最小延時。很明顯,要找到BDP, 很難在同一時刻找到最小的RTT和最大帶寬。這樣最小RTT和最大帶寬必須分別探測。

探測最大帶寬的方法就是不斷增加發送的數據量,把網絡中的buffer佔滿,直到帶寬在一段時間內不會增加,這樣可以得到此時的最大帶寬。

探測最小RTT的方法就是儘量把buffer排空,讓數據傳輸延時儘量低。

BBR的狀態機分爲4個階段,Startup,Drain,ProbeBW, ProbeRTT。

  • Startup

Startup類似於普通擁塞控制裏的慢啓動,增益係數是 2/ln2 = 2.88,每一個來回都以這個係數增大發包速率,估測到帶寬滿了就進入 Drain狀態,連續三個來回,測得的最大帶寬沒有比上一輪增大25%以上,進入Drain狀態機。

  • Drain

進入 Drain狀態,增益係數ln2/2小於 0.3,也就降速了。一個包來回,把 Startup狀態中超發的數據排空,怎樣纔算隊列排空了?發出去還沒有 ACK 的數據包量即爲 inflight,inflight < BDP 說明排空了,如果 inflght > BDP 說明還不能到下一個狀態,繼續保持 Drain狀態。

  • ProbeBW

ProbeBW是穩定狀態,這時已經測出來一個最大瓶頸帶寬,而且儘量不會產生排隊。之後的每個來回,在 ProbeBW狀態循環(除非要進入下面提到的 ProbeRTT狀態),輪詢下面這些增益係數,[1.25, 0.75, 1, 1, 1, 1, 1, 1],如此,最大瓶頸帶寬就會在其停止增長的地方上下徘徊。98%的時間都應該處於 ProbeBW狀態。

  • ProbeRTT

前面三種狀態,都可能進入 ProbeRTT狀態。超過十秒沒有估測到更小的 RTT 值,這時進入 ProbeRTT狀態,把發包量降低,空出道路來比較準確得測一個 RTT 值,至少 200ms 或一個包的來回之後退出這個狀態。檢查帶寬是否是滿的,進入不同的狀態:如果不滿,進入 Startup狀態,如果滿,進入 ProbeBW狀態。

BBR有很多優點,但是在低延時直播與RTC場景下應用,的確也存在問題:

  1. 收斂速度慢;
  2. 抗丟包能力不足,原版算法超過20%丟包,帶寬斷崖式下降;
  3. ProbeRTT只發4個包,不適合低延時流媒體應用。

如何解決這些問題?

  1. 收斂速度慢
  • 方法一:BBR V2提出在ProbeBw的0.75x週期一次排空到位;
  • 方法二:隨機化6個1x平穩發送週期,縮短排空需要的時間。

(2) 抗丟包能力不足:把非擁塞丟包率補償到ProbeBw的各個週期內,可以有效提升抗丟包能力。

(3) ProbeRTT只發4個包:BBR V2 把probe rtt縮短到2.5s一次,另外使用0.5xBDP發送。

通過上面的優化,我們看一下BBR與GCC的效果對比,第一個場景是帶寬限制300K,一段時間後取消限制,可以發現:

  1. BBR比GCC的帶寬估計更加準確(GCC:250K, BBR:300K);
  2. 帶寬限制取消後,GCC需要20s以上回復到最大帶寬,BBR僅需要2s恢復帶最大帶寬。

第二個場景是帶寬限制2.5Mbps,200ms Delay,200ms Jitter,可以發現GCC帶寬探測只有300K,BBR帶寬維持在2.5M附近波動。

服務器分發網絡

我們接下來聊聊低延時直播的服務器分發網絡。

傳統CDN的分發網絡一般是一個樹型結構或者是樹型結構的變體,這個結構擴展性很強,可以方便的接納海量用戶。但是這個結構在低延時或者RTC的場景也存在缺陷:

  1. 在上行數據的用戶越來越多後,頂層節點容易成爲系統的瓶頸和單點;
  2. 樹的深度越大,媒體數據的端到端延遲就會越大,所以基於傳統CDN的直播延遲至少在3~4秒以上。

接下來看看網易雲信是怎麼設計低延時拓撲方案的?

從整體上來看,我們採用的是一個混合架構,也就是Mesh網狀拓撲+樹型拓撲+代理加速的融合架構。

整個拓撲的中心是一個網狀兩兩互聯的核心路由轉發網絡,採用這種拓撲設計中心可以保證中心穩定和高可用,降低中心節點間數據路由的複雜度,同時保證中心數據傳輸的低時延。

而在中心網狀拓撲的外側,我們採用一個2層的樹,來保證邊緣的擴展性,同時保證用戶的最近接入。這個2層的樹根不是固定的,如果當前葉子節點的樹根發生宕機了,它們可以自動接到其它網狀拓撲的節點下,來保證高可用。

而代理節點的存在則是爲解決某些特殊場景,比如某些葉子節點沒有小運營商的接入能力的時候,就可以使用這個代理加速節點接入,代理加速節點與葉子節點最大的差異是,對於機器資源的需求不同。代理節點是一個無狀態對業務不可見的純加速節點,是完全根據我們的傳輸協議定製的一個高性能服務器。

我們一般會選擇BGP機房作爲Mesh節點,而選擇單線機房作爲樹型的葉子節點。因爲單線機房的費用往往數倍便宜於BGP機房。所以在選擇用戶接入的節點時,以及選擇用哪些機器構成整個網絡拓撲時,我們既要考慮用戶到節點的接入效果,節點間的網絡情況,也要關注費用,需要做好效果和費用的平衡,產品才能持久。通過這樣一種架構設計,我們既保證了框架的水平擴展,也控制了延時,同時讓拓撲中的機器沒有單點問題。

 

第1公里:分配與選路

所謂的第1公里,就是我們的調度中心如何爲客戶端分配接入節點。

首先會採用就近原則、運營商匹配原則和負載均衡原則,爲用戶選出理論最佳的多個節點;其中就近原則和運營商匹配原則的規則,會定期由真實客戶端上報的連接情況數據(丟包、時延和卡頓數據)觸發做出優先級調整。

用戶拿到分配列表後,在客戶端本地會開始對各節點做一個快速的測速,選擇出本次的最佳節點,去接入。其它節點會作爲Failover時快速接入的選擇。

採用這種策略,我們做到了理論分配、大數據分析與實際測速相結合,並保證了服務器不可用時的,用戶快速連接恢復。

邀請好友使用網易雲信,好友下單成功即可獲得500元網易考拉/嚴選無門檻現金券,點擊立即推薦>>

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章