MQTT 订阅标识符详解

简介: 本文介绍了 MQTT 5.0 中的订阅标识符,并通过一个实例演示了如何使用订阅标识符实现更高效的消息处理。

为什么需要订阅标识符

在大部分 MQTT 客户端的实现中,都会通过回调机制来实现对新到达消息的处理。

但是在回调函数中,我们只能知道消息的主题名是什么。如果是非通配符订阅,订阅时使用的主题过滤器将和消息中的主题名完全一致,所以我们可以直接建立订阅主题与回调函数的映射关系。然后在消息到达时,根据消息中的主题名查找并执行对应的回调函数。

但如果是通配符订阅,消息中的主题名和订阅时的主题过滤器将是两个不同的字符串,我们只有将消息中的主题名与原始的订阅挨个进行主题匹配,才能确定应该执行哪个回调函数。这显然极大地影响了客户端的处理效率。

MQTT Subscription

另外,因为 MQTT 允许一个客户端建立多个订阅,那么当客户端使用通配符订阅时,一条消息可能同时与一个客户端的多个订阅匹配。

对于这种情况,MQTT 允许服务端为这些重叠的订阅分别发送一次消息,也允许服务端为这些重叠的订阅只发送一条消息,前者意味着客户端将收到多条重复的消息。

而不管是前者还是后者,客户端都不能确定消息来自于哪个或者哪些订阅。因为即使客户端发现某条消息同时与自己的两个订阅相匹配,也不能保证在服务端向自己转发这条消息时,这两个订阅是否都已经成功创建了。所以,客户端无法为消息触发正确的回调。

MQTT Subscription

订阅标识符的工作原理

为了解决这个问题,MQTT 5.0 引入了订阅标识符。它的用法非常简单,客户端可以在订阅时指定一个订阅标识符,服务端则需要存储该订阅与订阅标识符的映射关系。当有匹配该订阅的 PUBLISH 报文要转发给此客户端时,服务端会将与该订阅关联的订阅标识符随 PUBLISH 报文一并返回给客户端。

Subscription Identifier

如果服务端选择为重叠的订阅分别发送一次消息,那么每个 PUBLISH 报文都应该包含与订阅相匹配的订阅标识符,而如果服务端选择为重叠的订阅只发送一条消息,那么 PUBLISH 报文将包含多个订阅标识符。

客户端只需要建立订阅标识符与回调函数的映射,就可以通过消息中的订阅标识符得知这个消息来自哪个订阅,以及应该执行哪个回调函数。

MQTT Subscription

在客户端中,订阅标识符并不属于会话状态的一部分,将订阅标识符和什么内容进行关联,完全由客户端决定。所以除了回调函数,我们也可以建立订阅标识符与订阅主题的映射,或者建立与 Client ID 的映射。后者在转发服务端消息给客户端的网关中非常有用。当消息从服务端到达网关,网关只要根据订阅标识符就能够知道应该将消息转发给哪个客户端,而不需要重新做一次主题的匹配和路由。

一个订阅报文只能包含一个订阅标识符,如果一个订阅报文中有多个订阅请求,那么这个订阅标识符将同时和这些订阅相关联。所以请尽量确保将多个订阅关联至同一个回调是您有意为之的。

如何使用订阅标识符

  1. 在 Web 浏览器上访问 MQTTX Web

  2. 创建一个使用 WebSocket 的 MQTT 连接,并且连接免费的公共 MQTT 服务器:

    MQTT over WebSocket

  3. 连接成功后,我们先订阅主题 mqttx_4299c767/home/+,并指定 Subscription Identifier 为 1,然后订阅主题 mqttx_4299c767/home/PM2_5,并指定 Subscription Identifier 为 2。由于公共服务器可能同时被很多人使用,为了避免主题与别人重复,这里我们将 Client ID 作为主题前缀:

    New Subscription 1

    New Subscription 2

  4. 订阅成功后,我们向主题 mqttx_4299c767/home/PM2_5 发布一条消息。我们将看到当前客户端收到了两条消息,消息中的 Subscription Identifier 分别为 1 和 2。这是因为 EMQX 的实现是为重叠的订阅分别发送一条消息:

    Receive MQTT Messages

  5. 而如果我们向主题 mqttx_4299c767/home/temperature 发布一条消息,我们将看到收到消息中的 Subscription Identifier 为 1:

    image.png

到这里,我们通过 MQTTX 演示了如何为订阅设置 Subscription Identifier。如果你仍然好奇如何根据 Subscription Identifier 来触发不同的回调,可以在 这里 获取 Subscription Identifier 的 Python 示例代码。

版权声明: 本文为 EMQ 原创,转载请注明出处。
原文链接:https://www.emqx.com/zh/blog/subscription-identifier-and-subscription-options

相关实践学习
RocketMQ一站式入门使用
从源码编译、部署broker、部署namesrv,使用java客户端首发消息等一站式入门RocketMQ。
消息队列 MNS 入门课程
1、消息队列MNS简介 本节课介绍消息队列的MNS的基础概念 2、消息队列MNS特性 本节课介绍消息队列的MNS的主要特性 3、MNS的最佳实践及场景应用 本节课介绍消息队列的MNS的最佳实践及场景应用案例 4、手把手系列:消息队列MNS实操讲 本节课介绍消息队列的MNS的实际操作演示 5、动手实验:基于MNS,0基础轻松构建 Web Client 本节课带您一起基于MNS,0基础轻松构建 Web Client
目录
相关文章
|
消息中间件 Java 物联网
一文搞懂MQTT,如何在SpringBoot中使用MQTT实现消息的订阅和发布
之前介绍了RabbitMQ以及如何在SpringBoot项目中整合使用RabbitMQ,看过的朋友都说写的比较详细,希望再总结一下目前比较流行的MQTT。所以接下来,就来介绍什么MQTT?它在IoT中有着怎样的作用?如何在项目中使用MQTT?
8809 5
一文搞懂MQTT,如何在SpringBoot中使用MQTT实现消息的订阅和发布
|
监控 物联网 API
【.NET+MQTT】.NET6 环境下实现MQTT通信,以及服务端、客户端的双边消息订阅与发布的代码演示
MQTT广泛应用于工业物联网、智能家居、各类智能制造或各类自动化场景等。MQTT是一个基于客户端-服务器的消息发布/订阅传输协议,在很多受限的环境下,比如说机器与机器通信、机器与物联网通信等。好了,科普的废话不多说,下面直接通过.NET环境来实现一套MQTT通信demo,实现服务端与客户端的双边消息发布与订阅的功能和演示。
963 0
【.NET+MQTT】.NET6 环境下实现MQTT通信,以及服务端、客户端的双边消息订阅与发布的代码演示
|
5月前
|
传感器 负载均衡 物联网
MQTT v5共享订阅是怎么回事?如何使用共享订阅提高消息订阅的灵活性和可伸缩性?
MQTT v5共享订阅是怎么回事?如何使用共享订阅提高消息订阅的灵活性和可伸缩性?
124 1
|
1月前
|
传感器 监控 网络协议
MQTT 发布、订阅模式介绍
【2月更文挑战第17天】
71 6
MQTT 发布、订阅模式介绍
|
6月前
|
消息中间件 安全 Go
动态订阅时 rocketmq-client-go 代码有map并发bug
动态订阅时 rocketmq-client-go 代码有map并发bug
36 2
|
6月前
|
消息中间件 存储 负载均衡
两个实验让我彻底弄懂了「订阅关系一致」
这篇文章,笔者想聊聊 RocketMQ 最佳实践之一:**保证订阅关系一致**。 订阅关系一致指的是同一个消费者 Group ID 下所有 Consumer 实例所订阅的 Topic 、Tag 必须完全一致。 如果订阅关系不一致,消息消费的逻辑就会混乱,甚至导致消息丢失。
两个实验让我彻底弄懂了「订阅关系一致」
|
3月前
|
消息中间件 Java
RabbitMQ中的消息发布-订阅模式是什么?如何实现?
RabbitMQ中的消息发布-订阅模式是什么?如何实现?
46 0
EMQ
|
9月前
|
存储 缓存 网络性能优化
MQTT 订阅选项的使用
在本文中,我们将重点介绍在 MQTT 中哪些订阅选项可供我们使用,以及它们的使用方法。
EMQ
174 0
MQTT 订阅选项的使用
EMQ
|
消息中间件 存储 网络性能优化
MQTT 客户端出现连接订阅等问题时如何排查?
这是一期EMQX社区专题FAQ,我们整理了近期社区中关注度较高的问题,在这里进行统一汇总解答。
EMQ
343 0
EMQ
|
消息中间件 传感器 存储
MQTT 发布/订阅模式介绍
MQTT发布/订阅模式区别于传统的客户端/服务器模式,它使发布者与订阅者分离,发布者与订阅者不需要建立直接联系。
EMQ
902 0
MQTT 发布/订阅模式介绍

热门文章

最新文章