【译文】MQTT 服务质量(QoS)– MQTT 基础: 第六部分

103 阅读8分钟

原文:www.hivemq.com/blog/mqtt-e…

本篇文章在翻译过程中,对相关内容进行了一些删减,比如文字超链接

作者: HiveMQ Team
发布时间: February 16, 2015
更新于: 2023年6月20日

MQTT服务质量(QoS)是消息发送方和接收方之间的一个协议,它定义了特定消息的传递保证级别。下面是 MQTT基础课程的第六部分,我们将深入研究MQTT中的不同服务质量(QoS)级别。如果您希望了解MQTT主题、通配符和最佳实践,请参阅本系列的第五部分。我们开始吧。

MQTT中的QoS指的是什么?

MQTT提供了3种级别的QoS:

  • 最多一次(QoS 0)
  • 至少一次(QoS 1)
  • 精准一次(QoS 2)

如何检查MQTT中的消息传递?

当讨论MQTT QoS时,需要重点考虑客户端和代理服务器之间的消息传递。消息传递在从发布客户端到代理服务器和从代理服务器到订阅客户端是有细微差别的。

发布消息到代理服务器的客户端在传输数据时,可以为消息定义QoS。代理服务器会根据每个订阅客户端定义的QoS来传输消息到订阅客户端。如果订阅客户端定义了比发布客户端低的QoS,代理服务器将使用值比较小的QoS来传递消息。

理解MQTT消息传递机制可以对理解QoS奠定基础。QoS能确保消息在发布端,代理服务器及订阅端之间可靠传输。

QoS为什么重要?

QoS在MQTT中非常重要,它可以让需要QoS能力的客户端选择一个服务质量级别,这个级别能满足网络可靠性和应用需求。MQTT本身具有重发和可靠传递能力,甚至在不可靠网络条件下,QoS尤为显得重要,因为QoS可以应对不可靠网络环境。通过提供不同QoS级别,MQTT授权客户端可以优化他们对网络的用法,并且平衡好可靠和高效指标。

现在我们理解了QoS在MQTT中的重要性,让我们探究一下QoS内部工作原理以及它如何做到在恶劣网络环境下确保消息高可靠性的传输。

QoS 0级别在MQTT中是如何工作的?

在MQTT中QoS 0是最低级别,提供最高效的消息传递机制,发送消息不关心是否有ACK,对消息传递结果也不做保障。 这意味订阅者也不会确认已收到消息,发送者也不保存已发送的消息或者重发消息。QoS 0, 通常叫做“发送即忘记”,类似于TCP底层协议,在没有进一步跟进或确认的情况下直接发送信息。

WX20230911-212117@2x.png

QoS 0 : 最多一次

QoS 1级别在MQTT中是如何工作的?

MQTT中的QoS 1, 重点是确保消息传递至少一次可以到达接收者。当消息以QoS 1发布时,发送者会保留一份副本,直到接收到PUBACK 包, 才能确认消息已接收成功。如果在一定时间内没有接收到PUBACK包, 消息还会被重新发一次,确保它已被收到.

WX20230911-212807@2x.png

QoS 1 : 至少一次

一旦接收到消息,接收者会立即处理消息。例如,如果接收者是一个代理服务器,它会分发消息到所有已订阅这个消息主题的客户端,并且回复一个PUBACK包确认已收到消息。

puback_packet.png

值得注意的是,在QoS 1时,如果发布者客户端重新发送了一条同样的消息,它会设置一个DUP标志。然而,这个标志是用于内部的,且不会被代理服务器或者客户端处理。不管DUP标志如何,一直到接收者发送PUBACK包才能被确认发送者的消息已成功传递。

QoS 1的目的是为了在消息传递的可靠性和效率之间寻求一个平衡,即确保消息至少抵达一次,也允许可能发生的消息重复现象。

QoS 2级别在MQTT中是如何工作的?

QoS 2 在MQTT中属于最高级别的服务质量,能确保每条消息精准仅发送一次就到达目标接收者。为了达到这个效果,QoS 2在发送者和接收者之间会涉及到4次握手动作。

WX20230911-214442@2x.png

QoS 2 : 精准一次

当接收者获取到一个QoS 2的发布包,它会相应的处理发布主题,并且给发布者回复PUBREC 包,以确认收到PUBLISH包. 如果发送者没有拿到PUBREC包,它会发一个带有DUP标志的重复包,直到收到确认。

pubrec_packet.png

一旦发送者从接收者收到PUBREC包,发送者就可以安全的抛弃之前发送成功PUBLISH包。发送者会存储来自接收者的PUBREC包,并且以PUBREL 包回复, 接收者抛弃所有的存储状态,并以PUBCOMP包回复.

pubrel_packet.png

接收者拿到PUBREL包之后,他会抛弃所有的存储状态,并且以PUBCOMP 包回复发送者 (当发送者收到PUBCOMP也是同理). 在接收者完成数据处理并且发送PUBCOMP包到发送者之前,接收者会存储涉及这个原始PUBLISH包的一切信息。为了避免消息被二次发送,这一步至关重要。

发送者收到PUBCOMP包后,已发布的消息包标识重新使用时会失效。

pubcomp_packet.png

当QoS 2流程完成后,各方都确保消息已被传递,并且发布者也确认了消息传递成功。

如果一个包丢失了,发送者有责任在预设时间内重发一次。这个机制对MQTT客户端或者MQTT broker都适用. 接收者有责任响应每条命令消息。

在MQTT中,对于QoS来讲,关键要考虑的是什么?

当理解MQTT中的QoS时,有一些关键点值得思考:

降低QoS

QoS被发送者和接收者可以定义为不一样。当代理服务器使用接收者订阅时的QoS时,发送消息到代理服务器的客户端也可以定义一个QoS。例如,如果发送者使用QoS 2,接收者订阅时使用QoS 1,那么代理服务器分发消息时,会使用QoS 1级别。这就会导致相同的消息被多次传递到接收者。

包标识是每个客户端唯一的

在客户端和代理服务器一次互动中,QoS 1和QoS 2消息的包标识符是唯一的。然后他们在交叉的所有客户端中不是唯一的。一旦一次完整的消息互动完成,包标识在重新使用时会失效。这就是包标识为什么不能超过65535,因为客户端在没有完成交互的情况下发送更多的消息是不现实的。

最佳实践到底是用MQTT QoS 0, QoS 1 和 QoS 2中哪一个?

我们时常被问到如何选择正确的QoS,选择合适的QoS依赖于你的使用场景。这里给出一些指导,可以帮助你做出明智的决定:

使用 QoS 0 的场景:

  • 在发布者和接收者之间,你已经有一个完成的或者基本完成的连接。QoS 0的一个典型场景是通过有线连接将测试客户端或前端应用程序连接到MQTT代理服务器。
  • 你不介意偶尔发生消息丢失,如果数据不重要或者短时间内数据会被发送,消息丢失是可以接受的。
  • 如果你不需要消息队列,只有当消息具有QoS 1,QoS 2 和持久会话时,才会在断开客户端连接时需要加入队列。

使用 QoS 1 的场景:

  • 您需要获取每一条消息,你的场景可以处理重复的消息。QoS 1是最常用的服务级别,因为它保证消息至少到达一次,但允许多次传递。当然,您的应用程序必须能够容忍重复,并能够相应地处理它们。
  • 您无法承受QoS 2的开销。 QoS 1传递消息的速度比QoS 2快得多。

使用 QoS 2 的场景:

  • 对于您的应用程序来说,准确地一次接收所有消息是至关重要的。如果重复传递可能会损害应用程序用户或订阅客户端。请注意开销,QoS 2交互需要更多的时间来完成。

QoS 1和 QoS 2的消息队列

所有被以QoS 1 和QoS 2发送的消息,对离线的客户端来讲,这些消息都会被加入队列,直到客户端再次连接有效。然而,如果客户端有一个持久会话,这个队列才可能会生效。

总结

MQTT基础课程系列的第六部分结束了。我们希望你发现的这些信息是有用的。