跳到主要内容

使用MQTT

消息队列遥测传输(MQTT)协议是一种轻量级、开放的协议,可用于机器对机器(M2M)和物联网(IoT)用例。

PubSub+ 事件代理支持 OASIS 标准 MQTT v3.1.1 和 MQTT v5.0。这允许客户端应用程序与 PubSub+ 事件代理互操作,而无需依赖 Solace 特定的 API 或自定义软件开发。

  • Solace 的 MQTT 实现符合 OASIS 标准 MQTT v3.1.1 和 MQTT v5.0。
  • 请参阅规范的注释版本(Solace MQTT 版本 3.1.1 协议合规性规范和 Solace MQTT 版本 5.0 协议合规性规范),这些版本突出了在协议规范的“应”和“可”条款中为 Solace 实现所做的任何偏差、限制或选择。我们强烈建议网络架构师和程序员审阅此文档。

MQTT概念

如果您之前没有一起使用过 MQTT 和 Solace PubSub+,您可能想查看概述:应用程序如何与 PubSub+ 消息组件交互页面的 MQTT 部分。它将带您参观 PubSub+ 事件代理的消息组件,并在高层次上解释它们如何使数据从生产者流向代理,以及从代理流向消费者。

MQTT会话

MQTT 客户端通过配置用于该消息 VPN 的专用 MQTT 端口连接到事件代理上的特定消息 VPN。MQTT 客户端连接还需要服务器上的一个 MQTT 会话。

MQTT 会话对象是存在于事件代理上的托管对象中的 MQTT 客户端连接的虚拟表示。MQTT 会话持有 MQTT 客户端的状态(即,它包含客户端的 QoS 0 和 QoS 1 主题过滤器集以及任何未投递的 QoS 1 消息)。

可以以下列方式创建 MQTT 会话:

  • 当客户端成功连接到事件代理时自动创建。
  • 由管理员使用 PubSub+ Broker Manager、Solace CLI 或 SEMP 创建。尽管 MQTT 规范不要求支持管理员配置的 MQTT 会话,但它们是允许的,并且它们为应用程序开发提供了更多的灵活性。有关管理员配置的 MQTT 会话的更多信息,请参阅管理 MQTT 会话。

MQTT会话持久性

根据客户端在连接到代理时提供的标志,相应的 MQTT 会话可能在客户端断开连接后持续存在,也可能不会。在客户端断开连接后仍然存在的会话称为持久会话。持久会话在重启后恢复,并在高可用性故障转移中存活,保留客户端的客户端 ID、主题过滤器和未投递的 QoS1 消息。

会话的行为取决于客户端使用的是 MQTT v3.1.1 还是 MQTT v5.0:

  • MQTT v3.1.1:当连接的 v3.1.1 客户端为 MQTT 会话提供 CleanSession=1 标志时,客户端现有的 MQTT 会话(如果存在)将被丢弃,客户端断开连接后,任何相关的信息(订阅集和未投递的消息)都不会被持久化。也就是说,该标志确保会话“干净启动”,会话“清理”自身,并且客户端断开连接后,事件代理上不存储任何信息。即使会话是通过 CLI 或 SEMP 管理配置的,也是如此。 如果客户端提供 CleanSession=0 标志,则 MQTT 会话在事件代理上被持久化(即,它是一个持久会话)。客户端可以稍后重新连接到这个持久会话。

  • MQTT v5.0:当连接的 v5.0 客户端为 MQTT 会话提供 CleanStart=1 标志时,客户端现有的 MQTT 会话(如果存在)将被丢弃。也就是说,该标志确保会话“干净启动”。 与之独立地,客户端可以提供一个会话过期间隔,以控制客户端断开连接后会话持续的时间。直到会话过期之前,它在事件代理上被持久化(即,持久的),并且客户端可以重新连接到它。

管理员始终可以通过 Solace CLI、SEMP 或使用 Broker Manager 删除 MQTT 会话。

服务质量级别

MQTT 发布消息和主题过滤器被分配了单独的服务质量(QoS)级别,这决定了应用于消息投递的保证级别。MQTT QoS 级别为:

  • QoS 0—至多一次投递。接收者(无论是事件代理还是订阅者)不需要做出响应,并且如果消息未投递,不会进行重试尝试。 Solace 对应 QoS 0 的是直接的消息投递模式。

  • QoS 1—至少一次投递。此级别确保消息至少投递一次。在 QoS 1 交换中,接收者(无论是事件代理还是订阅者)需要发送消息确认,以表明已收到消息。 Solace 对应 QoS 1 的是保证的消息投递模式。有关更多信息,请参阅保证消息。 要提供 QoS 1 服务,事件代理需要配置为保证消息。如果事件代理未配置为保证消息,所有 QoS 1 和 QoS 2 MQTT 主题过滤器将被降级为 QoS 0。此外,事件代理接受 QoS 1 和 QoS 2 消息,但它们作为 QoS 0 消息投递。有关如何配置事件代理以进行保证消息的更多信息,请参阅保证消息配置。

  • QoS 2—恰好一次投递。Solace 将发布的 QoS 2 消息转换为 QoS 1。

下图展示了在消息投递过程中可能应用于同一条消息的不同 QoS 级别。从发布者到事件代理,MQTT 发布消息使用消息发布者分配的 QoS 级别。从事件代理到消息订阅者,MQTT 发布消息使用匹配订阅(过滤器)的 QoS 和消息最初发布的 QoS 中的较小值。

img

消息类型变化时的有效载荷处理

本节讨论事件代理接收到的 MQTT 发布消息(即入站消息)的有效载荷在随后作为不同消息类型(无论是 SMF 还是 REST 消息)投递给具有匹配主题订阅的非 MQTT 客户端时如何处理。它还讨论了接收到的 SMF 或 REST 消息的有效载荷在随后作为 MQTT 发布消息投递给具有匹配主题过滤器的消费 MQTT 客户端时如何处理。

MQTT入站,SMF出站

当事件代理从客户端接收到 MQTT 发布消息时,接收到的消息的有效载荷(一系列字节)被封装在结果出站 SMF 消息中作为二进制附件。

MQTT入站,REST出站

对于 MQTT v3.1.1,当事件代理从客户端接收到 MQTT 发布消息时,接收到的消息的有效载荷以 "application/octet-stream" 的 HTTP Content-Type 进行投递。

MQTT v5.0 可以有自己的内容类型和有效载荷格式指示属性。如果接收到的 MQTT v5.0 消息具有内容类型属性,则投递的 HTTP 消息将具有匹配的 Content-Type。如果接收到的 MQTT v5.0 消息没有内容类型属性,但具有值为 1 的有效载荷格式指示属性,则投递的 HTTP 消息将具有 "text/plain" 的 Content-Type。

SMF入站,MQTT出站

SMF 消息包含以下内容:

  • SMF 标头(必须)和参数(可选)
  • XML 消息有效载荷(可选)
  • 二进制附件(可选)
  • 二进制编码的元数据(可选)

SMF 消息的 XML 消息有效载荷或二进制附件(但不是两者)可用于 MQTT 发布消息的有效载荷。此外:

  • 如果 SMF 消息仅包含二进制附件,则会发生以下情况:

    • 如果没有二进制元数据,则二进制附件被复制到 MQTT 发布消息的有效载荷字段中。
    • 如果存在描述二进制附件格式的二进制元数据,则指定类型的数据被复制到 MQTT 发布消息的有效载荷字段中。 Solace 消息 API 支持在消息的二进制附件中或作为用户定义的消息标头字段携带结构化数据类型(SDT),如映射和流。然而,这些 SDT 不能被 MQTT 客户端使用。因此,它们不包含在 MQTT 发布消息中。
  • 如果 SMF 消息仅包含 XML 消息有效载荷,则它被复制到 MQTT 发布消息的有效载荷字段中。 对于 MQTT v5.0,如果 SMF 消息没有 Content-Type,则 MQTT 消息将具有 "text/xml" 的 Content-Type 和值为 1 的有效载荷格式指示器。

  • 如果 SMF 消息同时包含二进制附件和 XML 消息有效载荷,则两者都不会发送,无论它们的内容如何。

  • 对于 MQTT v3.1.1,自定义用户属性和用户数据属性不会被复制到 MQTT 发布消息中。 对于 MQTT v5.0,如果可能,SMF 用户属性将被转换为文本,然后放入 MQTT 发布消息的用户属性中。如果 SMF 用户属性无法转换为文本,则整个消息被丢弃为 unformattable

如果原始 SMF 消息包含有效载荷,但上述过程导致没有有效载荷的 MQTT 发布消息,即使它没有有效载荷,MQTT 发布消息仍然被投递给 MQTT 客户端。在这种情况下,消息在 MQTT 会话统计信息中被标记为 unformattable

REST入站,MQTT出站

对于 MQTT v3.1.1,当事件代理接收到 REST 消息时,其有效载荷(由消息的 HTTP 标头之后传输的数据组成)将完整地在一个 MQTT 发布消息中投递给 MQTT 客户端。投递的消息的特定 Content-Type 并不重要。

对于 MQTT v5.0,HTTP Content-Type 被转换为 MQTT 内容类型。某些 HTTP Content-Type 值还会导致 MQTT v5.0 的有效载荷格式指示器为 1。

遗嘱消息

当连接到事件代理时,MQTT 客户端可以指定一个“遗嘱和遗嘱”(或简称“遗嘱”)消息。遗嘱消息与为客户端分配的 MQTT 会话信息一起存储,并在 MQTT 客户端意外从事件代理断开连接时发送。

MQTT v3.1.1 遗嘱消息由主题、QoS 级别和消息正文组成。MQTT v5.0 遗嘱消息还可以包含有效载荷格式、消息过期时间、内容类型、响应主题、相关数据和用户属性。遗嘱消息允许其他感兴趣的 MQTT 客户端检测到意外的连接丢失。

当由于事件代理重启、高可用性(HA)事件代理故障转移、消息 VPN 关闭或保证消息关闭而导致 MQTT 会话终止时,事件代理不会广播遗嘱消息。

保留消息

当发布者以不规则和/或不频繁的方式发送状态消息时,会使用保留消息。设置了保留位的已发布消息由 Solace 消息网络存储,并在订阅客户端订阅与保留消息发布的主题匹配的主题时投递给它们。这允许订阅者在订阅时立即收到最新的状态。

有关配置 Solace PubSub+ 事件代理以支持保留消息的更多信息,请参阅管理 MQTT 保留消息。

对 MQTT 保留消息的支持是一个受控可用性(CA)特性。请与 Solace 联系,以了解此特性是否支持您的用例。

MQTT保留缓存

在 Solace PubSub+ 事件代理中,保留消息被保存在称为 MQTT 保留缓存的特殊缓存集群中。换句话说,PubSub+ 缓存是用于存储、管理和选择在客户端添加主题过滤器时发布哪些保留消息的底层机制。

MQTT保留缓存辅助对象

当您创建一个 MQTT 保留缓存时,事件代理会创建以下辅助 PubSub+ 缓存对象。

对象类型名称注释
分布式缓存#retain-cache-<router-name>每个事件代理(或在 HA 部署中的配对)构成自己的分布式缓存。有关分布式缓存的更多信息,请参阅分布式缓存。
缓存集群#retain-cache-cluster每个作为保留缓存部署的缓存集群共享相同的名称。有关缓存集群的更多信息,请参阅缓存集群。
缓存实例(主)#retain-cache-instance-<router-name>-primary每个具有保留缓存的事件代理都运行一个保留缓存实例。主实例在 HA 配对中的主路由器上运行。有关缓存实例的更多信息,请参阅 PubSub+ 缓存实例。
缓存实例(备份)#retain-cache-instance-<router-name>-backup备份缓存实例类似于主缓存实例,只是它在启用冗余时在备份路由器上运行。

共享订阅

PubSub+ 事件代理支持 OASIS 标准 MQTT v5.0 共享订阅,适用于 v3.1.1 和 v5.0 客户端。您可以使用共享订阅在多个后端数据中心应用程序实例之间负载均衡大量客户端数据。每个数据中心应用程序实例加入共享订阅,匹配共享订阅的数据量在应用程序实例之间随机分配。

在实现共享订阅时,请考虑以下几点:

  • 只支持 QoS 0 的共享订阅。如果请求具有更高 QoS 的共享订阅,它将被降级为 QoS 0。

  • 只有在非持久会话上支持共享订阅(对应于以 CleanSession=1 连接的 v3.1.1 客户端或以 SessionExpiry=0 连接的 v5.0 客户端)。向持久 MQTT 会话添加共享订阅的请求将被事件代理拒绝。

  • 在 OASIS 标准 MQTT v5.0 中,一个 CONNACK 属性表明事件代理是否支持共享订阅。因为 MQTT v3.1.1 中没有 CONNACK 属性,所以事件代理无法将此信息传输给 v3.1.1 客户端。SolacePubSub+ 事件代理从 9.1 版本开始支持共享订阅。

  • 由于允许随意访问共享订阅是一个潜在的安全问题,您可以指定哪些客户端能够使用共享订阅。有关更多信息,请参阅允许共享订阅。

  • 如果事件代理配置为使用 ACL 控制客户端可以订阅的内容,它仅验证共享订阅的 {filter} 部分。

  • 在启用了订阅导出的 MNR 或 DMR 部署中,共享订阅默认被导出。在这些情况下,事件代理将每个导出的订阅视为一个单独的实体。换句话说,连接到不同节点的客户端不会作为一个组进行负载均衡。要防止事件代理导出订阅,请以 $noexport 开始订阅(主题过滤器)。例如,$noexport/$share/{ShareName}/{filter}

视频:使用MQTT的共享订阅

在本视频中,Leah Robert 谈论了共享订阅,并演示了如何使用 MQTT 设置它们。