文 / Boris Grozev
譯 / 元寶
審校 / 劉連響
原文
https://webrtchacks.com/sfu-cascading/ 部署WebRTC媒體伺服器有兩個主要挑戰,一個是擴充到多個伺服器,另一個是優化會議中所有使用者的媒體延遲。雖然像“将會議X中的所有使用者發送到伺服器Y”這樣的簡單分片方法很容易橫向擴充,但就媒體延遲而言,它們遠不是最佳的,而媒體延遲是使用者體驗的關鍵因素。将會議分發到位于使用者附近并在可靠骨幹網上互相連接配接的伺服器,可以同時解決這兩個問題。來自Jitsi團隊的Boris Grozev深入描述了級聯SFU問題,并展示了他們的方法以及他們遇到的一些挑戰。
“老鼠的神經元”,圖檔來自NIHD(CC-BY-2.0)
實時通信應用程式對吞吐量、延遲和丢包等網絡條件非常敏感。較低的比特率會導緻較低的視訊品質,更長的網絡延時會導緻端到端的音視訊延遲, 資料丢包會引起音頻的不連貫以及視訊的卡頓。
是以,在會議中選擇端點之間的最佳路徑非常重要。當隻有兩個參與者時,這就比較簡單了——WebRTC使用ICE協定在兩個端點之間建立連接配接以交換多媒體。如果可能,兩個端點直接連接配接,否則在不太典型的情況下使用TURN中繼伺服器。WebRTC支援解析域名以擷取TURN伺服器位址,這使得可以輕松地選擇基于DNS的本地TURN伺服器,例如使用AWS Route53的路由選項。
但是,當一個會議有更多的參與者通過中央媒體伺服器路由時,情況就複雜得多。許多WebRTC服務,如Hangouts,seem.in,Slack和我們自己的meet.jit.si,使用選擇性轉發單元(SFU)來更有效地在3個或更多參與者之間傳遞音頻和視訊。
星形拓撲問題
在這種情況下,所有端點都連接配接到一個中央伺服器(采用星形拓撲結構),與之交換多媒體。很明顯,選擇伺服器的位置會對使用者體驗産生巨大影響——如果會議中的所有參與者都位于美國,這時候使用一台在悉尼的伺服器就不是一個好的主意。
大多數服務使用一種在很多時候都能很好地運作的簡單方法——它們選擇靠近會議中第一個參與者的伺服器。但是,在某些情況下,這并不是最優的。例如,假設我們有三個參與者,如上圖所示,其中兩個位于美國東海岸,第三個是在澳洲。如果澳洲參與者(來電者C)首先加入會議,則此算法選擇澳洲的伺服器(伺服器2),但美國的伺服器1是更好的選擇,因為它更接近大多數參與者。
諸如此類的場景并不常見,但确實會發生。假設參與者加入的順序是随機的,這種情況發生在有3名參與者的會議中,其中一個是在一個偏遠的位置。
另一種更常發生的情況如下圖所示:我們在兩個地點有兩組參與者。在這種情況下,加入的順序無關緊要,我們将始終擁有一些彼此接近的使用者,但他們的媒體必須通過遠端位置的伺服器。例如,在下圖中,有2名澳洲來電者(C&D)和2名美國來電者(A&B)。
切換到伺服器1對于呼叫者C和D來說不是最佳的選擇。對于呼叫者A和B,伺服器2不是最佳的選擇。無論我們使用伺服器1還是伺服器2,都會有一些參與者通過非最佳遠端伺服器連接配接。
如果我們不限于使用一台伺服器呢?我們可以讓每個參與者都連接配接到本地伺服器,我們隻需要互連伺服器。
解決方案:級聯
稍後再說我們如何實際互連伺服器的問題,讓我們首先看看它對會議的影響。
從C到D的SFU連接配接沒有改變——仍然通過伺服器2。對于A和B之間的連接配接,我們使用伺服器1而不是伺服器2,如上圖所示,這顯然更好。有趣的部分實際上是從A到C(或任何其他效果類似的連接配接)的連接配接。我們使用A <=>伺服器1 <=>伺服器2 <=> C而不是使用A <=>伺服器2 <=> C.
非直連傳輸時間影響
像這樣連接配接SFU網橋既有優點也有缺點。一方面,我們的研究結果表明,在這種情況下當我們添加額外的跳數時,端到端往返時間會更高。另一方面,減少從用戶端到它連接配接的第一個伺服器的往返時間本身就具有優勢,因為我們可以在逐跳基礎上以更低的延遲執行流修複。
這是如何運作的?WebRTC使用RTP(通常通過UDP)傳輸媒體。這意味着運輸不可靠。當UDP資料包在網絡中丢失時,由應用程式決定是忽略/隐藏丢失,還是使用RTCP NACK資料包請求重傳。例如,應用程式可能選擇忽略丢失的音頻資料包,并請求一些但不是全部視訊資料包的重傳(取決于它們是否需要解碼後續幀)。
使用單個伺服器的RTP資料包重新傳輸
使用級聯橋接器,這些重傳可以限于本地伺服器。例如,在A-S1-S2-C路徑中,如果包在A和S1之間丢失,則S1将通知并請求重傳。如果在S2和C之間丢失資料包,C将請求重傳,S2将從其高速緩存中響應。如果兩個伺服器之間丢失資料包,則接收伺服器可以請求重傳。
使用兩台伺服器進行RTP資料包重傳。請注意,伺服器2不會重新傳輸資料包2,因為NACK在資料包發送後很快就會到達。
用戶端使用抖動緩沖器來延遲視訊的播放,以便允許延遲或重傳的資料包到達。此緩沖區的大小部分基于往返時間動态變化。當逐跳執行重傳時,延遲較低,是以抖動緩沖區可以更短,進而降低整體延遲。
簡而言之,盡管使用額外的伺服器,端到端往返時間會更高,但可以使得端到端媒體延遲降低(但我們還沒有在實踐中探索這種影響)。
實作級聯SFU
那麼我們如何在Jitsi Meet中實作它,以及如何在meet.jit.si上部署它?
信号與媒體
讓我們先看看信号。從一開始,Jitsi Meet就将信令伺服器(現在是Jicofo)和媒體伺服器/ SFU(jitsi-videobridge)的概念分開。這種分離允許我們相對容易地實作對級聯橋的支援。首先,我們可以将所有信号邏輯保持在一個中心位置——Jicofo。其次,我們已經擁有了Jicofo和Jitsi Videobridge(COLIBRI)之間的信令協定。我們隻需要為它添加一個小擴充。我們已經支援連接配接到一個信令伺服器的多個SFU(用于負載平衡)。現在我們必須為一個SFU添加選項以連接配接到多個信令伺服器。
我們最終得到了兩個獨立的伺服器池——一個jicofo執行個體池和一個jitsi-videobridge執行個體池。下圖說明了部分内容。
AWS上的Jitsi Meet Setup示例允許跨不同資料中心進行橋接級聯
我們系統的第二部分是橋到橋通信。我們希望保持這部分盡可能簡單,是以我們決定不在橋之間做任何明确的信号傳遞。所有信令都發生在jicofo和jitsi-videobridge之間,兩個網橋之間的連接配接僅用于來自用戶端的音頻/視訊和資料信道消息。
Octo協定
為了協調這種通信,我們提出了Octo協定,它将RTP資料包封裝在一個簡單的固定長度報頭中,并允許傳輸字元串消息。在目前的實作中,橋接器以全網狀連接配接到彼此,但是該設計也允許其他拓撲。例如,使用中央中繼伺服器(橋的星形)或為每個橋使用樹結構。
腳注:請注意,不是預先添加Octo标頭,而是可以将其添加為RTP标頭擴充,使網橋之間的流成為純RTP。未來版本的Octo可能會使用這種方法
第二個腳注:Octo并不真正代表什麼。我們最初計劃使用中央繼電器,出于某種原因,它讓我們想起了一隻章魚,是以我們為這個項目保留了這個名字。
Octo标題格式
在Jitsi Videobridge術語中,當橋接器是多橋會議的一部分時,它有一個額外的Octo通道(實際上是一個音頻通道和一個視訊通道)。該通道負責将媒體轉發到所有其他網橋,以及接收來自所有其他網橋的媒體。每個網橋綁定到Octo的單個端口(預設為4096),這就是為什麼我們需要會議ID字段能夠同時處理多個會議。
目前,該協定沒有自己的安全機制,我們将這個責任委托給更低的層。這是我們希望接下來要做的事情,但目前橋梁需要在一個安全的網絡中(我們使用單獨的AWS VPC)。
與Simulcast一起使用
Jitsi Meet的一個顯着特征是支援 simulcast ,其中每個參與者發送多個不同比特率的流,并且橋幫助選擇所需的比特。我們希望確定它繼續穩健地工作,是以我們轉發橋之間的所有聯播流。這允許在流之間更快地切換(因為本地橋不必請求新流)。但是,它在橋到橋流量方面并不是最優的,因為有些流通常不會被使用,隻是消耗額外的帶寬而沒有任何好處。
活躍發言人選擇
我們還希望繼續支援會議中的活躍發言人。事實證明這很簡單——我們隻是讓每個橋接器獨立地進行主導說話人識别,并通知其本地用戶端(這也是其他人使用過的方法)。這意味着計算需要多次完成,但它并不昂貴,并且允許我們簡化事情(例如,我們不必決定哪個橋接DSI,并且擔心路由消息)。
橋的選擇
通過目前的實作,橋的選擇算法很簡單。當新參與者加入時,Jicofo需要決定配置設定給它的橋。它是基于用戶端的區域以及可用橋梁的區域和負載來實作的。如果在與用戶端相同的區域中存在可用的橋,則使用它。否則,使用現有的一個會議橋。
有關設定Octo的文檔,請參見此處(
https://github.com/jitsi/jitsi-videobridge/blob/master/doc/octo.md)。
部署級聯SFU
我們現在已經在meet.jit.si上啟用了地理橋級聯,如上所述。
對于此部署,我們在Amazon AWS中運作所有計算機。我們在六個地區擁有伺服器(信令和媒體):
▪ us-east-1(弗吉尼亞北部),
▪ us-west-2(俄勒岡州),
▪ eu-west-1(愛爾蘭),
▪ eu-central-1(法蘭克福),
▪ ap-se-1(新加坡),
▪ ap-se-2(悉尼)。
我們使用一層 地理定位的HAProxy執行個體 來幫助确定用戶端來自哪個區域。meet.jit.si域由Route53管理并解析為HAProxy執行個體,該執行個體将其自己的區域添加到它轉發的請求的HTTP頭。然後這個頭用于設定變量 config.deploymentInfo.userRegion的值,這個值通過/config.js檔案提供給用戶端 。
對于診斷和示範此功能,meet.jit.si上的使用者界面顯示了正在使用的橋數以及每個參與者連接配接的位置。本地縮略圖的左上角部分滾動顯示伺服器數量以及所連接配接伺服器的區域。滾動遠端縮略圖會顯示遠端參與者所連接配接的伺服器區域,以及浏覽器與他們之間的端到端往返時間(如E2E RTT)。
您可以通過檢查Jitsi Meet中每個人的連接配接位置來檢視是否正在使用橋接級聯。
結論
我們最初是在8月份,在meet.jit.si上推出了Octo作為A / B測試。初步結果看起來不錯,現在每個人都可以使用。我們需要處理大量資料,我們計劃詳細了解Octo的執行情況并撰寫更多相關資訊。我們還計劃将這項工作作為支援大型會議的第一步(單個SFU是不夠的)。是以在接下來的幾個月裡,請繼續關注這方面的更多内容。
————————————————
版權聲明:本文為CSDN部落客「LiveVideoStack_」的原創文章,遵循CC 4.0 BY-SA版權協定,轉載請附上原文出處連結及本聲明。
原文連結:
https://blog.csdn.net/vn9PLgZvnPs1522s82g/article/details/84669933「視訊雲技術」你最值得關注的音視訊技術公衆号,每周推送來自阿裡雲一線的實踐技術文章,在這裡與音視訊領域一流工程師交流切磋。