服务热线
18914430266
几年前,很多人对在线网课还非常陌生。随着移动设的普及和音视频技术的发展,如今在线教育产品百花齐放。而在线教育产品能服务千万学子离不开流媒体分发技术的支撑。本次LiveVideoStackCon
2021 音视频技术大会北京站邀请到了网易有道研发工程师周晓天,为我们分享网易有道在线教育业务的流媒体分发相关内容。
大家好,我来自网易有道精品课研发团队。如今音视频被各界广泛关注,“直播+”成为一个热点,大也纷纷推出了一系列音视频的相关服务。
网易有道是一家以成就学习者“高效学习”为使命的智能学习,依托强大的互联网AI等技术手段,围绕学习场景,打造了一系列深受用户喜欢的学习产品和服务。除了面向多种场景的在线教育平台,还有有道词典、有道词典笔等市场的软硬件学习工具。
音视频技术内容广、链条长、每个点又会很深。所以今天分享的内容以有道的在线教育业务为主题,聚焦在有道团队流媒体分发服务端的部分。
今天的内容分为三个部分,分别是有道在线教育业务介绍、分发系统架构的演进和对分发难点的思考与实践。
不同班型对应着不同需求。2013年左右出现的是1V1课程、普通小班课。本质上是借助RTC实时通信模式构建的教育产品。后来游戏直播和娱乐直播被大家熟悉,而这个阶段被熟知的在线学习的主要形式是视频点播模式,比如网易公开课。随着音视频领域技术成熟,以及用户对在线教育需求的升级,直播网课迅速发展。直播课大约出现在2014年,在疫情后得到了空前的关注。
传统大班直播课是老师的单向推流,在互动大班课中,学生可以和老师进一步互动,获得更好的上课体验。学生连麦、屏幕/白板、老师视频和互动消息构成一节课的主要内容。
互动小班进一步优化产品的互动性,提升学员课堂参与感、学习体验与学习效果。音视频+H5互动组件+灵活的布局需求也带来额外复杂性。
面向业务设计服务,需要理解不同业务的差异再去采取相应的技术。这里提供一种思考的方式:以互动大班课为例,一个老师和一个学生正在连麦,再将连麦的过程分发给其他学生。对于流媒体分发,右侧列出一些考虑的要素:需要什么程度的延迟和流畅性?多大的规模?需要多高的媒体质量?当前业务线对方案成本的敏感度?
进一步可以用这种方式横向对比不同课程形态,通过它们的区别获得更精细的需求。
比如,对比大班直播课和互动大班课:对于规模为M的会话,大班直播课要把一个人的信息分发给M-1个人,这可以通过基于CDN的视频直播方式做到。如果进一步想要给产品增增加连麦互动性,成为互动大班课。连麦的增加会让简化模型变为两个部分,如何在一个教室内同时满足这两个需求?简单的思路是在原有CDN分发的基础上,让连麦内容通过RTC方式交换,再将它们的信息通过原有CDN系统分发,但这么做会带来内容延迟和用户切换延迟等问题。
对比互动大班和(线上、线下)双师班级,虽然模型类似,但具体到场景中双师班级中的一个“学生端”可能对应一个线下教室的全体学生,这会增加单路分发异常的代价,这样的差异也就要求系统能对不同场景配置不同策略。
除了在线教育,横向对比的思路同样可以用来分析其他场景的业务线,例如普通小班和游戏开黑。开黑看似和只发送语音的普通小班课程类似,但是在性能和网络占用方面要求更严格。在尽量不占用游戏带宽的同时,还需要尽量减少CPU的操作,为游戏提供充足的算力。如果直接用小班课程的RTC接口用于游戏,保证通话质量的同时反而会影响游戏。如果期望使用一套系统支持多种业务,那么在系统设计早期就要明确业务差异和设计需求。
通过以上的分析,可以列出了在线教育业务对媒体分发系统的一些主要需求点。要满足分发低延迟、上麦低延迟。第二点要做大规模分发。相对一些娱乐场景,要做到高稳定以及高可用。第四点要对成本进行控制。后,不同学生、不同教室对于上课场景的需求是不同的,所以一定要支持多端接入。
当多个业务线到小班、到大班直播、再到互动大班以及互动小班等课程,这会影响分发系统的演进过程。一种思路是随着业务的演变,分发架构逐渐复杂,不断支持越来越多的特性。有道并没有采用该思路,而是经历了从基于CDN的分发,到全部业务使用实时通信网络(RTN)的切换,没有架构上的中间过渡状态。
基于CDN网络的直播内容分发的树状架构十分清晰,架构本身决定数据的路由,同时易于维护、风险和成本可控。当一个用户选定一个边缘接入,媒体数据的分发路由就已经规划好了。同时它有自身的缺点,比如:只支持单向分发、协议带来的固定延迟等。
早期通过CDN模式部署的直播为了增加互动性和降低延迟,在CDN架构的基础上做了两个优化。一方面在边缘拉流节点支持RTC的方式接入(图中也写为RTN边缘节点),从而屏蔽掉媒体封装协议带来的延迟、不锈钢加工件增加IM互动效果,同时还能增加弱网抗性。另一方面为了进一步增加互动性,增加了RTC旁路系统以支持双向连麦,再将连麦内容转推到CDN网络中完成直播。一些“低延时CDN直播”产品就采用这样的原理。
刚刚提到用于连麦的旁路RTC系统需要转推内容到CDN分发网络,那是否能让这个系统把CDN大规模分发的任务也一起做了呢?于是就有了纯RTN的架构。该架构不再有鲜明的树状分发结构,而是用一个网状拓扑分发所有内容。任意单向拉流客户端可以随时切换为双向通信,不需要先做系统的切换。
通过上述的分析,我们可以大致总结出业内直播流媒体分发演进的方向——音视频直播CDN和RTC网络边界模糊,逐步融为一体。直播CDN商逐渐从单向大规模分发支持低延迟接入、连麦。之前的RTC产品,从面向小型会议的架构逐步为了能够同时服务千人、万人,也开始将分发网络变复杂。所以现在我们能看到网易的WE-CAN分布式传输网、阿里云GRTN 流媒体总线、以及其它“X-RTN”都是该演进过程的结果。
刚刚提到的架构主要是ToB商的产品,在ToC服务的场景中也会有如上图所示的架构,通过一个媒体服务器融合两个分发网络提供服务,特别是对于同时有自研和三方接入时。该结构在带来新的非功能特性的同时,也有很大的风险。有道没有选择使用类似的架构进行过度,而是直接用RTN分发网络对原有功能进行替代。
该架构能满足多种场景的需求,也支持多种推拉流客户端接入。例如当同学上公开课时,通过微信小程序或者浏览器直接看是为便捷的。已经使用课程APP、已经参加系列课程的用户,使用APP接入以获得体验。
相比CDN架构自身的拓扑结构决定了数据分发路由,RTN网状拓扑在带来灵活性的同时也增加复杂性。比如路由无法从拓扑直接获取,而是需要一个额外的调度中心去计算、规划路由,完成对应转发资源的调度,这也凸显了RTN架构下调度中心的重要性。
图中也有一个CDN旁路的部分,他的主要作用是做一些突发接入量过大的课程的负载均衡,增加系统的弹性。
有道在设计网络节点拓扑的时候更偏向于灵活性。一方面,分发节点没有分层、分级,采用扁平拓扑。另一方面,通过配置不同的属性、角色可以实现对网络分发特性的改变。
对于流媒体分发系统有以下四个要点——接入问题、网络连通性、路由建立以及转发。除此之外还想分享一下关于分层设计和通道的概念。
解决接入问题的核心理念是“就近”接入——网络质量的接入为“近”的接入。(不同类型的业务可能会有不同思路:有道的教学场景中力求现有每个用户体验尽可能,类似于贪心算法;但在别的业务中,思路可能会是在达到QoS限制的情况下选择全局成本的接入、路由方式)直观的方法是使用基于IP、位置的接入推荐。进一步利用对不同网关网络探测、连接历史数据优化推荐的结果。除了利用线上、线下数据统计获得的先验的知识进行接入推荐,考虑到这样的方法无法涵盖所有特殊形况,有道还引入人工配置的支持。支持手工热配对部分ToC场景非常有效
右下角是一个大班课老师上行丢包率打点图,可以看到存在有规律的、平均在9%左右的丢包。该老师长期在固定地点使用固定设进行直播,而且早期还有技术支持同学进行过网络检查,网络一直很好。按照之前的算法,他的位置没有变、网络没有变,使用的推荐数据库也变化不大,所以根据算法每次会给出相同的推荐结果。突然出现的有规律丢包推测是流量行为被运营商识别、分类,并对其进行了策略限制。
面对这种情况,修改算法是行不通的。通过有道热配置的方式,在发现问题进行上报的同时就可以人工修改配置,下一次老师接入会避开对应接入节点,解决丢包问题。
我们通过“过滤器”机制实现该操作:假如所有可接入节点构成一个池子,那么终“过滤”出的结果构成推荐给客户端进行接入的列表。所以把过滤规则的计算过程作为算法写入系统,将算法执行要使用的参数作为可以热更新的数据写在数据库来实现。
接入只解决了分发网络的入口问题,那么分发网络究竟是怎样的拓扑形态呢?这就涉及到网络节点的连通性设计问题。有道的网络是一个扁平的拓扑,每个机房都是拓扑中扁平的点。理论上可以给所有节点之间都建立连接,成为一个mesh网络,那么这样的网络将会无比灵活,任意一条通路都可以被规划出来,完全依赖算法进行实际路由的选择。有道并没有采用这样的方式。
我们还是引入了一些人工经验,比如根据经验将一些机房的连通性删除,成为非Full mesh的结构。可以认为是借助人工的方式进行了剪枝、组织。除了连通性,在路由计算时还需要解决权重的获取问题,也就需要对节点连接情况差异进行量化描述。这种量化是基于规律性的QoS探测完成的,类似前面接入选择的问题,算法可能没法精细地满足所有case或者一些特殊情况,那么在量化差异外,我们也通过可配置的属性描述定性的差异来增加拓扑的灵活性。
之所以这样提高灵活性、支持人工配置,是为了能满足不同业务的差异化需求。同时也有代价,就是复杂性的提高。所以或许没有的架构,只有更合适的架构。
在确定了接入位置(明确了分发的起点和终点)、建立了分发网络的连通性后,要解决的就是路由规划或者说调度问题。这里可以为大家分享的实践和思考有三点:一条路由的规划、多路径还有成本控制。规划单条路由是完成数据分发的基础,我们根据动态探测、刷新的网络QoS量化质量和基于当前节点状况、节点配置共同完成路由权重的计算。有了无向带权图、有了终点和起点,就可以计规划一条短分发路由。
解决了接入问题,又完成分发网络连通性定义,现在解决了媒体数据分发路由的规划,看似就可以完成分发任务了。但对于有道的业务要求这还不够,想进一步保障用户体验就需要提升分发网络对抖动、丢包的抗性。多路径分发是一种保障方式。有道分发网络有三种路径——主要路径、选路径、实时路径。主要路径直接用于业务分发;选路径是主要路径的份,在规划主要路径时生成,当主要路径异常时切换。实时路径是在主要路径之外额外建立的多路冗余分发路径,以提供更加强大的分发抖动、丢包抗性,这对一些重点任务、大规模分发任务有很高价值。
以图上橙色线路为例。边缘是移动、联通和电信三个单线机房,除了主路径之外,可以在两个边缘的联通运营商之间建立实时路径,在实现实时份的情况下降低份线路成本。
控制中心完成数据分发路径的规划后,就需要沿途节点执行转发任务。这涉及到高性能流媒体分发服务器的设计。上图显示了有道的转发服务器线程模型。协议、端口对应不同的线程,从而在有限端口情况下尽可能利用多核资源。
除了每个协议-端口对会绑定一个IO线程,还有一个core线程,完成来自不同接入的数据包路由。比如一个推流用户从协议A端口A1接入(如使用UDP,从3000端口推流),同会话另一个拉流用户采用协议B端口B1接入(如使用TCP,从0端口拉流),这两个用户根据IO线程模型不可能分配到同一个线程,所以需要进行跨线程数据转发。此时core线程会根据会话发布订阅的关系,将接收队列的内容向对应IO线程的队列进行转发。
该线程模型的设计和业务类型、比例也是相关的。当时系统负载以大班课为主,即推流人数大大小于拉流人数。如果业务类型发生变化,例如班型越来越小、课程每个成员都进行推流,而服务器总用户量如果不变,这会让core线程的转发负载相对大班课大大增加。这也是小班课业务带来的一项挑战,需要架构能随业务变化灵活应对。
除了上面四个关键问题外,借本次机会想额外分享、探讨两个细节:分层设计和通道的概念。
分层设计相当于转发问题的延伸。服务器拿到来自一个连接的数据以后,通过core线程分发。逻辑结构上可以理解为三层:链接层解决不同协议连入的问题;路由层负责处理数据在内部的分发、转移;会话层维护了发布订阅关系,指导路由进行分发,将数据发到正确的连接。该分层思想不仅用在单机线程模型中,也用在整个分发网络中。
当业务方接入一个实时通信SDK时,关于“通道”不同ToB商会有不同定义,简单理解就是对实时媒体传输资源的一种抽象。比如一些商所服务的业务场景的主要数据是人脸和屏幕共享,对应SDK可能就只提供两个通道资源,其中人脸通道支持大小流的同时推送。
上图以互动大班课为例介绍有道在“通道”设计方面的思考。左下角图片展示了互动大班的典型教师上课效果:右上角是主讲的老师,正在和左边的学生进行连麦,那么如何进一步把当前界面所有信息传递给其它学生?有道实时通信SDK提供了Live、RTC、Group等多个通道资源。SDK向外暴露的通道资源数量可以定义,同时可以差异化配置,虽然名字不同但是底层资源属于同一类。一个通道对应一路同步的音视频的分发能力。
仍以刚刚的场景为例:示意图左侧是教师,右侧是学生。橙色是RTC通道,不锈钢加工件这部分完成老师和学生的连麦。随后教师在端上进行混流——将连麦内容、课程白板等内容混为一路音视频通过Live通道向其它听课的学生发送。比如可以通过获取当前屏幕内容来做端上的混流。在互动大班型的业务场景下,所有学生需要获得信息都在这一张图里,都是视频和音频的媒体信息,这样就可以采取两个通道组合的方式,一个连麦、一个直播,从而完成整个业务。
不同的通道之所以有不同的名字而不是使用一个通道对象数组,是为了进一步降低客户端接入门槛。比如Live通道概念上相比RTC更强调流畅性,这可以对应一个更大的视频小缓冲区来提升网络抖动抗性。
业务中发现SDK提供通道这种资源的方式可能会影响业务方的思考方式:如果只有“人脸通道”和“屏幕通道”,这可能会限制业务产品对新课程形式的思考。
借本次机会可以和大家分享有道关于互动小班的尝试,在以下两个方面和大家交流:小班的“互动”到底是怎样的?以及互动课程的录制问题。
在小班课中,多位学生和老师全程可以连麦。不同的同学可以随时被拉到台上进行分享、答题。除了音视频、白板这些基本内容之外,我们还加入了一些互动元素:本地媒体元素播放、多人实时互动棋盘等。这样的互动元素带来什么影响呢?
前面提到的互动大班课可以在端上混再发送到Live通道,这样流既可以省去需要单独服务端混流带来的视频延迟和同步问题,同时完整地传递了所有课程信息。但是对于互动小班课,如果老师端通过这种截取屏幕将内容分发给其他学生的方式,就会丢失互动元素的可互动性、布局也无法改变。当一个学生回头看录播的时候无法进行参与,只能作为旁观者看到别的同学的互动过程。这也是互动小班课个难点——互动元素如何处理?如何进行录制?回放的时候如何保持同步?实际中是有很多坑点和挑战。
这里的部分内容截取自 ToB 商对痛点的分析,自研所遇到的问题可以分为以下几点:
成本:除了人力、资源覆盖、动态扩缩容的运维等,还有与之对应的机会成本。前两点都比较重要。另外不同业务带宽峰值位置不同,复用一套基础设施和带宽资源可以降低资源、能源的消耗。
边界:比如是否加入特殊配置解决业务问题,团队内做自研对于业务需求的边界如何把握的问题?
系统优化门槛:当跑通上文提到的所有内容后,业务可以跑起来。但如果想要进一步压缩成本,就需要对更深技术栈的理解,比如数据驱动的全链路传输优化,编解码的优化,难度和所需的人力可能都会更高。
对音视频基建的理解:音视频逐步成为一种基建,但如果团队只通过三方SDK的方式接入音视频能力可能无法深刻理解音视频技术的难点、无法正确评估风险、无法把握潜在的机会。
更多原子能力:自研技术可以根据复杂的业务需要按照业务线进行更灵活的配置,用合理的方式暴露更深的接口,这会让业务层获得更大的灵活性。
对产品、研发、技术支持提供帮助:音视频技术涉及广泛且复杂,让客户端研发同学、技术支持同学对业务出现的异常准确排错、根据埋点数据分析问题原因是很困难的。依赖音视频自研团队对业务中遇到的问题进行积累、理解更深层的原因、排查未来可能出现的隐患是一种行之有效的方法。通过音视频自研团队可以辅助产品进行设计、加速研发对音视频技术的落地,还能辅助技术支持在业务中确定用户问题原因、提早发现更深的隐患。毕竟再快的工单系统可能也无法比隔壁工位的支持来的更快。
成本控制、面向业务优化:当能操控的技术越底层,针对特定业务能做的优化空间也就越大,进一步优化体验的同时也有更多成本压缩的空间。
在 code_pc 项目中,前端需要使用 rrweb 对老师教学内容进行录制,学员可以进行录制回放。为减小录制文件体积,当前的录制策略是先录制一次全量快照,后续录制增量快照,录制阶段实际就是通过 MutationObserver 监听 DOM 元素变化,然后将一个个事件 push 到数组中。
为了进行持久化存储,可以将录制数据压缩后序列化为 JSON 文件。老师会将 JSON 文件放入课件包中,打成压缩包上传到教务系统中。学员回放时,前端会先下载压缩包,通过 JSZip 解压,取到 JSON 文件后,反序列化再解压后,得到原始的录制数据,再传入 rrwebPlayer 实现录制回放。
在项目开发阶段,测试录制都不会太长,因此录制文件体积不大(在几百 kb),回放比较流畅。但随着项目进入测试阶段,模拟长时间上课场景的录制之后,发现录制文件变得很大,达到 10-20 M,QA 同学反映打开学员回放页面的时候,页面明显卡顿,卡顿时间在 20s 以上,在这段时间内,页面交互事件没有任何响应。
页面性能是影响用户体验的主要因素,对于如此长时间的页面卡顿,用户显然是无法接受的。
经过组内沟通后得知,可能导致页面卡顿的主要有两方面因素:前端解压 zip 包,和录制回放文件加载。同事怀疑主要是 zip 包解压的问题,同时希望我尝试将解压过程放到 worker 线程中进行。那么是否确实如同事所说,前端解压 zip 包导致页面卡顿呢?
对于页面卡顿问题,首先想到肯定是线程阻塞引起的,这就需要排查哪里出现长任务。
所谓长任务是指执行耗时在 50ms 以上的任务,大家知道 Chrome 浏览器页面渲染和 V8 引擎用的是一个线程,如果 JS 脚本执行耗时太长,就会阻塞渲染线程,进而导致页面卡顿。
对于 JS 执行耗时分析,这块大家应该都知道使用 performance 面板。在 performance 面板中,通过看火焰图分析 call stack 和执行耗时。火焰图中每一个方块的宽度代表执行耗时,方块叠加的高度代表调用栈的深度。
可以看到,replayRRweb 显然是一个长任务,耗时接近 18s ,严重阻塞了主线程。
而 replayRRweb 耗时过长又是因为内部两个调用引起的,分别是左边浅绿色部分和右边深绿色部分。我们来看下调用栈,看看哪里哪里耗时比较严重:
熟悉 Vue 源码的同学可能已经看出来了,上面这些耗时比较严重的方法,都是 Vue 内部递归响应式的方法(右边显示这些方法来自 vue.runtime.esm.js)。
为什么这些方法会长时间占用主线程呢?在 Vue 性能优化中有一条:不要将复杂对象丢到 data 里面,否则会 Vue 会深度遍历对象中的属性添加 getter、setter(即使这些数据不需要用于视图渲染),进而导致性能问题。
在上面的代码中,创建了一个 rrwebPlayer 实例,并赋值给 rrWebplayer 的响应式数据。在创建实例的时候,还接受了一个 eventsRes 数组,这个数组非常大,包含几万条数据。
数据没有预先定义在 data 选项中,而是在组件实例 created 之后再动态定义 this.rrwebPlayer (没有事先进行依赖收集,不会递归响应式);
数据预先定义在 data 选项中,但是后续修改状态的时候,对象经过 Object.freeze 处理(让 Vue 忽略该对象的响应式处理);
数据定义在组件实例之外,以模块私有变量形式定义(这种方式要注意内存泄漏问题,Vue 不会在组件卸载的时候销毁状态);
重新加载页面,可以看到这时候页面虽然还卡顿,但是卡顿时间明显缩短到5秒内了。观察火焰图可知,replayRRweb 调用栈下,递归响应式的调用栈已经消失不见了:
可以看到问题还是出在 replayRRweb 这个函数里面,到底是哪一步呢:
由于 rrweb 录制回放 需要进行 dom 操作,必须在主线程运行,不能使用 worker 线程(获取不到 dom API)。对于主线程中的长任务,很容易想到的就是通过 时间分片,将长任务分割成一个个小任务,通过事件循环进行任务调度,在主线程空闲且当前帧有空闲时间的时候,执行任务,否则就渲染下一帧。方案确定了,下面就是选择哪个 API 和怎么分割任务的问题。
这里有同学可能会提出疑问,为什么 unpack 过程不能放到 worker 线程执行,worker
线程中对数据解压之后返回给主线程加载并回放,这样不就可以实现非阻塞了吗?
如果仔细想一想,当 worker 线程中进行 unpack,主线程必须等待,直到数据解压完成才能进行回放,这跟直接在主线程中 unpack
没有本质区别。worker 线程只有在有若干并行任务需要执行的时候,才具有性能优势。
提到时间分片,很多同学可能都会想到 requestIdleCallback 这个 API。requestIdleCallback 可以在浏览器渲染一帧的空闲时间执行任务,从而不阻塞页面渲染、UI 交互事件等。目的是为了解决当任务需要长时间占用主进程,导致更高优先级任务(如动画或事件任务),无法及时响应,而带来的页面丢帧(卡死)情况。因此,requestIdleCallback 的定位是处理不重要且不紧急的任务。
中渲染任务结束且还有剩余时间,才会执行。这种情况下,下一帧需要在 requestIdleCallback 执行结束才能继续渲染,所以
30ms,如果长时间不将控制权交还给浏览器,会影响下一帧的渲染,导致页面出现卡顿和事件响应不及时。
这样看来 requestIdleCallback 似乎很完美,能否直接用在实际业务场景中呢?答案是不行。我们查阅 MDN 文档就可以发现,requestIdleCallback 还只是一个实验性 API,浏览器兼容性一般:
查阅 caniuse 也得到类似的结论,所有 IE 浏览器不支持,safari 默认情况下不启用:
而且还有一个问题,requestIdleCallback 触发频率不稳定,受很多因素影响。经过实际测试,FPS 只有 20ms 左右,正常情况下渲染一帧时长控制在16.67ms 。
在项目中,考虑到 api fallback 方案、以及支持取消任务功能(上面的代码比较简单,仅仅只有添加任务功能,无法取消任务),终选用 React 官方源码实现。
查阅 rrweb 文档得知,rrWebplayer 实例上提供一个 addEvent 方法,用于动态添加回放数据,可用于实时直播等场景。按照这个思路,我们可以将录制回放数据进行分片,分多次调用 addEvent 添加。
按照上面的方案,我们重新加载学员回放页面看看,现在已经基本察觉不到卡顿了。我们找一个 20M 大文件加载,观察下火焰图可知,录制文件加载任务已经被分割为一条条很细的小任务,每个任务执行的时间在 10-20ms 左右,已经不会明显阻塞主线程了:
优化后,页面仍有卡顿,这是因为我们拆分任务的粒度是 100 条,这种情况下加载录制回放仍有压力,我们观察 fps 只有十几,会有卡顿感。我们继续将粒度调整到 10 条,这时候页面加载明显流畅了,基本上 fps 能达到 50 以上,但录制回放加载的总时间略微变长了。使用时间分片方式可以避免页面卡死,但是录制回放的加载平均还需要几秒钟时间,部分大文件可能需要十秒左右,我们在这种耗时任务处理的时候加一个 loading 效果,以防用户在录制文件加载完成之前就开始播放。
有同学可能会问,既然都加 loading 了,为什么还要时间分片呢?假如不进行时间分片,由于 JS 脚本一直占用主线程,阻塞 UI 线程,这个 loading 动画是不会展示的,只有通过时间分片的方式,把主线程让出来,才能让一些优先级更高的任务(例如 UI 渲染、页面交互事件)执行,这样 loading 动画就有机会展示了。
使用时间分片并不是没有缺点,正如上面提到的,录制回放加载的总时间略微变长了。但是好在 10-20M 录制文件只出现在测试场景中,老师实际上课录制的文件都在 10M 以下,经过测试录制回放可以在 2s 左右就加载完毕,学员不会等待很久。
假如后续录制文件很大,需要怎么优化呢?之前提到的 unpack 过程,我们没有放到 worker 线程执行,这是因为考虑到放在 worker 线程,主线程还得等待 worker 线程执行完毕,跟放在主线程执行没有区别。但是受到时间分片启发,我们可以将 unpack 的任务也进行分片处理,然后根据 navigator.hardwareConcurrency 这个 API,开启多线程(线程数等于用户 CPU 逻辑内核数),以并行的方式执行 unpack ,由于利用多核 CPU 性能,应该能够显著提升录制文件加载速率。
这篇文章中,我们通过 performance 面板的火焰图分析了调用栈和执行耗时,进而排查出两个引起性能问题的因素:Vue 复杂对象递归响应式,和录制回放文件加载。
对于 Vue 复杂对象递归响应式引起的耗时问题,本文提出的解决方案是,将该对象转为非响应式数据。对于录制回放文件加载引起的耗时问题,本文提出的方案是使用时间分片。
由于 requestIdleCallback API 的兼容性及触发频率不稳定问题,本文参考了 React 17 源码分析了如何实现 requestIdleCallback 调度,并终采用 React 源码实现了时间分片。经过实际测试,优化前页面卡顿 20s 左右,优化后已经察觉不到卡顿,fps 能达到 50 以上。但是使用时间分片之后,录制文件加载时间略微变长了。后续的优化方向是将 unpack 过程进行分片,开启多线程,以并行方式执行 unpack,充分利用多核 CPU 性能。
思否技术先锋年度榜单正式发布。网易有道技术团队同时登榜思否年度技术团队榜单和中国技术品牌影响力企业。
2022年1月13日,SegmentFault 思否作为中国的新一代开发者社区,根据社区用户行为大数据(如文章 & 问答发布数量、不锈钢加工件获得声望 & 点赞量等)综合分析,评选出了 30 个杰出的年度技术团队。
本次终评选出 30 支年度技术团队,有道技术团队入选,登上思否2021中国技术先锋年度榜单,荣获思否年度技术团队称号。
本文为网易有道企业发展高级效能项目经理张浩然《研发效能实践助力互联网行业项目管理“行之有效”》的演讲内容,围绕研发效能的实践和项目管理两个主题展开。
我写分享PPT的时候,起初想的是针对于互联网行业的项目管理。但现在不止是互联网,传统行业也在做数字化转型。所以,这个项目管理是全行业都可以一起探讨的。我之前做研发,后面主要做项目管理,过程中做过一段时间的产品管理。目前主要在网易有道企业发展部,做整个研发效能的推广和项目管理的提升。
有道纵横是网易有道旗下专为4-8岁量身打造的在线年启动,自研了全国首部在线交互式围棋动漫课程,从的理解力和喜好出发,采用直播互动的课程形式将围棋知识变得简单有趣、易懂好学,帮助掌握围棋的各类规则和技巧。不仅如此,课后还设有AI对弈功能,能够智能识别的段位水平匹配对局练习,从根源培养的思维习惯。每局对弈结束后的智能分析,会从大局观、计算力、稳定性、战斗和棋型五方面进行全方位分析,帮助在复盘中进步。
Google旗下Deepmind提出的AlphaGo、AlphaGo Zero、AlphaZero系列算法展示了深度强化学习在棋类领域超凡的能力。2016年AlphaGo横空出世击败欧洲围棋冠军樊麾二段,2017年以4:1击败韩国围棋职业九段,14个世界冠军得主李世石,2018年无师自通的AlphaGo Zero以3:0击败年轻的六冠王柯洁九段。至此以后再无人质疑AI在围棋领域的霸主地位,同时引发了职业棋手学习AI招法的热潮。在职业围棋赛场上,时常出现“狗招”,学习、研究AI招法的背后的逻辑,已是职业棋手的必修课。
本次以Redis为范例,阐述了有道基础架构团队在基础设施容器化道路上的实践,主要将从声明式管理,Operator工作原理,容器编排,主从模式,集群模式,高可用策略,集群扩缩容等方面展开。
Redis 是业务系统中较为常用的缓存服务,常用于流量高峰、数据分析、积分排序等场景,并且通过中间件可以实现系统之间的解耦,提升系统的可扩展性。
传统物理机部署中间件,需要运维人员手动搭建,启动时间较长,也不利于后期维护,无法满足业务快速发展的需求。
云原生相较于传统IT,可以助力业务平滑迁移、快速开发、稳定运维,大幅降低技术成本,节约硬件资源。
云原生中间件是指依托容器化、服务网格、微服务、Serverless等技术,构建可扩展的基础设施,持续交付用于生产系统的基础软件,在功能不变的前提下,提高了应用的可用性与稳定性。
在这种大趋势下,有道基础架构团队开始了云原生中间件的实践,除了本文介绍的 Redis,还包括 Elasticsearch、ZooKeeper 等。
以上信息由泰州拓锐金属制品有限公司整理编辑,了解更多不锈钢精密铸造,不锈钢浇铸件,不锈钢加工件信息请访问http://www.yzqlhzp.com
如果您有任何问题,请跟我们联系!
联系我们
Copyright © 2018-2020 泰州拓锐金属制品有限公司 版权所有 备案号:
地址: 手机:18914430266(刘总)