在这篇文章中,我们解释了 MQTT 中不同的服务质量级别。“服务质量”这个词在之前的帖子中出现过几次,让我们来看看这个词到底是什么意思。
服务质量(QoS) 级别是消息发送者和消息接收者之间的协议,它定义了特定消息的传递保证。MQTT 中有 3 个 QoS 级别:
最多一次(0)
至少一次(1)
恰好一次(2)。
在 MQTT 中谈 QoS 时,需要考虑消息传递的两个方面:
消息从发布客户端传递到代理。
从代理到订阅客户端的消息传递。
我们将分别查看消息传递的两个方面,因为两者之间存在细微差别。将消息发布到代理的客户端在向代理发送消息时定义了消息的 QoS 级别。代理使用每个订阅客户端在订阅过程中定义的 QoS 级别将此消息传输到订阅客户端。如果订阅客户端定义的 QoS 比发布客户端低,则代理会发送具有较低服务质量的消息。
QoS 是 MQTT 协议的一个关键特性。QoS 使客户端能够选择与其网络可靠性和应用程序逻辑相匹配的服务级别。因为 MQTT 管理消息的重新传输并保证传递(即使底层传输不可靠),QoS 使不可靠网络中的通信变得容易得多。
让我们仔细看看 MQTT 协议中每个 QoS 级别是如何实现的,以及它是如何发挥作用的:
QoS 0 - 最多一次
最低 QoS 级别为零。这种服务水平保证了尽力而为的交付。不保证交货。接收者不确认收到消息,并且消息不被发送者存储和重新发送。QoS 级别 0 通常被称为“即发即弃”,提供与底层 TCP 协议相同的保证。
服务质量级别 0:最多交付一次
QoS 1 - 至少一次
QoS 级别 1 保证一条消息至少一次传递给接收方。发送方存储消息,直到它 从接收方收到确认收到消息的PUBACK数据包。一条消息可以多次发送或传递。
服务质量级别 1:至少交付一次
发送方使用每个数据包中的数据包标识符将 PUBLISH 数据包与相应的 PUBACK 数据包匹配。如果发送方在合理的时间内没有收到 PUBACK 数据包,则发送方重新发送 PUBLISH 数据包。当接收者收到一条 QoS 为 1 的消息时,它可以立即处理它。例如,如果接收方是代理,则代理将消息发送给所有订阅客户端,然后使用 PUBACK 数据包进行回复。
QoS 2 - 恰好一次
QoS 2 是 MQTT 中最高级别的服务。此级别保证每条消息仅由预期的收件人接收一次。QoS 2 是最安全和最慢的服务质量级别。该保证由发送方和接收方之间的至少两个请求/响应流(四部分握手)提供。发送方和接收方使用原始 PUBLISH 消息的数据包标识符来协调消息的传递。
服务质量级别 2:仅交付一次
当接收方从发送方获得 QoS 2 PUBLISH 数据包时,它会相应地处理发布消息,并使用确认 PUBLISH 数据包的[PUBREC数据包回复发送方。如果发送方没有从接收方收到 PUBREC 数据包,它会再次发送带有重复 (DUP) 标志的 PUBLISH 数据包,直到收到确认。
接收方收到PUBREL包后,可以丢弃所有存储的状态,并以PUBCOMP包应答(发送方收到PUBCOMP时也是如此)。直到接收方完成处理并将 PUBCOMP 数据包发送回发送方,接收方存储对原始 PUBLISH 数据包的数据包标识符的引用。此步骤对于避免再次处理消息很重要。发送方收到 PUBCOMP 数据包后,已发布消息的数据包标识符就可以重新使用。
如果数据包在途中丢失,发送者有责任在合理的时间内重新传输消息。如果发送方是 MQTT 客户端或MQTT 代理,这同样适用。接收者有责任相应地响应每个命令消息。
QoS 的某些方面乍一看并不是很明显。使用 QoS 时要记住以下几点:
QoS 降级
正如我们已经提到的,发送(发布)消息的客户端和接收消息的客户端之间的 QoS 定义和级别是两个不同的东西。这两种交互的 QoS 级别也可以不同。向代理发送 PUBLISH 消息的客户端定义了消息的 QoS。但是,当代理将消息传递给接收者(订阅者)时,代理会使用接收者(订阅者)在订阅期间定义的 QoS。例如,客户端 A 是消息的发送者。客户端 B 是消息的接收者。如果客户端 B 订阅了 QoS 1 的代理,客户端 A 将消息发送到 QoS 2 的代理,则代理将消息传递给 QoS 1 的客户端 B(接收者/订阅者)。消息可以多次传递给客户端B,因为QoS1 保证至少传输一次,并不会阻止多次传递。
每个客户端的数据包标识符都是唯一的
MQTT 用于 QoS 1 和 QoS 2 的数据包标识符在特定客户端和交互中的代理之间是唯一的。此标识符在所有客户端之间不是唯一的。一旦流程完成,数据包标识符就可以重复使用。这种重用是包标识符不需要超过 65535 的原因。客户端可以发送超过这个数量的消息而不完成交互是不现实的。
我们经常被问及如何选择正确的 QoS 级别的建议。以下是一些可以帮助您做出决策的指南。适合您的 QoS 在很大程度上取决于您的用例。
当……时使用 QoS 0
您在发送方和接收方之间建立了完全或大部分稳定的连接。QoS 0 的一个经典用例是通过有线连接将测试客户端或前端应用程序连接到 MQTT 代理。
您不介意偶尔丢失一些消息。如果数据不是那么重要或数据发送间隔很短,一些消息的丢失是可以接受的
您不需要消息队列。仅当断开连接的客户端具有 QoS 1 或 2 和持久会话时,消息才会排队。
当……时使用 QoS 1
您需要获取每条消息,并且您的用例可以处理重复消息。QoS 级别 1 是最常用的服务级别,因为它保证消息至少到达一次,但允许多次传递。当然,您的应用程序必须容忍重复并能够相应地处理它们。
您无法承受 QoS 2 的开销font>。QoS 1 传递消息的速度比 QoS 2 快得多。
当……时使用 QoS 2
对您的应用程序来说,只接收一次所有消息至关重要。如果重复交付可能会损害应用程序用户或订阅客户端,则通常会出现这种情况。请注意开销,并且 QoS 2 交互需要更多时间才能完成。
使用 QoS 1 和 2 发送的所有消息都会排队等待离线客户端,直到客户端再次可用。然而,只有当客户端有一个持久会话时,这种排队才是可能的。
在下一篇文章中,我们将讨论与服务质量级别密切相关的主题:MQTT 中的持久会话。