写点什么

作业帮直播间前端架构优化实践

  • 2022-06-22
  • 本文字数:3266 字

    阅读完需:约 11 分钟

作业帮直播间前端架构优化实践

背景介绍


作业帮的直播间以信令为基础做教师端,学生端的同步渲染。整个直播间包括推拉流,流媒体渲染,聊天区,课件区,连麦, 通用互动等功能,其中课件区包括 H5 课件、Cocos 课件、白板、互动题、小游戏等。整体课件区内容的呈现是在 Webview 里,Webview 运行时聚合了多个不同种类的内容。下图为作业帮直播间功能简图。


技术难点


  • 终端碎片化带来多种内容渲染的稳定性;

  • 直播间性能保证,整体内存 /CPU 控制,子功能模块内存 /CPU 分配;

  • 信令到达保证及各个环节的有序执行;

  • 容错,任一内容环节出问题,如何保证不影响后续运行;

  • 不同技术栈内容的持续性接入。

现状


前面介绍了整个直播间多背景知识以及前端的一些技术挑战,前端的主要功能区在课件区,可以看下优化之前的老架构,对整体有个粗略的认识。



所有的业务层代码聚合在称之为 zb 的模块,从图中可以粗略看出 zb 模块是一个比较庞大的模块,承载了众多不同技术体系的内容渲染和调度,也是反馈问题的重灾区,运行在一个常驻的浏览器之上。

随着用户规模的不断增大,不同的用户机型设备的增多以及内容的丰富度和效果的提升,我们的 zb 稳定性以及性能遇到了很大的挑战,线上的工单反馈也有上升趋势。来自用户侧反馈的问题大概为以下几类:


  • 课件区黑屏,白屏,花屏;

  • 卡在某一个具体的页面,中断了同步;

  • 卡顿;

  • 互动题做不了;

  • 看不到老师笔记。

问题分析


通过大量的测试以及问题排查列举出我们的架构存在以下问题:


  • Webview 内存占用持续上升,无法及时 GC,内存不足是导致黑白屏的根本原因,Webview 的回收机制对我们来说是黑盒,尤其是基于 DOM 方式的渲染,研发无法通过代码触发 GC;

  • 卡顿的原因来源于一些动画造成 CPU, 内存瞬间增长;

  • 信令全链路到达有丢失,服务 -> NA -> Webview ,NA -> Webview 通信没有机制保障,兜底保证通信代码较多,即使信令到达,执行的时机以及完成时机都有一定程度业务的耦合;

  • 渲染不同内容的调度逻辑耦合较多业务逻辑,逻辑链路较深,排查问题较难;

  • 任一内容的逻辑出错或者报错有可能影响后续信令处理和调度逻辑;

  • 统一运行在同一个 Webview,不同内容的消耗很难通过指标进行量化;

  • 课件区内部分层不清晰,耦合较重;

  • 排查问题与不同角色的技术,边界不清晰,沟通成本高,排查效率低。

设计目标


根据直播间的面临的技术难点以及结合我们目前架构所面临的问题,我们希望新架构能够实现以下几个目标:


  • 底层保证内存及时回收;

  • 底层渲染 Runtime 可切换;

  • 通信可靠性保证(NA/FE);

  • 内容隔离;

  • 调度逻辑与不同内容解藕;

  • 单个内容针对性降低内存 /CPU 并且可量化

实践 & 探索


作业帮直播间的前端架构

容器及 SDK 设计

容器设计


容器的定义


容器是直播间任何内容的载体,容器可以是 Native 容器,里面运行着 Native 的组件,可以是一个 Webview 容器,可以是一个 Cocos 容器。容器有以下几个特点:


  • 载体;

  • 独立无依赖;

  • 生命周期;

  • 独立开发,独立部署。


有了容器之后,我们可以把调度逻辑独立出来,下沉到端,这一层可以更专注任务的调度以及信令的处理,与内容解耦。


容器的状态


容器 SDK 设计


有了容器的抽象,各个内容如何集成到容器内以及如何感知容器的不同的状态切换,需要一个标准 SDK 去帮助封装所有的底层细节,对业务无感。SDK 需要具备以下能力:


  • 生命周期钩子;

  • 支持自定义调试;

  • 支持后续的扩展;

  • 基础工具库。


可以通过下面这张图,简单了解 SDK 的容器周期和实现逻辑:


内容播放器


有了容器以及调度,作为内容的业务开发,可以更专注于某一个内容本身,为了保证后续内容的可持续规范性接入,我们针对不同的内容做了一层抽象,定义为内容播放器。我们的主要播放器有 H5 PPT 播放器,H5 互动题播放器,Cocos 课件及互动播放器,画版播放器等,下面会重点介绍下 H5 PPT 播放器以及详细介绍下 Cocos 播放器架构层面的一些优化方案。

H5 PPT 播放器


这里我们以 H5 PPT 为例来介绍基于新架构播放器的分层,H5 PPT 是由编辑器生产出一份数据 + 资源去驱动内容及动画的展示,参考下图,自底往上分别为: 


1. 容器层,负责播放器运行时;

2. 前端的基础库; 

3. 适配层, 播放器纯渲染层和直播间的适配,包括容器生命周期的桥接,信令的注册与处理 ;

4. 播放器的渲染层。


Cocos 内容播放器设计与优化


Cocos 内容播放器是比较复杂的一个播放器,代码量非常庞大,接下来会重点介绍下我们针对 Cocos 播放器结合新架构做的一系列优化。


当前问题


  • 信令恢复不稳定容易出问题;

  • 加载和恢复性能差,耗时久;

  • 线上问题排查困难,不易锁定。


问题分析


  • 依赖过程的同步同步逻辑,如果出现信令丢失或者信令顺序错误,则会造成逻辑错误,并且后续的所有操作和渲染逻辑都会受到影响;

  • 每次加载 Cocos 引擎、Framework、互动内容都会消耗大量的加载时间,同时依赖过程的恢复逻辑类似于帧同步,决定了断线恢复的时候要恢复之前的所有逻辑,耗时较长,CPU 占用较高;

  • 同步逻辑是同步的 Touch 事件派发,所以数据中的事件表示不出业务逻辑,只有客户端响应后才知道触发了何种逻辑。


解决方案及技术难点


  • 重构信令恢复机制,改为状态同步,状态同步可以解决数据错乱和丢包造成的结果不正确问题,以及恢复时耗时的性能问题,同时排查线上问题也能有明确数据内容来锁定问题。但状态同步有两个问题需要解决:与业务解耦和同步的数据量;

  • 加载性能和内存问题,一个通过采用 Runtime 提前初始化,另一个采用生产时对内容进行标准化限制。


状态同步设计


设计思路:底层捕获输入事件以及渲染数据变化,避免业务感知同步逻辑,状态数据的同步与业务逻辑解耦,降低研发成本,同时增加增量状态和全量状态两种数据,来解决数据量大的问题。

下面这张图是节点状态变化的捕获和分发流程,这个机制在多个端之间也可以正常运作,比如从 A 端捕获的状态派发给 B 端,这就满足的主讲的操作可以同步到学生端的诉求。



下面是状态数据量的优化策略,虽然全部数据已经通过上面的逻辑控制的比较低了,但是为了更高效,并不是每帧都同步全部数据,是在关键帧把数据同步,其它帧只同步增量,这样既保证了数据量也保证了准确性,即使有丢失错乱,但是在下次全量数据是也一定能够恢复正确状态。


内存和 cpu 优化


上一部分容器的抽象,容器可以被调度,可以被销毁,在一定程度可以保证渲染内容的及时回收,接下来这部分针对不同内容做的一些优化手段。内存 /CPU 优化在我们场景中有很多的优化动作,包括客户端独立进程,Cocos 方向等,下面的环节重点介绍基于 Webview 运行时的内容的优化。

浏览器渲染过程



上面是浏览器渲染相关比较核心的一张图,如果你深入理解了浏览器整个渲染流程,就很清楚浏览器会在哪些阶段会有 CPU 以及内存的消耗,我们可以大概列举如下:


  • JS 代码复杂度及运行频率,会导致 CPU 消耗,操作 DOM 也会消耗内存;

  • JS 代码内存泄漏;

  • DOM 会被解析 LayoutObject,所以复杂大量的 DOM 嵌套,会导致 CPU 和内存的消耗;

  • CSS 同样会被解析 Object,复杂的 CSS 规则会导致 CPU,CSS 规则也可能导致 GPU 内存的消耗;

  • 图片资源,解码 CPU 消耗,渲染是高内存消耗;

  • 回流、重绘会导致 CPU 内存增长;

  • 巧用合成层会减少 GPU 内存消耗,要避免层爆炸。

图片渲染过程


  • IO;

  • 解码(CPU 解码,位图 -> GPU);

  • 渲染管线 (顶点计算 / 光栅化 / 片元着色 / 帧缓冲渲染到屏幕)。

图片内存


  • 位深 (color depth (32 /24 …)。

  • 尺寸 (图片分辨率)。

  • 体积 (磁盘存储所需大小)。


图片占用显存的计算方式如下:


width * height * (colorDepth/8) /(1024 * 1024)= X (M)

1024 * 1024 * (32/8)/(1024 * 1024) = 4M


可以看出图片尺寸对于内存的影响较大。

优化手段


  • 图片压缩 / 图片裁剪;

  • GIF 抽帧,GIF 按照 12fps 抽帧;

  • 动画降帧,Lottie 按照设计帧率运行,并降低至 12fps;

  • 互动题题版,运行时按需加载;

  • GIF 作为合成层渲染,GPU 降低较明显;

  • 信令发送频率及数据量降低;

  • 白板相关优化涉及内容较多,不在这里阐述;

  • Cocos 框架优化,在上一部分内容播放器优化里有介绍。

 总结


  • 黑白屏降至千分位;

  • 追查问题高效;

  • 复杂度降低,迭代成本降低;

  • 单一内容问题,不影响后续播放。


作者介绍:


张士标,作帮直播课堂前端团队负责人,致力于课件、互动系统的持续性能优化和探索。

2022-06-22 11:503630

评论

发布
暂无评论
发现更多内容

C 语言数组教程:定义、访问、修改、循环遍历及多维数组解析

小万哥

程序人生 编程语言 软件工程 C/C++ 后端开发

实战rabbitmq-exporter,prometheus实现rabbitmq监控

智慧源点

​我的 2023 年度自我总结

Java 工程师蔡姬

程序员 大厂 年终总结

CodeWhisperer: 让开发效率翻倍的AI助手

不会算法。

替代企业微信、钉钉等平台,WorkPlus打造企业完美的私有化部署解决方案

BeeWorks

旧年好,祝新年更好

阿里云CloudImagine

云计算 视频云

揭密支付安全:为什么你的交易无法被篡改

隐墨星辰

支付系统 签名验签 支付安全 支付系统设计与实现

CloudEon V1.3.0版本发布!

CloudEon开源

WorkPlus私有化即时通讯的标杆,助力企业实现信息管控与保障

BeeWorks

技术写作:漏斗内容策略、认知博客、支柱内容、研究报告、通用门控内容、电子书和教程

小万哥

程序人生 软件工程 博客 后端开发 技术写作

终于!极狐GitLab 支持 ARM 啦!

极狐GitLab

高效视频处理框架BMF实践

轻口味

音视频

跨界宠粉!五粮液包机送“五粉”直击湖南跨年晚会!

新消费日报

INFINI Labs 产品更新 | Console 数据迁移支持 Percentiles 均匀分区

极限实验室

console 极限科技 产品更新发布

IINA for Mac:功能强大的开源媒体播放器

Rose

mac视频播放器 IINA下载 好用的苹果媒体播放器 IINA for Mac下载

快速体验Spark Connect

CloudEon开源

文心一言 VS 讯飞星火 VS chatgpt (169)-- 算法导论13.2 2题

福大大架构师每日一题

福大大架构师每日一题

DAPP矩阵公排模式系统开发

l8l259l3365

什么是数据驱动?它和模型驱动、领域驱动、元数据驱动、DSL驱动之间有什么区别?

canonical

领域驱动设计 低代码 领域驱动 Nop平台

Mac操作系统的专业音频处理软件:Hit'n'Mix RipX DAW PRO

Rose

音频处理器 苹果破解软件下载 Mac音频处理 Hit'n'Mix RipX DAW PRO

炫酷鼠标悬停随机渐变文本动画效果

南城FE

CSS 前端 css动画

Linux学习笔记0 - 三个感想

袁世超

Linux 学习 内核

保护你的游戏服务器——游戏盾的功能和优势

德迅云安全_初启

笔记:写Flink SQL Helper时学到的一些姿势

泊浮目

vscode ANTLR antlr4 FlinkSQL

Casper Network 推出 “DevRewards” 计划:允许所有开发者赚取激励

股市老人

2023 总结:我在上海做程序员的第八年

拭心

android 程序员 年度总结

macOS 上最完整、最通用、最强大的菜单栏日历:Calendar 366 II

Rose

Mac日历软件 苹果破解软件下载 Calendar 366 II中文版 Calendar 366 II Mac下载 菜单栏日历工具

音视频:音视频的编解码 | 社区征文

笨笨的鸟

音视频

WorkPlus:领先的IM即时通讯软件,打造高效沟通协作新时代

BeeWorks

RocksDB深度解析

俞凡

架构

作业帮直播间前端架构优化实践_大前端_作业帮技术团队_InfoQ精选文章