雲上視訊業務基於邊緣容器的技術實踐

騰訊雲原生發表於2021-01-12

視訊閘道器是視訊雲系統下的一個邊緣容器裝置,它起著將視訊資料承上啟下的功能。

視訊雲

說到邊緣視訊閘道器就不得不提到雲端計算中的視訊雲,它是各領域的視訊系統比如安防監控等向著智慧化、物聯網、上雲發展的產物。

在雲平臺上通過雲伺服器和邊緣視訊裝置將採集的視訊輸出編碼後經過網路實時傳輸給終端,終端進行實時解碼後顯示輸出。終端同時可以進行操作,經過網路將操作控制資訊實時傳送給雲端應用後臺對邊緣視訊裝置進行控制。

視訊雲一般框架

一個物聯網場景下雲邊協同的智慧視訊雲系統,具有實時流、歷史錄影功能,並支援對視訊資料演算法分析與結果聯動控制,可以相容市面上大多數廠商的視訊裝置比如攝像頭和NVR。不僅可以在公有云/私有云部署,甚至提供支援有損服務的本地區域網視訊最小系統。

雲/邊端服務框架

視訊閘道器

視訊閘道器是雲端計算在視訊垂直領域中的邊緣容器裝置,可以將其理解連線視訊資料在視訊感測器與雲上服務之間的橋樑,是視訊雲系統中的關鍵一環,實現視訊裝置廣泛的相容性以及雲邊協同都離不開它的身影。設計一個功能完備,可擴充套件,高可用的視訊閘道器是非常值得投入的。

如何實現

視訊閘道器需要實現的基本功能包括視訊流採集與推送、視訊裝置接入與管理等,作為一個與底層硬體打交道的裝置,又涉及到雲端計算中的接入、安全以及雲邊協同等方面,可謂麻雀雖小五臟俱全。

視訊資料採集

視訊雲系統中視訊資料的採集由位於邊緣側的視訊閘道器完成,視訊閘道器連線視訊採集裝置比如IPC/NVR, 通過廠家SDK或者ONVIF協議對視訊採集裝置進行管理,閘道器拉取視訊採集裝置的資料流並推送雲端或者邊緣側的視訊服務,由視訊服務對視訊資料進行轉碼、資料流協議轉換等操作以適配不同的播放客戶端。

視訊雲架構

視訊裝置管理

攝像頭、NVR等視訊裝置位於使用者區域網內,通過邊緣視訊閘道器接入到視訊雲系統中。邊緣視訊閘道器和視訊裝置需要在管理平臺上通過匯入的方式做登記以便明確視訊閘道器與視訊裝置以及視訊閘道器與業務的繫結關係。視訊閘道器管理視訊裝置並將裝置狀態實時同步到雲視訊系統中,管理平臺實現"裝置影子"並提供對視訊閘道器以及視訊裝置狀態資訊的增刪改查介面。

裝置影子管理

資料安全

視訊上雲需要安全認證,視訊雲系統中邊緣容器裝置接入雲端服務、邊緣容器裝置之間以及邊緣容器裝置與雲端服務之間的資料流採用標準國密演算法保證其執行的安全性,其中邊緣容器裝置接入雲視訊流程中採用國密sm2非對稱祕鑰技術保證接入安全,邊緣容器裝置與雲視訊之間的資料通道採用國密sm4對稱祕鑰技術保證信令與視訊資料的安全。

裝置接入

視訊雲系統中視訊閘道器等邊緣容器裝置通常位於使用者區域網內,視訊閘道器在區域網內連線視訊裝置比如IPC或者NVR,並作為一個邊緣容器裝置接入到雲視訊。視訊閘道器通過註冊、登入方式接入雲視訊保證安全性,整個裝置接入流程中視訊閘道器與雲視訊之間通訊採用國密sm2非對稱加密技術進行訊息加密與簽名校驗,接入雲視訊後視訊閘道器與雲視訊之間的信令通道採用國密sm4對稱祕鑰方式進行資料加解密。

1)在視訊雲開放平臺為視訊閘道器裝置申請sn序列號後即可以得到視訊閘道器的私鑰以及接入雲視訊所需的公鑰;

2)視訊閘道器接入雲視訊的註冊階段,首先閘道器使用閘道器私鑰對自身資訊進行簽名,然後使用雲視訊公鑰將簽名資訊以及裝置sn等資訊進行加密併傳送雲視訊,這一過程可以保證閘道器的註冊請求只能被雲視訊解析,並且雲視訊可以通過簽名驗籤識別訊息是由視訊閘道器發出。

3)註冊雲視訊成功後,雲視訊會將其與視訊閘道器之間的信令通道等相關資訊經過雲視訊私鑰加密後返回給視訊閘道器,視訊閘道器通過雲視訊公鑰可以解析。

4)視訊閘道器接入雲視訊的登入階段會與雲視訊協商信令通道對稱祕鑰,首先閘道器使用閘道器私鑰對自身資訊進行簽名,然後使用雲視訊公鑰將簽名資訊以及裝置唯一標識、對稱祕鑰向量等資訊進行加密後傳送雲視訊,這一過程可以保證閘道器的登入請求只能被雲視訊解析,並且雲視訊可以通過簽名驗籤識別訊息是由視訊閘道器發出。

5)登入雲視訊成功後,雲視訊會將其與視訊閘道器之間信令通道中使用的對稱祕鑰key、token以及有效時間等資訊經過雲視訊私鑰加密後返回給視訊閘道器,視訊閘道器通過雲視訊公鑰可以解析。

資料通道

邊緣容器裝置與雲視訊之間的業務資料,比如視訊閘道器與雲視訊之間的視訊流推送、攝像頭列表維護等訊息通過資料通道傳達,採用國密sm2對稱祕鑰技術加密,如果資料通道的token、對稱祕鑰過期需要視訊閘道器重新登入雲視訊獲取。

以邊緣視訊閘道器向雲視訊推送視訊流這一過程為例說明,視訊閘道器採集到攝像頭裝置的視訊流後對視訊幀加密後傳輸到雲端視訊後臺服務,其中視訊閘道器與雲端視訊後臺服務之間推視訊流建立握手的token以及推流資料加密使用的國密sm4 key等安全資訊是通過視訊閘道器與雲視訊之間的資料通道下發的,視訊鏈路保證該加密資訊的單次使用時效性,也就是說單次推流的信令中所包含的加密資訊如果在一個時間閾值內不使用或者握手成功後就不可再次複用了。

視訊雲系統中邊緣容器裝置接入與資料通道的安全認證機制如下圖所示。

img

雲邊協同

靈活的雲邊協同和邊緣計算能力,集中管理能力雲端收攏,部分邏輯下沉邊緣,保證快速響應,即便在雲環境網路異常下也能提供基礎的本地視訊服務實現高可用。

在傳統的視訊監控領域,攝像頭、演算法和監控軟體會部署在同一個區域網內,對於使用者而言,往往有在公網短時播放的需求。如果將視訊放到公網上進行播放,又會帶來頻寬成本以及安全問題。視訊雲系統為解決以上問題,提供雲邊協同和邊緣計算能力,在雲端控制邊緣節點,可以將已訓練好的演算法或者事件聯動能力下沉到邊緣容器裝置進行執行,大大降低雲端壓力。同時擁有靈活邊緣路由能力,根據雲端拉流需求,將部分視訊推到雲端進行播放,極大降低頻寬成本,提高系統的穩定性。

雲邊系統高可用

雲邊系統高可用

技術方案

跨平臺程式設計

視訊閘道器作為一種嵌入式媒體閘道器裝置,主要有兩種裝置形態,一種是以通用伺服器搭載閘道器服務的形式,這樣的系統比較重,成本比較高但是效能強勁,另一種是嵌入式盒子裝置比如樹莓派,成本低同時效能較低,按照專案應用場景合理搭配解決方案。

視訊閘道器作為一個可以跨平臺,跨系統並深度融合雲端計算視訊雲領域的服務,軟體我們採用了golang語言,藉助於其天然的跨平臺特性,可以支援閘道器服務執行在各種晶片平臺以及作業系統之上。go tool dist list 可以看到go語言支援的平臺和系統如下。

作業系統 主控晶片平臺
linux 386/amd64/arm/arm64/mips/mips64/mips64le/mipsle/ppc64/ppc64le/riscv64/s390x
android 386/amd64/arm/arm64
darwin 386/amd64/arm/arm64
freebsd 386/amd64/arm/arm64
solaris amd64
plan9 386/amd64/arm
openbsd 386/amd64/arm/arm64
netbsd 386/amd64/arm/arm64
aix ppc64
windows 386/amd64/arm

從上述列表可以看出,從linux/arm64的嵌入式系統到linux/s390x的大型機系統,再到Windows、linux和darwin(mac)這樣的主流作業系統、amd64、386這樣的主流處理器體系,Go對各種平臺和作業系統的支援不可謂不廣泛。

go語言被稱作網際網路時代的c語言其優點很多,語法簡單、原生支援併發、平臺可移植性好、執行速度快、有功能豐富並且統一的標準庫等等,其中關於跨平臺有一種說法go是為了解決c/c++那些複雜的依賴而來的,這一定程度上得益於Go獨立實現了runtime,作為技術棧上的選型這裡關於runtime多說一些。

runtime是支撐程式執行的基礎。libc(C執行時)是目前主流作業系統上應用最普遍的執行時,通常以動態連結庫的形式(比如:/lib/x86_64-linux-gnu/libc.so.6)隨著系統一併釋出,它的功能大致有如下幾個:

  1. 提供基礎庫函式呼叫,比如:strncpy;

  2. 封裝syscall(作業系統提供的API口,當使用者層進行系統呼叫時,程式碼會trap(陷入)到核心層面執行),並提供同語言的庫函式呼叫,比如:malloc、fread等;

  3. 提供程式啟動入口函式,比如:linux下的__libc_start_main。

早期的系統的磁碟/記憶體資源十分緊張,採用動態連結庫的方式可以使得編譯的程式/程式磁碟/記憶體佔用小。不過時代變了,現在的伺服器配置已經足夠,由於libc等c runtime lib是基於執行緒模型的並且歷史版本複雜,對於開發人員來說這裡的負擔很重,一些從事c/c++開發多年的同學可能有過這樣的經歷,連結runtime庫時需要選擇連結支援多執行緒的庫還是隻支援單執行緒的庫。

img

go獨立實現runtime層,封裝了syscall將Go user-level code與OS syscall解耦,把go 移植到一個新平臺時,將runtime與新平臺的syscall對接即可,基本擺脫對libc的依賴,這樣靜態編譯的go程式具有很好的平臺適應性。而且交叉編譯很簡單,只涉及兩個重要的環境變數:GOOS和GOARCH,分別代表Target Host OS和Target Host ARCH,這裡需要注意CGO_ENABLED=0的情況下,即不涉及cgo的前提下go採用純靜態編譯。

業務功能

視訊閘道器位於視訊系統的邊緣側,主要業務功能是負責拉取視訊流並推送到視訊後臺服務。在系統管理層面,視訊閘道器需要連線裝置側的IPC/NVR等,並接入到視訊系統的控制核心,作為邊緣容器裝置接收雲視訊系統核心的信令對視訊裝置進行管理,執行相應的操作,並將視訊裝置的反饋結果以及狀態上報到雲視訊系統核心。

功能框架

網路接入

視訊閘道器不僅可通過固網接入視訊雲系統,也可通過蜂窩網,wifi等無線方式接入。視訊閘道器通過驅動搭載WIFI/4G/5G等通訊模組實現無線接入能力,其中區域網內可以使用WIFI等協議,連線網際網路可以使用4G/5G通訊。視訊閘道器可根據視訊系統組網的實際情況以及現場視訊裝置的實際能力,將整個視訊系統的有線/無線網路結合。

無線接入框架

裝置初始化

視訊閘道器在接入層採用外掛化的框架,向下可以相容ONVIF協議、SDK等多種方式接入視訊裝置,向上可以相容mqtt/http等物聯網傳輸協議接入雲端計算視訊平臺。

初始化能力集

視訊閘道器通過視訊裝置的裝置影子中廠商、流來源等屬性判斷使用ONVIF協議還是廠商SDK對視訊裝置進行初始化,獲取視訊裝置的能力列表比如RTSP連線等。

視訊裝置初始化流程

初始化訊息通道

視訊閘道器和雲視訊系統核心之間的訊息通道支援http/mqtt等物聯網通訊協議,視訊閘道器具體使用某種通訊協議由使用者選擇相應的配置在系統啟動階段完成初始化。

訊息通道的初始化流程

安全策略

視訊閘道器在接入雲視訊系統核心過程支援雙向鑑權,信令通道以及視訊流傳輸支援資料加密等多種安全策略。

視訊閘道器接入雲視訊系統核心分為註冊、挑戰、登入三步,閘道器與核心之間採用tcp私有協議方式通訊,接入過程中使用sm2/4國密進行資料加密和簽名。其中視訊閘道器的裝置私鑰、裝置公鑰以及雲視訊系統核心的公鑰由視訊閘道器在申請雲視訊系統核心放號的過程中獲取。

視訊閘道器安全策略

視訊流加密

核心下發推流訊息命令字通知視訊閘道器推視訊資料流,閘道器根據訊息中的流來源欄位區分收流裝置是IPC還是NVR,閘道器推送視訊流的目的端資訊以及視訊流加密祕鑰由核心下發訊息指定。

推流加密

信令加密

閘道器接入雲視訊系統核心成功後即可通過訊息通道實現閘道器與核心間的雲邊協同,為了增強訊息安全性在視訊閘道器與核心之間的訊息通道設定了token過期時間,當token過期,閘道器在接收與上報訊息將出現異常,此時需要閘道器主動重新登入核心換取新token,閘道器在定時心跳過程中維護檢測token過期機制。

Token 過期策略

雲邊協同

事件處理

視訊閘道器具有邊緣節點監控、資料統計與告警、事件處理能力。

視訊閘道器接入雲視訊系統核心後,由雲視訊系統核心下發訊息控制視訊閘道器執行相關功能,定義視訊閘道器與核心之間訊息命令字。視訊閘道器與核心之間的訊息通道可以採用mqtt/http等協議。訊息通道中使用管道實現佇列的能力,核心下發訊息通過管道分發到不同的接收訊息任務中併發處理,閘道器上報訊息通過管道由傳送任務上報核心。

事件處理流程

狀態上報

閘道器與雲視訊系統核心之間通訊的加密key通過閘道器的心跳上報定時檢測更新。

訊息上報流程

視訊閘道器位於裝置側區域網內,可以通過其與雲視訊系統核心之間的訊息通道上報統計與告警訊息。實現對裝置狀態全程監控、有效實時獲取狀態變更通知。

視訊閘道器通過訊息通道上報統計和告警訊息到雲視訊系統核心,結合雲端計算視訊雲的後臺服務以及繫結接入的應用實現告警上報。

訊息通道上報統計與告警

雙機熱備

為避免視訊閘道器單點異常當機對視訊服務造成影響,視訊閘道器採用主備方式提高服務可用性,結構簡單容易維護。

主備模式下裝置側區域網內多個視訊閘道器涉及排程和配置管理,這裡使用了專案中zookeeper元件提供分散式搶佔鎖和配置中心的能力,zookeeper使用znode目錄節點作為鎖和共享儲存。

img

閘道器接入

視訊閘道器作為接入視訊雲系統的邊緣容器裝置具有唯一性,主備模式下區域網內同一時間只有一個視訊閘道器作為主閘道器提供服務,其餘閘道器作為主閘道器的從閘道器監視主閘道器狀態,當主閘道器出現異常從閘道器嘗試切換成為主閘道器。其中多個視訊閘道器對視訊雲系統等效為一個接入裝置。具體部署可以是一主一從或者一主多從。

使用zookeeper的臨時目錄編號節點(EPHEMERAL_SEQUENTIAL)實現分散式搶佔鎖可以為多個閘道器的執行提供排程,保證同一時刻只有一個閘道器接入到視訊雲核心(IOT)。

img

閘道器切換

主閘道器由於當機與zk斷開連線或者業務異常主動釋放與zk之間的鎖時,zk將對應的編號節點刪除,並通知其他監聽臨時節點的閘道器可以搶佔,新搶佔到鎖的閘道器成為主閘道器。

img

邊緣部署

隨著Docker為代表的容器技術和Kubernates為代表的容器編排工具逐漸成熟,越來越多的應用通過容器封裝、分發和執行,這種部署方式非常合適邊緣計算場景。

按照端裝置—邊緣—雲”三層模型, 視訊閘道器作為一種邊緣裝置與攝像頭、nvr等視訊終端裝置直接相連,然而邊緣節點的硬體資源往往比較緊張, 視訊雲系統需要十分靈活的對邊緣節點的計算能力與資源排程策略進行調整。

使用容器技術對邊緣節點進行資源隔離,不僅CPU、記憶體和儲存的開銷非常小,而且容器可以實現在毫秒級開啟和關閉,生命週期管理非常快捷。

img

視訊雲系統中邊緣視訊閘道器往往分散在建築、園區等各個區域性區域中,遠離雲中心。隨著使用者對視訊播放需求的變化,邊緣視訊閘道器的資源分配與部署也需要隨時調整,並且需要支援監控、日誌等等運維手段。採用了tke edge邊緣容器架構支撐視訊雲系統的邊緣計算場景,tke edge支援邊緣計算、多雲管理和混合雲,具有完備的k8s功能與標準api,可以方便的從中心雲運維邊緣容器,具有邊緣自治能力,支援邊緣節點健康檢查,服務可以下沉到邊緣機房,而且和tke擁有一致的控制檯頁面,運維管理視覺化十分便捷。

效能調優

視訊閘道器的業務場景決定了其主要功能模組是裝置接入與訊息通道、任務排程、採集與推送視訊流,效能優化的關鍵點往往就在這裡。

go tool可以很方便的使用pprof對程式詳細的效能分析,使用 -memprofile 和 -cpuprofile 選項生成cpu和記憶體取樣檔案,再用工具go tool pprof檢視檔案內容。

在開發過程中遇到的效能優化問題挑了兩個比較典型的案例進行分析。

Mqtt 訂閱

視訊閘道器與雲視訊系統核心(IOT)之間的mqtt訊息通道使用了開源的paho.mqtt.golang,視訊閘道器作為客戶端需要訂閱IOT分配的topic,開發除錯過程中發現閘道器程式在啟動後既沒有接收來自於IOT的訊息也沒有推流的情況下,cpu佔用都有2~3個點,於是通過火焰圖對呼叫介面進行效能分析,發現mqtt客戶端的Subscribe介面cpu時間佔用異常。

img

檢查程式碼原來是由於介面誤使用,訂閱介面本來在mqtt客戶端初始化的時候訂閱一次就可以了,但是寫程式碼時把它當成了非同步阻塞接收介面,在一個輪詢的迴圈中不停的呼叫,結果就是不停的在訂閱同一個topic。

token := client.Subscribe(m.subOption.topic, m.subOption.qos, msgSubscribeHandler)
token.Wait()
if token.Error() != nil {
   log.Errorf("Subscribe msg to mqtt broker error:%s", token.Error().Error())
}

使用開源庫中介面不熟悉誤用造成的問題比較低階也很典型,如果沒有pprof這樣的工具,排查起來還是挺麻煩了,採用了正確的姿勢,再分析可以看到已經沒有訂閱介面的時間佔用了。

img

優化推流 buffer

既然視訊閘道器的主要功能是推流那麼網路傳輸介面這塊一定是cpu和記憶體效能的消耗大戶,通過火焰圖發現封裝的推流介面cpu佔用時間幾乎都集中在底層的Write和recv,這一塊優化空間不大,但是發現runtime.gcBgMarkWorker(垃圾回收器)這塊消耗比較高,排查程式碼原來是推流任務中的buffer申請時機不合理導致。

img

func (v *videoPush) PushToWeLink(pushData *pb.PushReq) error {
   //申請記憶體空間
   packet := make([]byte, mvsTCPHeadLen)
   //組裝資料
   ......
   //傳送資料
   middleware.SendTCPMsg(v.Conn, v.packet)
   return err
}

在每次收到視訊幀並推流的時候都新申請一塊buffer,造成go的gc壓力過大,其實對於視訊閘道器每次從視訊採集裝置收到的資料幀大小是可以預估的,在每次建立推流任務初始化的時候可以針對任務將固定空間的buffer預留好。

//videoPush
type videoPush struct {
   //攝像頭推流屬性等
//token與祕鑰等
   //與視訊伺服器連線等
//狀態等
   ……
   PushCtx       context.Context
   PushCancel    context.CancelFunc
   frameHead     []byte                            //加密幀頭
   packet        []byte                            //sharp包體
   head          *com_tencent_weling_proto.MvsHead //sharp包頭
}

func (v *videoPush) PushToWeLink(pushData *pb.PushReq) error {
   //取記憶體空間
   v.packet = v.packet[0:mvsTCPHeadLen]
   //組裝資料
   ......
   //傳送資料
   if err = middleware.SendTCPMsg(v.Conn, v.packet); err == nil {
      //更新推流狀態, 線上、推流時間戳
      v.camerasInfo.setPushingByIntDinSubDin(v.SDin, int(v.StreamID), v.StreamType, v.getVideo.StreamHandler)
   } else {
      log.Errorf("push send msg error:%s, packet len:%d", err.Error(), len(v.packet))
   }
   return err
}

經過簡單適配,可以看到gc的效能消耗已經有了明顯改善。

img

專案總結

基於go的技術棧實現了一個跨晶片平臺的視訊閘道器,使用者可以選擇邊緣伺服器或者邊緣嵌入式硬體等環境部署視訊閘道器,融合雲端計算敏捷靈活、可靠穩定的特點,將網路連線、管理運維及排程的能力應用於視訊場景,提供實時、可靠的視訊端到端服務。

通過外掛化的網路接入層,視訊閘道器可以選擇多種物聯網協議接入雲端計算服務,並且相容多種廠商的視訊裝置;

通過雲邊協同,實現雲端下發邊緣處理,提供有損服務能力,系統可用性強;

通過邊緣側狀態監控、統計與告警,掌握視訊裝置實時狀態上報,構建全鏈條的打點資料採集,裝置級的精細化狀態追蹤,支援裝置行為軌跡等資料分析;

通過從端到雲全方位的安全策略。視訊閘道器裝置接入雲端過程中雙向身份認證,保證裝置唯一性不受篡改,全面杜絕偽造裝置/雲伺服器傳送請求。視訊流資料加密傳輸防止敏感資訊洩露。

使用效果

以公司普通計算型伺服器的配置(8核16G記憶體千兆網路卡)為例,設定動態位元速率2m以內的攝像頭實時流推流實測可以支援到400路。樹莓派3B+搭載視訊閘道器在同樣場景下可以支援不低於100路攝像頭實時流推流。

目前go重構的視訊閘道器已經在多個專案環境中使用,整體表現良好,並計劃在後續的新專案以及老專案的視訊閘道器升級改造中逐步替換成go重構版本。

設計感悟

現在的裝置正逐漸朝著物聯網,智慧化方面發展,探索發現一條適合未來智慧裝置發展要求的技術棧是雲相關產品開發工程師必須面對的;

不要重複造輪子,優秀的官方庫,活躍的開源社群可以讓開發工作穩定可控並且豐富多彩;

追求產品質量和開發效率是每位開發同學都需要要考慮的問題,有了它們才能保證產品在市場競爭中立於不敗之地,用合適的工具做合適的事。

【騰訊雲原生】雲說新品、雲研新術、雲遊新活、雲賞資訊,掃碼關注同名公眾號,及時獲取更多幹貨!!

相關文章