RocketMQ MQTT 概述
传统的 Message Queue MQ 主要用于服务(端)之间的消息通信,例如电商领域中的交易消息、支付消息、物流消息等。然而,在消息的总类别下,还有一个非常重要且常见的领域,那就是物联网终端设备消息。近年来,我们见证了智能家居和工业互联带来的物联网设备导向型消息的爆炸式增长,而移动互联网的移动 APP 端消息,经过十多年的发展,依然是数量级巨大的。终端设备的消息数量级比传统服务器高出很多个数量级,并且还在快速增长。
如果有一个统一的消息系统(产品)来提供多场景计算(如流、事件)和多场景(IoT、APP)接入,实际上是非常有价值的,因为消息也是重要的数据。只有一个系统,可以最大限度地降低存储成本,并有效避免不同系统之间数据同步带来的数据一致性问题和挑战。
基于此,我们引入了 RocketMQ-MQTT 扩展项目,实现 RocketMQ 对 IoT 设备和服务器消息的统一接入,提供一体化的消息存储和互通能力。
MQTT 协议
在 IoT 终端场景下,MQTT 协议目前在行业内被广泛使用,它是 OASIS 联盟定义的标准开放协议,起源于物联网的 IoT 场景。由于 IoT 设备种类繁多,运行环境各不相同,因此标准的接入协议尤为关键。
MQTT 协议定义了 Pub/Sub 通信模型,与 RocketMQ 类似,但在订阅方式上更加灵活,可以支持多级 Topic 订阅(如 "/t/t1/t2"),甚至可以支持通配符订阅(如 "/t/t1/+")。
模型介绍
队列存储模型
我们设计了多维分布的主题队列模型。如上图所示,消息可以来自各种接入场景(如服务器端的 MQ/AMQP 和客户端的 MQTT),但只会写入并存储在 commitlog 中的一份副本,然后分发到多个需求场景的队列索引(ConsumerQueue)。例如,服务器端场景(MQ/AMQP)可以根据一级 Topic 队列进行传统的服务器端消费,而客户端 MQTT 场景可以根据 MQTT 多级 Topic 和通配符订阅进行消费。
这样的队列模型可以同时支持服务器和终端场景的接入和消息收发,实现一体化的目标。
推拉模型
上图展示了推拉模型。图中的 P 节点是协议网关或 Broker 插件,终端设备通过 MQTT 协议连接到网关节点。消息可以来自各种场景(MQ/AMQP/MQTT)。存储在 Topic 队列后,会存在一个 notify 逻辑模块实时感知新消息的到来,然后生成一个消息事件(即消息的主题名称)。该事件被推送到网关节点,网关节点根据连接的终端设备的订阅状态进行内部匹配,找到哪些终端设备可以匹配,然后触发对存储层的拉取请求,读取消息并推送到终端设备。
架构概述
我们的目标是基于 RocketMQ 实现一个一体化、自闭环的系统,但我们不希望 Broker 被入侵到更多场景逻辑中。我们抽象了一个协议计算层,它可以是网关或 Broker 插件。Broker 专注于解决 Queue 问题,并做一些 Queue 存储适配或转换以满足上述计算需求。协议计算层负责协议接入,必须是可插拔的和可部署的。