MQTT v5 共享订阅
MQTT5 共享订阅
MQTT 5.0 引入了共享订阅(Shared Subscription)的概念,这是一种新的订阅模式。
允许多个客户端共同订阅相同的主题,但只有一个客户端接收和处理该主题的消息。
示例

下面是一个 MQTT v5 中使用共享订阅的示例。
假设我们有多个 MQTT v5 客户端需要共同消费相同主题的消息,而不会重复接收到相同的消息。
为了实现这一点,客户端将使用 $share/{group_name}/{topic_filter} 的格式来订阅主题。
示例背景:
假设我们有一个 MQTT 代理(Broker),主题是 sensor/temperature,多个客户端需要订阅并处理这个主题的消息。
我们希望通过共享订阅,让多个客户端分担接收消息的负载。
共享订阅的格式:
共享订阅的订阅主题格式为:
$share/{group_name}/{topic_filter}
其中:
{group_name}:共享订阅的组名,表示多个客户端组成一个消费组。所有在同一个消费组中的客户端会平衡地接收到消息。{topic_filter}:订阅的主题过滤器,与普通的 MQTT 订阅相同,表示客户端对消息的兴趣。
示例 1:共享订阅的具体操作
假设我们有 3 个 MQTT v5 客户端,它们分别属于同一个消费组 group1,并且都希望订阅 sensor/temperature 主题。它们将分别使用以下订阅:
- 客户端 1(
client1)订阅:$share/group1/sensor/temperature - 客户端 2(
client2)订阅:$share/group1/sensor/temperature - 客户端 3(
client3)订阅:$share/group1/sensor/temperature
详细步骤:
-
发布消息: 假设有一个 MQTT v3.1.1 或 v5 客户端(
publisher)发布了消息到sensor/temperature主题,消息内容是:温度: 22°C -
共享订阅: 这时,
client1、client2和client3都通过共享订阅的方式来订阅sensor/temperature主题。它们分别使用:$share/group1/sensor/temperature这些客户端不会收到相同的消息,而是通过负载均衡的方式,消息会均匀地分配给这三台客户端中的某一台。
-
负载均衡:
- 在这种设置下,
client1、client2和client3将轮流接收消息。例如:client1可能首先接收到消息温度: 22°C。- 下一条消息将由
client2接收。 - 然后是
client3,依此类推。
- 消息会被轮流分配给这些客户端,避免重复接收。
- 在这种设置下,
-
客户端断开和重连: 如果某个客户端(例如
client2)断开连接并重新连接,它将重新加入共享订阅组,Broker 会根据当前的负载均衡策略,决定将消息分配给哪个客户端。
通配符
是的,$share/{group_name}/{topic_filter} 格式在 MQTT v5 中是支持通配符的。
支持的通配符:
与普通的 MQTT 订阅一样,$share/{group_name}/{topic_filter} 也支持使用通配符来订阅多个主题。具体支持的通配符包括:
+(单层通配符):表示匹配主题层级中的单个元素。#(多层通配符):表示匹配主题中的多个层级(包括零个层级)。
示例 1:单层通配符(+)
假设你希望共享订阅所有以 sensor/ 开头的主题,比如 sensor/temperature、sensor/humidity 等。你可以使用单层通配符 + 来订阅:
$share/group1/sensor/+
这个订阅会匹配所有以 sensor/ 开头的主题,例如:
sensor/temperaturesensor/humiditysensor/pressure
示例 2:多层通配符(#)
如果你想订阅所有以 home/ 开头的主题,并且包含任意层级的子主题,可以使用多层通配符 #:
$share/group1/home/#
这个订阅会匹配以下主题:
home/livingroom/temperaturehome/kitchen/humidityhome/bedroom/airquality
注意事项:
- 通配符使用的限制:
+通配符只能替代一个主题层级,而#通配符只能出现在主题的末尾,且只能用一次(比如不能在中间或主题的其他部分使用#)。 - 共享订阅组与通配符:使用通配符的共享订阅,多个客户端将会根据共享订阅的规则进行负载均衡。例如,
$share/group1/sensor/+会将所有匹配sensor/开头的主题的消息分配到共享订阅组group1中的客户端。
总结:
在 MQTT v5 中,$share/{group_name}/{topic_filter} 格式确实支持使用通配符。你可以灵活地订阅多个主题,确保消息的负载均衡和高效处理,尤其适用于需要处理大量不同主题的场景。
SpringBoot 代码
依赖
<!-- MQTT -->
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-mqtt</artifactId>
</dependency>
<!-- 使用 MQTT v5 版本 -->
<dependency>
<groupId>org.eclipse.paho</groupId>
<artifactId>org.eclipse.paho.mqttv5.client</artifactId>
<version>1.2.5</version>
</dependency>
代码
原来
/**
* 入站
*/
@Bean
public MessageProducer inbound() {
MqttPahoMessageDrivenChannelAdapter adapter = new MqttPahoMessageDrivenChannelAdapter("consumerClient-" + UUID.randomUUID().toString(),
mqttClientFactory(), "/test/#");
adapter.setCompletionTimeout(5000);
DefaultPahoMessageConverter defaultPahoMessageConverter = new DefaultPahoMessageConverter();
adapter.setConverter(defaultPahoMessageConverter);
adapter.setQos(1);
adapter.setOutputChannel(mqttInputChannel());
return adapter;
}
订阅主题通配符由 test/# 改为:$share/test-group/test/#,其他代码不修改。
/**
* 入站
*/
@Bean
public MessageProducer inbound() {
MqttPahoMessageDrivenChannelAdapter adapter = new MqttPahoMessageDrivenChannelAdapter("consumerClient-" + UUID.randomUUID().toString(),
mqttClientFactory(), "$share/test-group/test/#");
adapter.setCompletionTimeout(5000);
DefaultPahoMessageConverter defaultPahoMessageConverter = new DefaultPahoMessageConverter();
adapter.setConverter(defaultPahoMessageConverter);
adapter.setQos(1);
adapter.setOutputChannel(mqttInputChannel());
return adapter;
}
如果使用 MQTT 客户端测试,还可以订阅主题 test/#,不会影响共享订阅组。
订阅组名称
$share/test-group/test/# 的结构:
$share/是 MQTT v5 中的一个特殊前缀,用于标识共享订阅。test-group是你为这个共享订阅组自定义的名称。可以自定义成任何字符串,用于区分不同的订阅组。test/#是你实际订阅的主题,#是一个通配符,表示匹配test/下的所有子主题。
特点和注意事项
共享订阅特点
这有助于分散负载和实现协同订阅的需求。
以下是 MQTT 5.0 共享订阅的主要特点:
- 订阅组(Subscription Group):在 MQTT 5.0 中,多个客户端可以共同订阅相同的主题,这些客户端被组织成一个订阅组。每个订阅组内只有一个客户端会接收到发布到该主题的消息。
- 消息负载均衡:共享订阅允许多个客户端在一个订阅组内共享消息的负载。这意味着,当消息发布到被共享订阅的主题时,代理会选择订阅组内的一个客户端来接收消息,以实现负载均衡,确保不会让所有客户端都接收相同的消息。
- 组成员管理:MQTT 5.0 提供了一些机制来管理订阅组的成员。客户端可以加入或离开订阅组,以便灵活地控制哪个客户端会接收消息。
- 订阅选项:MQTT 5.0 的共享订阅引入了一些新的订阅选项,如"不公平"(Unfair)和"公平"(Fair)订阅。不公平订阅是默认的,它只发送消息给订阅组内的一个客户端,而公平订阅会轮流发送消息给不同的组成员,确保公平分配消息。
- 附加数据:MQTT 5.0 还允许在共享订阅时使用附加数据。这可以用于在选择哪个客户端接收消息时提供额外的信息或条件。
共享订阅的优势:
- 负载均衡:通过共享订阅,多个客户端可以共同处理高频率的消息流,避免某一个客户端过载。
- 消息不重复:多个客户端不必重复处理同一条消息,避免浪费计算资源。
- 弹性扩展:可以根据需要增加或减少客户端,负载均衡会自动调整。
注意事项:
- 共享订阅必须由 MQTT v5 客户端发起,MQTT v3.1.1 客户端无法使用共享订阅功能。
- Broker 支持:不是所有的 MQTT Broker 都完全支持 MQTT v5 和共享订阅,因此需要确保你的 Broker 支持这些特性(例如,Eclipse Mosquitto、EMQX、HiveMQ 等 Broker 支持 MQTT v5 和共享订阅)。
总结
通过共享订阅,多个客户端可以高效地协作处理消息,避免重复消费,提高系统的吞吐量和性能。这种机制特别适用于需要横向扩展的消息处理场景。

浙公网安备 33010602011771号