MQTT-共享订阅
共享订阅
在普通的订阅中,每发布一条消息,所有匹配的订阅端都会收到该消息。当某个订阅端的消费速度无法跟上消息的生产速度时,没有办法将其中一部分消息分流到其他订阅端来消费。这就使得订阅端容易成为整个消息系统的性能瓶颈。

- 解决办法
MQTT 5.0 引入了共享订阅特性,它使得 MQTT 服务端可以在使用特定订阅的客户端之间均衡地分配消息负载。这表示,当我们有两个客户端共享一个订阅时,那么发布的消息都只投递给其中一个客户端。类似:订阅者集群,负载均衡,提高消费性能
订阅分类
启用共享订阅:为一组订阅者的原始主题添加指定前缀
| 前缀格式 | 示例 | 前缀 | 真实主题名 |
|---|---|---|---|
| 群组格式 | $share/g/test/a | $share/g | test/a |
| 非群组格式 | $queue/test/a | $queue/ | test/a |
群组订阅
通过在原始主题前 添加 $share/<group-name> 前缀为分组的订阅者启用共享订阅。组名可以是任意字符串。EMQX 同时将消息转发给不同的组,属于同一组的订阅者可以使用负载均衡接收消息。
案例说明
订阅者 sub_1、sub_2 和 sub_3 是组 g1 的成员,订阅者 sub_4 和 sub_5 是组 g2 的成员,而所有订阅者都订阅了原始主题 test/1。共享订阅的主题是 $share/g1/test/1 和 $share/g2/test/1。
当 EMQX 发布消息 msg1 到原始主题 test/1 时:
- EMQX 将
msg1发送给g1和g2两个组。 sub_1、sub_2、sub_3中的一个订阅者将接收msg1。sub_4和sub_5中的一个订阅者将接收msg1。

案例演示
创建订阅者
- sub_1
- 主题
$share/g1/test/1
- 主题

- sub_2
- 主题
$share/g1/test/1
- 主题

- sub_3
- 主题
$share/g1/test/1
- 主题

- sub_4
- 主题
$share/g2/test/1
- 主题

- sub_5
- 主题
$share/g2/test/1
- 主题

发布者发布消息
- publish 发布消息
- 主题
test/1
- 主题

订阅者接收消息
g1组 中 只有sub_2接收到

g2组 中 只有sub_5接收到

非群组订阅
通过在原始主题前 添加 $queue/ 前缀为非群组订阅者启用共享订阅。它是 $share 订阅的一种特例,可以理解为所有订阅者都在一个订阅组。
案例说明
订阅者 sub_queue_1、sub_queue_2 和 sub_queue_3 都订阅主题 $queue/test/q。原始主题为 test/q。 发布消息 msg1、msg2、msg3到原始主题 test/q 时,sub_queue_1、sub_queue_2 和 sub_queue_3 各自收到一个消息。

案例演示
创建订阅者
- sub_queue_1
- 主题
$queue/test/q
- 主题

- sub_queue_2
- 主题$queue/test/q

- sub_queue_3
- 主题
$queue/test/q
- 主题

发布者发布消息
- publish 发布消息
- 主题
test/q - 连续发送三个消息
- 三个订阅者各收到一条
- 主题

订阅者接收消息
sub_queue_1

订阅者 sub_queque_1 收到 消息 3
sub_queue_2

订阅者 sub_queque_2 收到 消息 1
sub_queue_3

订阅者 sub_queque_3 收到 消息 2
负载均衡策略
可通过Dashboard进行负载均衡算法的配置【管理>>MQTT配置】

策略简介
- 随机(Random)
在共享订阅组内随机选择一个会话发送消息。
- 轮询(Round Robin)
在共享订阅组内按顺序选择一个会话发送消息,循环往复。
- 哈希(Hash)
基于某个字段的哈希结果来分配。
- 粘性(Sticky)
在共享订阅组内随机选择一个会话发送消息,此后保持这一选择,直到该会话结束再重复这一过程。
- 本地优先(Local)
随机选择,但优先选择与消息的发布者处于同一节点的会话,如果不存在这样的会话,则退化为普通的随机策略。
