陌陌移動端直播P2P技術

直播業務的主要成本就表現在於帶寬上,尤其是在用戶要求日益提高的未來,帶寬帶來的成本問題會越來越大。本文來自陌陌流媒體高級研發工程師白松靈在LiveVideoStack線上分享的演講,詳細剖析如何僅僅藉助傳統CDN技術,不依賴於分片服務器實現簡單有效的P2P技術。

文 / 白松靈

整理 / LiveVideoStack

直播回放:https://www2.tutormeetplus.com/v2/render/playback?mode=playback&token=369633933ec94b36b8102f4e838325e4

大家好,我是來自陌陌的技術工程師白松靈,非常榮幸能與大家一起來了解學習直播P2P技術,我將從以下幾個方面展開今天的分享。

陌陌移動端直播P2P技術

1. 簡要介紹

1.1 傳統直播模式

陌陌移動端直播P2P技術

傳統的直播技術尤其是一些最簡單的直播技術,其主要依賴於主播端推送的RTMP流,或者其他流媒體格式的流數據至CDN進行轉化分發,在觀眾端一般使用HLS、RTMP等各種協議,這是一個常規的直播數據傳輸模式,在該模式下主要的成本消耗都體現在CDN上,主要依賴的也是直播的成本帶寬;我們引入P2P最主要的目的就是節省帶寬。對於一個直播公司來說,大部分的成本消耗都是針對於帶寬,我們今天引入P2P技術,就是為了實現與CDN的解耦合,

與傳統直播模式相同,推流設備將RTMP數據推入CDN,數據流不需要分片也不需要中間其他服務器的轉發,觀眾可拉取http/flv或RTMP數據便可進行分享,觀眾之間進行的是p2p(peer to peer)傳輸;數據從推流設備傳輸到CDN之後,P2P節點也就是每個觀眾都可作為分享端(也可以說是一個Peer節點)的邊緣節點,這一邊緣節點可提供分享數據,從而有效避免流量資源在服務器上的浪費,降低整套服務器的運維成本。

1.2 架構簡介

陌陌移動端直播P2P技術

該方案和原本的一些直播傳輸技術並不相同,其並不依賴於CDN公司提供的P2P技術方案。一般來說P2P+CDN方案會將原本的協議進行轉協議處理,或是將原本的數據進行分片。我們主要是一家業務公司而非雲服務提供商,並不能在CDN上做太多修改,於是我們希望繞過CDN直接在端上或使用其他解決方案來實現P2P傳輸;實現推流及拉流均勻,同時與CDN解耦合。

該方案不與CDN存在必然關係,而只需要CDN支持傳統直播功能。同時推流與拉流均基於RTMP協議,不會對原本協議作出更改;並且這套技術不會給我們的平臺整體帶來太大影響,包括卡頓率、秒開、延遲原本播放質量等;可實現在控制成本的同時儘可能降低複雜度,不會對手機本身性能造成過多負擔,找到實現P2P功能的捷徑。

2. 架構介紹

2.1 服務器架構介紹

陌陌移動端直播P2P技術

假設直播房間裡有1000個觀眾,如果客戶端使用CDN拉流那麼就算1人1MB的帶寬,核算後整體下行帶寬消耗也是個不小的數字;如果使用P2P技術,那麼相當於原本從CDN拉流的A用戶會從B、C等更多用戶那裡獲取數據,達到CDN的功能並使得A用戶不再依賴服務器。

我們把每個接入P2P的觀眾看作是一個Node節點,當用戶進入系統或進入直播間時,用戶端的信息會被上傳至DiscoverService用於Node的註冊、認證、查詢與分類,DiscoverService主要用於用戶的發現、給用戶提供P2P分享表單、對每個節點進行分類等;CentreService則會被用於所有P2P相關自定義信息的交互與統計P2P的狀態等,例如後期對P2P網絡進行分析統計,當然還有轉播功能與未來可能會對一些策略進行分析等;StunService則主要用於對Node提供打洞網絡穿透服務。

接下來我們將詳細介紹StunService,也就是如何實現網絡穿透與打洞。

陌陌移動端直播P2P技術

現在用戶所使用的直播網絡普遍建立在IPV4之上,但這對於絕大多數設備來說是不夠用的,因此我們希望引入StunService。StunService是NAT的UDP的簡單穿越,是一種客戶機-服務器的網絡協議,由RFC 3489 定義。該協議定義了一些消息格式,大體上分為Request/Response。這個協議主要作用是可以在兩個處於NAT路由器之後的主機之間建立UDP通信。它允許位於NAT後的客戶端找出自己的公網地址,確定自己位於的NAT是哪種類型,以及NAT為這個客戶端的本地端口所綁定的對外端口。

一個公有IP可能內部有很多個內網IP一起使用,這就會造成在同樣網絡下的兩段不同網絡,內網之間需要透過一個NAT網絡否則無法直接通信;而每個用戶並不知道自己的外網IP的,所以也無法通過服務器直接暴露公網IP而後客戶端直接連接的方法實現連接,此時就需要在兩個處於NAT路由器之後的主機之間建立UDP通信,也就是打洞機制。

陌陌移動端直播P2P技術

打洞機制的原理很簡單:一個P2P節點A與一個分享節點建立連接並且開始嘗試打洞,打洞時P2PNode A穿過很多層NAT服務訪問StunService,StunService會獲取其一系列的IP接口。同樣分享節點SuperNode B也會訪問服務器並且獲得一系列IP接口,之後二者相互交換IP地址,開始嘗試多種組合的打洞連接。最終確定一個IP和一個端口可以成功建立連接,二者打洞連接成功。

接下來我們需要知道NAT有哪些類型,一般來說NAT分為以下4種:

  • 完整錐型NAT(Full Cone NAT)

內網的ip或者port會映射到一個Nat的端口上,通過發送數據包給NAT上轉換後的ip和端口之後,NAT會自動將數據包送到機器A。NAT 對發送給A的數據包來者不拒,不過濾。

  • 受限錐型NAT(Restricted Cone NAT)

同樣都會映射到一個NAT的端口上,但是隻有當內網Endpoint1曾經發送過報文給外部主機ip才會接受,否則會拒絕。

  • 端口受限型NAT(Port Restricted Cone NAT)

同樣都會映射到一個NAT的端口上,但是隻有當內網Endpoint1曾經發送過報文給外部主機ip和端口才會接受,否則會拒絕。

  • 對稱型NAT(Symmetric NAT)

每次傳輸都會映射新的端口

前面三種 NAT 是可以穿透的,但是,對稱型NAT 無法穿透。

一般來說NAT存在保護機制,假設用戶A在一個NAT下訪問外網的一個端口或一個IP,可以直接向外訪問;而如果從該外部端口訪問內網則會被拒絕。

對於對稱型NAT或者其他打洞不成功的網絡,每一個P2PNode每次都會與多個可分享節點進行連接,由於進行了多組嘗試,加大了打洞的成功率。並且為了確保播放的流暢性只有確保p2p數據通道建立成功並且有正確數據流入才會關閉cdn拉流;除此之外,我們並沒加入TURN服務器,畢竟是服務器做轉發同樣消耗帶寬。

打洞成功之後P2PNode可能會與其他多個分享節點建立連接並分享數據,如何在分享數據的時候保證數據對齊?

為了確保流播放的流暢,目前的解決方案是隻保證一個連接是真正通信的而其他連接都是備用通信;A用戶進行分享,會與B、C、D、E、F等建立連接而只會與B進行長時間的有效通信;當A發現B出現網絡波動或不穩定,則會立刻切換到C或者其他更加高質量的鏈路;同時其他所有連接均保持存在,P2P端口都沒有中斷。

當然,這裡同時建立連接的端口數量不能太多,一般是5~6個,因為如果端口太多則會導致佔用NAT端口太多,也會引發一系列網絡問題。

2.2 客戶端架構簡介

陌陌移動端直播P2P技術

整套系統的重點是客戶端的實現,與CDN完全解耦合。這裡在播放器外部提供了一箇中間層的概念,客戶端以本地代理的方式,將原本的http播放地址提供給本地代理模塊,代理會提供一個轉換後的本地播放地址供播放器播放。其中代理模塊的內部會確定p2p切換,對於播放器本身是不感知的。但這種方案在播放器內部並不安全,內部我們需要安全性更好的分享機制,

在播放器內部,我們會把P2P的分享節點分為以下三類:SuperNode、NormalNode以及P2pNode。P2P傳輸期間會在這三種模式之間不停切換,

  • SuperNode:可分享節點

它會根據當前的網絡狀態,例如客戶端的網絡狀況、播放時間等因素穩定之後,通知狀態切換為可分享態。例如當用戶穩定連接Wi-Fi或長時間處於直播間內,這些數據會被上報至list,也就是CenterService在DiscoverService那裡進行備案已記錄該節點可分享;當有另一個P2P用戶進入直播間需要獲取分享列表時,CenterService會基於SuperNode記錄的這些可分享節點,提供給該用戶一個節點列表。

  • NormalNode:普通節點

目前不能提供分享不過可以向discover請求p2p連接的節點,例如用戶使用上行帶寬資源非常受限的移動網絡,不能作為資源分享節點但可以正常獲取數據。

  • P2PNode:正在利用分享端數據播放的節點

以上三種節點之間可以相互切換,如果可分享節點的網絡狀況穩定,那麼該節點會被提供給多人作為分享端;P2P節點會向discover服務器獲取一個排序後的可分享節點表單,其中包括一些關鍵信息、IP或運營商信息等。;P2P節點會根據詳細的排序列表,同時向這個表單中的多個節點進行連接,數量大約為5個,保證數據的完整。同一時間p2p節點只會與一個分享節點數據傳輸其他節點備用,如果網絡稍微出現異常就會切換其他節點;以往的BT形式的P2P,A用戶可能會向B用戶索取一段切片好的數據,再向C用戶索要一片數據並嘗試拼在一起;如果拼接成功則播放,如果未成功則回源到CDN拉流。在我們的架構中,如果系統發現當前播放器的緩衝已經低於閾值就會切換回cdn拉流,當然這裡會有一定的數據浪費。我們這套方案原本設計就是隻依賴傳統CDN服務器,不會包括分片、轉碼等僅是依賴於CDN或服務器工作。例如切片則主要使用DASH或HLS、邊緣節點進行分片,主要基於現有P2P+CDN解決方案,這裡不再贅述。

陌陌移動端直播P2P技術

P2P拓撲結構非常多,可能採用圓形或環形拓撲結構;但由於P2P是直播,對實時性要求非常高,所以如果還按照原本的那種環形結構則會造成數據的混亂。我們通常採用樹形圖形,但如果用戶太多,在該結構下則會導致用戶延遲變大,當然也不便於管理。

陌陌移動端直播P2P技術

正常來說,CDN不會關注主播提供的RTMP時間戳,因為如果推流中斷則需要重新推流,此時對於CDN來說RTMP時間戳可能會清零;所以RTMP中的時間戳不可靠,對於觀眾端來說則必須要有個依賴,P2P分享必須有對應的時間戳進行數據同步,這裡我們引入了H.264、H.265中的拓展字段sei。


陌陌移動端直播P2P技術

Sei字段並不是一個標準協議內部必須的東西,當NAL Unit Type為5時,其實就是把一個自定義時間戳添加到信息當中;這也是我們的一項缺點,也就是我們必須依賴於推流添加上這個字段,否則就無法實現.

陌陌移動端直播P2P技術

一般來說sei會按順序排列,具體序列如上圖所示。為了確保P2P穩定性,GOP越小越好。這樣就解決了用戶A和B分享,A向B發送一個sei關鍵時間點,B就會給A提供其所想要的數據。這裡並不採用BT的並行方式傳播而是順行方式,實際上sei就是一個順序列表。A會和B連,B無法連接就與C連,C無法連接就與D連,以此類推。

陌陌移動端直播P2P技術

A會確保嘗試儘可能多的連接,如果嘗試所有連接之後依然不成功那麼則會切換到回源,當然這裡我們會盡量避免切換回源CDN,因為質量優劣完全取決於回源,回源多則會造成P2P質量較低。

由於這裡RTMP時間戳不再使用,所以我們會重新計算時間戳。相應的這套時間戳其實就是計算Δt的時間增量,根據增量與常用碼率重新計算Δt給到播放器。sei只在視頻上被使用而在音頻上並沒有,所以時間的間隔其實也是根據視頻的Δt來計算的。數據在本地存儲時會根據Sei中的時間戳對每組Gop進行最多8個gop的數據存儲,每當提供分享時分享端會根據播放端提供的Sei時間戳進行查找如果有則進行分享沒有則關閉連接。

陌陌移動端直播P2P技術

上圖展現了基本傳播方式,首先p2p通過CenterService向DiscoverService獲取可分享列表,打洞成功之後發起訂閱請求,如果訂閱成功才會建立私有信息的傳輸;分享列表判斷Sei是否正確,並決定返回正確數據或者斷開。

3. 分享節點的選擇

選擇分享節點時,CenterService與DiscoverServer交互並上報自身信息 。這些信息包括:

(1)滿足分享節點上報信息:

  • 網絡條件允許(WIFI) 自評之後服務器評價;
  • 在直播間內持續一定時間

(2)不滿足分享節點了註銷信息

  • 退出直播間
  • 網絡情況不允許(數據長時間不夠)

(3)心跳上傳信息

  • 更新自己的信息,測評作為分享節點的能力

上報後與DiscoverServer交互,獲取在線的分享者列表 ,此時用戶使用直播間ID檢索,獲取在線的分享者用戶列表。根據上傳信息打分,以一定排序規則獲取這些信息如運營商信息、帶寬、網絡、CPU、內存、分享次數等;同時返回的用戶列表個數支持可配置,通常在5個左右。

最後,分享節點的排序基於一定邏輯:首先,相同IP排在最優先的位置,接下來同城市運營商排在前,例如成都聯通排在最前面;同城市的不同運營商次之,不同城市的不同運營商排在最後另外,我們會對不同運營商之間進行NAT穿透成功率的對比,同時建立連續打洞失敗使用黑名單,當運營商不同時,我們會根據之前得到的成功率經驗按照優先級來排序。

4. P2P技術融入直播場景

下圖展示的就是P2P技術融入直播場景下某個直播間的分享信息,其中藍色區域代表P2P拉流,綠色區域代表CDN拉流。對比詳細分享率佔比,隨機某個較大的直播間在高峰期的分享率可達到 53.2% (圖中是未使用p2p的佔比),整體的帶寬可以減少40%。

陌陌移動端直播P2P技術

展望未來,我們希望進一步優化節點之間使用UDP傳輸優化帶寬自適應或實現更加細緻的網絡評估,也會引入RTC的一些特性,如提前預測帶寬以保證連接承載的時間更長;同時我們也希望用到更多的拓展協議,在未來拓展協議的更多可能。


分享到:


相關文章: