写点什么

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

  • 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:503503

评论

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

Vue中如何在线预览pdf文件

y

产品经理第 0 期训练营第九周作业提交

Krystal

2021金三银四总结面试必备清单:字节/蚂蚁金服/腾讯/百度

比伯

Java 程序员 架构 互联网 技术宅

「产品经理训练营0期」第八周作业

🌟

产品 产品经理训练营

一文搞懂 Flink Stream Join原理

shengjk1

flink源码 flink join

systemedctl使用指南

happlyfox

3月日更

携手百度智能云推动实现工业AR空间智能化

百度大脑

AR 百度智能云

产品经理训练营 Week11 学习心得

Mai

用户路径地图与漏洞模型

思亭

用户路径地图 漏洞模型

结合 Flink 学习装饰者模式

shengjk1

flink源码 flink源码分析

阿里混沌工程平台实践

心远

阿里巴巴 混沌工程

this指向

y

this指针

你有没有领导力?

石云升

领导力 28天写作 职场经验 管理经验 3月日更

作业 - 第八章 数据分析

hao hao

Android 系统开发做什么?

吴小龙同学

产品经理训练营第八章作业

新盛

「架构师训练营 4 期」 第十二周 - 001&2

凯迪

架构师训练营 4 期

继承

y

继承

用户路径地图+漏斗模型总结

mas

产品 0 期 - 第八周作业

曾烧麦

产品训练营

maven项目下的重复依赖校验

程序员架构进阶

maven 持续集成 28天写作 3月日更 Jar包扫描

产品经理训练营 Week11 作业

Mai

第八章作业-用户路劲图

z

云原生AI成过去式,AI原生的云才是通向未来的“藏宝图”

脑极体

用户路径地图+漏斗模型

mas

Flink SQL 自定义 Source format

shengjk1

flink sql

一文搞懂 Flink 处理水印全过程

shengjk1

用户路径地图

王一凡

架构师:始于理性思考,成于科学实践——郭东白老师分享总结

青春不可负,生活不可欺

成长 架构设计 架构师

API 工具链研发的理论基础 - 导读

李宇飞

工具链 API sdk

数据分析

王一凡

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