MQTT - AWS IoT Core

MQTT

MQTT 是一种广泛采用的轻型消息传递协议,专为受限制的设备而设计。AWS IoT 对 MQTT 的支持基于 MQTT v3.1.1 规范,但有一些差异。有关 AWS IoT 与 MQTT v3.1.1 规范有何不同的信息,请参阅 AWS IoT 与 MQTT 3.1.1 版规范的区别

AWS IoT Core 支持使用 MQTT 协议和 MQTT WSS 协议上并由客户端 ID 标识的设备连接。AWS IoT Device SDK 支持这两种协议,并且是将设备连接到 AWS IoT 的推荐方法。AWS IoT 设备 SDK 支持设备和客户端连接和访问 AWS IoT Core 服务所需的功能。设备 SDK 支持 AWS IoT 服务所需的身份验证协议以及 MQTT 协议和 MQTT over WSS 协议所需的连接 ID 要求。有关如何使用 AWS IoT Device SDK 连接到 AWS 的信息以及指向受支持语言形式的 AWS IoT 示例的链接,请参阅 使用 AWS IoT Device SDK 与 MQTT 连接。有关 MQTT 消息的身份验证方法和端口映射的更多信息,请参阅协议、端口映射和身份验证

虽然我们建议使用 AWS IoT Device SDK 连接到 AWS IoT,但它们并不是必需的。但是,如果您不使用 AWS IoT Device SDK,则必须提供必要的连接和通信安全性。客户端必须在连接请求中发送服务器名称指示 (SNI) TLS 扩展。不包括 SNI 的连接尝试将被拒绝。有关更多信息,请参阅 AWS IoT 中的传输安全。使用 IAM 用户和AWS凭证对客户端进行身份验证的客户端必须提供正确的 Signature Version 4 身份验证。

使用 AWS IoT Device SDK 与 MQTT 连接

本节包含指向 AWS IoT Device SDK 以及演示如何将设备连接到 AWS IoT 的示例程序源代码的链接。此处链接的示例应用程序演示如何使用 MQTT 协议和基于 WSS 的 MQTT 协议连接到 AWS IoT。

C++

使用 AWS IoT C++ 设备 SDK 连接设备

Python

使用适用于 Python 的 AWS IoT 设备 SDK 连接设备

JavaScript

使用适用于 JavaScript 的 AWS IoT 设备 SDK 连接设备

Java

使用适用于 Java 的 AWS IoT 设备 SDK 连接设备

Embedded C

使用适用于嵌入式 C 的 AWS IoT 设备 SDK 连接设备

重要

该 SDK 供经验丰富的嵌入式软件开发人员使用。

MQTT 服务质量 (QoS) 选项

AWS IoT 和 AWS IoT Device SDK 支持 MQTT 服务质量 (QoS) 级别 01。MQTT 协议定义了第三级 QoS(即级别 2),但 AWS IoT 不支持它。只有 MQTT 协议支持 QoS 功能。HTTPS 通过传递查询字符串参数 ?qos=qos 来支持 QoS,其值可以是 0 或 1。

下表描述了每个 QoS 级别如何影响发布到消息代理和由消息代理发布的消息。

QoS 级别为...

消息为...

注释

QoS 级别 0

不发送或发送多次

此级别应该用于通过可靠通信链接发送的消息,或者可以毫无问题地错过的消息。

QoS 级别 1

至少发送一次,然后重复发送,直到收到 PUBACK 响应

在发送方收到指示成功传递的 PUBACK 响应之前,该消息不被认为是完整的。

使用 MQTT 持久性会话

持久性会话存储客户端尚未确认的服务质量 (QoS) 为 1 的客户端订阅和消息。当断开连接的设备重新连接到持久性会话时,该会话将恢复,其订阅恢复,并将在重新连接之前收到的、尚未由客户端确认的订阅消息发送给客户端。

创建持久性会话

您可以通过发送 CONNECT 消息并将 cleanSession 标记设置为 0 来创建 MQTT 持久性会话。如果发送 CONNECT 消息的客户端不存在会话,则会创建一个新的持久性会话。如果客户端已存在会话,则客户端会恢复现有会话。

持久性会话期间的操作

客户端使用连接已确认 (CONNACK) 消息中的 sessionPresent 属性确定是否存在持久性会话。如果 sessionPresent1,则存在持久性会话,并且在客户端收到 CONNACK 后立即将为客户端存储的所有消息传送给客户端,如重新连接到持久性会话后的消息流量中所述。如果 sessionPresent1,则客户端无需重新订阅。但是,如果 sessionPresent0,则不存在持久性会话,并且客户端必须重新订阅主题筛选条件。

客户端加入持久性会话后,它可以发布消息并订阅主题筛选条件,而无需在每个操作上附加任何标记。

重新连接到持久性会话后的消息流量

持久性会话表示客户端与 MQTT 消息代理之间的持续连接。当客户端使用持久性会话连接到消息代理时,消息代理会保存客户端在连接期间所做的所有订阅。当客户端断开连接时,消息代理将未确认的 QoS 1 消息和发布的新 QoS 1 消息存储到客户端订阅的主题。消息根据账户限制进行存储,超过该限制的消息将被删除。有关持久消息限制的更多信息,请参阅 AWS IoT Core 终端节点和配额。当客户端重新连接到其持久性会话时,将恢复所有订阅,并以每秒 10 条消息的最大速率将所有已存储消息发送到客户端。

重新连接后,以每秒限制为 10 条已存储消息的速率将已存储消息与任何当前消息流量一起发送到客户端,直到达到 Publish requests per second per connection 限制。由于已存储消息的传递速率受到限制,如果会话在重新连接后有超过 10 条已存储消息要传递,则传递所有已存储消息将需要几秒钟的时间。

结束持久性会话

以下条件描述了持久性会话的结束方式。

  • 持久性会话到期时间已过。当消息代理检测到客户端已断开连接(通过客户端断开连接或连接超时)时,持久性会话到期计时器将启动。

  • 当客户端发送将 cleanSession 标记设置为 1CONNECT 消息时。

注意

会话结束时等待发送给客户端的已存储消息将被丢弃;但是,即使无法发送,也仍按标准消息传递费率计费。有关消息定价的更多信息,请参阅 AWS IoT Core 定价。您可以配置到期时间间隔。

持久性会话到期后重新连接

如果客户端在其持久性会话到期之前未重新连接到该会话,则该会话结束并丢弃其存储的消息。当客户端在会话到期后重新连接并将 cleanSession 标记设置为 0 时,服务会创建一个新的持久性会话。上一个会话中的任何订阅或消息都不可用于此会话,因为它们在上一个会话到期时被丢弃。

持久性会话消息费用

当消息代理向客户端或离线永久性会话发送消息时,消息将向您的AWS 账户收费。当具有持久会话的离线设备重新连接并恢复其会话时,存储的消息将传递到设备并再次向您的账户收费。有关消息定价的更多信息,请参阅 AWS IoT Core 定价 - 消息收发

通过使用标准限制增加过程,可以将默认的持久性会话到期时间延长 1 小时。请注意,增加会话过期时间可能会增加消息费用,因为额外的时间可能允许离线设备存储更多消息,而这些额外的消息费用将按标准消息收发费率计入您的账户。会话到期时间为大约时间,会话的持续时间最多可能比账户限制长 30 分钟;但是,会话时间不会短于账户限制。有关会话限制的更多信息,请参阅 AWS Service Quotas

使用 MQTT 保留消息

AWS IoT Core 支持 MQTT v3.1.1 中描述的 RETAIN 标志。当客户端在发布的 MQTT 消息上设置 RETAIN 标志时,AWS IoT Core 保存该消息。然后可以将其发送给新订阅者,通过调用 GetRetainedMessage 操作进行检索,并在 AWS IoT 控制台中查看。在最后一次更新或访问消息后,AWS IoT Core 会将保留消息存储三年。三年后,消息将被删除。

使用 MQTT 保留消息的示例

  • 作为初始配置消息

    客户端订阅主题后,MQTT 保留消息会被发送给客户端。如果希望订阅主题的所有客户端在订阅后立即接收 MQTT 保留消息,您可以发布设置了RETAIN 标志的配置消息。只要发布新的配置消息,订阅客户端也会收到该配置更新。

  • 作为最后一个已知的状态消息

    设备可以在当前状态消息上设置 REATIN 标志,以便 AWS IoT Core 保存它们。当应用程序连接或重新连接时,它们可以订阅此主题并在订阅保留消息主题后立即获得上一次报告状态。这样,它们就不必等到设备发出下一条消息才能看到当前状态。

将 MQTT 保留消息存储在 AWS IoT Core 中的常见任务

AWS IoT Core 使用 RETAIN 标志设置保存 MQTT 消息。这些 保留消息 被作为普通的 MQTT 消息发送给已订阅该主题的所有客户端,同时也被存储起来发送给该主题的新订阅者。

客户端需要特定的策略操作授权才能访问 MQTT 保留消息。获取有关使用保留消息策略的示例,请参阅 保留的消息策略示例

本节介绍了涉及保留消息的常见操作。

  • 创建保留消息

    客户端在发布 MQTT 消息时确定是否保留消息。客户端可以在发布消息时使用 设备 SDK 设置 RETAIN 标志。应用程序和服务可以在使用 Publish 操作 发布 MQTT 消息时设置 RETAIN 标志。

    每个主题名称只保留一条消息。发布到主题的带有 RETAIN 标志设置的新消息将替换先前发送到该主题的任何现有保留消息。

    注意: 如果您设置了 RETAIN 标志则不能发布到 预留主题

  • 订阅保留消息主题

    客户端订阅保留消息主题,就像订阅任何其他 MQTT 消息主题一样。通过订阅保留消息主题接收的保留消息均有 RETAIN 标志设置。

    当客户端将具有 0 字节消息负载的保留消息发布到保留消息主题时,将从 AWS IoT Core 中删除保留消息。已订阅保留消息主题的客户端也将收到该 0 字节消息。

    订阅包含保留消息主题的通配符主题筛选条件可使客户端接收发布到保留消息主题的后续消息,但在订阅时不会传递保留消息。

    注意: 要在订阅时接收保留消息,订阅请求中的主题筛选条件必须与保留消息主题完全匹配。

    订阅保留消息主题时收到的保留消息有 RETAIN 标志设置。订阅客户端在订阅后收到的保留消息则没有。

  • 检索保留消息

    当客户端使用保留消息订阅主题时,保留消息会被自动发送给客户端。要让客户端在订阅时收到保留消息,必须订阅保留消息的确切主题名称。通过订阅包含保留消息主题的通配符主题筛选条件,客户端可以接收发布到保留消息主题的后续消息,但不会在订阅时传送保留消息。

    服务和应用可以通过调用 ListRetainedMessagesGetRetainedMessage 列出和检索保留消息。

    设置 RETAIN 标志的情况下,客户端不会被阻止发布消息到保留消息主题。这可能会导致意外结果,例如保留消息与订阅主题收到的消息不匹配。

  • 列出保留消息主题

    您可以通过调用 ListRetainedMessages 列出保留消息,并且可以在 AWS IoT 控制台 中查看保留消息。

  • 获取保留消息详细信息

    您可以通过调用 GetRetainedMessage 获取保留消息的详细信息,并且可以在 AWS IoT 控制台 中查看这些信息。

  • 保留 Will 消息

    连接设备时创建的 MQTT Will 消息 可以通过设置 Connect Flag bits 字段中的 Will Retain 标记保留。

  • 删除保留消息

    通过将设置了 RETAIN 标志的消息和空(0字节)消息负载发布到要删除的保留消息的主题名称,设备、应用程序和服务可以删除保留消息。从 AWS IoT Core 中删除保留消息的此类消息被发送给订阅了该主题的客户端,但 AWS IoT Core 不会保留此类消息。

    还可以通过访问 AWS IoT 控制台 中的保留消息以交互的方式删除保留消息。通过 AWS IoT 控制台 删除的保留消息也会向已订阅保留消息主题的客户端发送 0 字节的消息。

    保留消息在删除后无法恢复。客户端需要发布新的保留消息才能取代已删除的消息。

  • 保留消息的调试和故障排查

    AWS IoT 控制台 提供多个工具来帮助您进行保留消息故障排查:

    • 保留消息 页面

      AWS IoT 控制台中的 保留消息 页面提供您的账户在当前区域中存储的保留消息的分页列表。在此页面上,您可以:

      • 查看每条保留消息的详细信息,例如消息负载、QoS、接收时间。

      • 更新保留消息的内容。

      • 删除保留消息。

    • 打开 MQTT 测试客户端

      AWS IoT 控制台中的 MQTT 测试客户端 页面可以订阅并发布到 MQTT 主题。发布选项让您可以在发布的消息上设置 REATEIN 标志,以模拟设备的行为方式。

    在 AWS IoT Core 中如何应用保留消息的这些方面可能会产生一些意外的结果。

    • 保留消息限制

      当帐户存储了最大数量的保留消息时,对于使用 RETAIN 设置且有效负载大于 0 字节的发布消息,AWS IoT Core 将返回限制响应,直到一些保留消息被删除且保留消息数量低于限制。

    • 保留消息传递顺序

      不保证保留消息和订阅消息传递的顺序。

账单和保留消息

从客户端通过使用 AWS IoT 控制台或调用 Publish 发布设置了 RETAIN 标志的消息会产生 AWS IoT Core 定价-消息收发 中说明的额外消息收发费用。

除了正常的 API 使用费之外,通过客户端、使用 AWS IoT 控制台或调用 GetRetainedMessage 检索保留消息还会产生消息收发费用。AWS IoT Core 定价-消息收发 中说明了此类额外费用。

在设备意外断开连接时发布的 MQTT Will消息 会产生 AWS IoT Core 定价-消息收发 中说明的消息收发费用。

有关消息传递定价的更多信息,请参阅 AWS IoT Core 定价 - 消息传递

比较 MQTT 保留消息和 MQTT 持久会话

保留消息和持久会话是 MQTT 3.1.1 的标准功能,使设备能够接收离线时发布的消息。持久会话中可以发布保留消息。本节介绍这些功能的主要方面及其如何协作。

保留消息

持久会话

持久会话中的保留消息

主要功能

在连接大量设备后,保留消息可用于配置或通知这些设备。

如果您希望设备仅接收重新连接后发布到主题的最后一条消息,也可以使用保留消息。

持久会话对于间歇性连接而可能错过多条重要消息的设备非常有用。

设备可以连接持久会话来接收离线时发送的消息。

常规会话和持久会话中均可使用保留消息。

示例

保留消息可以在设备上线时提供有关其环境的配置信息。初始配置可以包括应该订阅的其他消息主题的列表,或者如何配置本地时区的相关信息。

通过间歇连接的蜂窝网络连接的设备可以使用持久会话,避免丢失在设备超出网络覆盖范围或需要关闭其蜂窝无线电时发送的重要消息。

持久会话示例中的蜂窝设备可以使用保留消息,以在初始连接时接收初始配置。

初始订阅主题时收到的消息

订阅带有保留消息的主题后,会收到最近的保留消息。

在订阅没有保留消息的主题后,向该主题发布消息之前不会收到任何消息。

订阅带有保留消息的主题后,会收到最近的保留消息。

重新连接后订阅的主题

如果没有持久会话,客户端必须在重新连接后订阅主题。

重新连接后,将恢复订阅的主题。

重新连接后,将恢复订阅的主题。

重新连接后收到的消息

订阅带有保留消息的主题后,会收到最近的保留消息。

在设备断开连接时,所有以 QOS = 1 发布并使用 QOS =1 订阅的消息都将在设备重新连接后发送。

在设备断开连接时,所有以 QOS = 1 发布并使用 QOS =1 订阅的消息都将在设备重新连接后发送。

客户端订阅的主题中更新的保留消息也会发送给客户端。

如果在客户端离线时向某个主题发布了多条保留消息,在重新连接后,客户端可以接收多条存储到该主题的保留消息。

数据会话过期

保留消息不会过期。它们将被存储,直至被替换或删除。

如果未在超时期限内重新连接客户端,持久会话将过期。持久会话过期后,在设备断开连接时以 QOS = 1 发布并使用 QOS =1 订阅的客户端订阅和保存消息将被删除。

获取有关持久会话的会话过期时间的更多信息,请参阅 使用 MQTT 持久性会话

保留消息不会过期。它们将被存储,直至被替换或删除,即使是从已过期的持久会话中发送的也是如此。持久性会话过期后,在设备断开连接时,会删除以 QOS = 1 发布并使用 QOS =1 订阅的客户端订阅和保存消息。

有关持久性存储的信息,请参阅 使用 MQTT 持久性会话

使用保留消息,发布客户端可确定是否应在连接后保留消息并将其传送到设备,是否有上一个会话。是否存储消息由发布者自行选择,存储的消息将被发送给所有使用 QoS 0 或 QoS 1 订阅的当前和未来客户端。保留消息一次只保存一条给定主题的消息。

当帐户存储了最大数量的保留消息时,AWS IoT Core 将对使用 RETAIN 集和大于 0 字节的有效负载发布的消息返回限制响应,直到删除一些保留消息且保留消息数不超过限制。

MQTT 保留了消息和 AWS IoT Device Shadows

保留消息和 Device Shadows 都保留来自设备的数据,但它们的行为不同,用途也不同。本节介绍它们的相似之处和不同之处。

保留消息

设备影子

消息有效负载具有预定义的结构或架构

正如实施所定义的。MQTT 没有为其消息负载指定结构或架构。

AWS IoT 支持特定的数据结构。

更新消息负载会生成事件消息

发布保留消息会将消息发送到订阅的客户端,但不会生成其他更新消息。

更新 Device Shadow会出现更新描述更改的消息

消息更新已编号

保留消息不会自动编号。 Device Shadow 文档具有自动版本号和时间戳。

消息有效负载附加到事物资源上

保留消息不会附加到事物资源。

Device Shadows 附加到事物资源。

更新消息有效负载的单个元素

如果不更新整个消息负载,就无法更改消息的单个元素。

可以更新 Device Shadow 文档的各个元素,而无需更新整个 Device Shadow 文档。

客户端在订阅时收到消息数据

在订阅带保留消息的主题后,客户端会自动收到保留消息。

客户端可以订阅 Device Shadow 更新,但他们必须故意请求当前状态。

索引和可搜索性

保留消息不会编制索引进行搜索。

实例集索引 Device Shadow 数据进行搜索和聚合。

使用 ConnectAttributes

ConnectAttributes 允许您在 IAM policy 中指定要在连接消息中使用的属性,如 PersistentConnectLastWill。借助 ConnectAttributes,您可以构建预设情况下不允许设备访问新功能的策略,这在设备受到威胁时很有帮助。

connectAttributes 支持以下功能:

PersistentConnect

当客户端和代理之间的连接中断时,使用 PersistentConnect 功能可以保存客户端在连接期间所做的所有订阅。

LastWill

当客户端意外断开连接时,使用 LastWill 功能可以向 LastWillTopic 发布消息。

预设情况下,您的策略具有非持久连接,并且没有为此连接传递任何属性。如果您想要具有持久连接,则必须在 IAM 策略中指定持久连接。

有关 ConnectAttributes 示例,请参阅连接策略示例

AWS IoT 与 MQTT 3.1.1 版规范的区别

尽管消息代理的实施基于 MQTT v3.1.1 规范,但与该规范有如下区别:

  • AWS IoT 仅支持 MQTT 服务质量 (QoS) 级别 0 和 1。AWS IoT 不支持使用 QoS 级别 2 进行发布或订阅。在请求 QoS 级别 2 时,消息代理不会发送 PUBACK 或 SUBACK。

  • 在 AWS IoT 中,订阅具有 QoS 级别 0 的主题意味着将消息传送零次或多次。消息可能会多次发送。多次发送的消息在发送时可能会使用不同的数据包 ID。在这些情况下,不会设置 DUP 标志。

  • 在响应连接请求时,消息代理将发送 CONNACK 消息。此消息包含一个标志,用于指明该连接是否会恢复上一个会话。

  • 在发送其它控制数据包或断开连接请求之前,客户端必须等待从 AWS IoT 消息代理发送到设备的 CONNACK 消息。

  • 当由于客户端未被授权进行连接而拒绝连接时,AWS IoT 会返回错误代码 7,而不是 CONNACK 错误代码 5。

  • 当客户端订阅主题时,在消息代理开始发送 SUBACK 和客户端开始收到新的匹配消息之间存在时间延迟。

  • 当客户端在订阅主题的主题过滤条件中使用通配符 # 时,主题层次结构中处于及其级别以下的所有字符串均会匹配。但是,父主题不匹配。例如,订阅主题 sensor/# 接收发布到主题sensor/sensor/temperaturesensor/temperature/room1 的消息,但不是发布到 sensor 的消息。有关通配符的更多信息,请参阅 主题筛选条件

  • 消息代理使用客户端 ID 标识每个客户。客户端 ID 作为 MQTT 负载的一部分从客户端传递到消息代理。客户端 ID 相同的两个客户端无法同时连接到消息代理。当某个客户端使用另一客户端正在使用的客户端 ID 连接到消息代理时,会接受新的客户端连接,而之前连接的客户端会断开连接。

  • 在极少数情况下,消息代理可能会使用不同的数据包 ID 再次发送相同的逻辑 PUBLISH 消息。

  • 订阅包含通配符的主题筛选条件无法接收保留消息。要接收保留消息,订阅请求必须包含与保留消息主题完全匹配的主题筛选条件。

  • 消息代理并不保证收到消息和 ACK 的顺序。

  • 每个发布请求的有效负载不能大于 128 KB。AWS IoT Core 拒绝大于此大小的发布和连接请求。有关更多信息,请参阅《AWS IoT 参考指南》中的AWS IoT Core消息代理和协议限制与限额