前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >TRTC Web SDK新架构设计解析(GMTC逐字稿)

TRTC Web SDK新架构设计解析(GMTC逐字稿)

作者头像
我不是码神
发布2022-07-28 15:55:32
9280
发布2022-07-28 15:55:32
举报
文章被收录于专栏:流媒体技术流媒体技术

腾讯实时音视频(Tencent Real-Time Communication,TRTC)是腾讯云基于 QQ 在音视频通话技术上的积累,它还结合了腾讯浏览服务 TBS WebRTC 能力与腾讯实时音视频 SDK ,为客户提供多平台互通、高品质、可定制化的实时音视频互通服务解决方案。目前腾讯云团队正在开发的 TRTC Web SDK 新架构。

在 2021 年 GMTC 全球大前端技术大会【深圳站】中,来自腾讯云的高级工程师李宇翔,重点分享了新架构中运用了哪些设计思想和技巧,来提高程序的性能和代码的可维护性。

背景介绍

腾讯云的 TRTC 产品主要提供了音视频领域的一些基础功能,并通过 SDK 供用户使用,用户可以使用 TRTC 提供的底层能力构建自己的产品。TRTC 提供的能力主要分为终端和云端两个部分:云端部分均基于腾讯云,而终端部分覆盖了主流的 Windows、macOS、iOS、Android等原生端,以及小程序等 Web 端。

WebRTC 是 TRTC SDK 使用的开源解决方案。WebRTC 本质上是前端可以调用的中间算法与模块,对前端工程师而言,相当于一个封装到浏览器内部的黑盒。WebRTC方案有自己的优势和劣势,其中优势包括无需插件即可运行、前端开发难度低、开源免费、自带 P2P 功能等。

而 WebRTC 方案的劣势也比较明显:

  1. 编解码器是封装好的,无法自定义;
  2. 传输方式固定,无法自定义;
  3. 服务端需要适配 WebRTC ,即便云端有很多自制功能,接入了自有体系,依旧需要通过WebRTC 实现沟通;
  4. WebRTC 无法运行在 Worker 中,只能运行在主线程上。

为了解决上述问题,腾讯云团队自行开发了一套 WebRTC 的替代方案:

该替代方案主要分为算法层和传输层两部分。传输层的选择更加灵活,支持现有和未来出现的各种 Web 传输方案,如 DataChannel、WebSocket、WebTransport等;算法层面支持WebRTC 的所有模块,通过 Webassembly 的方式在浏览器运行,从而支持自定义编解码。该方案要求 M94 版本以上的浏览器环境,考虑到目前 M94 刚刚发布不久,就已经有40%的占有率,这个方案的兼容性是比较乐观的。

新老架构对比

从下图中可以明显发现,新旧方案 SDK 使用的主要技术是有一些差异的:

从架构层面来看,WebRTC SDK的架构如下图所示:

可以看到Client、LocalStream、RemoteStream 是对外暴露的部分,为了实现平稳迭代升级,如下图所示,新方案的第一个版本整体架构没有变化。

在改造过程中,团队还对原有的开源代码做了优化。以 Client 类为例,原始代码多达3500行,现在经过分层优化实现了大幅瘦身;

老方案的代码以 JavaScript 为主,很容易出错,所以新方案转向了 TypeScript 。TypeScript的强类型检查、引用跳转、类型约束等特性可以明显提升开发效率。与此同时,TypeScript 可以支持渐进式迁移,项目无需一次性全部转换到 TS ,迁移成本非常低。

如何解决性能问题

向新方案第一次迁移的过程中,团队就遇到了性能问题,其原因在于主线程的压力过大。典型的前端脚本执行机制如下图所示:

一般情况下,浏览器以 60hz 的速度渲染页面,每 16ms 渲染一次 UI 并执行脚本,16ms 中剩余的时间 CPU 会空闲,但由于界面特别复杂,渲染耗时过长,脚本执行时间就会不足,导致脚本无法正常执行:

第二种情况,JS 代码中包含了 wasm 执行部分,导致脚本执行时间过长,留给渲染的时间减少,就会导致渲染卡顿的现象。

为此,新方案选择用 Worker 通过分工方式来降低 CPU 占用。主线程主要做渲染与采集,其它工作尽可能放到 Worker 中执行。Worker 中有定时器可以做到精确执行,不受 UI 线程渲染影响。加入Worker后整体架构如下图所示:

其中 Worker 线程负责与后端网络通讯,后端先同 Worker 通讯,Worker 再把一部分数据传给主线程。这里的设计原则是尽量减少线程间通讯,避免主线程与 Worker 之间通讯过于频繁增大开销。为此,Worker 端需要更为复杂的设计,包含了大部分耦合度较高的主要逻辑:

优雅管理生命周期

生命周期是指一件事情从开始到终结的完整周期,例如进房到退房、发布到取消发布、订阅到结束订阅等。其中,能够被用户感知到的周期(如进房到退房)称为宏观生命周期。

在开发环境中,一些复杂页面可能并没有明显的开始与结束的区分。如果程序开发中出现大量生命周期,其中存在众多异常情况,程序就要在每一种生命周期出现异常时做判断。如何以更好的模式,优雅地管理这些生命周期,是新 SDK 架构面临的挑战。

除宏观生命周期外还有微观生命周期。以一场分享活动举例,活动开始到结束的过程相当于程序启动到退出的过程。每一位参会者都有自己独立的生命周期,就像程序中每一个生成的对象都有自己的生命周期一样。正常情况下,分享活动会按照流程有序推进直到结束,但有时遇到天气、灾害等不可抗力的因素时,活动就需要立刻结束,这就相当于程序中的突发事件导致生命周期发生了变化。

为了更好地处理微观生命周期,团队引入了 ReactiveX 响应式编程技术。

响应式编程其实就是发布订阅者模式。上图左边的观察者与右边的订阅者形成了一个宏观生命周期。左边开始订阅,生命周期开始;左边的发布者发布结束,生命周期就完成。中途出现异常或者取消订阅,生命周期也会终结。

从上图的代码视角来看,左侧程序主要采集生命周期,用来采集音视频数据。右边代码负责编码。这两者形成了一个生命周期,先采集数据然后编码,两者互相依赖。出现异常时,例如编码生命周期突然结束,就需要通知采集周期同样结束,反之亦然。

使用 ReactiveX 可以清晰地撰写上述生命周期相关的代码,这种编程方式与常见的事件驱动编程模型是有很大不同的。在事件驱动模型中涉及大量回调,程序开发的视角类似于一场活动的主办方视角。主办方要事无巨细地关注活动中的所有细节,开发者也需要对每一个事件的所有逻辑做好处理,这样才能保证程序正常运行。

而发布订阅模式可以称为参与者视角。每一位参与者只关心最终的调遣。比如通知演讲人演讲即将开始,演讲人不用关心之前发生了哪些事件,只要在通知自己开始的时候上台演讲即可。演讲结束亦是如此。

这种参与者视角不直接处理回调,而是将原来的回调转化为一个信号,各个信号再自由组合成需要的信号。组合完成后的信号就是最后要处理逻辑的事件。

上图的 ReactiveX 三极管模型中,有一个主信号不断发出数据,还有控制信号用来终止主信号和响应逻辑。主信号、响应逻辑和控制信号等都有自己的微观生命周期,它们整体形成宏观生命周期。宏观生命周期结束时,就可以通知所有微观生命周期自动结束。宏观生命周期可以通过控制信号控制,而所有的控制信号也是信号,可以被其他控制信号所控制。各种控制信号的组合最终可以实现级联控制:

为了让整个过程更加优雅无痛,团队引入了 Go 语言中的 Context 模型,它是一个可以取消的轻量对象,可以携带少量数据、级联结束,还可以被传递和持有。

例如进房之后,首先创建 roomCtx ,推拉流都依赖于 roomCtx。推拉流操作都可能中途启动或停止,但如果 roomCtx 退房就要结束所有周期。

传统代码要在退房代码中写很多判断。比如退的时候判断是否正在推流,如果是就停止推流,等等。

改用新方式进行实现会优雅许多:在退房的回调函数里只写一行代码取消 Context 。它的取消会触发子级 Context 全部取消,自动将其他微观生命周期全部终止。这样就无需关心其它生命周期的状态,只需关心 Context 是否结束即可。这样就实现了更优雅的生命周期管理,有效减轻了开发过程中的心智负担。

目前这套 SDK 新方案还在开发之中,预计在性能、稳定性等指标上会有明显提升。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021-12-21,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 背景介绍
  • 新老架构对比
  • 如何解决性能问题
  • 优雅管理生命周期
相关产品与服务
实时音视频
实时音视频(Tencent RTC)基于腾讯21年来在网络与音视频技术上的深度积累,以多人音视频通话和低延时互动直播两大场景化方案,通过腾讯云服务向开发者开放,致力于帮助开发者快速搭建低成本、低延时、高品质的音视频互动解决方案。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档