EMQ 的共享订阅

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了EMQ 的共享订阅相关的知识,希望对你有一定的参考价值。

参考技术A

EMQ 是一款基于高并发的 Erlang/OTP 语言平台设计,支持百万级连接和分布式集群,发布/订阅模式的开源MQTT消息服务器。

EMQ 单节点支持100万并发MQTT连接峰值负载,超过了绝大多数的后端服务对消息的处理能力。因此往往需要多个后端服务节点来分担。但是基于的 MQTT 3.1.1 协议标准,如果多个后端服务节点订阅了相同的 topic,来自这些 topic 消息会被同时派发给所有的后端服务。为了解决这样的问题,EMQ 提供了共享订阅这个机制。

EMQ 提供了如下两种共享订阅的方式:

队列共享订阅是指以 $queue/ 开头的 topic 例如 $queue/topic1,如果有多个客户端同时订阅了,EMQ 会把发送到 topic1 的消息以负载均衡的方式派发给所有客户端,保证一条消息只会派发给一个客户端。需要注意前缀 $queue 只适用于订阅时,发布消息时不需要。

分组共享订阅是一个更加灵活的方式,实现方式为所有以 $share/<group>/ 开头的的 topic 会以 group 来分组进行消息的负载均衡派发。例如有4个客户端依次订阅了$share/group1/topic1,$share/group1/topic1,$share/group2/topic1 和 $share/group1/topic1。所有发送到 topic1 的消息会被同时派发到分组 group1 和 group2,但是两个分组中的每次都只会有一个客户端收到消息。同样前缀$share/<group>/ 只适用于订阅时,发布消息时不需要。

以上都是基于单个 EMQ 节点的共享订阅方法,在多个 EMQ 节点组成的集群环境下也能实现共享订阅的消息只会到达一个或者每组中的一个订阅客户端吗?

很遗憾,答案是不能。虽然 EMQ 能简单的通过 HAProxy 来搭建分布式集群,但是直到最新的 2.3.11 版本,都没有支持集群环境下的共享订阅。如果在集群中使用共享订阅,在消息到达时,集群机制会把消息发送到每个 EMQ 节点上,随后每个 EMQ 节点会把消息以负载均衡的方式派发给与自己建立连接的订阅客户端。换句话说,集群环境中的每个节点上都会有一个或者每组一个订阅客户端收到共享订阅的消息。

幸运的是,结合 EMQ 提供的本地订阅机制可以实现,可实现 伪 集群下的共享订阅。

本地订阅的方式跟队列共享订阅很相似,都是在普通的 topic 前加上固定的前缀。本地共享订阅的前缀是 $local/。

使用本地共享订阅以后,来自订阅的 topic 的消息只会在消息发布客户端连接的 EMQ 节点上进行派发,也就做到了只有这个节点上一个或者每组中的一个共享订阅客户端收到消息。

如果消息发布客户端所在的 EMQ 节点上没有订阅客户端,由于本地订阅的特性,其他节点上订阅客户端也无法收到消息。因此必须保证 EMQ 集群中的每个节点上都至少得一个本地共享订阅客户端才能达真正意义上的共享订阅。

由于该实现机制要求每个 EMQ 节点上都有共享订阅客户端,结合业务就是要求每个 EMQ 节点上至少有一个消息处理服务连接,考虑备份则每个节点需要至少两个服务。扩容 EMQ 节点需要同时对服务节点相应扩容,因而称该实现方式为 伪 集群环境下的共享订阅。

EMQ 官方团队已经表明会在下次大版本更新时支持集群下的共享订阅,因此如果目前单 EMQ 节点足够支撑业务需求可延缓集群化时间,等待下个大版本更新的发布。

EMQ ---客户端上线自动订阅主题

通过修改配置文件即可实现。

emq v2.3.11,软件架构做了调整,把功能集成在了emq_modules模块,/data/loaded_plugins默认会加载emq_modules。

我们只需要改动配置文件emqx-rel-2.3.11/deps/emq_modules/etc/emq_modules.conf

##--------------------------------------------------------------------
## Subscription Module
##--------------------------------------------------------------------
 
## Enable Subscription Module.
##
## Value: on | off
module.subscription = on
 
## Subscribe the Topics automatically when client connected.
module.subscription.1.topic = %c/w
## Qos of the subscription: 0 | 1 | 2

  

把module.subscription设置为on,

把module.subscription.1.topic设置为%c/w,%c是通配符,会自动切换成clientId。注意是%c,而不是$c。

 



以上是关于EMQ 的共享订阅的主要内容,如果未能解决你的问题,请参考以下文章

EMQ ---客户端上线自动订阅主题

取消订阅 Apache pulsar 共享订阅类型

什么是“共享订阅/发布”?

EMQ 学习---订阅$SYS主题,捕获客户端上下线消息

EMQ ---v2.3.11源码成熟度

2019-07-10-mqtt-mosquitto系列13之共享主题