MQTT - AWS IoT 核心

本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。

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 协议和基于 WSS 的 MQTT 协议的设备连接。AWS IoTDevice SDK支持这两种协议,并且是将设备连接到 AWS IoT 的推荐方法。AWS IoT 设备软件开发工具包支持设备和客户端连接和访问 AWS IoT Core 服务所需的功能,并且支持 AWS IoT 服务所需的身份验证协议。有关如何使用 AWS 设备软件开发工具包连接到 AWS IoT 的信息以及指向受支持语言形式的 AWS IoT 示例的链接,请参阅 使用 AWS IoT 设备软件开发工具包与 MQTT 连接。有关 MQTT 消息的身份验证方法和端口映射的更多信息,请参阅协议、端口映射和身份验证

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

使用 AWS IoT 设备软件开发工具包与 MQTT 连接

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

C++

使用 AWS IoT C++ 设备软件开发工具包连接设备

Python

使用适用于 Python 的 AWS IoT 设备软件开发工具包连接设备

JavaScript

使用适用于 JavaScript 的 AWS IoT 设备软件开发工具包连接设备

Java

使用适用于 Java 的 AWS IoT 设备软件开发工具包连接设备

Embedded C

使用适用于嵌入式 C 的 AWS IoT 设备软件开发工具包连接设备

重要

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

MQTT 服务质量 (QoS) 选项

AWS IoT 和 AWS IoT 设备软件开发工具包支持 MQTT 服务质量 (QoS) 级别 01。MQTT 协议定义了第三级 QoS(即级别 2),但 AWS IoT 不支持它。只有 MQTT 协议支持 QoS 功能。HTTPS 不支持 QoS。

下表描述了每个 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 消息存储到客户端订阅的主题。当客户端重新连接到其持久性会话时,将恢复所有订阅,并以每秒 10 条消息的最大速率将所有已存储消息发送到客户端。

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

结束持久性会话

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

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

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

注意

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

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

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

持久性会话消息费用

当消息代理从客户端接收消息和向客户端发送消息时,将向您的 AWS 账户收取消息费用。如果具有持久性会话的设备未连接,则在客户端重新连接时要发送的已存储消息的费用也会计入您的账户。持久性会话到期时,为此会话存储的消息将被丢弃;但是,您的账户仍需支付其存储费用。有关消息定价的更多信息,请参阅 AWS IoT Core 定价 - 消息传递

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

使用 ConnectAttributes

ConnectAttributes 允许您在 IAM 策略中指定要在连接消息中使用的属性,如 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 消息。此消息包含一个标志,用于指明该连接是否会恢复上一个会话。

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

  • MQTT 规范提供了相应的预配置,以供发布者用于请求代理将发送到主题的最新消息保留下来并发送给未来的所有主题订阅者。AWS IoT 不支持保留的消息。如果请求保留消息,则将断开连接。

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

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

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