写点什么

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

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

评论

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

专访阿里巴巴研究员吴翰清:白帽子的网络安全世界观

五分钟学大数据

网络安全 采访

那些打不垮你的,终究使你更强大

小天同学

读书 励志 个人感悟 4月日更

Flink中的状态编程

大数据技术指南

flink 4月日更

Flink的基石

五分钟学大数据

flink 4月日更

未来已来,HarmonyOS 开发者日全记录

清秋

华为 开发 物联网 新闻 HarmonyOS

方寸之间,书写天地

石云升

4月日更 1 周年盛典 我和写作平台的故事 InfoQ 写作平台 1 周年

CTO 说要接入实时音视频 SDK,我到底该批多少预算?

融云 RongCloud

手把手教大家实现一个电子签名

麦洛

Java canvas

这个GItHub上的Java项目开源了 2021最全的Java架构面试复习指南

比伯

Java 编程 架构 面试 程序人生

趣题与算法(1)

阳龙生

不为人知的网络编程(十二):彻底搞懂TCP协议层的KeepAlive保活机制

JackJiang

TCP 即时通讯 IM

计算机原理学习笔记 Day10

穿过生命散发芬芳

计算机原理 4月日更

架构实战营作业2

冷酷小绵羊

泰山版震撼来袭!阿里巴巴Java面试参考权威指南四月版开源

Java架构追梦

Java 阿里巴巴 架构 面试

推进智慧城市建设 博睿数据亮相长三角城市数字化转型高峰论坛

博睿数据

数字化转型高峰论坛

架构思维

无心

架构

欢迎参与 KubeVela 官方文档翻译活动

阿里巴巴云原生

容器 云原生 开发工具 OAM 资源调度

架构实战营模块1作业指导

华仔

#架构实战营

最新分享:如何避免线程安全的坑?看这一篇就够了

学Java关注我

Java 编程 程序员 架构 计算机

开源 1 年半 star 破 1.2 万的 Dapr 是如何在阿里落地的?

阿里巴巴云原生

Java 微服务 云原生 中间件 API

企业如何做数字化转型?想要资产状况及时把控,它的作用至关重要!

一只数据鲸鱼

数据挖掘 数字化 数据可视化 资产管理

GitHub面试题库+阿里巴巴2021年Java岗面试26大核心专题,成功助我砍下7家大厂Offer

Java架构追梦

Java 阿里巴巴 架构 面试

Linux free 命令

一个大红包

linux命令 4月日更

如何在云中构建数字核心

云计算

【全球年青人召集令】Hello World,Hello 2050

阿里巴巴云原生

容器 开发者 云原生 活动

简单了解InnoDB底层原理

leonsh

MySQL 数据库 innodb

回顾过去,展望未来,我在 InfoQ 写作平台的一周年!

JackTian

程序员 个人总结 4月日更 1 周年盛典 InfoQ 写作平台 1 周年

2021安擎昇腾AI服务器产品发布会在京成功举行

DT极客

华为云AI论文精读会2021第一期:高效语义分割模型Fast-SCNN分享

华为云开发者联盟

AI 华为云

如何提高Linux水平

cdhqyj

知乎万赞回答:程序员面试为什么被要求造航母,而工作拧螺丝?

Java架构师迁哥

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