MQTT系列-MQTT的QoS介绍

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MQTT系列-MQTT的QoS介绍相关的知识,希望对你有一定的参考价值。

参考技术A MQTT设计了一套保证消息稳定传输的机制,包括消息应答、存储和重传。
为了保证消息被正确的接收
在这套机制下,提供了三种不同层次QoS(Quality of Service):

QoS 是消息的发送方(Sender)和接受方(Receiver)之间达成的一个协议:

::: warning
QoS是Sender和Receiver之间的协议,而不是Publisher和Subscriber之间的协议。
换句话说,Publisher发布了一条QoS1的消息,只能保证Broker能至少收到一次这个消息;

而对于Subscriber能否至少收到一次这个消息,还要取决于Subscriber在Subscribe的时候和Broker协商的QoS等级。
:::

QoS0等级下,Sender和Receiver之间一次消息的传递流程如下:

Sender向Receiver发送一个包含消息数据的PUBLISH包,然后不管结果如何,丢掉已发送的PUBLISH包,一条消息的发送完成。

QoS1要保证消息至少到达一次,所以有一个应答的机制。Sender和Receiver的一次消息的传递流程如下:

1.Sender向Receiver发送一个带有数据的PUBLISH包,并在本地保存这个PUBLISH包;
2.Receiver收到PUBLISH包以后,向Sender发送一个PUBACK数据包,PUBACK数据包没有消息体(Payload),在可变头中有一个包标识(Packet Identifier),和它收到的PUBLISH包中的Packet Identifier一致。
3.Sender收到PUBACK之后,根据PUBACK包中的Packet Identifier找到本地保存的PUBLISH包,然后丢弃掉,一次消息的发送完成。

但是消息传递流程中可能会出现问题:

相比QoS0和QoS1,QoS2不仅要确保Receiver能收到Sender发送的消息,还需要确保消息不重复。它的重传和应答机制就要复杂一些,同时开销也是最大的。QoS2下,一次消息的传递流程如下所示:

1.Sender发送QoS为2的PUBLISH数据包,数据包 Packet Identifier 为 P,并在本地保存该PUBLISH包;

2.Receiver收到PUBLISH数据包后,在本地保存PUBLISH包的Packet Identifier P,并回复Sender一个PUBREC数据包,PUBREC数据包可变头中的Packet Identifier为P,没有消息体(Payload);

3.当Sender收到PUBREC,它就可以安全的丢弃掉初始Packet Identifier为P的PUBLISH数据包。同时保存该PUBREC数据包,并回复Receiver一个PUBREL数据包,PUBREL数据包可变头中的Packet Identifier为P,没有消息体;

4.当Receiver收到PUBREL数据包,它可以丢掉保存的PUBLISH包的Packet Identifier P,并回复Sender一个可变头中 Packet Identifier 为 P,没有消息体(Payload)的PUBCOMP数据包;

5.当Sender收到PUBCOMP包,那么认为传输已完成,则丢掉对应的PUBREC数据包;

上面是一次完整无误的传输过程,然而传输过程中可能会出现以下情况:

针对上述的问题,较为详细的处理方法如下:

Receiver收到PUBREL数据包后,正式将消息递交给上层应用层,投递之后销毁Packet Identifier P,并发送PUBCOMP数据包,销毁之前的持久化消息。
之后不管接收到多少个PUBREL数据包,因为没有Packet Identifier P,直接回复PUBCOMP数据包即可。

在 MQTT 协议中,从 Broker 到 Subscriber 这段消息传递的实际 QoS 等于:Publisher 发布消息时指定的 QoS 等级和 Subscriber 在订阅时与 Broker 协商的 QoS 等级,这两个 QoS 等级中的最小那一个。

Actual Subscribe QoS = MIN(Publish QoS, Subscribe QoS)

如果 Client 想接收离线消息,必须使用持久化的会话(Clean Session = 0)连接到 Broker,这样 Broker 才会存储 Client 在离线期间没有确认接收的 QoS 大于 等于1 的消息。

在以下情况下你可以选择 QoS0:

在以下情况下你应该选择 QoS1:

在以下情况下你应该选择 QoS2:

https://blog.csdn.net/programguo/article/details/100125177

ESP32-IDF05-5 WIFI-MQTT高级内容

mqtt高级内容

声明
该部分是参考的太极创客的内容完成的,感觉他们的视频和教程非常好,本文仅仅是笔记,可以去听原版的

mqtt高级内容

1. Qos服务质量等级

1.1 什么是Qos

  Qos是服务质量等级的缩写,用于告诉物联网系统,哪些信息是重要信息,需要准确无误的传输,哪些信息不那么重要,即使丢失也没有问题。

1.2 Qos服务质量级别

  • Qos=0 最多发一次
  • Qos=1 最少发一次
  • Qos=2 保证收一次

  级别高,传输稳定,但是占用的网络带宽资源就多

1.2.1 Qos=0

   0级别表示服务端和客户端交互数据是完全没有保障的。客户端和服务端不会对传输信息是否成功进行确认和检查。

  发送端数据只发送一次。信息能不能传输到,依靠网络的可靠性。

1.2.2 Qos=1

   至少发送1次,要求接收端给发送端1个确认信息,发送端会继续给接收端发送信息。

1.2.3 Qos=2

   发送端会发送两次确认信息。两次确认信息都得到回复以后,才会认为对方接收到了

1.3 如何发送Qos>0 的数据

1.3.1 发送Qos=1的数据

  分为三步,缺一不可

  • 在发送端发送数据的时候,Qos就必须为1

  • 接收端在连接服务端的时候cleansession要设置为false

  • 客户端进行订阅主题的时候,要设置Qos=1

1.3.2 发送Qos=2的数据

  • 接收端连接服务端的时候cleansession设置为false
  • 接收端订阅主题的时候Qos=2
  • 发布端发布消息的时候Qos=2

1.4 服务质量降级

  如果发布客户端和接收客户端服务质量不同,会按照更低的服务质量进行。也就是上面那个案例,接收客户端会按照服务质量1级进行接收

  上图案例会按照服务质量0进行数据传输

2. 保留消息

2.1 什么是保留消息

  当我们向任何主题发布一个保留消息的时候。任何一个接受客户端,订阅这个主题的时候,会马上受到这个消息

2.2 如果修改保留消息

  如果向订阅主题发布新的保留消息,原来的那个就会取消

2.3 如何删除保留消息

  如果要删除保留消息,只需要向订阅主题发布一条空的保留消息即可

2.4 保留消息报文

2.5 保留消息的用途

  比如有些客户端向服务端发送数据一天才发送一次,这样的话,新客户端订阅这个主题第一次收到消息可能需要等一天,所以使用保留消息的话,可以让订阅的客户端马上就能收到消息。

3. 心跳机制

3.1 心跳机制是什么

  客户端需要向服务端不断发送心跳信息,表示客户端与服务端是连接的。

3.2 机制

  客户端需要不断将向服务端发送PINGREQ心跳数据包,而服务端会向客户端发送PINGRESP心跳响应。

  在客户端向服务端进行connect的时候,会有一个心跳时间信息,就是说客户端必须在心跳时间间隔内向服务端发送消息

  客户端只有在必要的时候才会向服务端发送心跳数据包。因为如果在心跳时间内,客户端向服务器发送过其他数据,是不需要发送心跳数据包的。

  如果服务端没有在1.5倍心跳间隔时间内收到客户端的数据,就认为客户端掉线了。

4. mqtt遗嘱

4.1 什么是遗嘱(will)

  当发送客户端与服务端意外断开的时候,服务端会向订阅了主题遗嘱信息的客户端发送遗嘱信息。

4.2 断开连接与意外断开

  客户端会向服务端发送disconnect数据包,客户端会和服务端正常断开连接

  当服务端通过心跳机制发现客户端断开连接的时候,会认为是意外断开

4.3 遗嘱的使用

  在客户端与服务器连接的时候,可以设置遗嘱信息。这部分相关的设置包括

  • 遗嘱主题:接收客户端可以订阅这个遗嘱主题,当这个发送设备意外断开的时候,服务器就向订阅了这个遗嘱主题的客户端发送遗嘱信息
  • 遗嘱信息:要发送的信息
  • 遗嘱Qos
  • 遗嘱保留信息

4.4 遗嘱使用建议

5. 用户密码认证

  在connect数据包中进行填写

以上是关于MQTT系列-MQTT的QoS介绍的主要内容,如果未能解决你的问题,请参考以下文章

MQTT协议分析

Android使用MQTT订阅及发布消息(初步了解Mqtt以及实现Android操作mqtt服务)

了解 mqtt 订阅者 qos

ESP32-IDF05-5 WIFI-MQTT高级内容

MQTT qos参数无效

Spring Boot MQTT Too many publishes in progress错误的解决方案