EMQ 的共享订阅

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

EMQ 的共享订阅_第1张图片
EMQ

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

共享订阅 (Shared Subscription) 是指在多订阅者间采用分组负载平衡方式派发消息

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

  • $queue/ 队列共享订阅
  • $share/

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

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

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

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

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

本地订阅(Local Subscription) 只在本节点创建订阅与路由表,不会在集群节点间广播全局路由

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

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

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

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

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

你可能感兴趣的:(EMQ 的共享订阅)