iOS 你不知道的新鲜事iOS 开发成长中心程序员

MQTT Part 6 服务质量 0、1、2

2017-06-17  本文已影响1098人  qinwenbo

本文翻译自http://www.hivemq.com/blog/mqtt-essentials-part-6-mqtt-quality-of-service-levels

未经允许,不得转载

服务质量

什么是服务质量?

服务质量QoS)级别是一种关于发送者和接收者之间信息投递的保证协议。MQTT中有三种QoS级别:

当我们谈到QoS时,针对一个消息可以分为两个方面:发布者到broker及broker到订阅者。我们需要对其分开来看,因为它们之中有一些细小差异。发布者客户端到broker的QoS由发布者所设置的消息体中的QoS级别来确定。当broker将消息转发给订阅者时,QoS由订阅者之前所设定的QoS级别来确定。这意味着,如果消息被一个低级别QoS的订阅者所订阅,那么消息的服务质量级别有可能会在转发时进行降级。

为什么服务质量那么重要?

QoS是MQTT的一个主要功能,它使得在不可靠的网络下进行通信变得更为简单,因为即便是在非常不可靠的网络下,协议也可以掌控是否需要重发消息并保证消息到达。它也能帮助客户端根据网络环境和程序逻辑来自由选择QoS。

它是怎样工作的?

MQTT是怎样实现它的?让我们来逐个分析。

QoS 0 - 至多一次

零是最低的级别,但它具有最高的传输性能。接收者不会应答消息,发送者也不会保存和重发消息。这种模式常被称作“发射后不管”,它提供和TCP协议一致的可靠性。


QoS 1 - 至少一次

当使用级别1时,它可以保证消息至少被送达到接收者一次,但也可能被送达到多次。



发送者会保存消息,直至其收到接收者发送的PUBACK格式的应答命令。


系统通过对比包的标识符来确定一对PUBLISH和PUBACK的完成情况,如果在规定时间内没有收到PUBACK,发送者会重发PUBLISH消息。如果接收者收到一个QoS为1的消息,他会立即处理此消息,举例来说,假如broker收到了此消息,它会将消息投递给所有此消息的订阅者,然后向发布者应答一个PUBACK。
重复(DUP)标志会在PUBLISH被重发时设置,这个标志只被用作程序内部,既不会被broker处理,也不会被客户端处理。无论重复(DUP)标志如何,接收者都会发送一个PUBACK应答。

QoS 2 - 只有一次

QoS 2 是最高级别的,它可以保证每条消息只被接收一次。它是最安全的但也是最慢的服务级别。其通过发送者和接收者的两次对话来实现。


如果接收者接收到一条QoS为2的PUBLISH消息,他会处理此消息并返回一条PUBREC进行应答。



接收者会存储包标识符以作为参考,直至其发送了PUBCOMP消息。此机制避免了消息被二次处理。当发送者收到PUBREC消息后,它就可以安全丢弃掉之前的发布消息,因为它已经知道接收者成功收到了消息。发布者会保存PUBREC消息并应答一个PUBREL。



在接收者收到PUBREL消息后,它会丢弃掉所有已经保存的状态,并应答一个PUBCOMP。同样的,当发送者收到PUBCOMP消息时也会清空之前所保存的状态。

当一个流程走完之后,发送者就可以确认消息已经被送达。
无论在传输过程中何时出现丢包,发送端都负责重发上一条消息。不管发送端是MQTT的客户端还是broker,都是如此。因此,接收端也需要对每一条命令消息都进行应答。

好消息

在使用QoS时,你只需要记住这几点即可。

QoS降级

正如前面所说,在发布者和订阅者之间有两个传输过程,它们的QoS可能会不一样。这意味着QoS级别在发布者和订阅者两端可能不同。发送端到broker的QoS级别由发送端定义,broker到接收端的QoS由接收端定义。假如一个客户端B以QoS 1级别订阅一个消息,客户端A以QoS 2级别订阅同一个消息,那么客户端B就会以QoS 1的级别收到消息。当然了,消息可能会被发送到客户端B多次,因为QoS 1的级别只能保证消息到达至少一次。

对于同一个客户端来说,每一个数据包的标识符都是唯一的

另一个重点是,在同一个客户端和broker之间的每一个数据包的标识符(用在QoS 1和QoS 2时)都是唯一的。如果一个通信流程执行完毕,那么相同的包标识符就可以被复用。这也是为什么数据包的标识符不需要大于65536,因为客户端不可能发送那么多条消息还没走完一个通信流程。

最佳实践

我们经常会被问到如何选择服务器级别。如果也你对此感到困惑,下列内容将为你提供一些指导建议。当然,最终如何选择要由你具体的使用场景来判定。

使用QoS 0的情况

使用QoS 1的情况

使用QoS 2的情况

QoS 1 和 QoS 2 的队列

所有以1和2级别发送给掉线设备的消息将会存储起来,直到设备再次可用。但是队列只在客户端使用持久会话时才会产生。

上一篇 下一篇

猜你喜欢

热点阅读