新东方教育科技集团定位于以学生全面成长为核心,以科技为驱动力的综合性教育集团。新东方线上教育业务的云教室系统支持了视频直播、转码、点播等新东方所有在线教育场景。随着业务量的增大,由于直播转录及视频转码任务处理平台具有明显的波峰波谷特性,自建机房较低的资源利用率成为了业务的核心痛点。
为了提升计算资源利用率,进一步实现降本提效目标,在几次尝试之后,新东方踏上了 Serverless 实践之路。以下内容是由新东方教育科技集团云教室直播平台技术负责人 么敬国 在云栖大会的分享。
新东方除了自己的线上教育业务使用云教室平台以外,还通过美刻云直播对外开放了新东方的直播能力。云教室直播平台主要支持四种业务模式:
直播+录播是新东方主推的课程交付模式。直播课程互动性强,可以实现良好的课堂互动,激发学生的学习兴趣;教师可以基于学生的课堂反馈或互动直接与学生进行互评,便于教师及时对教学环境作出微调,从而让教学过程更有针对性;通过互动和课堂答疑,可以让教学过程和效果更有保障,直播课程比较适合低幼年龄段的学生。
而面对高中及高中以上年龄段的学生,录播课更为合适,录播课特点为学习时间灵活,学生可以自主对学习内容进行检索,进行有选择性的学习,一般适用于高中和高中以上年龄段学生。录播课的优点在于可以对授课内容不断进行打磨、编辑,制作精品课程,需求量逐步加大。最初团队采用地录制技术方案为客户端录屏,将老师的直播进行录制,方便学生反复观看,但这样的方式出错率高, CPU 占用率也较高,无法对录制 UI 布局进行灵活定制,只能是看到什么录什么,这样的方式仅能满足低幼年龄段的课程需求。今年,新东方开始对接大学生线上教育业务,对录播课程的质量提出了更高的要求。团队开始考虑采用服务端录制的方式解决问题。服务端录制的两个核心点在于直播录制和视频标准化生产。我们的业务模式决定了我们很难准确预测业务量,因此,新东方关键的技术任务是实现计算弹性。
三种选择,函数计算脱颖而出要解决服务端录制的问题,摆在团队面前的有三个可选的技术路线:
经过反复比对,新东方团队选择使用函数计算来解决服务端录制问题。
我们首先在录播转码场景下进行了尝试。录播转码的核心诉求是对直播流进行实时转码,保存为标准的视频格式,方便后续加工使用。
在这个场景中,我们第一次感受到了函数计算 FC 带来的弹性优势。在老师进入房间发起转码请求后,可快速启动函数实例进行转码。在上课结束后,结束转码任务,将临时音视频结果上传至云存储后即可立即释放函数实例,不会存在任何计算资源的浪费。
有了在录播转码项目中应用函数计算的经验以后,我们对函数计算方案有了更大的信心。
之后,我们启动了云端录制项目。使用 Chrome 浏览器加入直播房间,对浏览器界面进行截屏录制,该方案的关键在于弹性提供浏览器实例。
因此,我们利用阿里云函数计算启动 Linux 容器,在 Linux 容器运行 Chrome 浏览器实现弹性提供浏览器实例。
整个的录制流程是这样的:老师进入教室以后,开始进行音视频推流以及白板操作。同时,录制平台发起录制请求,启动函数处理,开始接收教室的音视频流和白板操作,并在浏览器展现整个教室的画面,同时做截屏。课程结束后,平台发起结束录制请求,函数计算平台会优雅地终止实例。终止之前,实例会将临时结果上传至云存储,随后函数实例被销毁,整个过程不存在任何资源浪费。
我们认为,可观测能力对于函数计算平台至关重要。首先,业务高峰期需要启动大量函数实例,因此,必须要完整的 metrics、log 和 trace 才能有效对海量实例进行监控。其次,因为函数计算实例按需创建,完成任务之后被销毁,平台必须保存完整的日志,以便发现问题后开发人员进行排错。
我们曾在开发录制服务的过程中面临的问题是:启动函数实例以后,Chrome 浏览器要访问直播服务,此时网络出现问题,导致录制失败。后续我们使用阿里云 SLS 日志平台查看日志,发现 Chrome 浏览器内核对网络处理过于敏感。找出问题后对症下药,加入了重试机制,问题得以解决。
在使用函数计算技术之前,我们期望它能通过百毫秒拉起上万个实例,定时预热彻底解决冷启动困难,帮助我们承载直播转码和录屏业务业务洪峰。有效应对大规模突发在线流量,按量付费,提高资源利用率,减少 20% 资源成本开支,极大程度降低运维成本,让我们可以只专注业务创新。
在实际使用的过程中,我们发现函数计算不但能够中我们完美满足我们的需求,还带来了惊喜:让我们的开发人员只需掌握几个新概念、使用几个 API ,即可轻松使用平台。函数计算方案运行一段时间以来,云资源费用得到较大降低。另外,函数计算允许根据自己的业务场景制作模板,并且可供其他业务方使用,也为我们带来意外收获。
作者 | 么敬国(新东方教育科技集团云教室直播平台技术负责人)& 灏正(阿里云 Serverless 架构师)
本文为阿里云原创内容,未经允许不得转载。
很好奇,就使用rubyonrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提
当我尝试安装Ruby时遇到此错误。我试过查看this和this但无济于事➜~brewinstallrubyWarning:YouareusingOSX10.12.Wedonotprovidesupportforthispre-releaseversion.Youmayencounterbuildfailuresorotherbreakages.Pleasecreatepull-requestsinsteadoffilingissues.==>Installingdependenciesforruby:readline,libyaml,makedepend==>Installingrub
我真的为这个而疯狂。我一直在搜索答案并尝试我找到的所有内容,包括相关问题和stackoverflow上的答案,但仍然无法正常工作。我正在使用嵌套资源,但无法使表单正常工作。我总是遇到错误,例如没有路线匹配[PUT]"/galleries/1/photos"表格在这里:/galleries/1/photos/1/edit路线.rbresources:galleriesdoresources:photosendresources:galleriesresources:photos照片Controller.rbdefnew@gallery=Gallery.find(params[:galle
导读:随着叮咚买菜业务的发展,不同的业务场景对数据分析提出了不同的需求,他们希望引入一款实时OLAP数据库,构建一个灵活的多维实时查询和分析的平台,统一数据的接入和查询方案,解决各业务线对数据高效实时查询和精细化运营的需求。经过调研选型,最终引入ApacheDoris作为最终的OLAP分析引擎,Doris作为核心的OLAP引擎支持复杂地分析操作、提供多维的数据视图,在叮咚买菜数十个业务场景中广泛应用。作者|叮咚买菜资深数据工程师韩青叮咚买菜创立于2017年5月,是一家专注美好食物的创业公司。叮咚买菜专注吃的事业,为满足更多人“想吃什么”而努力,通过美好食材的供应、美好滋味的开发以及美食品牌的孵
我认为我的问题最好用一个例子来描述。假设我有一个名为“Thing”的简单模型,它有一些简单数据类型的属性。像...Thing-foo:string-goo:string-bar:int这并不难。数据库表将包含具有这三个属性的三列,我可以使用@thing.foo或@thing.bar之类的东西访问它们。但我要解决的问题是当“foo”或“goo”不再包含在简单数据类型中时会发生什么?假设foo和goo代表相同类型的对象。也就是说,它们都是“Whazit”的实例,只是数据不同。所以现在事情可能看起来像这样......Thing-bar:int但是现在有一个新的模型叫做“Whazit”,看起来
我有一个要在我的Rails3项目中使用的数组扩展方法。它应该住在哪里?我有一个应用程序/类,我最初把它放在(array_extensions.rb)中,在我的config/application.rb中我加载路径:config.autoload_paths+=%W(#{Rails.root}/应用程序/类)。但是,当我转到railsconsole时,未加载扩展。是否有一个预定义的位置可以放置我的Rails3扩展方法?或者,一种预先定义的方式来添加它们?我知道Rails有自己的数组扩展方法。我应该将我的添加到active_support/core_ext/array/conversion
我正在尝试将一个资源属性的默认值设置为另一个属性的值。我正在为我正在构建的tomcat说明书定义一个资源,其中包含以下定义。我想要可以独立设置的“名称”和“服务名称”属性。当未设置服务名称时,我希望它默认为为“名称”提供的任何内容。以下不符合我的预期:attribute:name,:kind_of=>String,:required=>true,:name_attribute=>trueattribute:service_name,:kind_of=>String,:default=>:name注意第二行末尾的“:default=>:name”。当我在Recipe的新block中引用我
参见下面的示例,我想最好使用第二种方法,但第一种也可以。哪种方法最好,使用另一种的后果是什么?classTestdefstartp"started"endtest=Test.newtest.startendclassTest2defstartp"started"endendtest2=Test2.newtest2.start 最佳答案 我肯定会说第二种变体更有意义。第一个不会导致错误,但对象实例化完全过时且毫无意义。外部变量在类的范围内不可见:var="string"classAvar=A.newendputsvar#=>strin
我是(相当)一位经验丰富的程序员,但对Ruby和RubyonRails完全陌生。RoR看起来很适合快速工作,特别是用于CRUD操作的自动屏幕生成。它确实能让您快速提高工作效率。问题是最后20%的工作,那时我必须完成我的申请。RoR公约不会妨碍我吗?因为不是每个数据库表都必须对所有用户可用,也不是所有用户都可以编辑所有列和/或所有行,而且View必须适应我网站的外观等。我知道RoR已成功用于现场,但在第一阶段烧毁后,如何在RoR中获得足够的速度以逃避重力。 最佳答案 我认为脚手架无法让您达到80%。脚手架很好,因为它向您展示了Rail
如果我构建了一个应用程序来访问来自Gmail、Twitter和Facebook的一些数据,并且我希望用户只需输入一次他们的身份验证信息,并且在几天或几周后重置,那会怎样是在Ruby中动态执行此操作的最佳方法吗?我看到很多人只是拥有他们客户/用户凭证的配置文件,如下所示:gmail_account:username:myClientpassword:myClientsPassword这看起来a)非常不安全,b)如果我想为成千上万的用户存储此类信息,它就无法工作。推荐的方法是什么?我希望能够在这些服务之上构建一个界面,因此每次用户进行交易时都必须输入凭据是不可行的。