3.1 IM 集成:群组与消息类型
把音视频房间跑通之后,我做的第一件错事是在建群这件事上栽了跟头。第一次试讲,我把 30 个学生拉进一个普通群,结果课前闲聊全堆在消息历史里,老师讲课时学生的提问瞬间被刷没,老师根本来不及看;第二次我干脆不建群,学生提问只能干喊,课堂安静得像看录播。这两次教训让我明白,课堂消息不是“加个聊天框”的事,群组形态和消息分类得从一开始就设计好。
这一节讲我们最终定下的方案:六类课堂群、六种消息类型、群从课前到课后的完整生命周期,以及谁能对群做什么。
群组类型怎么选
即时通信 IM 一般会提供好几种群组形态,成员上限和消息留存策略各不相同。选错的代价很具体:形态选重了,成员频繁进退的开销大、消息历史膨胀;形态选轻了,学生挤不进来,或者课后想翻提问记录翻不到。我们的选型结论如下:
| 群组类型 | 成员上限 | 消息历史 | 适合的课堂场景 |
|---|---|---|---|
| 直播群 | 万人级以上 | 不存漫游 | 大班公开课,学生随进随出 |
| 聊天室 | 万人级 | 可查询 | 跨班讲座、公开答疑 |
| 公开群 | 数百人 | 保存 | 班级群,可搜索加入 |
| 普通群 | 数百人 | 保存 | 小班互动课,邀请加入 |
| 临时群 | 跟随课节 | 不保存 | 连麦候场、分组讨论 |
| 通知群 | 全量用户 | 仅通知类 | 全站上课提醒、放假通知 |
实测下来的经验:小班课用普通群,消息可漫游,课后学生能翻到自己没跟上的提问记录,老师也能复盘课堂互动密度;大班课必须用直播群,它为“大量成员频繁进退”做过专门优化,进群退群不会把消息通道搅乱,代价是不保存消息历史——但这恰恰是优点,老师讲课时不会被堆积的历史消息拖慢接收速度。
还有一类是全校性的通知群,只发通知不让大家闲聊,实质上是个广播通道。把“通知”和“互动”分开,是我们做的第一个正确决定:家长找通知时不用在几百条闲聊里翻,学生上课时也不会被无关消息打扰。
建群的工程细节
设计定下来,落地还有一堆细节。我们的建群流程跑在业务服务器上:排课时读取课程表和学生名册,调用 IM 的建群能力创建班级群,再把学生逐个拉进群。听着简单,真正上线后踩了三个坑:
一是批量入群要分批。一个年级 200 人一次性全部拉入,接口会限流,部分学生静默失败。我们改成每批 50 人、失败自动重试两次,并在课后报表里对账:名册人数和实际入群人数对不上就补拉。
二是群名要带规则。最初群名是“三年级编程周二班”,重名导致助教经常点错群。后来统一成“学期加课程加班级”的格式,学期结束归档时也好检索。
三是进群欢迎语先写好。学生进群后自动收到一条欢迎消息,写明上课时间、提问方式和纪律公约。省了助教重复回答同样的问题,这是小投入大回报的细节。
消息类型分类
课堂里发的每一样东西,背后都对应一个明确的消息类型。我们把消息分成六类,各自承担不同职责:
| 消息类型 | 课堂用途 | 未读计数 | 备注 |
|---|---|---|---|
| 文本消息 | 提问、回答、讨论 | 计入 | 最常用,注意长度上限 |
| 图片消息 | 传作业截图、拍题提问 | 计入 | 图片本身走对象存储 |
| 自定义消息 | 举手、连麦、禁言等信令 | 不计入 | 见 3.2,绝不用文本拼 |
| 系统通知 | 上课提醒、进退群提示 | 不计入 | 格式固定,可折叠 |
| @提醒消息 | 点名提问、求助老师 | 强提醒 | 老师端可单独筛选 |
| 撤回/删除 | 撤回误发的答案 | 原消息失效 | 限时内可操作 |
自定义消息是整个第三篇的主角。它本质上是一段结构化数据,比文本消息多一个自定义载荷,天生适合承载控制指令。如果用文本消息拼信令(比如约定“举手”两个字代表举手),解析容易出错,学生误发一句“举手”也会触发——这个笑话在试讲时真实发生过。在 3.2 会看到,举手连麦整套时序全是拿自定义消息拼出来的。
关于图片消息要补一句:图片文件本身存在对象存储里,消息只承载一个引用地址,客户端拿到地址再去拉图。存储服务怎么选、桶怎么规划,《腾讯云产品实践》里有完整的对比,我们当时就是照着那张表做的决定。
群组类型怎么选的补充:历史消息怎么处理
选群型还有一个现实因素:旧数据迁移。我们从旧系统迁过来时,历史答疑消息有几千条,不可能丢,但又不需要实时可查。最终的做法是历史数据整体导出存对象存储,课堂群只保留当学期的消息,页面里放一个“查看历史答疑”的入口指到归档文件。这样课堂群保持轻量,历史内容也不丢。
这个思路其实和录播视频的冷热分层是一回事:热数据贵但快,冷数据便宜但要绕一步。对象存储的分层实践可以翻《NAS 家庭服务器指南》,里面有不同存储介质的取舍分析,选型逻辑可以直接套用到云端。
课堂群的生命周期管理
群不是建好就完事。我们给每个课程群定义了四个阶段,由课程表驱动自动流转:
- 课前建群:排课时系统自动创建班级群,学生名册同步进群;开课前 15 分钟推送上课提醒,学生点通知直达课堂,不用再翻聊天记录找链接。
- 课中值守:老师进房后,群自动切换到授课模式(全员禁言加提问通道),助教在群里维持纪律,具体手段见 3.3。
- 课后归档:下课后群不解散,保留 7 天供学生复习提问、补交作业;7 天后转为只读,消息记录转存对象存储备查。
- 学期清理:课程结束后班级群整体归档,释放群数量配额,群里只留下一个指向录播列表的公告。
这套生命周期跑通后,教务再没问过“群越来越多怎么管”。归档转存这一步顺便解决了审计需求:教务回查消息、家长要求举报不当言论时,有据可查。具体做法在 3.4 展开。
转存脚本跑在我们的业务服务器上,那台机器的初始化流程直接复用了《Lighthouse 建站指南》里的部署清单,省了不少事。
权限与角色
课堂群不能人人平等。老师能禁言、能踢人;学生只能发言和撤回自己的消息。我们的角色权限表:
| 角色 | 发消息 | 禁言他人 | 撤回消息 | 连麦上麦 | 管理群成员 |
|---|---|---|---|---|---|
| 老师 | 允许 | 允许 | 全员消息 | 允许 | 允许 |
| 助教 | 允许 | 允许 | 全员消息 | 允许 | 仅本课堂 |
| 学生 | 允许 | 否 | 仅自己的 | 需先举手 | 否 |
| 游客 | 仅公开课可发言 | 否 | 否 | 否 | 否 |
| 旁听教务 | 只读 | 否 | 否 | 否 | 只读 |
两个细节值得说。一是助教的管理权限限定在当堂课,课程一结束自动回收,避免临时拉来帮忙的人误操作其他班——这个限定是在一次跨班误踢事件后加的。二是学生“仅撤回自己的消息”这条必须做:小学生经常误发作业答案,能自己撤回就没必要每件事都喊老师,老师和助教也能专注讲课。
集成过程中关于鉴权还有一段插曲:给每个学生签发登录凭证绕了不少弯,踩了几次“凭证过期学生被踢下线”的坑,这部分我写进了第二篇接入准备一节,这里就不重复了。
消息和音视频房间的号怎么对上
一个容易被忽略的架构问题:TRTC 房间和 IM 群是两条通道,用户在两边的标识必须严格一致。我们在业务侧给每个学生维护一个统一的用户编号,进 TRTC 房间用它、进 IM 群也用它,课堂里所有“谁干了什么”的日志才能串起来。试讲时曾用过两套编号(报名号一个、IM 账号一个),结果点名时举手列表里的人名和视频画面对不上,排查了一下午才发现是映射表脏了。从此以后单一编号来源,绝不再开第二个。
课堂场景里两条通道的分工是这样的:音视频走 TRTC,承载看和听;控制和文字走 IM,承载说和管。下课后音视频房间立刻销毁,群保留 7 天——这个时间差就是为什么互动数据必须挂在 IM 侧而不是房间里。
上线第一周的反馈
整套方案上线后,我们做了个小范围回访。老师最喜欢的功能不是任何炫技的东西,而是“@提醒消息能单独筛”——上百条滚动消息里,被@到的那条永远不漏。学生反馈最多的则是课后还能翻到提问记录。这两个反馈印证了本节的核心判断:课堂消息系统的价值不在“能发消息”,而在于分类清晰、各归各位。
还有一条来自教务的反馈出乎意料:归档后的课堂消息成了排课依据。统计各班每节课的提问条数和活跃时段,能看出哪节课互动最充分、哪个时间段学生最容易走神。数据本来是为审计留的,顺手变成了教学运营的输入,这是典型的计划外收益。
上线前的群清单
每次新学期开课,我们都会跑一遍这张检查表,避免低级事故:
| 检查项 | 标准 | 出过错吗 |
|---|---|---|
| 学生全员入群 | 名册人数与实际一致 | 批量拉人限流漏过人 |
| 群名与课节对应 | 学期加课程加班级格式 | 重名导致点错群 |
| 欢迎语已配置 | 包含上课时间与纪律公约 | 曾靠助教手动发 |
| 只读归档时间设好 | 课后第 7 天自动转只读 | 忘配导致旧群仍可发言 |
| 权限模板套对 | 助教权限限定本课堂 | 跨班误踢事件 |
这张表本身也是被事故喂出来的。每一行背后都是一次夜里被叫起来修的问题,现在跑一遍只要五分钟,值。
