• <strike id="fdgpu"><input id="fdgpu"></input></strike>
    <label id="fdgpu"></label>
    <s id="fdgpu"><code id="fdgpu"></code></s>

  • <label id="fdgpu"></label>
  • <span id="fdgpu"><u id="fdgpu"></u></span>

    <s id="fdgpu"><sub id="fdgpu"></sub></s>
    您當前的位置是:  首頁(yè) > 資訊 > 文章精選 >
     首頁(yè) > 資訊 > 文章精選 >

    如何使用開(kāi)源SFU構建RTC云服務(wù)

    2020-07-02 13:36:12   作者:李永興    來(lái)源:LiveVideoStack   評論:0  點(diǎn)擊:


      編者按:本文由百度智能云RTC產(chǎn)品技術(shù)負責人 李永興LiveVideoStack線(xiàn)上分享的內容整理而成,從系統架構角度,分析了常見(jiàn)的開(kāi)源SFU在分布式部署以及高可用、高并發(fā)方面的不足,并提出相應的解決方案。
      大家好,我是來(lái)自百度智能云的李永興,在百度智能云媒體云團隊主要負責RTC產(chǎn)品的研發(fā)工作。
      01、開(kāi)源SFU的現狀與不足
      在研發(fā)RTC產(chǎn)品的過(guò)程中,我們調研了許多優(yōu)秀的開(kāi)源WebRTC服務(wù)器,例如:Janus、MediaSoup、Licode、SRS4等,這些SFU都有不同的設計理念和特點(diǎn),我們從中受益頗多。同時(shí)我們也發(fā)現如果要基于這些優(yōu)秀的開(kāi)源的SFU構建一個(gè)高可用高并發(fā)的RTC云服務(wù),就必須對這些SFU進(jìn)行相應的改造。本次分享會(huì )主要介紹這些“改造部分”,這些改造其實(shí)具備一些普遍性,即針對開(kāi)源SFU普遍存在的問(wèn)題進(jìn)行優(yōu)化和改造,并不局限于某一特定的SFU。
      RTC云服務(wù)的要求
      要想構建一個(gè)RTC云服務(wù),存在以下幾點(diǎn)要求:
    • 高并發(fā):RTC云服務(wù)必須要支持海量并發(fā)用戶(hù),同時(shí)還需要支持海量房間。
    • 高性能:除了單機性能,能抗更多的流次外,還要具備更高的連通率,保證通信的穩定。同時(shí)還要求有很強的抗弱網(wǎng)性能。
    • 高可用:?jiǎn)螜C單節點(diǎn)出現故障時(shí)不影響系統可用性。
    • 彈性伸縮:系統可以很方便的進(jìn)行擴容操作,并且擴容時(shí)盡可能減少相應配置,這樣可以使系統迅速進(jìn)行擴容。
      當前一些開(kāi)源SFU的現狀,例如Janus和MediaSoup,其服務(wù)端都會(huì )開(kāi)UDP的操作范圍,即服務(wù)端用不同的端口服務(wù)不同的客戶(hù)端的媒體連接。同時(shí)在Janus中,信令和媒體是耦合在一起的;而在MediaSoup中,官方提供了nodejs庫,其本身只是一個(gè)媒體層的庫。但同時(shí)官方也提供了一個(gè)Demo,其媒體層和信令也是耦合在一起的;SRS4實(shí)際是國產(chǎn)之光,產(chǎn)品推出的時(shí)間不久,目前只支持WebRTC拉流功能。
      對于這些開(kāi)源SFU,主要的改進(jìn)點(diǎn)有:
    • 使用端的UDP服務(wù)端端口進(jìn)行流媒體的傳輸;
    • 信令和媒體層分離設計,可以支持大規模分布式部署;
    • 關(guān)于級聯(lián)方面,各個(gè)開(kāi)源SFU都沒(méi)有相對完整的解決方案。在我們的系統中,采用路由表方式的級聯(lián),并且是私有協(xié)議的級聯(lián),可以很好的支持和用戶(hù)就近接入。
      當然對于整個(gè)RTC云服務(wù),除了SFU這個(gè)核心功能之外,RTC云服務(wù)還需要支持一些混流、錄制、多協(xié)議網(wǎng)關(guān)支持(例如RTMP的接入:方便微信小程序的接入、SIP的接入)等。
      02、單端口方案
      目前無(wú)論是Janus還是MediaSoup,服務(wù)端都是使用單獨的UDP端口服務(wù)單獨的PeerConnection, SFU在啟動(dòng)時(shí)會(huì )配置一個(gè)可用的UDP的端口范圍,用于客戶(hù)端的數據傳輸。服務(wù)端接收到客戶(hù)端的請求后,會(huì )從配置的端口范圍內為客戶(hù)端分配一個(gè)未被使用的端口,通過(guò)SDP把服務(wù)端的端口傳給客戶(hù)端。客戶(hù)端收到SDP端口并進(jìn)行解析,然后就可以向服務(wù)端發(fā)送或接收數據。這就要求服務(wù)端同時(shí)暴露成千上萬(wàn)個(gè)端口,對于網(wǎng)絡(luò )安全性是很不友好的,同時(shí)可運維性也較差。另外,客戶(hù)端的網(wǎng)絡(luò )可能會(huì )對目的端口進(jìn)行一些限制,如果分配的端口在允許范圍之外,那么客戶(hù)端就連接不到服務(wù)器,導致整個(gè)連通的失敗。
      為了實(shí)現云服務(wù)的高可用、彈性伸縮一般會(huì )配置負載均衡設備作為網(wǎng)絡(luò )的接入設備。在真正生產(chǎn)環(huán)境中,可能一個(gè)IP后面會(huì )掛著(zhù)幾十甚至上百臺機器,當機器宕機時(shí)不會(huì )導致整個(gè)服務(wù)的不可用。常見(jiàn)的負載均衡設備中很少看到有支持UDP PortRange方式的,即使支持了,由于暴露了很多端口,健康檢查方面實(shí)際是不可能完成的任務(wù)。
      鑒于以上問(wèn)題,我們就需要對SFU進(jìn)行相應的改造,以使得服務(wù)端使用單端口對流媒體的數據進(jìn)行傳輸。
      Janus使用了Libnice庫作為底層網(wǎng)絡(luò )傳輸庫,該庫本身是多端口的實(shí)現,因此要在Janus基礎上實(shí)現單端口存在兩種方案:一種是直接替換掉Libnice庫,重新構建底層,改為單端口的傳輸方式。但是由于Janus和Libnice庫的耦合非常緊密,若要使用重新構建底層的方式,實(shí)現較為復雜的,難度很大;另外一種方式就是保留Libnice多端口的實(shí)現,在Janus上增加單端口代理的功能。代理的功能是指將單一的對外端口傳輸的客戶(hù)端的數據,在接收到數據之后,同時(shí)將相應的數據轉發(fā)到Libnice內部分配的不同服務(wù)端的內部端口中。這種方式修改起來(lái)會(huì )更簡(jiǎn)單一些。
      若選擇使用代理方式,其實(shí)現難點(diǎn)在于來(lái)自不同客戶(hù)端的數據都是通過(guò)同一個(gè)服務(wù)端端口進(jìn)行傳輸,服務(wù)端該如何判斷傳輸的數據與用戶(hù)的對應關(guān)系。對此,我們可以通過(guò)SDP協(xié)商里面的ICE-Ufrag字段進(jìn)行解決,當服務(wù)端接收到客戶(hù)端的SDP后,按照之前的流程,會(huì )創(chuàng )建本地服務(wù)的端口,并且將相應的ICE-Ufrag與該端口映射起來(lái)。服務(wù)端會(huì )將對外的IP端口寫(xiě)入SDP傳給客戶(hù)端,然后一直監聽(tīng)對外端口。客戶(hù)端建聯(lián)時(shí)會(huì )發(fā)送Stun包, Stun包中會(huì )帶有ICE-Ufrag,服務(wù)端接收并解析出ICE-Ufrag,再根據之前的映射關(guān)系,從IP-MAPS中找到對應的服務(wù)端端口。同時(shí)服務(wù)端還會(huì )記錄Stun包的來(lái)源客戶(hù)端IP和端口,服務(wù)端就會(huì )將用戶(hù)側的IP和端口與服務(wù)端的IP和端口映射起來(lái)。每次收到客戶(hù)端的數據之后,就可以查看數據源的IP和端口,通過(guò)MAP的映射關(guān)系查到對應的服務(wù)端的端口,將數據轉發(fā)到相應的服務(wù)端端口中。同理,服務(wù)端發(fā)出的數據也會(huì )從映射關(guān)系中找到對應客戶(hù)端的IP和端口,通過(guò)單個(gè)端口發(fā)出。
      通過(guò)這種單端口的方案,我們就可以將SFU部署在負載均衡設備之后,并且可以很方便的進(jìn)行臺線(xiàn)擴容和健康檢查,達到高并發(fā)和高可用的目的。另外,服務(wù)端是有公網(wǎng)地址的,因此WebRTC的ICE、打洞的操作實(shí)際上也就不需要了。在進(jìn)行地址映射時(shí),需要使用客戶(hù)端Stun包的真實(shí)地址。在測試中我們發(fā)現,有時(shí)候真實(shí)地址與客戶(hù)端發(fā)送過(guò)來(lái)的Candidate中的地址不一樣,如果使用Candidate中的地址則會(huì )存在連通失敗的問(wèn)題。
      MediaSoup雖然也是多端口方案,但是并未使用Libnice庫,因此可以直接在底層實(shí)現整套單端口方案,并不需要Porxy的存在。
      這里值得一提的是SRS4,雖然SRS4目前只支持WebRTC的拉流,但是其實(shí)現是基于原生的單端口方案,沒(méi)有使用Libnice庫,整個(gè)MAP的建立過(guò)程與前面所描述的是一致的,也不需要Porxy的存在。SRS4在單端口方面還是相當友好的,可以很簡(jiǎn)單的實(shí)現集群化的分布式部署。
      03、信令分離
      WebRTC標準本身并沒(méi)有規定信令的部分,因此各個(gè)開(kāi)源的SFU基本都是自定義實(shí)現的。Janus實(shí)現了基于HTTP或WebSocket的信令,MediaSoup本身是nodejs的庫,不包含信令部分,但是其官方的Demo也實(shí)現了HTTP或WebSocket的信令。它們的共同點(diǎn)是信令部分的實(shí)現和媒體部分的實(shí)現是集成在一起的。信令一般基于TCP協(xié)議的,媒體一般是基于UDP協(xié)議的。如果它們的實(shí)現集成在一起的話(huà),就需要一個(gè)客戶(hù)端的TCP信令和UDP流媒體數據發(fā)送到服務(wù)端的同一臺機器上。這主要是因為服務(wù)端在收到客戶(hù)端的信令后,會(huì )在本機進(jìn)行一些資源的初始化工作,如果TCP信令和UDP流媒體數據不在同一臺機器上是無(wú)法完成的。
      這樣就存在兩種簡(jiǎn)單的方案,其一:每臺機器都有一個(gè)單獨的公網(wǎng)IP;其二使用源地址哈希的負載均衡。
      如果選擇單獨的公網(wǎng)IP的方案,功能實(shí)現沒(méi)有問(wèn)題,但并不能達到高可用、高并發(fā)的要求。一臺機器對應一個(gè)IP,如果這臺機器上的流特別多,就會(huì )很難負載,無(wú)法進(jìn)行彈性擴容。
      我們的主要目的就是希望同一個(gè)客戶(hù)端的TCP和UDP負載到同一個(gè)服務(wù)器上,而使用源地址哈希的方式,會(huì )出現兩個(gè)問(wèn)題:一個(gè)是負載不均衡的問(wèn)題,如果多個(gè)用戶(hù)共享同一個(gè)網(wǎng)絡(luò )出口的話(huà),會(huì )造成負載的不均衡;另外一個(gè)問(wèn)題是在實(shí)際網(wǎng)絡(luò )過(guò)程中,即使是同一個(gè)客戶(hù)端,它的TCP出口與UDP出口也可能并不相同,這就會(huì )導致客戶(hù)端的整個(gè)連通失敗。
      根據以上分析可知,造成這種問(wèn)題的根本原因是由于SFU同時(shí)提供了信令和媒體服務(wù),我們的解決方案就是將信令從SFU中分離出來(lái),信令分離其實(shí)有兩層意思,其一:是將信令服務(wù)從SFU中分離,SFU作為單純的流媒體處理器使用。其二:是將信令分為兩部分,一部分是與客戶(hù)端交互的信令,另外一部分是信令服務(wù)器與SFU或MeidiaServer之間的內部交互信令。
      將信令服務(wù)分離之后,就可以單獨實(shí)現信令服務(wù)器,為客戶(hù)提供基于TCP的信令服務(wù),包括SDP解析、生成服務(wù)。客戶(hù)端首先要連接到信令服務(wù)器上,進(jìn)行媒體協(xié)商,信令服務(wù)器會(huì )根據一定的策略選擇SFU或MeidiaServer的節點(diǎn)的IP通過(guò)SDP返回給客戶(hù)端,同時(shí)信令服務(wù)器還會(huì )把接收到的客戶(hù)端信息向對應的分配的SFU進(jìn)行廣播。客戶(hù)端接收到SDP之后,根據IP相應的連接到SFU的節點(diǎn),SFU的節點(diǎn)中的所有機器其實(shí)都已經(jīng)具備了客戶(hù)端的信息,這樣客戶(hù)端就可以進(jìn)行正常的推拉流。
      因為采用了信令分離,所以也就不需要依賴(lài)于源地址哈希的負載均衡策略。同一個(gè)客戶(hù)端的多個(gè)PeerConnection可能會(huì )打到后端不同的SFU上,也就達到了比較好的負載均衡的目的。
      信令分離之后,緊接著(zhù)的一個(gè)問(wèn)題就是:信令服務(wù)器與SFU或MeidiaServer之間內部信令如何交互。信令服務(wù)器需要向SFU或MeidiaServer廣播用戶(hù)的信息,SFU需要向信令服務(wù)器上報一些媒體狀態(tài)。這些內部信令的特點(diǎn)就是可以異步處理,不需要等待處理的返回結果,因此就可以使用消息隊列去完成內部信令的交互,消息隊列的引入進(jìn)一步使得信令服務(wù)器與SFU進(jìn)行應用的解耦,二者的部署就更加靈活。信令服務(wù)器可以與SFU進(jìn)行混合部署,也可以進(jìn)行單獨部署。
      信令服務(wù)器除了向客戶(hù)端提供一些信令服務(wù)之外,還會(huì )使用客戶(hù)端真實(shí)的IP通過(guò)http-DNS服務(wù)獲得最佳的SFU節點(diǎn)地址,并返回給客戶(hù)端。這樣就會(huì )使得SFU的調度更加的準確,提供更好的服務(wù)。
      Janus的信令與媒體的耦合較為緊密,因此分離起來(lái)會(huì )稍顯復雜,同樣有兩種方案:一種是基于現有的Videoroom的插件去做修改,另外一種是直接自己實(shí)現一個(gè)SFU插件。兩者的工作量都不算太小,如果自己實(shí)現SFU插件,Janus Core里面的部分也需要進(jìn)行修改。
      對于MediaSoup本身來(lái)說(shuō),它只是一個(gè)nodejs庫,不包含信令部分,只需要實(shí)現一些上層消息隊列的收發(fā)以及內部信令的解析功能即可,需要一個(gè)單獨的信令服務(wù)器與客戶(hù)端提供信令服務(wù)。
      SRS4內部有一個(gè)很簡(jiǎn)單的拉流信令部分,如果想用SRS4實(shí)現WebRTC的拉流功能,信令的分離工作也是需要去做的。
      04、級聯(lián)Relay
      對于級聯(lián)Relay部分的改造,RTC的多方通話(huà)存在跨地域、跨運營(yíng)商的問(wèn)題。為滿(mǎn)足更多用戶(hù)的優(yōu)質(zhì)體驗,需要用戶(hù)就近接入,即通話(huà)多方分布在不同的SFU上。這就需要我們的SFU具備級聯(lián)Relay的能力,將相關(guān)的媒體流轉發(fā)到需要媒體流的SFU上。目前開(kāi)源的Janus和MediaSoup都不具備完備的級聯(lián)能力,都需要進(jìn)行相應的改造。
      級聯(lián)主要涉及兩個(gè)問(wèn)題:其一,網(wǎng)絡(luò )拓撲的問(wèn)題,其二是級聯(lián)協(xié)議的問(wèn)題。
      級聯(lián)網(wǎng)絡(luò )拓撲問(wèn)題中最主要的是級聯(lián)路由選擇的問(wèn)題。傳統的CDN網(wǎng)絡(luò )是樹(shù)形結構,由中心節點(diǎn)和邊緣節點(diǎn)構成,其主要優(yōu)點(diǎn)是回源結構比較簡(jiǎn)單,多級放大,并發(fā)能力較強。其主要缺點(diǎn)是由于中心源棧的存在,多級的回源結構導致延遲較大,不太適合RTC的應用。
      由于網(wǎng)絡(luò )狀況每時(shí)每刻都在發(fā)生變化,所以我們也不能確定RTC的應用最適合哪種結構。因此我們在設計的時(shí)候,最看重的是網(wǎng)絡(luò )的靈活性和自適應性。
      網(wǎng)絡(luò )靈活性是指可以靈活的通過(guò)配置的方式,改變網(wǎng)絡(luò )的拓撲結構,并且可以適應多種網(wǎng)絡(luò )環(huán)境。級聯(lián)可能會(huì )有很復雜的應用場(chǎng)景,例如,Relay可能是在公網(wǎng)做的,也可能是內網(wǎng)做的,也可能是幾點(diǎn)間或內部進(jìn)行級聯(lián)。
      自適應性是指系統可以根據實(shí)時(shí)的網(wǎng)絡(luò )狀況自動(dòng)調整路由選擇。為此,在級聯(lián)中我們引入了路由表的設計,路由表就包括目的地址和下一跳地址。中心控制節點(diǎn)會(huì )將路由表下發(fā)到各個(gè)節點(diǎn)的SFU中,與CDN回源不同,由于RTC中沒(méi)有中心源站上的概念,因此采用的是主動(dòng)轉發(fā)的方式,而不是類(lèi)似CDN拉流回源的方式。中心節點(diǎn)其實(shí)會(huì )保存每條流的節點(diǎn)位置的信息,當某個(gè)節點(diǎn)需要某條流時(shí),中心節點(diǎn)會(huì )向距離最近的并且有這條流的節點(diǎn)轉發(fā)命令,SFU收到轉發(fā)命令之后,會(huì )將路由信息寫(xiě)到轉發(fā)包的頭里面,并根據路由表查詢(xún)下一跳到哪里,進(jìn)行轉發(fā)。下一跳接收到轉發(fā)包之后,重復相應的過(guò)程,直到到達最后的目的地。這種做法的優(yōu)點(diǎn)在于每次轉發(fā)只需要中心節點(diǎn)下發(fā)一次命令即可,后續的轉發(fā)完全由SFU自主完成。
      中心控制節點(diǎn)還具備路由表的自動(dòng)生成能力,如果有新節點(diǎn)上線(xiàn),會(huì )自動(dòng)生成新節點(diǎn)相關(guān)的路由表并下發(fā),這樣就可以保證新節點(diǎn)上線(xiàn)時(shí),自動(dòng)的完成數據流轉的暢通。自適應的原理是節點(diǎn)主動(dòng)對相鄰的節點(diǎn)進(jìn)行延遲和丟包的探測,并將這些探測結果上傳到中心節點(diǎn),中心節點(diǎn)根據這些探測結果對路由表進(jìn)行一些調整、下發(fā),這個(gè)功能目前我們還在處于測試階段。
      級聯(lián)的另外一個(gè)問(wèn)題是協(xié)議的問(wèn)題,級聯(lián)主要是在SFU之間進(jìn)行,我們采用的是通過(guò)私有協(xié)議進(jìn)行級聯(lián)。WebRTC的協(xié)議本身是基于P2P的,因此如果使用WebRTC協(xié)議做SFU之間的級聯(lián)就太重了,很多內容是不需要的。同時(shí)我們會(huì )將一些業(yè)務(wù)信息,例如房間號、用戶(hù)號、路由信息等加到私有協(xié)議中,當接收端收到包之后就不需要再單獨進(jìn)行查詢(xún)操作,同時(shí)也可以自動(dòng)完成路由數據包的轉發(fā)。
      SFU使用單獨的Relay端口進(jìn)行私有協(xié)議和數據的監聽(tīng)和轉發(fā),同時(shí)級聯(lián)的端口也可以開(kāi)放給客戶(hù)端,客戶(hù)端也就可以通過(guò)私有協(xié)議接入RTC系統。由于有一些公網(wǎng)Relay場(chǎng)景的存在,私有協(xié)議里我們還會(huì )加入丟包重傳FEC的功能,以保證公網(wǎng)之下Relay的質(zhì)量。
      Janus有一個(gè)RTP forword的功能,可以將用戶(hù)的媒體流以RTP的方式forword到一個(gè)地址里。如果要基于Janus做級聯(lián),可以基于這個(gè)功能進(jìn)行一些改造,增加級聯(lián)的監聽(tīng)功能,可以實(shí)現整個(gè)媒體流的轉發(fā)。
      05、RTC云架構
      上圖所示是整體的RTC云架構,除了前面講到的流媒體服務(wù)器,還包含其它一些模塊,例如業(yè)務(wù)后臺的模塊Platform,包括Relay、路由表、房間等控制,Platform、信令服務(wù)器、流媒體服務(wù)器之間使用MQ進(jìn)行信令的同步和轉發(fā),另外還有一些混流的服務(wù),將多路視頻流混成一路,推向旁路直播或者存儲,混流服務(wù)器的流媒體轉發(fā)也是通過(guò)Relay的方式進(jìn)行的。除了以上,還有一些多協(xié)議的網(wǎng)關(guān),例如支持RTMP(微信小程序)或SIP(傳統的視頻會(huì )議、終端)的接入。
      【線(xiàn)上分享】移動(dòng)音視頻SDK工程實(shí)踐
      今晚19:30,我們邀請到了百度智能云音視頻SDK產(chǎn)品技術(shù)負責人李明路從音視頻數據角度出發(fā),梳理音視頻SDK的發(fā)展和技術(shù)演進(jìn)。分析數據在常見(jiàn)音視頻模塊上遇到的問(wèn)題與挑戰,并提出相應的解決思路和技術(shù)實(shí)踐。
      掃描下方二維碼或點(diǎn)擊【閱讀原文】預約報名

    【免責聲明】本文僅代表作者本人觀(guān)點(diǎn),與CTI論壇無(wú)關(guān)。CTI論壇對文中陳述、觀(guān)點(diǎn)判斷保持中立,不對所包含內容的準確性、可靠性或完整性提供任何明示或暗示的保證。請讀者僅作參考,并請自行承擔全部責任。

    專(zhuān)題

    CTI論壇會(huì )員企業(yè)

    亚洲精品网站在线观看不卡无广告,国产a不卡片精品免费观看,欧美亚洲一区二区三区在线,国产一区二区三区日韩 富蕴县| 德兴市| 萨嘎县| 台中市| 疏勒县| 蒙城县| 金华市| 黎平县| 巴林右旗| 沁水县| 泉州市| 桃江县| 改则县| 普定县| 碌曲县| 汉中市| 南郑县| 长沙县| 乳山市| 宜黄县| 阿克苏市| 开江县| 林州市| 舟山市| 玛沁县| 云安县| 依兰县| 称多县| 满洲里市| 五华县| 新民市| 广宁县| 海兴县| 菏泽市| 西乡县| 哈巴河县| 西宁市| 宁夏| 麻江县| 射阳县| 进贤县| http://444 http://444 http://444 http://444 http://444 http://444