服务质量 0,1,2 - MQTT 核心系列:第六章
作者:HiveMQ 团队
翻译:索隆有几把刀
欢迎来到MQTT核心系列的第六章。这个系列一共有十章,用来介绍MQTT的核心特性和概念。在这一章中,我们将讲解MQTT中的不同的服务质量。我们在先前的文章中已经多次提到过服务质量,现在让我们来深入了解下吧。
服务质量
什么是服务质量
服务质量是消息发送方和消息接收方之间的一种约定,它定义了特定消息的传递保证的等级。一共有三种等级:
- 最多一次(0)
- 至少一次(1)
- 刚好一次(2)
当你在讨论服务质量的时候,你应该考虑两个方面的消息传递:
- 消息从推送方发送到代理
- 消息从代理推送到订阅方
对于这两种消息传递我们应该分别看待,因为它们二者之间有细微的差异。当消息从推送方发送到代理时,服务质量取至消息。当消息从代理推送给订阅方时,服务质量取至客户端的订阅信息。如果,客户端订阅时定义的服务质量低于消息发送方,那么代理会依照这个更低的服务质量。
为什么服务质量很重要
服务质量是MQTT协议的关键特性。服务质量让客户端能够选择与它的网络质量和应用逻辑相匹配的服务等级。由于MQTT能管理消息的重新发送并保障消息的传递(即使是底层传输不可靠),这让在不可靠网络中的通信变得简单。
它是怎么工作的
让我们近距离看看每一种服务质量是如何实现MQTT协议并且是如何工作的:
(下文中直接使用QoS代替服务质量)
QoS 0 - 至多一次
QoS中最小的等级是0。这种服务等级保证投递的最高效率。但他对投递本身没有保障。在这种等级下,消息接收方不会对消息接受进行确认并且消息发送方也不会保存消息和重新投递。它提供的保障和TCP一样,我们可以用"拔吊无情"来形容它。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VBoxqVgY-1613553907970)(https://www.hivemq.com/img/blog/qos-levels_qos0.svg)]
QoS 1 - 至少一次
QoS 1保障消息至少能被投递给接收方一次。消息发送方会存储消息直到它接受到了消息接收方返回的确认消息。这可能会导致消息被多次投递。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UFj7fg6R-1613553907970)(https://www.hivemq.com/img/blog/qos-levels_qos1.svg)]
消息发送方会用发送的消息的数据包标志来匹配返回的确认消息包,假如消息发送方在一个合理的时间内没有接收到匹配的确认消息包,那么消息发送方会重新发送消息。当消息接收方接收到一个QoS为1的消息时,它会立即处理这条消息,并且返回PUBACK数据包。
当客户端重新发布消息的时候,它会在消息上带上一个重新发送(DUP)的标志,这个标志仅用于内部,它不会被客户端或者代理处理。消息接收方会发送一个PUBACK消息,但是不会带上DUP标志符。
QoS 2 - 刚好一次
QoS是最高的服务等级。这种级别能保证消息会且仅会被预定接收方接受一次。QoS 2是最安全的级别但同时也是最慢的服务级别。因为想要达到这种级别的保障,需要消息发送和接受双方进行至少两次请求/响应过程。消息接受和发送双方使用原始PUBLISH消息的数据包标志符来协调信息的传递。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rOBfl5lS-1613553907972)(https://www.hivemq.com/img/blog/qos-levels_qos2.svg)]
当消息接受方接收到一个服务质量为QoS的PUBLISH消息时,它会对消息发送一个PUBREC的消息包来对PUBLISH消息包进行确认。如果这个消息发送没有收到返回的确认消息,那么他就会重新发送PUBLISH消息,并附带上DUP标志,直到他收到返回的确认消息。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bVP7FYbG-1613553907975)(https://www.hivemq.com/img/blog/pubrec_packet.png)]
一旦消息发送方从消息接收方哪里接收到了PUBREC消息包,那么消息接收方就会安全的丢弃原始的PUBLISH消息包。然后消息发送方会将收到的PUBREC消息存储起来,并回复一个PUBREL消息包。
在消息接收方收到PUBREL消息包后,它会丢弃所有存储的状态,并且会应答一个PUBCOMP消息包。消息接收方会一直持有一个原始PUBLISH消息包标识符的引用,直到它完成对消息的处理并返回一个PUBCOMP的消息包给消息发送方。这一措施对避免消息的重复处理起总要作用。在消息发送方接收到PUBCOMP消息包后,数据包的标识符就可以重用了。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2SbaYjjk-1613553907977)(https://www.hivemq.com/img/blog/pubcomp_packet.png)]
当QoS 2的流程结束后,双方都可以确认消息投送成功。
如果数据包在途中丢失,则发件人有责任在合理的时间内重新传输消息。无论发送者是MQTT客户端还是MQTT代理都一样。相应的,接收者有责任相应地响应每个命令消息。
最佳实践
我们经常被要求提供有关如何选择正确的QoS级别的建议。以下是一些可以帮助您进行决策的准则。具体该怎么抉择取决于您的使用场景:
在以下情况下使用QoS 0:
- 消息接收方和消息发送方之间具有完全或几乎稳定的连接。例如用网线连接客户端和服务端。
- 您不介意偶尔丢失几条消息。
- 您不需要消息队列。如果QoS 为 1或者2,或者时持久会话,那么需要将消息放入队列中,以备投递给断开连接的客户端。
在以下情况下使用QoS 1:
- 您需要获取每一条消息,并且您的应用可以处理重复消息。
- 您无法忍受QoS的开销。QoS 1传递消息的熟读比QoS 2要快的多。
在以下情况下使用QoS 2:
- 对您的应用程序来说,准确接受说有消息至关重要。如果重复交付会损害应用程序用户或订阅客户,通常会出现这种情况。请注意开销,并且QoS 2交互需要更多时间才能完成。
QoS 1 和 QoS 2的消息队列
所有QoS为1或者2的消息会被放入队列,以备离线客户端再次可用。当然,这种入列机制需要客户端拥有持久会话。
以上就是我们的MQTT核心系列的第6章了。我们希望这些能对你有所帮助。在下一章中,我们将讲解与服务质量相关的一个主题:持久会话