在线直播教育的场景通常会涉及多个直播间,且每个直播间中也会有多名成员。本文以单直播间、一名老师、两名学生的场景为例,说明如何使用微消息队列 MQTT 版实现直播互动消息、禁言、成员上下线通知以及系统消息通知,其中,老师和学生的客户端以 HTML 网页为例,后端应用以 Java 为例。

背景信息

使用微消息队列 MQTT 版需与后端存储队列绑定,目前仅支持消息队列 RocketMQ 版,详情请参见 MQTT 与 RocketMQ 的消息结构映射

使用微消息队列 MQTT 版的客户端收发消息时,服务端会根据 MQTT 客户端设置的 Username 和 Password 参数来进行鉴权。针对不同的权限验证场景,Username 和 Password 参数具备不同的含义。在此场景下,Token 鉴权模式更加适用。详情请参见 Token 鉴权概述

说明 本文不涉及其他产品中的操作,如需了解其他产品的操作请参见在线教育视频直播最佳实践

文中提及的名词概念,请参见下文中的名词解释

场景详情

四个场景均以一名老师和两名学生的在线教育场景为例。老师和学生使用不同的 MQTT 客户端,通过不同的 Group ID 分组,不同的老师和学生通过 Device ID 区分。同一直播间的客户端发送和订阅消息的 Topic 需分开创建和使用,以免消息队列 RocketMQ 版形成消费死循环。具体示例如下。

例如,一个在线教育直播间中有三名成员,一名老师和两名学生。学生 A 在直播间发文字消息,直播间所有成员全部可见。您可以将一个直播间与一个 MQTT 的 Topic 对应,例如客户端发送消息使用的 Topic 为 roomSend/message,订阅消息使用的 Topic 为 room/message/123456,其中:

  • roomSend 为直播间所有客户端发送消息使用的父级 Topic,需要在微消息队列 MQTT 版控制台创建。
  • room 为直播间所有客户端订阅的父级 Topic,需要在微消息队列 MQTT 版控制台创建。
  • /message 为自定义的二级 Topic,无需在微消息队列 MQTT 版控制台创建,本示例中其含义为文字消息。
  • /123456 为自定义的三级 Topic,无需在微消息队列 MQTT 版控制台创建,本示例中其含义为直播间的 ID。

同一个直播间的所有成员都订阅 room/message/123456 Topic。具体消息流向如下图所示。

场景一:直播互动消息

流程说明如下:

  1. 学生 A 通过客户端发送一条消息至微消息队列 MQTT 版。消息示例如下:
    topic: "roomSend/message",body: "{ 'peer': 'xxx', 'roomId': '123456', 'msg': 'xxx' }"
    

    说明:HTML 网页客户端发送的消息格式为 JSON。

  2. 微消息队列 MQTT 版将消息转发至消息队列 RocketMQ 版。
  3. 订阅了消息队列 RocketMQ 版 Topic 的后端应用消费该消息以实现业务处理,例如内容审核。
  4. 后端应用将处理后的消息再次发送至消息队列 RocketMQ 版的 Topic。
  5. 消息队列 RocketMQ 版将该消息转发至微消息队列 MQTT 版。
  6. 微消息队列 MQTT 版将该消息推送至所有网页客户端,涉及成员老师、学生 A 以及学生 B。

此场景是使用微消息队列 MQTT 版 P2P 消息收发功能的典型场景,老师禁止某位同学在直播间发言的指令消息会被发送至需要禁言的学生客户端上实现禁言效果。同时,服务端也会添加禁言名单用于业务校验和消息过滤。老师的客户端需将消息发送至 roomSend/command Topic,其中:

  • roomSend 为直播间所有客户端发送消息使用的父级 Topic,需要在微消息队列 MQTT 版控制台创建。
  • command 为自定义二级 Topic,无需在微消息队列 MQTT 版控制台创建,command 与 message 二级 Topic 作区分,表示指令类的消息。

说明:P2P 消息无需订阅,此场景下示例值为 room/p2p/GID_student@@@002。

具体消息流向如下图所示。

场景二:学生禁言

流程说明如下:

  1. 老师通过客户端发送一条禁言指令消息至微消息队列 MQTT 版。
  2. 微消息队列 MQTT 版将消息转发至消息队列 RocketMQ 版。
  3. 订阅了消息队列 RocketMQ 版 Topic 的后端应用接收到该条指令消息后,进行必要检验处理并保存禁言名单用于后续过滤被禁言学生的消息。同时发送一条 P2P 消息(room/p2p/GID_student@@@002)给学生 B 的客户端,使学生 B 的客户端显示禁言效果。

通过微消息队列 MQTT 版的客户端状态异步通知功能,已在直播间的所有成员都可以收到其他成员上下线的通知消息。此场景下,所有的客户端都需订阅 room/status Topic,其中:

  • room 为父级 Topic,需要在微消息队列 MQTT 版控制台创建。
  • status 为自定义二级 Topic,无需在微消息队列 MQTT 版控制台创建,本示例中表示与客户端状态相关的消息。

每个 MQTT 客户端都订阅该 Topic 后,当某个客户端上下线时,MQTT 服务都会触发一条事件消息到消息队列 RocketMQ 版。具体消息流向如下图所示。

场景三:成员上下线通知

流程说明如下:

  1. 微消息队列 MQTT 版将学生 A 进入直播间的上线事件消息发送至消息队列 RocketMQ 版。
  2. 订阅了消息队列 RocketMQ 版 Topic 的后端应用消费该消息以实现业务处理,例如考勤记录。
  3. 后端应用将处理后的消息再次发送至消息队列 RocketMQ 版的 Topic。
  4. 消息队列 RocketMQ 版将该消息转发至微消息队列 MQTT 版。
  5. 微消息队列 MQTT 版将该消息广播至所有客户端,涉及成员老师、学生 A 以及学生 B。

此场景使用微消息队列 MQTT 版的消息收发功能,系统的更新通知都会发送到直播间的所有成员。此场景下,所有的客户端都需订阅 room/system Topic,其中:

  • room 为父级 Topic,需要在微消息队列 MQTT 版控制台创建。
  • system 为自定义二级 Topic,无需在微消息队列 MQTT 版控制台创建,本示例中表示系统发送的消息。

具体消息流向如下图所示。

场景四:系统通知消息

流程说明如下:

  1. 后端应用更新消息发送至消息队列 RocketMQ 版的 Topic。
  2. 消息队列 RocketMQ 版将该消息转发至微消息队列 MQTT 版。
  3. 微消息队列 MQTT 版将该消息推送至所有客户端,涉及成员老师、学生 A 和学生 B。

操作流程

在线直播教育所涉及的四个场景的流程如下所示,各个场景所使用的微消息队列 MQTT 版功能各不相同,因此使用的 SDK 客户端代码有所差异,请以每个场景的具体描述为准。

live_house_process

操作步骤

  1. 微消息队列 MQTT 版控制台上,创建以下资源。
    资源 示例值 参考文档
    实例 N/A 创建 MQTT 实例并绑定后端存储资源
    父级 Topic(一级 Topic)
    • room:直播间客户端订阅的父级 Topic。
    • roomSend:直播间客户端发送消息的父级 Topic。
    创建 MQTT Topic
    子级 Topic 各场景下的子级 Topic 示例如下:
    • 直播互动消息场景:/message/123456
    • 学生禁言场景:/command 以及 /p2p/GID_student@@@002(典型的 P2P 消息场景)
    • 成员上下线通知:/status
    • 系统通知消息:/system
    说明 子级 Topic 无需创建。详情请参见名词解释
    N/A
    Group ID
    • 老师:GID_teacher
    • 学生:GID_student
    创建 MQTT Group ID
    其中,老师和学生的客户端与 Group ID 的对应关系如下所示。
    角色 Group ID Device ID Client ID
    老师 GID_teacher 001 GID_teacher@@@001
    学生 A GID_student 001 GID_student@@@001
    学生 B GID_student 002 GID_student@@@002
    说明 Device ID 无需创建,详情请参见名词解释
  2. 执行微消息队列 MQTT 版为您提供的客户端和后端应用示例代码,完成各个不同场景下的消息收发。
    示例代码下载地址如下所示:
    说明 代码中所涉及的参数请以代码注释描述为准。

名词解释

MQTT

一个基于订阅/发布的长连接双向通信模型,订阅方便灵活,非常适合直播消息互动场景。微消息队列 MQTT 版基于标准的 MQTT 协议,广泛服务于终端应用场景。

MQTT 服务器

微消息队列 MQTT 版提供的 MQTT 协议交互的服务端节点,用于完成与 MQTT 客户端和消息队列 RocketMQ 版各自的消息收发。

MQTT 客户端

用于和 MQTT 服务器交互的移动端节点,本文直播互动场景主要是手机或 PC 电脑。

父级 Topic(Parent Topic)

MQTT 协议基于 Pub/Sub 模型,因此任何消息都属于一个 Topic。根据 MQTT 协议,Topic 存在多级,定义第一级 Topic 为父级 Topic,使用微消息队列 MQTT 版前,需先在控制台创建该父级 Topic,可以在微消息队列 MQTT 版控制台创建,或者直接在消息队列 RocketMQ 版的控制台创建。

子级 Topic(Subtopic)

MQTT 的二级 Topic,甚至三级 Topic 都是父级 Topic 下的子类。使用时,直接在代码里设置,无需创建。需要注意的是微消息队列 MQTT 版限制父级 Topic 和子级 Topic 的总长度为 64 个字符,如果超出长度限制将会导致客户端异常。

Client ID

微消息队列 MQTT 版的 Client ID 是每个客户端的唯一标识,要求全局唯一,使用相同的 Client ID 连接微消息队列 MQTT 版服务会被拒绝。

Client ID 由两部分组成,组织形式为 <GroupID>@@@<DeviceID>。Client ID 的长度限制为 64 个字符,不允许使用不可见字符。详情请参见使用限制

Group ID

用于指定一组逻辑功能完全一致的节点共用的组名,代表一类相同功能的设备。Group ID 需要在微消息队列 MQTT 版的控制台创建,创建后方可使用。

Device ID

每个设备独一无二的标识,由业务方自己指定。需要保证全局唯一,例如每个传感器设备的序列号。

P2P 消息

微消息队列 MQTT 版在标准的 MQTT 协议基础上提供的一种特殊消息,该类型消息无需普通的订阅关系匹配,便可直接发送给指定的单个目标 MQTT 客户端。详情请参见 P2P 消息收发模式(MQTT)

音视频通信 RTC

阿里云覆盖全球的实时音视频开发平台,依托核心音视频编解码、信道传输、网络调度技术,提供高可用、高品质、超低延时的音视频通信服务,让用户快速搭建多端实时应用,适用于在线教育、视频会议、互动娱乐、音视频社交等场景。

直播场景需要传输流媒体服务,详情请参见音视频通信 RTC。本文只涉及 MQTT 互动消息收发内容。