官网上关于共享订阅的机制说明:https://www.emqx.io/docs/zh/v5.0/mqtt/mqtt-shared-subscription.html#%E6%9C%BA%E5%88%B6%E4%BB%8B%E7%BB%8D
摘抄部分内容:
共享订阅是在多个订阅者之间实现负载均衡的订阅方式,EMQX 在 MQTT v3.1.1 中已经实现共享订阅共享订阅,MQTT v5.0 协议中这一特性成为标准的一部分。
共享订阅能够解决以下问题:
集群模式下,如果订阅者所在的节点发生故障,则发布者的消息会丢失(QoS 0)或者堆积在节点中(QoS 1, 2)。可以通过增加订阅节点的方式解决这一问题,但这样又产生了大量的重复消息浪费了性能,并增加了业务的复杂度。
当发布者的生产能力较强时,可能会出现订阅者的消费能力无法及时跟上的情况,此时只能由订阅者自行实现负载均衡来解决,又一次增加了用户的开发成本。
机制介绍
在原有主题的基础上,添加 $share 前缀即可为一组订阅端启用共享订阅。
![](https://i-blog.csdnimg.cn/blog_migrate/073508ab1511642c9aef7c7e403ce02f.png)
上图中,共享 3 个 subscriber 用共享订阅的方式订阅了同一个主题 $share/g/topic,其中topic 是它们订阅的真实主题名,而 $share/g/ 是共享订阅前缀。EMQX 支持两种格式的共享订阅前缀:
示例 | 前缀 | 真实主题名 |
$share/abc/t/1 | $share/abc/ | t/1 |
上面这段话已经基本讲明白为啥我们要用共享订阅了。 网上的很多免费版消息转存方案还是5.0以前的版本下的措施,emqx5.0已经提供了一个稳定的多个消费端订阅同一个主题消息的机制,可以方便的来实现数据持久化。
一、测试共享订阅
使用emqx官方的mqttx客户端测试共享订阅,比如我的订阅topic
$share/tahmshare/JQTAHMCSM
其中$share是共享订阅关键字前缀,tahmshare是订阅组的名称,JQTAHMCSM是原始topic主体名称。
![](https://i-blog.csdnimg.cn/blog_migrate/f83d56d9640ac5516490b1614ace8279.png)
二、修改配置文件
1、输入命令查找emqx.conf
find / -name emqx.conf
得到如下两个文件列表:
/var/lib/docker/overlay2/8ad64a73a84ad1443eeda366ff0ee3f33269f9ff679599daccb9f55908afee8a/diff/opt/emqx/etc/emqx.conf
/var/lib/docker/overlay2/e7ffe9fd835f55b9e87708d721e55248b660b479db716f9369b43a28f38fbdce/merged/opt/emqx/etc/emqx.conf
关于diff和merged这两个目录的解释可以参考我的另一篇记录:
https://blog.csdn.net/yangyong1250/article/details/129403344?spm=1001.2014.3001.5501
2、修改merged目录的emqx.conf
在配置文件中加入如下配置:
# 均衡策略
broker.shared_subscription_strategy = random
# 当设备离线,或者消息等级为 QoS1、QoS2,因各种各样原因设备没有回复 ACK 确认,消息会被重新派发至群组内其他的设备。
broker.shared_dispatch_ack_enabled = true
配置 broker.shared_dispatch_ack_enabled 的引入是为了在持久化会话的情况下改善负载共享的逻辑。当设置为 true 时,EMQX 派发消息时会检查设备的在线状态,如果设备是离线的,将会把消息分配给组内的其他成员。
我让硬件同事开了一个设备发送数据,开了一个客户端发送数据,然后我开了2个共享订阅。测试结果如下。 经过短期观察,这个均衡策略也不见得完全均衡, 2个消费端收到的消息数量最大差距有四五条(一个收到8条,一个还只收到4条),具体原因不明。不过他官网对radom策略的解释本身就是随机发,2个消费端也不能排除随机的次数多的。
![](https://i-blog.csdnimg.cn/blog_migrate/3e65c615e286eca1554393083cea565a.png)