低延时直播与RTC融合架构设计②:直播与RTC低延时方案
本文整理自網易云信多媒體資深技術架構師吳桐在 QCon 全球軟件開發大會上海站的演講內容《超高清4K視頻低延時直播與RTC融合架構設計》,為該系列的第二篇文章。
回顧該系列第一篇文章《超高清4K視頻低延時直播與RTC融合架構設計①:5G與未來的網絡格局》。
在本篇文章中,吳桐從傳輸協議、擁塞控制算法的選擇說起,分享了網易云信對于BBR算法在低延時直播與RTC場景下的優化實踐,以及網易云信低延時拓撲的設計方案。
?
直播火了,這是近幾年大家最直觀的感受。從2015年開始,各個平臺風起云涌、百家齊放,到2016、2017年,大家開始尋求互動連麥直播的差異化體驗。如今,直播已經進入下半場,低延時直播成為了新的突破口。
相信很多人都看過《瘋狂動物城》,閃電雖然非常可愛,但是誰都不希望直播里的女主播,反應像他這么慢吧。
那么低延時由哪些因素決定呢?
- 傳輸協議
- 擁塞控制算法
- 服務器分發網絡
- 第1公里:分配與選路
- 發送端采集、編碼、前處理延時
- 接收端Jitterbuffer處理延時
- 接收端解碼、后處理、渲染與播放延時
今天由于時間關系,我們主要來探討一下傳輸維度的決定因素。
?
傳輸協議的選擇
首先我們來看看傳輸協議的選擇。
RTMP協議是當前應用最廣泛的直播推拉流協議,標準的RTMP協議傳輸層使用的是TCP,所以它的缺陷也是顯而易見的:
綜上,標準的RTMP不適用于低延時場景。
想必大家對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)作為一種通用協議,對音視頻媒體不友好,沒辦法理解音視頻媒體數據的具體含義,它以一視同仁的角度來對待這些媒體數據。
這兩年還有一個傳輸協議進入大家視野,那就是SRT(Secure Reliable Transport)。它由Haivision 和 Wowza共同創建,并于2017開源。它具備以下特點:
- 安全方面:SRT支持AES加密,保障端到端的視頻傳輸安全;
- 可靠性方面:SRT通過前向糾正技術(FEC)保證傳輸的穩定性;
- 低延遲方面:SRT底層使用UDT協議,UDT協議是一個老牌的基于UDP的可靠傳輸協議,當然原生的UDT傳輸延遲是比較高的,SRT在此基礎上做了不少的擁塞控制策略的相關優化以降低傳輸延時。
SRT協議當前還相對小眾,我們沒有選擇它作為我們的傳輸協議主要原因有兩個:
(1)協議復雜度較高;
(2)丟包場景下速度退避較大。
?
4. 自研低延時傳輸協議
其實無論是QUIC還是SRT,他們的設計有很多共性:
因此我們的選擇是:基于UDP協議,自研低延時傳輸協議,同時應用在低延時直播和RTC場景。
在這里和大家分享我們設計這個協議的主要特征:
其實RTP已經是一個非常優秀的媒體傳輸協議了,我們設計協議的目的是在云信的場景及服務器架構下可以更方便地使用,如果大家沒有特殊的需求,可以直接使用RTP協議,使用RTP Extension來實現其它相對復雜功能。
在談好了協議后,我們進入下一步,就是如何選擇一個擁塞控制算法。
?
擁塞控制算法選擇
擁塞控制算法在音視頻領域一直都是一個熱門話題,而且也是業界一直在不停探索的一個方向。
TCP協議里,從最早的Reno、BIO到現在廣泛使用的Cubic算法,都有非常巧妙的算法和數學原理,由于他們是基于丟包的,所以此類擁塞控制算法對于丟包過于敏感,同時延時不可控,因此無法用于低延時傳輸。
GCC算法是大家普遍使用的一個RTC里的擁塞控制算法,它也是開源WebRTC當前默認使用的,算法是主要基于時延+丟包,核心模塊有三個:
GCC算法這幾年也在不斷的更新迭代,早期帶寬在接收端估計,發送端在媒體包頭上需要攜帶abs-sendtime,接收端采用的是卡爾曼濾波器,估算出帶寬后用REMB協議帶回發送端;后來帶寬估計在發送端來做,發送端在媒體包頭上需要攜帶統一序transport-sequence-number,然后接收端將收包信息,主要包括收包時間等使用transportCC報文帶回發送端,在發送端采用線性濾波器進行相關帶寬估計。
因為GCC算法在業界比較成熟,這里我就不多做介紹,簡單分享一下我們在實踐的過程中發現的幾個問題:
當然這些問題,隨著GCC的持續優化有些會逐漸被優化,但是有些問題卻是在GCC框架下無法解決的。后來,我們關注到了BBR。
BBR(Bottleneck Bandwidth and Round-trip propagation time)是2016年由谷歌提出并推廣的,BBR算法是基于帶寬和延遲反饋的算法。BBR算法有很多優點,我認為其中最核心的三點是:
網易云信從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場景下應用,的確也存在問題:
如何解決這些問題?
- 方法一:BBR V2提出在ProbeBw的0.75x周期一次排空到位;
- 方法二:隨機化6個1x平穩發送周期,縮短排空需要的時間。
(2) 抗丟包能力不足:把非擁塞丟包率補償到ProbeBw的各個周期內,可以有效提升抗丟包能力。
(3) ProbeRTT只發4個包:BBR V2 把probe rtt縮短到2.5s一次,另外使用0.5xBDP發送。
通過上面的優化,我們看一下BBR與GCC的效果對比,第一個場景是帶寬限制300K,一段時間后取消限制,可以發現:
第二個場景是帶寬限制2.5Mbps,200ms Delay,200ms Jitter,可以發現GCC帶寬探測只有300K,BBR帶寬維持在2.5M附近波動。
服務器分發網絡
我們接下來聊聊低延時直播的服務器分發網絡。
傳統CDN的分發網絡一般是一個樹型結構或者是樹型結構的變體,這個結構擴展性很強,可以方便的接納海量用戶。但是這個結構在低延時或者RTC的場景也存在缺陷:
接下來看看網易云信是怎么設計低延時拓撲方案的?
從整體上來看,我們采用的是一個混合架構,也就是Mesh網狀拓撲+樹型拓撲+代理加速的融合架構。
整個拓撲的中心是一個網狀兩兩互聯的核心路由轉發網絡,采用這種拓撲設計中心可以保證中心穩定和高可用,降低中心節點間數據路由的復雜度,同時保證中心數據傳輸的低時延。
而在中心網狀拓撲的外側,我們采用一個2層的樹,來保證邊緣的擴展性,同時保證用戶的最近接入。這個2層的樹根不是固定的,如果當前葉子節點的樹根發生宕機了,它們可以自動接到其它網狀拓撲的節點下,來保證高可用。
而代理節點的存在則是為解決某些特殊場景,比如某些葉子節點沒有小運營商的接入能力的時候,就可以使用這個代理加速節點接入,代理加速節點與葉子節點最大的差異是,對于機器資源的需求不同。代理節點是一個無狀態對業務不可見的純加速節點,是完全根據我們的傳輸協議定制的一個高性能服務器。
我們一般會選擇BGP機房作為Mesh節點,而選擇單線機房作為樹型的葉子節點。因為單線機房的費用往往數倍便宜于BGP機房。所以在選擇用戶接入的節點時,以及選擇用哪些機器構成整個網絡拓撲時,我們既要考慮用戶到節點的接入效果,節點間的網絡情況,也要關注費用,需要做好效果和費用的平衡,產品才能持久。通過這樣一種架構設計,我們既保證了框架的水平擴展,也控制了延時,同時讓拓撲中的機器沒有單點問題。
?
第1公里:分配與選路
所謂的第1公里,就是我們的調度中心如何為客戶端分配接入節點。
首先會采用就近原則、運營商匹配原則和負載均衡原則,為用戶選出理論最佳的多個節點;其中就近原則和運營商匹配原則的規則,會定期由真實客戶端上報的連接情況數據(丟包、時延和卡頓數據)觸發做出優先級調整。
用戶拿到分配列表后,在客戶端本地會開始對各節點做一個快速的測速,選擇出本次的最佳節點,去接入。其它節點會作為Failover時快速接入的選擇。
采用這種策略,我們做到了理論分配、大數據分析與實際測速相結合,并保證了服務器不可用時的,用戶快速連接恢復。
邀請好友使用網易云信,好友下單成功即可獲得500元網易考拉/嚴選無門檻現金券,點擊立即推薦>>
總結
以上是生活随笔為你收集整理的低延时直播与RTC融合架构设计②:直播与RTC低延时方案的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 网易干货 | 浅析视频Jitter Bu
- 下一篇: 网易技术干货 | 云信跨平台C++ SD