P2P技術如何將實時視頻直播帶寬降低75%? 頂 轉

本文內容來自學霸君資深架構師袁榮喜的技術分享。

1、前言

實時視頻直播經過去年的千播大戰後已經成爲互聯網應用的標配技術,但直播平臺的成本卻一直居高不下,各個平臺除了挖主播、挖網紅以外,其背後高額的帶寬費用也是他們最大的一塊成本。

現階段直播技術在傳輸方面分爲兩塊:

CDN :負責流媒體的分發傳輸;
連麥系統:負責解決同時多個主播間互動的實時通信傳輸問題。

我們始終認爲基於 CDN+ 連麥系統的直播技術是一個高成本高消耗的技術,從各大直播平臺紛紛虧損來看就驗證了這一點。除了帶寬成本,延遲問題也是現在直播技術的一個硬傷。我們很早就意識到現在這種傳統的直播技術是無法大規模進行在線教育互動直播的,所以學霸君從 2016 年下半年就開始研發基於 UDP 和 P2P 技術的互動直播系統。

整個系統的設計目標是:

端到端延遲控制在秒級範圍之內;
在不影響視頻質量的情況下盡力節省分發帶寬。

基於 P2P 技術的整個分發架構在一個 10W+ 直播平臺上進行了 9 個月的測試和調優,初步達成了設計目標。

那整個系統是怎麼設計的?使用了哪些技術來達成目標?接下來我來重點分享一下架構設計和技術細節。

(本文同步發佈於:http://www.52im.net/thread-1289-1-1.html

2、分享者介紹

 

 

 

 

袁榮喜:學霸君資深架構師,2015年加入學霸君,負責學霸君的網絡實時傳輸和分佈式系統的架構設計和實現,專注於基礎技術領域,在網絡傳輸、數據庫內核、分佈式系統和併發編程方面有一定了解。

3、基於P2P的實時視頻直播分發網絡架構

3.1 基本架構

傳輸分發網絡中我們把連麥系統和分發系統合二爲一,將分佈式推流與邊緣節點分發作爲一套傳輸體系,通過服務之間的 P2P 通信和路由選擇來實現連麥的最小時延。

架構如下圖:

 

 

 

 

整個傳輸分發網絡分爲三部分:

推流部分;

服務之間 P2P;

客戶節點 P2P。

這個傳輸網絡有一個系統錨點:假定推流者 speaker 推到 Edge server 上是不會發生丟包和延遲的,Edge server 會通過服務間 P2P 快速將收到的流數據分發到其他的 Edge server,而且在這個過程也不會發生延遲和丟包。

爲什麼需要這樣一個錨點?因爲在客戶節點的 P2P 網絡需要保證流暢性和最小延遲,也就是要求所有的 Edge server 在最短時間週期內擁有完整的數據,至於爲什麼要這樣,後面我們在流補償環節重點介紹。

我將通過整個流數據傳輸過程來解析具體的技術細節,但在這之前首先要解決的就是媒體數據分片問題,所有的傳輸過程會基於分片 (segment) 來設計。

3.2 媒體數據分片

媒體數據分片是整個分發傳輸系統中最爲基礎的部分,我們在設計分片時主要考慮的是時延和消耗的問題,分片如果太大,傳輸的時延就會越高,例如 HLS;如果分片太細,網絡中回饋報文就會很多,對 P2P 網絡來說額外的消耗也是個問題。

最後我們借鑑了 RTP 和 FLV 中的經驗,採用按幀來做數據分片,這樣做有以下幾個好處:

按幀分片延遲粒度小,可以在幀傳輸進行延時優化;

實現簡單,與編解碼器編碼原則一致;

組合靈活,可以實現播放 buffer 無縫結合。

每一個分片稱作爲 segment,用一個自增長的 32 位 ID 來表示唯一性,傳輸過程都是以這個 ID 爲標示來確定數據的完整性。

3.3 推流與連麥

確定好了媒體分片就可以進行推流了,我們把推流和分發的路徑合二爲一,上麥者是將流數據 segment 推送到離自己最近的 Edge server 上,而不是推送到專門的連麥系統上。我們推流傳輸使用的是 RUDP 傳輸算法,這個 RUDP 是採用了類似 BBR 基於延遲和丟包來設計的擁塞算法,並且對報文做了擁塞丟棄。

示意圖如下:

 

 

 

 

關於 RUDP 的細節可以參考我的另一篇文章《怎麼讓不可靠的UDP可靠?》。至於爲什麼不採用 RTP 或者 RTMP/TCP 來推流,因爲 RTP 雖然是基於 UDP 的,但需要通過 RTCP 和 NACK 來保證可靠性,需要設計擁塞算法,也需要對 RTP 進行改造擴展,而且還受 RTP 協議本身的限制,所以我們並沒有直接採用 RTP。使用 RTMP/TCP 來設計是很簡單的,但在弱網環境延遲很大,而且容易引起重連,所以在設計之初也否定了。

3.4 Server 間的 P2P

因爲整個傳輸分發網絡是分佈式的,由多個 Edge server 組成,所以基於系統錨點,媒體數據分片到 Edge server 上必須儘快分發到其他 Edge server 上。最早我們是統一用 BGP server 來中轉,這樣耗費的 BGP 帶寬很多,而且 BGP server 一旦異常,整個 Edge server 之間的通信就中斷了。

其實大部分時間跨運營商的 Edge server 之間延遲也沒有想象的那麼大,這可以考慮使用 Edge server 之間點對點通信來解決問題,所以我們設計了一個基於 RUDP 無窗口多路徑的傳輸模型來進行 Edge server 之間的通信,如下圖:

 

 

 

 

上圖的通信模型是一個多路徑並聯通信模型,我們在 RUDP 發送前添加了一個路徑路由表,這個路由表記錄了各個路徑的分發概率,RUDP 每次向接收端發送包時會通過路由表中的概率來選取路徑。那麼確定路由表概率就是一個非常重要的事情。我們通過 RUDP 實時 ACK 反饋和路徑實時 ping 探測來得到網絡的狀態 (丟包、延遲、抖動),再將網絡狀態參數輸入到逼近函數 f(x) 來確定各條路由的概率,這裏有條原則:如果 Edge server 之間直連的延遲和丟包足夠小的情況下,直連通信路由的概率將會接近 100%,如果某一條路由出現週期性斷開或者延遲超過 200ms,它的概率會接近 0。

以下是整個路由概率評估的過程示意圖:

 

 

 

 

4、基於P2P的實時視頻直播網絡構建過程

媒體流數據通過 Edge server 間的 P2P 多路徑傳輸網絡到達各個 Edge server 上,接下來每個 Edge server 需要將流數據分片下發到各個客戶節點上,我們針對上麥節點做了傳輸特殊處理讓時延更小,過程和普通的 RTC 通信模型相似,這裏就不贅述了。觀看節點上分發採用自組織 P2P 網絡,既然是通過 P2P 下發的,那麼就要在客戶節點羣構建一個 P2P 網絡,這個網絡是怎麼構建的?具體分爲三步:連接、評估、分層。

4.1 連接

客戶節點程序是運行在客戶機上的,大部分客戶節點都會在路由器或者 NAT 後面,他們之間要相互建立連接,必須穿越彼此的 NAT 和防火牆。雖然現在穿越 NAT 的方法有很多,如 STUN、ICE 等,但穿越連通率始終是一個問題,如果穿越率太低,會讓很多優質的節點資源得不到充分利用。

在設計穿越方案時我們將直連連通率放在第一位,通過修改 STUN 協議設計了一種基於端口多次猜測和嘗試的穿越機制。首先通過類似 STUN 協議判斷 NAT 類型、NAT 端口變化規律、NAT 是否有黑名單機制等信息,然後將這些信息存到轄區連接中的 Edge server 中,當有夥伴節點來與它穿越,會交換彼此的這些信息,不同的排列組合會有不同的穿越策略,每一次穿越的過程和結果都會記錄到我們的後臺數據庫,我們會週期性地將這些數據進行分析並調整協商穿越策略。如下圖:

 

 

 

 

穿越完成後,節點之間就會進行連接握手和身份證書認證(關於爲什麼要證書後面細講),建立通信聯繫和鄰居關係。那麼鄰居關係是怎麼動態變化的呢?

4.2 鄰居關係與評估

【鄰居問題】:

連接一旦完成,節點與節點之間就成爲鄰居,彼此會進行狀態交換和心跳,那麼問題來了,一個直播系統有成千上萬的節點參與,如果都兩兩相連的話光心跳通信就可以將客戶節點的上傳帶寬佔滿。我們設計了一個節點 LRU 淘汰鏈表,鏈表中保持 40 個聯繫的鄰居節點,老的節點會退出,新的節點會加入,LRU 會根據鄰居與自己的通信狀態來進行 LRU 新增和淘汰,原則如下:

就近原則,內網優先,同城同一運營商網絡次之;
週期性評測延遲和媒體分片命中率,末位淘汰;
當 LRU 列表中節點不足 40 個時會從備用節點列表中選取新的節點進行連接並加入到 LRU 中。

【節點評估】:

每個客戶節點的計算能力、通信能力和網絡分區等都不一樣,這使得我們必須對每個節點做一個評價,對一個節點的評價分爲兩部分:鄰居節點對自己的評價和自己對自己的評估。

鄰居評價主要是:

RTT;
丟包率;
請求命中率。

通過這三個參數會對每個鄰居計算出一個親和力分值 score,這個值會用於後面的分發選擇。

主要評估自己這幾點:

CPU、內存;
網絡類型:WIFI/4G/ 有線網絡;
上傳帶寬。

節點會週期性計算這兩類參數,通過一個網絡 QOS 收斂函數 f(x) 來計算節點能力和對鄰居 QOS 策略。

4.3 節點分層

節點評估最終的目的是讓有能力的節點成爲超級節點(super node)來分擔 Edge server 的分發壓力。

那麼一個節點成爲超級節點的條件是什麼呢?有以下幾個條件:

有足夠的上傳帶寬,4G 和弱 WIFI 下不能成爲超級節點;

有空閒的 CPU 和內存,計算能力不夠的低端移動設備不能成爲超級節點;

對鄰居通信友好,不是通信孤島;

得到 Edge server 的任命,和 Edge server 之間通信順暢。

超級節點如果性能衰減了怎麼辦?答案是會退化成普通節點,因爲節點評估是週期性實時進行的,如果發現節點性能衰減,Edge server 會讓其退化。

既然任命了超級節點,那麼超級節點是怎麼工作的?每一個超級節點在被任命時都會分配到一個分組 ID,Edge server 會根據自己轄區的超級節點數量進行分組,每個分組由多個超級節點組成,分組內的超級節點負擔自己分組的媒體分片分發。例如:有 5 個超級節點分組,這時單位週期內有 1 ~ 20 個 segment,那麼第一個分組負責 1、6、11、16 編號的 segment 分發,以此類推第二組負責 2、7、12、17 ……這樣做是爲了防止單個超級節點失效,增強了 P2P 分發的穩定性。

示意圖如下:

 

 

 

 

5、基於P2P的實時視頻直播流媒體分發過程

通過上面的 P2P 網絡構建過程我們知道整個 P2P 網絡其實是一個分層有向圖分發網絡,那麼具體是怎麼進行流數據分發的呢?也分三步:先推 (push)、後拉 (pull)、再補償。下面來仔細解釋是怎麼實現的。

5.1 push

在介紹超級節點時有提到會根據 segment ID 將數據推到對應的超級節點分組羣上,超級節點收到這些 segment 後怎麼進行處理呢?按照 P2P 設計的原理應該將數據轉發到其他分組的超級節點或者普通節點上,但是如果都這樣推有可能會造成網絡發送冗餘而消耗過多的帶寬。

爲了解決這個問題我們設計了一個預先訂閱機制,原理就是每個 P2P 客戶節點會根據自己緩衝區最大的 segment ID 來進行預訂,提前預訂 10 秒以後的媒體數據分片,預訂請求要根據節點評估出來的親和力值 score 做權衡,收到這些請求的超級節點會將預訂的分片請求信息保存下來,等到 Edge server 推送這個分片到這個超級節點,它就會無條件轉發這些被預訂的報文給發起預訂的節點,如下圖所示:

 

 

 

 

從上圖中可以看出以下幾個原則:

從 Edge server 到所有節點路徑最多兩層,這樣做是爲了控制鏈路延遲;

不同分組 super node 之間會相互訂閱對應分組的 segment;

普通 node 只會向 super node 發起訂閱。

5.2 pull

數據 segment 通過預先訂閱的方式進行 push 推送到各個客戶節點,但網絡是會丟包的,super node 也有可能會中途退出,這樣就會造成最終的節點發生丟包,那丟包了我們怎麼辦?

我們設計一個向鄰居拉取缺失分片的機制,大致的流程如下:

節點週期性檢查丟失分片的信息和收到分片的信息,構建一個 gossip 協議向鄰居交換緩衝區信息;

節點收到鄰居的 gossip 信息,將對方擁有的分片信息記錄到本地;

本地根據記錄鄰居的分片信息查找自己丟失的分片,通過鄰居親和力值 score 進行權衡隨機選取鄰居,並向選取的鄰居發起 pull 請求;

收到鄰居拉取分片請求,將分片發往請求的節點。

整個步驟會週期性嘗試多次拉取,示意圖如下:

 

 

 

 

這裏值得一說的是因爲會週期性交換緩衝區的 gossip 信息,這意味着緩衝區的 gossip 信息越小越好,我們設計了一個類似 bloom filter 來描述 gossip 信息,不僅可以減小 gossip 報文的數據大小,而且比對速度也很快。

5.3 補償

因爲 P2P 的客戶節點是不穩定的,有可能某個 segment 通過拉取多次還是沒有收到,這個 segment 又臨近播放位置,那麼缺失這個 segment 的節點會直接向 Edge server 請求補償讓其儘快傳送這個分片,這樣做的目的是防止因爲 P2P 通信造成丟包的卡頓。這也就是說每個 Edge server 需要擁有所有分片數據,這也就是系統的錨點。

流程如下圖:

 

 

 

 

這個流程大部分情況下沒有問題,但如果同一時刻大部分客戶節點都缺失某幾個 segment 分片,會有大量的補償請求到 Edge server 上,這會造成網絡風暴。我們在應對這個問題時設計了一個稀缺評估和拒絕服務的機制。這個機制是指當單位時間內太多個補償請求到達 Edge server,那麼這個 Edge server 會拒絕自己承受能力之外的請求,只重發承受範圍之內的分片。而且這個過程還會對補償請求做稀缺評估,如果某個分片大部分節點都沒有,它會主動將這個分片通過 super node 羣再推送一次。

5.4 緩衝 buffer 與時延控制

通過上面的三個階段可以將所有數據 segment 分發到每個客戶節點上,但客戶節點需要一個緩衝 buffer 來配合這個三個階段和本地的播放,buffer 如果緩衝時間過長,會引起不必要的延遲,如果過短會造成卡頓和三個階段不完整。

爲此我們設計了一個三階段 buffer 動態緩衝區,如下圖所示:

 

 

 

 

下邊解釋一下上圖各個區間的意思:

push 區間:因爲分片是通過不同的 super node 推送過來的,那麼必然會造成一定的抖動,所以在 buffer 最開始的頭上會有一個 jitter 緩衝階段,直到第一個鄰居節點 gossip 信息中有這個分片 push 位置結束,這個階段一般持續 100 ~ 300ms;

pull 區間:分片時序進入 pull 區間後,會週期性檢查丟失的分片,根據 gossip 掌握的鄰居進行權衡拉取,會進行 3 次嘗試,每一次嘗試時間是本地節點與鄰居之間的 RTT 值。3 次失敗則進入補償區間;

補償區間:分片時序進入補償區間後,也會週期檢查丟失的分片,根據丟失的分片 ID 直接向 Edge server 請求拉取,嘗試 4 次,每次嘗試時間爲一個本地節點與 Edge server 之間的 RTT。如果 4 失敗則進行 waiting 狀態,等待鄰居 gossip 或者 Edge server 主動推送;

過期區間:被播放後的分片會放到這個過期區間中而不是立即刪除,爲什麼呢?因爲每一個節點的播放時間點不同,有可能本地播放的分片正是其他節點丟失的分片,有可能其他節點會通過 pull 來拉取,所以我們會把播放後的分片放在過期區間 3 秒後再刪除。

5.5 秒開問題

上面分發的三個階段和 buffer 控制解決了流持續分發和播放延遲控制問題,但現階段所有的直播技術必須要有秒開,其實 P2P 分發在解決秒開問題上比單純的 Server CDN 轉發要更加簡單。秒開就是用戶進入直播間時瞬間能看到主播的視頻圖像,秒開的宗旨是新進入的客戶節點要求服務端邊緣節點從視頻的上一個 GOP 關鍵幀開始發送數據,客戶節點再根據視頻編碼器從這個 GOP 關鍵幀零等待加速播放。我們在 P2P 分發網絡中新進入的節點會收到 Edge server 的上一個 GOP 關鍵幀分片 ID,客戶節點根據這個 ID 從各個鄰居中快速拉取整個 GOP 分片數據,而不是單純地讓 Edge server 來發,秒開的速度平均縮短了 100 毫秒。

6、基於P2P的實時視頻直播內容授權

直播分發技術除了傳輸分發以外,還需要考慮內容防盜和授權,P2P 系統中更加需要考慮系統安全性。我們引入了 CA 證書和雙端協商加密方案來保證鏈路的合法性。大致的做法是每個合法的節點單元(Edge server 和所有的客戶節點)會向 CA 發起合法校驗,如果檢驗通過,CA 會根據節點的 ID、節點 RSA 公鑰、授權起始時間和授權終止時間等信息利用 CA 的 RSA 進行證書生成。每個拿到證書的節點單元需要和其他的節點進行通信,先交換證書,校驗對方證書的合法性,然後利用證書中 RSA 公鑰加密算法的 KEY 返回給證書方,證書方收到加密的 KEY 後會用 RSA 私鑰解密得到對稱加密的 KEY,這樣雙方就完成了合法性校驗並利用這個交換的 KEY 進行報文加解密通信。

流程如下圖:

 

 

 

 

7、線上數據對比

上面的技術分析只是幫助讀者理解這個系統的運作機理,除此以外,當然需要公佈一下線上數據來佐證下系統可行性,下圖是一個 10W+ 在線直播平臺使用了這套 P2P 系統後線上的對比數據。我們在同一個 Edge server 上的同一個直播間對象中,把一半的用戶節點關閉 P2P,一半的用戶開啓 P2P,來觀察一天中同一個 Edge server 上這兩部分用戶羣的帶寬消耗情況。

 

 

 

 

從上圖可以看出,P2P 模式帶寬消耗只有不開啓 P2P 模式的 1/4,我們這個 P2P 系統節省了 75% 的帶寬成本。這個數據的視頻樣本是單路 480P 800kps 碼率的直播流,高峯期真實節點數 1000+,最終所有終端的平均延遲是 1.07 秒。

8、本文小結

到這裏關於 P2P 分發網絡的技術解析就結束了,P2P 技術從產生到現在已經經歷了 19 年,而且 P2P CDN 也是下一代 CDN 的主體技術,P2P 技術和模型也一直變化改進。我們在直播分發領域使用 UDP 和 P2P 是想從成本和延遲上來解決我們教育場景互動的問題,出發點不一樣,也就會得到不一樣的結果,如果你遇到成本和延遲的困擾,可以嘗試使用這種技術來解決問題。

附錄:更多實時音視頻技術文章

[1] 開源實時音視頻技術WebRTC的文章:
開源實時音視頻技術WebRTC的現狀
簡述開源實時音視頻技術WebRTC的優缺點
訪談WebRTC標準之父:WebRTC的過去、現在和未來
良心分享:WebRTC 零基礎開發者教程(中文)[附件下載]
WebRTC實時音視頻技術的整體架構介紹
新手入門:到底什麼是WebRTC服務器,以及它是如何聯接通話的?
WebRTC實時音視頻技術基礎:基本架構和協議棧
淺談開發實時視頻直播平臺的技術要點
[觀點] WebRTC應該選擇H.264視頻編碼的四大理由
基於開源WebRTC開發實時音視頻靠譜嗎?第3方SDK有哪些?
開源實時音視頻技術WebRTC中RTP/RTCP數據傳輸協議的應用
簡述實時音視頻聊天中端到端加密(E2EE)的工作原理
實時通信RTC技術棧之:視頻編解碼
開源實時音視頻技術WebRTC在Windows下的簡明編譯教程
網頁端實時音視頻技術WebRTC:看起來很美,但離生產應用還有多少坑要填?
>>  更多同類文章 ……
[2] 實時音視頻開發的其它精華資料:
專訪微信視頻技術負責人:微信實時視頻聊天技術的演進
即時通訊音視頻開發(一):視頻編解碼之理論概述
即時通訊音視頻開發(二):視頻編解碼之數字視頻介紹
即時通訊音視頻開發(三):視頻編解碼之編碼基礎
即時通訊音視頻開發(四):視頻編解碼之預測技術介紹
即時通訊音視頻開發(五):認識主流視頻編碼技術H.264
即時通訊音視頻開發(六):如何開始音頻編解碼技術的學習
即時通訊音視頻開發(七):音頻基礎及編碼原理入門
即時通訊音視頻開發(八):常見的實時語音通訊編碼標準
即時通訊音視頻開發(九):實時語音通訊的迴音及迴音消除�概述
即時通訊音視頻開發(十):實時語音通訊的迴音消除�技術詳解
即時通訊音視頻開發(十一):實時語音通訊丟包補償技術詳解
即時通訊音視頻開發(十二):多人實時音視頻聊天架構探討
即時通訊音視頻開發(十三):實時視頻編碼H.264的特點與優勢
即時通訊音視頻開發(十四):實時音視頻數據傳輸協議介紹
即時通訊音視頻開發(十五):聊聊P2P與實時音視頻的應用情況
即時通訊音視頻開發(十六):移動端實時音視頻開發的幾個建議
即時通訊音視頻開發(十七):視頻編碼H.264、VP8的前世今生
實時語音聊天中的音頻處理與編碼壓縮技術簡述
網易視頻雲技術分享:音頻處理與壓縮技術快速入門
學習RFC3550:RTP/RTCP實時傳輸協議基礎知識
基於RTMP數據傳輸協議的實時流媒體技術研究(論文全文)
聲網架構師談實時音視頻雲的實現難點(視頻採訪)
淺談開發實時視頻直播平臺的技術要點
還在靠“喂喂喂”測試實時語音通話質量?本文教你科學的評測方法!
實現延遲低於500毫秒的1080P實時音視頻直播的實踐分享
移動端實時視頻直播技術實踐:如何做到實時秒開、流暢不卡
如何用最簡單的方法測試你的實時音視頻方案
技術揭祕:支持百萬級粉絲互動的Facebook實時視頻直播
簡述實時音視頻聊天中端到端加密(E2EE)的工作原理
移動端實時音視頻直播技術詳解(一):開篇
移動端實時音視頻直播技術詳解(二):採集
移動端實時音視頻直播技術詳解(三):處理
移動端實時音視頻直播技術詳解(四):編碼和封裝
移動端實時音視頻直播技術詳解(五):推流和傳輸
移動端實時音視頻直播技術詳解(六):延遲優化
理論聯繫實際:實現一個簡單地基於HTML5的實時視頻直播
IM實時音視頻聊天時的回聲消除技術詳解
淺談實時音視頻直播中直接影響用戶體驗的幾項關鍵技術指標
如何優化傳輸機制來實現實時音視頻的超低延遲?
首次披露:快手是如何做到百萬觀衆同場看直播仍能秒開且不卡頓的?
Android直播入門實踐:動手搭建一套簡單的直播系統
網易雲信實時視頻直播在TCP數據傳輸層的一些優化思路
實時音視頻聊天技術分享:面向不可靠網絡的抗丟包編解碼器
P2P技術如何將實時視頻直播帶寬降低75%?
>>  更多同類文章 ……

(本文同步發佈於:http://www.52im.net/thread-1289-1-1.html

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