未经允许,不得转载
服务质量
什么是服务质量?
服务质量(QoS)级别是一种关于发送者和接收者之间信息投递的保证协议。MQTT中有三种QoS级别:
- 至多一次(0)
- 至少一次(1)
- 只有一次(2)
当我们谈到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的情况
- 在你的发动端和接收端具备一个完整的或基本可靠的连接。一个典型场景是使用有线网连接broker和测试版客户端或者是前端平台。
- 你不怎么关心是否会有一两个数据包丢失。一般是在数据不怎么重要,或者发送周期比较短暂的情况下,这种情况下丢帧是无所谓的。
- 你无须任何消息队列。消息队列只在当QoS为1或2,并且的客户端掉线时产生。
使用QoS 1的情况
- 你需要获得每一条消息,并且消息重复发送对你的使用场景无影响。最常用的QoS就是1级,因为它能保证消息至少送达一次。当然了,你的程序必须能够接受重复的消息并可以相应地进行处理。
- 你无法接受QoS为2的资源开销。当然了QoS为1时的消息传递速度要比QoS为2时快得多。
使用QoS 2的情况
- 仅收到一次消息对你的应用来说很重要。一般是用在重复的消息会对你的应用或订阅者产生危害的情况下。你应该意识到QoS 2会带来相对较高的资源开销,以及相对较慢的传输速度。
QoS 1 和 QoS 2 的队列
所有以1和2级别发送给掉线设备的消息将会存储起来,直到设备再次可用。但是队列只在客户端使用持久会话时才会产生。