1.3 整体架构设计:直播、互动与回放三条线

概念弄清楚之后,我在白板上把整个平台画成了三条线:直播线负责音视频怎么传,互动线负责课堂消息怎么走,回放线负责课后视频怎么存、怎么发。这三条线各自独立、又在课堂这个场景里交汇。之所以一开始就分线设计,是因为它们的故障模式完全不同——直播卡了是音视频问题,聊天室刷屏是消息问题,回放看不了是存储分发问题。分开之后排错、扩容、压成本都能按线处理,互不拖累。

三条线各用什么产品

线路 涉及产品 数据流向
直播线 TRTC 老师推流 → TRTC 房间 → 学生拉流
互动线 IM 聊天、举手、系统通知在课堂群里广播
回放线 COS 与 CDN 云端录制入 COS → CDN 分发 → 学生点播
质量监控 云监控 三条线的指标统一采集、统一告警
业务服务 云服务器 排课、鉴权、课堂状态管理,串起三条线

直播线是主干,互动线贴着直播线跑,回放线在课后才真正发力。业务服务器是三条线的交汇点:开课时由它创建房间和课堂群,下课时由它触发录制文件处理。这套结构在后面迭代了一年多,始终没做过伤筋动骨的改动。

三条线的产品选择也不是拍脑袋定的。互动线选 IM 而不是自己在 WebSocket 上撸一套聊天,一来群组、消息漫游、离线推送这些能力 IM 已经备好,二来 3.2 节要讲的举手连麦信令完全可以复用消息通道,不用额外维护一条长连接。回放线用 COS 加 CDN 的组合,则是看中存储和分发的解耦:源文件在 COS 里安安静静存着,分发速度交给 CDN,两边可以各自优化、各自计费。

一堂课的完整链路

光看产品拼图还是抽象,我把一堂课从头到尾的时序拆开列在下面。这张表后来成了我和机构老师对需求时的通用语言,谁在哪个环节出问题,顺着表一指就清楚。

步骤 动作 涉及线路
1 学生打开课堂页面,业务服务校验身份与上课时间 业务服务
2 学生进 TRTC 房间,拉老师的老师画面与声音 直播线
3 学生在 IM 课堂群发消息、抢答、提问 互动线
4 学生举手,老师同意后学生上麦推流 直播线加互动线
5 下课后,云端录制文件落入 COS 存储桶 回放线
6 回放页从 CDN 拉取视频,学生按目录复习 回放线

第 4 步是最能体现两条线配合的环节:举手本身是 IM 消息,上麦本质是 TRTC 角色切换,老师在同意的那一刻由业务服务通知两端同时动作,任何一端慢了半拍,学生就会看到“已经被叫起来但画面没出来”的尴尬场面。

这张时序表后来还被我用作了验收清单:每接一个新功能,先看它在链路上落在哪一步,会不会把前后步骤的接口改坏。比如后期加“随堂测验”,它的位置在第 3 步和第 5 步之间,挂在互动线上,和直播线完全解耦——学生在等题目的时候,老师的讲课画面是一秒都不能卡的。

各模块职责划分

三条线确定之后,我把每个模块的职责也固定了下来,避免开发时互相推诿。这张表建议在团队里过一遍再开工,能省掉大量扯皮的时间。

模块 职责 不做什么
TRTC 房间 音视频传输与连麦调度 不管聊天内容
IM 课堂群 聊天、举手、公告等消息广播 不传音视频
云端录制 把房间音视频录成文件 不管文件存储与分发
COS 存储桶 录制文件落地、生命周期管理 不做播放加速
CDN 回放加速与防盗链 不存源文件
云监控 全链路指标采集与告警 不参与业务逻辑

边界清晰之后,每个模块的选型、压测、成本优化都能单独推进。比如后来回放流量上涨,我只需要调 CDN 的缓存策略,完全不用动直播线的代码,这就是分线设计带来的好处。

“不做什么”这一列列出来的时候,团队里还讨论过录制归谁。云端录制本身只在上课时工作,产物是文件;文件落进 COS 之后怎么管、谁在管,就是存储层的事。这条边界让 4.2 节的生命周期管理可以完全独立演进,不用拉着音视频模块一起改。

部署拓扑:哪些东西放哪里

架构图落在部署上其实很轻:一台云服务器跑业务服务,承载排课、鉴权、课堂状态管理;TRTC 房间和 IM 课堂群都在云服务的后端,我们只管调用;COS 存储桶开了几个,按课程体系分目录;CDN 接上回放域名;云监控盯住前面所有东西。整个平台我们自己维护的机器只有那一台业务服务器,其余全是云服务,这对小团队的意义不用多讲。

部署拓扑还有一个设计原则:无状态的部分尽量托管,有状态的部分握在手里。课堂的排期、学生名单、权限这些业务数据放业务服务自己的数据库;音视频流转给云服务;视频文件托管给 COS。真要迁移或扩容的时候,要动的只有业务服务那一层。

容灾与降级的初步考虑

三条线架构另一个好处是天然支持降级。直播线挂了,互动线还在,老师可以先用语音加文字把课上完;互动线挂了,直播线还在,大不了临时用外部群沟通;回放线是课后的事,和上课完全错开,完全不影响课堂进行。弱依赖的模块之间互相兜底,整个平台的可用性比把鸡蛋放一个篮子里高得多。云监控负责在第一时间告诉我哪条线在报警,这部分的实战配置我放在 5.2 节展开。

顺带说明,三条线的思路对排课也有影响。系统排课时会把一节课的三条线一起初始化:创建 TRTC 房间、创建 IM 课堂群、预约录制任务。三件事在一个事务里完成,任何一件失败就整节课回滚,避免出现“有房间没聊天室”这种半拉子状态。课堂结束后也是统一下课:解散群、销毁房间、确认录制文件落盘。一致性这根弦从设计第一天就要绷紧,不然线上数据会越积越乱。

这份架构最后还通过了机构负责人的一次“灵魂拷问”:如果明天学生数量翻三倍,系统撑得住吗?答案是三条线的扩容方式各不相同:直播线和互动线是云服务,弹性由厂商保障,我们要做的只是提前确认套餐余量;回放线靠 CDN 缓存,翻三倍流量也主要是缓存命中率的问题;真正需要评估的只有业务服务器那一台。架构拆清之后,“撑不撑得住”这个问题从玄学变成了可以逐项回答的清单,这也是我喜欢这套设计的原因。

一句话版本

整套架构压缩成一句话,就是:老师推流到 TRTC 房间,聊天和举手走 IM 课堂群,房间录制成文件后落入 COS,学生课后经 CDN 点播回放,云监控全程盯梢。这句话挂在我们团队协作区的墙上,新来的兼职开发看一眼就知道平台怎么转。

再展开半句:所有跨线的协调动作(开课、下课、上麦同意、录制回滚)都由业务服务器发起,它是唯一有“全局视角”的角色。为什么不让客户端直接相互通信?因为客户端的网络环境千差万别,让一个可靠的中心节点做裁判,比让三十个终端互相协商稳定得多。这也是为什么业务服务器虽小,却是整套架构里最不能掉链子的一环。

这套架构也不是没有代价。代价是业务服务器的实现复杂度集中:它要对三条线做协调,任何一条线的接口变动都会牵动它。所以我把业务服务的接口按线分了包,每条线的协调逻辑互不混杂。这算不上优雅,但对十人团队刚刚好——维护复杂度可控,排错时跟着线走就能定位到问题模块。

架构设计小结

设计决策 理由
三线分离 故障隔离,各自扩容
业务服务器统一协调 客户端环境复杂,中心裁判更稳
课堂状态一次性初始化 避免半拉子状态污染数据
录制与存储解耦 分发优化不影响课堂

架构想清楚之后,后面几篇就是逐线填代码。下一节先解决最现实的问题:这套架构每个月要花多少钱,以及怎么把预算控制在机构能接受的范围内。

本篇从选型到概念、从架构到成本,形成了一个完整的决策闭环。从下一篇开始,我们进入真正的代码实战,先从 TRTC 房间的接入讲起。

为什么三条线要分开设计

分线设计还有一个考虑:三条线的资源消耗节奏完全不同。直播线随上课时间走,一小时课消耗一小时时长;互动线随在线人数走,消息量与并发挂钩;回放线的流量则在课后集中爆发,而且可以慢慢优化。如果揉成一团,一条线的波动一定会连累另外两条。比如开学季回放流量猛增时,因为回放走的是 CDN,直播课堂数据完全不受影响。三线分离的本质是“把不稳定隔离在各自的桶里”,这个原则在我后来做扩容和成本复盘时反复被验证是对的。

再往前想一步,分线还方便定责任。出故障的时候第一句话永远是“哪条线挂了”,而不是“谁的代码挂了”。监控大盘按线分屏,告警按线分组,值班表自然也按线排。对一个兼职运维的团队,这种清晰度比任何花哨的架构图都实用。

架构图有了,下一节就要面对最现实的问题:这样一套东西每个月要花多少钱。如果你对云产品计费方式还不太熟悉,可以先翻翻 《腾讯云实战清单》 里的计费章节;对监控指标体系感兴趣的,《数据看板实战》 可以为第 5 篇的质量监控打打基础;想扩展自动化运维能力的,也可以提前了解 《1Panel 面板常见问题》 中的服务器管理技巧。

延伸阅读