WebRTC 開發實踐 如何實現 SFU 伺服器

2021-10-02 23:35:15 字數 2370 閱讀 6675

1 什麼是 sfu ?

我們可以想象一下 web 伺服器和直播伺服器的工作原理,瀏覽器/直播客戶端,要想完成與伺服器之間的資料交換,通常離不開如下幾個步驟:

2. 客戶端使用 「約定」 的信令協議(如:http,rtmp),傳送請求給伺服器,實現資料交換的準備工作

3. 客戶端開始上行資料給伺服器,或者伺服器開始下發資料到客戶端,結束後,通過信令關閉連線

4. 靜態的資源型的資料(檔案、網頁),通常服務端是讀取磁碟上的資料拷貝乙份給需要的客戶端

5. 非靜態的實時資料(如:直播流),伺服器則通過在 「記憶體」 中拷貝並**給需要的客戶端

同樣,webrtc 客戶端與 sfu 伺服器之間的互動,也是離不開這些步驟的,特別是 4/5,其實就是所謂的 one-to-many 能力。

2 信令和傳輸通道的建立

首先我們解決第乙個問題,即 webrtc 客戶端是如何跟 sfu 伺服器建立資料傳輸通道的 ?

如圖,我們先看看瀏覽器與 web 伺服器的建聯過程:瀏覽器通過 dns 解析 url 中的網域名稱,拿到 ip 後通過 80 埠連線上伺服器(後續的資料傳輸均復用這條 tcp 鏈路)。

webrtc 其實也是類似的,但是與標準的 http 服務或者 rtmp 直播服務相比,還是有些區別的,如下:

1,信令和資料通道是 「分離」 的,信令目前沒有統一的實現方案,可以使用任何方案(如:http、tcp 自定義協議、sip 等等),但是資料並不走這條信令鏈路,而是走單獨的 udp 埠

2,資料通道使用的 udp 協議,不像 tcp 有 「連線」 的概念,客戶端僅僅知道伺服器的 udp 埠,但不 「連線」 是無法預判傳輸通道是否真的 ok(主要是部分 nat 閘道器型別的限制,導致並不是所有 udp 傳輸都能通),因此需要借助一些框架和協議來判斷 udp 通道的可用性(即 ice 協議)

上述內容分析完了,我們就可以看看如何實現 sfu 的信令和傳輸通道了:

實現 http web server 服務(或者 sip 或者基於 tcp 自定義協議),用於提供 「信令」 的支援(如:推流命令、拉流命令等)

通過 libnice 庫或者自己 coding 的方式,實現 ice 協議,用於提供 udp 「資料通道」 的檢測和建聯

實現 udp 資料監聽和傳送,用於接收客戶端的資料,**其他客戶端的資料

3 需要實現哪些 「信令」 ?

對於 http 協議,實現的 「信令」 包括:get,post,delete 等等,定義了瀏覽器期望進行的行為。同理,對於 sfu,我們也要定義一系列必要的信令,以約定客戶端和伺服器對應的行為,那具體有哪些呢 ?

其實 webrtc 客戶端,與 sfu 伺服器需要協商的事情,無外乎就是如下幾點:

2. 發布流/取消發布流:客戶端通知伺服器準備好接收資料

3. 訂閱流/取消訂閱流:客戶端通知伺服器準備好**資料

因此,sfu 伺服器通過任意一種方式(http/tcp 等),提供 ice connection/publish/subscribe 信令即可,sfu 在信令背後需要實現的邏輯分別如下:

1. ice connection:新增一路 udp 通道

2. publish:新增乙個邏輯上的資料 producer,通過 udp 通道 recv 客戶端的資料,通知邏輯上的 consumers

3. subscribe:新增乙個邏輯上的資料 consumer,收到 producer 通知後,通過 udp 通道 send 給客戶端

4 如何實現 one-to-many ?

這是 sfu 最核心的功能,其實也不是 webrtc sfu 特有,如前面所述,凡是非靜態資源型的服務(資料實時產生實時消費)均需要在服務端實現 one-to-many,比較典型的例子就是 rtmp 直播流伺服器,需要將客戶端推流上來的資料,實時**給多個拉流的客戶端。

實現 one-to-many ,最重要的一點是需要把資料的生產者(publisher)和資料的消費者(subscriber)關聯起來,怎麼關聯呢 ?

5 資料傳輸協議

webrtc 採用的是標準的 rtp/rtcp 協議進行資料的封包和網路狀態反饋,因此,sfu 伺服器也需要支援 rtp/rtcp 的封包和解包,從而能夠 「理解」 客戶端的 udp 資料報的含義,如:提取出 ×××c 或者 timestamp 等必要的資訊,也能及時地向客戶端反饋網路狀態(rtcp)。

關於 rtp/rtcp 傳輸協議,已經發展多年,是比較成熟的多**傳輸協議了,也有很多不錯的開源庫,這裡就不再贅述了。

6 小結

以上就是關於如何實現 sfu 伺服器最核心的知識點了,暫且就分享到這裡了。

Android開發實踐 如何設定NDK的編譯選項

1.概述 android.mk,負責配置如下內容 1 模組名 local module 2 需要編譯的原始檔 local src files 3 依賴的第三方庫 local static libraries,local shared libraries 4 編譯 鏈結選項 local ldlibs ...

Android開發實踐 如何設定NDK的編譯選項

1.概述 android.mk,負責配置如下內容 1 模組名 local module 2 需要編譯的原始檔 local src files 3 依賴的第三方庫 local static libraries,local shared libraries 4 編譯 鏈結選項 local ldlibs ...

K8S雲管平台開發實踐 報警功能01

要實現完整的報警功能,我們需要5步 1.建立規則 2.收集資料 3.將規則資料和收集到的資料進行比較 4.產生報警資料 5.推送報警資料 而在運管平台中,我們整合了小公尺開源監控系統open falcon,對應上面分析的步驟,我們給出的方案是 1.k8s雲管平台提供報警管理模組,可以管理報警規則 2...