一、背景
项目介绍
励步双师课堂是以录播视频和线下中教老师结合的 AI 智能化面授教学课程。课堂中有三个角色:
- 主播老师: 视频哈佛外教老师,带着小朋友进行英文知识点的教学。主要承载“教”的职能。
- 主教老师: 主要负责引导,陪伴,激励小朋友,组织课堂纪律,关注小朋友上课的情况,和家长进行一对一沟通等等。主要承载“育”的职能。
- 学生: 上课小朋友,2-8 岁。
目前整体的教学组织架构是以深圳研发中心示范班+加盟校区的方式进行教学研发、培训、常规授课。通常新功能会先预发布到深圳示范班预授,稳定后才会发布到其他加盟校区。这样既能保证其他加盟校区稳定教学、又能快速迭代新功能。以下一个简化的组织架构图。
上文已经提到双师课堂是以录播的形式进行教学,必然需要课件视频。其中课件视频会经历几个流程:录制、上传、打点、审核、教学使用。早期起步阶段只有深圳研发中示范班授课,因此课件视频存储在本地机房,在同一内网下能正常使用。随着产品逐渐打磨成形,必然要落地到加盟校区使用。可是一个迫切要解决的问题摆在我们面前:加盟校区如何获取课件视频?
要解决的几个问题:
- 一个课件视频的容量比较大: 1-2G, 一节课的课件视频总和: 2-3G。研发中心的教研人员如何快速上传课件视频和预览课件视频,并且支持加盟校区主播端播放线上课件视频
- 加盟校区外网环境不稳定的情况下,如何保证课件视频流畅地播放.
- 如何在研发中心示范班和加盟校区间针对课件视频做灰度发布和A/B测试
在这样背景下,蒲公英发布平台在内部开始推进。总得来说大概经历3个阶段:
- 阶段1: 课件视频从 “研发中心本地机房” => “云端OSS”
- 阶段2: 课件视频从 “研发中心本地机房” => “云端OSS” => “校区机房”
- 阶段3: 教学资源从 “研发中心本地机房” => “云端OSS” => “发布平台(管理)” => “校区机房”
二、蒲公英总体架构图
上方是蒲公英的总体架构图。最上层是现阶段支持的发布资源类型:课件视频/图片、APP安装包、页面静态资源、互动多媒体资源、docker镜像、脚本文件、Nodejs扩展库DLL等
下半部分是云端和校区的系统:
- CMDB:管理校区资产信息。蒲公英将发布的资源和cmdb的资产信息(校区城市、分校、教室、教学设备、校区服务器)关联一起.
- 版本管理:记录各终端使用的各类资源的当前版本号、历史版本、版本升级依赖.
- 发布平台:后台系统,负责资源的手动发布、自动发布、灰度发布、回滚等发布策略
- Mercedes Server: 负责接收上游发布平台的资源分发消息、转发消息给相应校区节点的Agent服务
- Beetle: 负责上传资源/下载资源
- Talgate:负责Mercedes Server和所有校区节点Agent服务地注册,会话连接管理,消息通信等
- Mercedes Agent: 负责接收Server的分发消息、调度Beetle从云端OSS下载资源、同校区两台服务器的资源同步
- Cadillac: 负责接受校区教室主播端访问内网资源请求、校区教学服务的api gateway.
三、起源
痛点:课件视频文件很大,教研老师上传视频时间长、上传过程出现网络波动或者关闭页面需重新上传。课件打点审核通过后,如何快速提供给示范班使用。
解法:
- 课件系统是一个提供给教研老师制作课件、管理课件的后台系统。它是一个BS架构的WEB系统,上传文件的方式是通过http直传,上传过程中一旦有中断,只能重新上传, 这样大大降低教研老师工作效率。经过调研决定采用tus协议实现断点续传上传大文件。tus协议是一种基于HTTP/1.1和HTTP/2机制用于文件断点续传。这里画了一个大致上传流程图,详细内容请查看tus官方文档(https://tus.io/)。
- 教研老师上传课件后,还需经过审核员预览、审核通过后才能交付使用。因此考虑可以先上传到研发中心的资源服务器,因为是在同一个内网环境,不需要经过外网,这样加快了上传速度。待课件经审核员审核通过后,再经由资源服务器上传到云端OSS。
- 课件视频上传问题已经解决了。但加盟校区的主播端播放视频的优化方案还未到位,考虑到示范班和加盟校区想尽早使用,前线业务不能耽搁的情况下。我们评估了走外网播放视频方案的可行性:校区教学网络外接两条电信线路上网,一条为30M专线网络,一条为200M拨号光纤。互为备份,避免单线故障。我们在研发中心模拟校区的实际网络带宽,使用10台PC 通过有线网卡,同时播放视频,通过监控防火墙出口流量峰值、查看cacti 流量实时状况,并实际在PC 体验视频播放的流畅度
测试结果:流量下行峰值为173.8M,平均值为50M。 流量上行峰值为5M. PC播放视频的实际体验效果不错,流畅度良好.
就这样这套方案平稳地帮我们过滤到下一个阶段。
下面给出早期版本的简化架构图:
相应的简化流程:课件 => 断点续传 => 在线预览播放 => 审核通过,触发上传任务 => 异步上传到oss => 主播端播放课件视频
落地效果:基本满足早期业务需求
四、资源分发
痛点:各校区当地外网环境无法100%保证全天候稳定,主播端在线播放课件视频出现卡顿、加载中现象。极端情况下影响正常授课。
解法:课件资源如果在授课前已经存储在校区的服务器、开始授课时主播端只需要从内网拉取资源,这样就不依赖于外网环境。源着这个思路开始构思一个异地多校的资源分发系统。
Q:资源分发系统的云端Server和分校节点Agent如何端到端的实时通信?
A:复用双师教学系统的长连接网关服务Talgate,各个节点(server, agent)需要先往网关中心Talgate注册,建立长连接数据通道。
Q:如何保证长连接通信双方消息不丢失?
A:ACK+ 超时重传 + 去重
- Server推送消息时,携带一个标识 SID,推送出消息后会将当前消息添加到“待 ACK 消息列表”。Agent成功接收消息后,会给Server回一个业务层的 ACK 包,包中携带有本条接收消息的 SID。Server接收后,会从“待 ACK 消息列表”记录中删除此条消息。【ACK】
- 如果Agent接收不到消息,Server的“待 ACK 消息列表”会维护一个超时计时器,一定时间内如果没有收到Agent的 ACK 包,会从“待 ACK 消息列表”中重新取出那条消息进行重推。【超时重传】
- 如果Agent接收到消息了,but ACK包丢了,导致Server重传消息,可能会让Agent收到重复的消息,这时Agent需要根据SID来进行业务层的去重。 【去重】
Q:Server或者Agent宕机可能导致重传失效。下一次重新连接上,Agent之前有若干条消息丢失,怎么办?
A:Server需要进行完整性检查,利用“时间戳比对”机制,发现Agent“有消息丢失”的情况,可以重新同步丢失的数据。
- Server给接收方Agent推送 task1,顺便带上一个最新的时间戳 timestamp1,接收方 Agent 收到 task1 后,更新本地最新消息的时间戳为 timestamp1。
- Server推送第二条消息 task2,带上一个当前最新的时间戳 timestamp2,task2 在推送过程中由于某种原因接收方 Agent 和 Server连接断开,导致 task2 没有成功送达到接收方 Agent。
- Agent 重新连上Server,携带本地最新的时间戳 timestamp1,Server将Agent 暂存的消息中时间戳大于 timestamp1 的所有消息返回给Agent,其中就包括之前没有成功的 task2。
- Agent 收到 task2 后,更新本地最新消息的时间戳为 timestamp2。通过时间戳机制,Agent 可以成功地让丢失的 task2 进行补偿发送。
Q: 校区Agent收到任务后,开始从云端OSS下载资源,如何避免重复下载,下载资源失败怎么办?
A:Beetle是上传/下载服务组件,部署在校区,负责接收Agent的下载指令,执行实际的从云端下载资源文件的工作。
- Beetle先从本地文件列表检查文件是否已经下载或者下载中,若已经下载则返回成功,若正在下载中则返回下载中,否则执行下一步。
- Beetle计算待下载文件大小 检查是否大于 可用容量(磁盘剩余容量-下载中文件大小),若大于的情况,现在方案是返回失败。后续迭代方案是给资源文件按等级、文件大小做加权值,优先下载权值高的文件。
- Beetle对于大文件的下载,按断点续传下载文件,若出现网络不稳定下载失败,根据配置文件的重试次数,执行重试机制。若重试后无效,返回失败。
- Agent收到下载失败结果,更新分发任务状态为“下载失败”,通知Server任务失败。并触发告警到质量监控平台。
Q: 如果校区存储资源的一台服务器出现故障,如何保证资源正常加载?
A:每个校区部署两台服务器,使用LVS做主机冗余,避免一台机器宕机,出现单点故障。
- Mercedes Server根据校区节在网关注册的先后顺序选举Master,先给校区Master 服务器A发送分发任务,服务器A完成资源分发后,需同步资源给Slave服务器B。
- 使用类Rsync+Sesync的机制实现服务器文件双向同步,双方比对文件列表,若发现缺失则同步资源。
- 如果服务器A出现故障无法使用,服务器B被选举为Master,接管资源分发任务,待故障机器A恢复后,服务器B检查是否有新资源要同步给服务器A, 有则同步资源。
Q: 如果资源没有及时分发到校区节点,如何保证主播端正常加载资源?
A:每个校区的网关服务Cadillac提供查询课件资源文件URL,Cadillac会检查资源文件是否发布,如果发布则返回内网URL地址,若未发布则返回外网URL地址。
另外避免一些误操作导致已经发布的资源丢失的情况,而无法提前发现,建立了一套预警机制:Cadillac每晚11点会查询往后7天所有校区课表的课件资源URL列表,通过http head方法批量检查资源是否存在于内网,若不存在则触发告警、流转到质量监控报警平台。
Q: 如果校区两台服务器都出现硬件故障或者长时间断电的情况下,如何保证主播端正常加载课件资源?
A:主播端当主动探测到校区内网服务器无法工作后,自动切换到外网访问云端服务,加载外网课件资源。
下面给出相应的简化架构图:
相应的简化流程:课件 => 断点续传 => 在线预览播放 => 审核通过,触发上传任务 => 异步上传到oss => Mercedes Server创建课件分发任务 => 选取指定校区的Master服务器、给它发送任务 => Mercedes Agent接收到任务、记录任务、给Beetle发送下载任务、Beetle接到任务、记录下载任务、下载课件 => 校区服务器双向同步资源 => 内网不可用时切换到外网.
落地效果:课件资源不依赖外网环境,主播端正常播放课件视频,提高教学系统的可用性。
五、多类型资源分发、版本管理
痛点:现有课件分发策略粒度比较粗,仅支持自动分发到所有校区。 一旦课件内容有问题,必将影响所有校区的正常教学。
解法:搭建统一发布平台,打通上游业务系统、CI/CD系统和下游资源分发系统。管理资源版本号、发布记录、制定按城市、校区、版本三个维度的发布策略。监控发布流程,出现失败的任务触发告警。
Q: 蒲公英发布平台除了支持课件视频发布外,也支持包括互动多媒体资源、安装包、Nodejs扩展库DLL、页面静态资源、脚本文件、Docker镜像等多种类型资源的发布。不同类型资源是否有共性,能不能抽象成通用的一种资源,实现统一管理?
A:多种类型资源都有一些必要的属性:类型、发布源、版本号、文件名称、文件大小、文件存放OSS地址、MD5值、创建时间等,由此可以抽象成:“资源”、“发布任务”、“发布策略”、”发布任务历史“ 四个实体对象组成蒲公英的基础单元。
Q:其他类型资源的分发方式是否跟课件资源一样:由蒲公英主动推送分发任务给校区节点,再由校区Agent执行下载资源操作?
A:对于主播端、主教端、电子班牌、手表这类安装包,需要客户端执行下载安装操作。显然无法保证客户端24小时在线,蒲公英有发布任务时,很大概率是客户端不在线或者正在授课使用中,无法实时升级。因此被动接受发布任务的方式不适用于客户端升级。所以蒲公英需要提供接口给客户端检查是否有新版本更新,由客户端定期检查和执行升级。另外考虑到所有客户端都是运行在校区内,为了减少外网环境的依赖,大文件的安装包先分发到校区服务器,再由校区网关Cadillac提供版本更新接口,提高客户端升级成功率。
相应的简化流程:课件 => 断点续传 => 在线预览播放 => 审核通过,触发上传任务 => 异步上传到oss => 创建课件分发任务 => 蒲公英发布 => 选取指定校区的Master服务器、给它发送任务 => Mercedes Agent接收到任务、记录任务、给Beetle发送下载任务、Beetle接到任务、记录下载任务、下载课件 => 校区服务器同步资源 => 内网不可用、切换外网.
落地效果:蒲公英统一发布平台上线1个月左右来共发布250+个课件、1000+个互动多媒体资源、20+次客户端版本(主播端、主教端、手表)升级。
六、未来规划
持续优化各服务组件,优化系统使用交互体验,优化用户角色权限 ,解藕业务侧逻辑,解藕部署环境的依赖,引入多租户的组织结构,开放能力给集团其他伙伴使用。
七、经验总结
从技术架构角度来说,励步双师教学系统是一个异地多校的分布式架构,它复杂度来源主要包括:高可用,可扩展性。这里主要介绍了分布式资源分发(蒲公英)平台的架构演进过程,基于业务发展阶段,分别引入资源分发、资源双备、版本管理,灰度发布等功能。
招聘信息
好未来技术团队正在热招前端、算法、后台开发等各个方向高级开发工程师岗位,大家可点击本公众号“技术招聘”栏目了解详情,欢迎感兴趣的伙伴加入我们!
也许你还想看
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。