学而思网校直播课堂架构演进之路
学而思网校是好未来教育集团旗下在线教育品牌,为 6-18 岁孩子提供小初高全学科课程辅导。近年来,网校业务高速发展,学而思网校逐渐发展成按照学科拆分的多套大班双师课堂,不仅业务形态各异,而且技术实现也不同。并且,随着用户量的快速增长,性能瓶颈凸显,稳定性风险高。为此,学而思网校教学环节后端负责人吕本伟在 2019 年开始整合多套单体应用,落地微服务架构。为深入了解学而思网校直播课堂的架构实践详情,InfoQ 记者采访了学而思网校教学环节后端负责人吕本伟。
学而思网校的业务特点
据吕本伟介绍,学而思网校的业务有三大特点:
1. 主要服务 K12 人群,涵盖从幼儿园小班到高中的在校学生。业务模型比较复杂,线下教学有教学大纲编写、教材设计与印刷,有报名、分班、排课、课中教学、课后作业、考试等环节。与之对应,在线教育也有课件设计、课程生产、报名分班、虚拟直播教室等。与线下不同的是,一名老师可能会给几万人进行在线授课,为此演变成双师模式:主讲老师负责课中教学,班主任老师为学员提供辅导、答疑等服务。业务流程如图所示:
2. 与线下课外辅导班类似,网校的业务流量有明显的周期性:每年暑期、寒假是流量高峰,每周五晚、周六和周日也是流量高峰,是平时流量的数倍。今年受疫情影响,整个在线教育行业高速发展,在读学员量也快速增长,而面对的技术挑战尤为显著。
3. 网校的每位用户都属于大额消费用户(简称大 R),他们对稳定性更敏感,对系统要求更高。
面临的挑战
从 2019 年暑期后,吕本伟带领团队开始进行新系统开发。当时,它们有 4 套按学科拆分的系统,面临着一些问题:
1. 功能复用性比较差
很多功能有较强的学科定制性。比如,语文学科老师看到数学学科有一个比较好的功能,也想使用,需要等待排期开发;一个新需求可能需要四个团队分别开发一遍,这样不仅极大地增加了工作量,而且浪费了时间、人力和各种资源。
2. 业务耦合严重
据悉,多次因为非核心业务,甚至其他部门的微小变更导致学员上课环境出现问题,造成非常不好的影响。
3. 性能与稳定性状况频出
同时上课的学员有几倍的增长,在一个教室同时上课的学员也有几倍的增长,老系统在某些场景的性能跟不上,小问题频发,甚至出现多次线上事故,最终也需要人员花费大量的精力值班来解决线上客户投诉问题。
直播课堂架构升级实践
通过整合多套单体应用,他们想整合为能支持未来 3 年的系统。具体来说,有三个目标:
业务扩展性高:可以低成本支撑新学科、新业务线,低成本扩展新功能;
性能扩展性高:具备支撑每日千万学员在线学习的能力,弹性扩缩容;
稳定性高:5 分钟内发现问题,15惊悚片 分钟内止损
为此从 2019 年下半年开始,吕本伟带领团队启动对多套单体应用的整合,首先基于 DDD(领域驱动设计)的理念进行领域拆分、解耦。
吕本伟提到,行业内做架构设计一般精简为以下三个层面:
业务架构——分析业务需求,设计业务模块及其关系
系统架构——设计系统和子系统的模块
技术架构——选择采用的语言、框架、存储等
DDD 的核心理念是深入理解业务痛点,面向业务演进构建清晰合理的业务架构,并映射到系统架构;后续迭代中,追求系统架构低成本随业务架构进行演进。微服务架构追求设计出来的系统架构和业务一致,达到系统层面的功能复用。工程实现时,系统模块可以按需灵活选择技术架构,遵循职责单一的原则高度自治,去中心化地治理数据;模块间“高内聚、低耦合”,最小依赖降低风险。
具体来讲,主要是从几个方面实施:
按照业务职责进行领域拆解,梳理、精简领域间交互原语——梳理业务架构
从领域中寻找核心实体和关键行为,人为拆分为有清晰职责边界的限界上下文,并按照 DDD 上下文映射的思想进行集成,明确各 BC 间的交互关系——系统架构雏形
按照平台化思路进一步思考各个限界上下文间的“变”与“不变”,“不变”的部分沉淀为平台核心功能,对于易变的部分采用防腐层设计进行解耦
领域拆解
在整合之初,组织层面已按照需要解决的问题领域拆分成不同的部门:
课程生产:依据教学大纲和师资情况生产讲课场
内容生成:依据教学内容进行课件编排
招生排课:拉新、续报
课中教学:主讲老师直播授课
视频直播:音视频基础设施支持
辅导答疑:班主任老师提供课下服务
但是由于历史原因,在系统层面几大领域依然"藕断丝连"。
直播课堂最核心的业务场景为进教室与课中互动,举例看下“课中教学”领域和其他领域之间的耦合情况。进教室环节核心功能为验证是否已临近上课时间、学员是否购课、完成教室直播间初始化等工作,对课程生产领域、招生排班领域的核心依赖应该是比较轻量的。现实情况是,进教室时需要关注场次是标准场次还是非标场次、甚至需要关注什么是大纲、什么是场次包等等信息,对于课堂来讲是严重的信息过载。
课中互动环节也存在类似的问题,学员作答互动题,需要了解诸如课件、讲义、自传互动题等等信息。
系统解耦
面对上述问题,他们采取了三个措施:
1. 统一领域语言
梳理自身业务上下游依赖,进行走访、串讲,搞清楚各自团队的核心术语,形成一套“交互原语”。团队内部各系统实现、wiki 记录均遵守该原语。
跨部门之间,按照最小依赖的原则,减少要暴露的信息。
2. 问题分解——子域拆分,界定核心域、支撑域、通用域
按照 5W1H 原则讲述用户故事(user story),明确系统要解决的核心问题(即核心域),要解决这一核心问题的关键依赖(即支撑域)以及其他周边依赖(即通用子域)。如下图所示
以进教室这一业务场景为例,我们划分的核心域为“课堂教学”,支撑域为“班课”与“互动”,诸如用户、信令、课件等均有行业通用解决方案或可以通过外包等方式获得的模块归于我们的通用子域。
(班课:即上课日程管理系统,包括班级、课程、上课直播场次等数据)
3. 划分限界上下文及上下文映射
梳理出核心概念对象和关键行为,基于此进行人为的限界上下文的拆分。
我们抽象出虚拟教室这一上下文作为系统的核心,由它对外部依赖(课件、直播流等)进行集成。一方面明确上下文之间的依赖关系;另一方面提前思考将来的架构演进,尤其对于会扩展或替代的依赖(比如班课),我们参考 DDD 的防腐层设计进行影响隔离。
平台化——进一步抽象
前文提到,期望打造的系统将来可以更好的赋能多业务线、可以低成本扩展新功能,基于通用子域的思考,让每个非核心依赖具备可替代的能力;基于防腐层的设计可以很好的提升单个系统扩展能力,开了个好头,按照平台化的方式进一步思考:
可为哪些角色赋能?如何赋能更多用户?
可提供的核心功能有哪些?
易变的模块如何低成本替代或扩展?
如图所示,课堂的六要素都是可变的,每个互动功能是相对稳定的,为此抽象为:
双师课堂 PaaS:
班课:统一领域实体抽象;制定 API 对接规范,新业务按照规范开发 API 进行对接
课件:目前网校大部分课件统一由一套课件平台生产,课件与终端之间有标准的通信协议;其他平台生产的课件可以适配该协议完成对接使用;另外,沉淀出一套课件课前预下载、元信息课前预拉取、基于信令的发题 & 收题、教师侧互动统计等标准化作答流程。
视频直播:和众多娱乐直播平台类似,一般为自研源站 + 动态 CDN 调度的方式。不同的业务成本预算不同、对服务质量要求也不同,作为平台方提供质量分级能力
互动能力 SaaS:双师课堂中诸如红包、送礼、连麦等互动功能可根据不同的年级、学科进行开启或关闭、使用不同的 UI 展示等。同时,需开放标准化流程与协议,允许部分业务团队进行个性化扩展。
基于对直播教室和互动的定位思考,团队将服务拆分为:
大班双师直播教室:以直播课提供服务,师生上课的虚拟空间
录直播教室:以录播课的形式提供,学员可参与少部分互动
临场互动:老师即兴发起的诸如红包、送礼、连麦等互动
教学互动:依赖课件进行的 H5 互动,大多为题目作答类互动
小组互动:同组学员一块完成的竞争或合作的游戏类互动
激励:诸如连对称号、金币等激励
在每个服务集内,进一步按照“高内聚、低耦合”以及“职责单一”的原则进一步拆分成独立的微服务,比如大班直播教室类比现实世界,需要从外部对接班课、课件、学员、老师等信息,为此抽象出“课堂中心”与“用户中心”等核心服务,完成班、课、场、人的信息封装,以及外部系统的适配工作。最终沉淀出下图中所示业务架构中的“后端服务层”。
从单体到微服务
在整合前,大家的共识是采用微服务架构,但具体的实施经验不多。因此,分成三个阶段:
1. 打底基础设施。统一语言(Golang)、框架(Gin/RPCX),自研脚手架、日志等类库,统一解决微服务注册发现、日志监控、CI/CD 等基础问题。
2. 微服务开发
结合前文提到的上下文映射关系,按需采用 RPC 或 MQ 进行通信;
工程组织分为两层:
业务 API:根据业务规则进行灵活变化
业务服务:根据职责进行抽象沉淀
3. 基础设施升级。统一解决 Trace、全链路压测、流量录制与回放、建设放火平台模拟故障、搭建预案平台等工作。
解决性能瓶颈
随着在线教育的快速发展,用户量不断攀升,他们不断面临性能上的压力。据吕本伟介绍,他们逐步去优化性能瓶颈。
1. 持续完善基础设施,比如链路追踪、影子库、全链路压测、流量录制与回放等;
2. 上游依赖数据自治,异步化处理,解耦外部依赖
比如,课堂环节对班课系统是强依赖,但班课数据变更频次较低,为此,他们采取预热缓存 + 事件驱动更新的方式解耦数据层面的强依赖,独立自治。一方面提高系统稳定性,另一方面也获得更好的性能。
3. 业务上支持小班模式,优化并发模型解决教师端性能瓶颈。
在小班模式下,教师端可能需要同时给几百甚至几千个班级同时发送指令,原来遍历发送的方式变得不适用,因此需要调整发送模型来解决类似的性能瓶颈。
4. 热 Key 问题
前面有提到在线教育的流量有较强的潮汐性,大量的学员会在几分钟内暴涨。另外,某些互动场景会导致“惊群”现象,老师一个信令大量学员同时请求后端,造成所谓的热 Key 现象。尤其对于 10 万级学员同时上课的情形,可能会达到 Redis 单实例的性能上限,影响是灾难性的。目前,对于这种情况,我们采用前端机本地缓存的方式解决读场景;对于写场景,有些是在客户端进行指令级削峰,有些是在服务端进行削峰处理。
稳定性提升
之前多次线上事故是依赖“人”的反馈:学员遇到问题 ->反馈给家长 ->家长反馈给客诉 ->反馈给研发,效率低下。为此,从事前预防、事中干预、事后规避几个维度进行稳定性建设,逐步夯实稳定性。
从单体到微服务,业务架构的升级不仅让系统的复用带来人效的提升,而且资源隔离,提升了功能模块扩容的便利性。并且,核心与非核心的资源隔离,避免了交叉影响,稳定性得到很大提升。
架构领域的新尝试
当前,他们正在尝试进一步提高自动化。据悉,网校的部分业务在自建机房,还有部分业务在云上。吕本伟表示,随着业务的高速发展,核心业务具备快速扩容能力是一个基本要求。并且,在线教育的流量有较强的潮汐性,这类业务上云是比较经济的选择。因此未来一段时间的探索是建设多机房,以及基于 Kubernetes 的弹性扩缩容。
其次,他们还在尝试不断提高智能化。在他看来,课中学员与老师之间的亲密度建设至关重要,但是老师的精力是有限的。所以,他们正在探索结合大数据和 AI 的能力赋能课堂教学。
活动推荐
除了学而思的架构分享外,在 2021 年 1 月 8-9 日 QCon 北京站上,业务架构专场还有阿里大麦网业务架构演进、快狗业务架构及快手业务架构演进,从大麦网的票务系统到快狗车网调度,再到快手短视频的架构演进,不同的业务场景来阐述架构演进的过程、难点及解决思路。更多演讲资讯,关注 QCon 全球软件开发大会。
查看大会最新日程