云上视频业务基于边缘容器的技术实践

视频网关是视频云系统下的一个边缘容器设备,它起着将视频数据承上启下的功能。node

视频云

说到边缘视频网关就不得不提到云计算中的视频云,它是各领域的视频系统好比安防监控等向着智能化、物联网、上云发展的产物。linux

在云平台上经过云服务器和边缘视频设备将采集的视频输出编码后通过网络实时传输给终端,终端进行实时解码后显示输出。终端同时能够进行操做,通过网络将操做控制信息实时传送给云端应用后台对边缘视频设备进行控制。android

视频云通常框架

一个物联网场景下云边协同的智能视频云系统,具备实时流、历史录像功能,并支持对视频数据算法分析与结果联动控制,能够兼容市面上大多数厂商的视频设备好比摄像头和NVR。不只能够在公有云/私有云部署,甚至提供支持有损服务的本地局域网视频最小系统。c++

云/边端服务框架

视频网关

视频网关是云计算在视频垂直领域中的边缘容器设备,能够将其理解链接视频数据在视频传感器与云上服务之间的桥梁,是视频云系统中的关键一环,实现视频设备普遍的兼容性以及云边协同都离不开它的身影。设计一个功能完备,可扩展,高可用的视频网关是很是值得投入的。golang

如何实现

视频网关须要实现的基本功能包括视频流采集与推送、视频设备接入与管理等,做为一个与底层硬件打交道的设备,又涉及到云计算中的接入、安全以及云边协同等方面,可谓麻雀虽小五脏俱全。算法

视频数据采集

视频云系统中视频数据的采集由位于边缘侧的视频网关完成,视频网关链接视频采集设备好比IPC/NVR, 经过厂家SDK或者ONVIF协议对视频采集设备进行管理,网关拉取视频采集设备的数据流并推送云端或者边缘侧的视频服务,由视频服务对视频数据进行转码、数据流协议转换等操做以适配不一样的播放客户端。编程

视频云架构

视频设备管理

摄像头、NVR等视频设备位于用户局域网内,经过边缘视频网关接入到视频云系统中。边缘视频网关和视频设备须要在管理平台上经过导入的方式作登记以便明确视频网关与视频设备以及视频网关与业务的绑定关系。视频网关管理视频设备并将设备状态实时同步到云视频系统中,管理平台实现"设备影子"并提供对视频网关以及视频设备状态信息的增删改查接口。windows

设备影子管理

数据安全

视频上云须要安全认证,视频云系统中边缘容器设备接入云端服务、边缘容器设备之间以及边缘容器设备与云端服务之间的数据流采用标准国密算法保证其运行的安全性,其中边缘容器设备接入云视频流程中采用国密sm2非对称秘钥技术保证接入安全,边缘容器设备与云视频之间的数据通道采用国密sm4对称秘钥技术保证信令与视频数据的安全。api

设备接入

视频云系统中视频网关等边缘容器设备一般位于用户局域网内,视频网关在局域网内链接视频设备好比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)这样的主流操做系统、amd6四、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重构版本。

设计感悟

如今的设备正逐渐朝着物联网,智能化方面发展,探索发现一条适合将来智能设备发展要求的技术栈是云相关产品开发工程师必须面对的;

不要重复造轮子,优秀的官方库,活跃的开源社区可让开发工做稳定可控而且丰富多彩;

追求产品质量和开发效率是每位开发同窗都须要要考虑的问题,有了它们才能保证产品在市场竞争中立于不败之地,用合适的工具作合适的事。

相关文章
相关标签/搜索