MQTT QoS 介绍

简介: MQTT QoS 介绍

QoS是用来干什么的?

QoS(Quality of Service) 是消息的发送方( Sender )和接受方( Receiver )之间达成的一个协议。用来保证消息稳定传输的机制,包括消息应答、存储和重传。


在这套机制下,提供了三种不同层次 QoS

QoS 级别 含义
QoS0 至多一次 Sender 发送的一条消息,Receiver 最多能收到一次,也就是说 Sender 尽力向 Receiver 发送消息,如果发送失败,也就算了
QoS1 至少一次 Sender 发送的一条消息,Receiver 至少能收到一次,也就是说 Sender 向 Receiver 发送消息,如果发送失败,会继续重试,直到 Receiver 收到消息为止,但是因为重传的原因,Receiver 有可能会收到重复的消息
QoS2 确保只有一次 Sender 发送的一条消息,Receiver 确保能收到而且只收到一次,也就是说 Sender 尽力向 Receiver 发送消息,如果发送失败,会继续重试,直到 Receiver 收到消息为止,同时保证 Receiver 不会因为消息重传而收到重复的消息


注意:QoSSenderReceiver 之间的协议,而不是 PublisherSubscriber 之间的协议。换句话说, Publisher 发布了一条 QoS1 的消息,只能保证 Broker至少收到一次这个消息;而对于 Subscriber 能否至少收到一次这个消息,还要取决于 SubscriberSubscribe 的时候和 Broker 协商的 QoS 等级。


QoS0

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

QoS0消息传递流程图.png

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


QoS1

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

QoS1消息传递流程图.png


流程:

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


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

  1. 如果Sender在一段时间内没有收到PUBLISH包对应的PUBACK,它将该PUBLISH包的DUP标识设为1(代表是重新发送PUBLISH包),然后重新发送该PUBLISH包。
  2. Receiver可能会重复收到消息,需自行去重。


QoS2

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

QoS1消息传递流程图.png


流程:

  1. Sender发送QoS2PUBLISH数据包,数据包 Packet IdentifierP,并在本地保存该PUBLISH包;
  2. Receiver收到PUBLISH数据包后,在本地保存PUBLISH包的Packet Identifier P,并回复Sender一个PUBREC数据包,PUBREC数据包可变头中的Packet IdentifierP,没有消息体(Payload);
  3. Sender收到PUBREC,它就可以安全的丢弃掉初始Packet IdentifierPPUBLISH数据包。同时保存该PUBREC数据包,并回复Receiver一个PUBREL数据包,PUBREL数据包可变头中的Packet IdentifierP,没有消息体;
  4. Receiver收到PUBREL数据包,它可以丢掉保存的PUBLISH包的Packet Identifier P,并回复Sender一个可变头中 Packet IdentifierP,没有消息体(Payload)的PUBCOMP数据包;
  5. Sender收到PUBCOMP包,那么认为传输已完成,则丢掉对应的PUBREC数据包;


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

  • 情况1:Sender发送PUBLISH数据包给Receiver的时候,发送失败;
  • 情况2:Sender已经成功发送PUBLISH数据包给Receiver了,但是Receiver发送PUBREC数据包失败;
  • 情况3:Sender已经成功收到了PUBREC数据包,但是PUBREL数据包发送失败;
  • 情况4:Receiver已经收到了PUBREL数据包,但是发送PUBCOMP数据包时发送失败


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

  • 不管是情况1还是情况2,因为Sender在一定时间内没有收到PUBREC,那么它会把PUBLISH包的DUP标识设为1,重新发送该PUBLISH数据包;
  • 不管是情况3还是情况4,因为Sender在一定时间内没有收到PUBCOMP包,那么它会重新发送PUBREL数据包;
  • 针对情况2Receiver可能会收到多个重复的PUBLISH包,更加完善的处理如下:

Receiver 在收到 PUBLISH 数据包之后,马上回复一个 PUBREC 数据包。并会在本地保存 PUBLISH 包的 Packet Identifier P ,不管之后因为重传多少次这个 Packet IdentifierP 的数据包, Receiver 都认为是重复的,丢弃。同时 Receiver 接收到 QoS2PUBLISH 数据包后,并不马上投递给上层,而是在本地做持久化,将消息保存起来(这里需要是持久化而不是保存在内存)。

  • 针对情况4,更加完善的处理如下:

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


QoS降级

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

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


QoS和会话

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

在发送 QoS12 的情况, Broker (此时为 Sender )会将发送的 PUBLISH 数据包保存到本地,直到收到一系列回复的数据包,然而 Client (此时为 Receiver )在离线期间无法回复相应的数据包,所以会一直存储。


QoS等级使用建议

QoS0 Client 和 Broker 之间的网络连接非常稳定,例如一个通过有线网络连接到 Broker 的测试用 Client
可以接受丢失部分消息,比如你有一个传感器以非常短的间隔发布状态数据,所以丢一些也可以接受
不需要离线消息
QoS1 需要接收所有的消息,而且应用可以接受并处理重复的消息
无法接受 QoS2 带来的额外开销,QoS1 发送消息的速度比 QoS2 快很多
QoS2 应用必须接收到所有的消息,而且应用在重复的消息下无法正常工作,同时也能接受 QoS2 带来的额外开销
相关实践学习
消息队列RocketMQ版:基础消息收发功能体验
本实验场景介绍消息队列RocketMQ版的基础消息收发功能,涵盖实例创建、Topic、Group资源创建以及消息收发体验等基础功能模块。
消息队列 MNS 入门课程
1、消息队列MNS简介 本节课介绍消息队列的MNS的基础概念 2、消息队列MNS特性 本节课介绍消息队列的MNS的主要特性 3、MNS的最佳实践及场景应用 本节课介绍消息队列的MNS的最佳实践及场景应用案例 4、手把手系列:消息队列MNS实操讲 本节课介绍消息队列的MNS的实际操作演示 5、动手实验:基于MNS,0基础轻松构建 Web Client 本节课带您一起基于MNS,0基础轻松构建 Web Client
目录
相关文章
|
11月前
|
传感器 数据采集 物联网
MQTT 的 QoS 等级:QoS 0、QoS 1、QoS 2
MQTT 的 QoS 等级:QoS 0、QoS 1、QoS 2
1250 0
EMQ
|
存储 传感器 缓存
MQTT QoS 0, 1, 2 介绍
MQTT协议中规定了消息服务质量QoS(Quality of Service),其核心是设计了多种消息交互机制来提供不同的服务质量,来满足用户在各种场景下对消息可靠性的要求。
EMQ
1048 0
MQTT QoS 0, 1, 2 介绍
|
存储 网络协议 安全
最火的物联网技术MQTT,其服务质量QoS的三个级别分别是什么意思,本文一定对您有帮助!
MQTT是在 TCP/IP 之上使用的轻量级发布-订阅协议,常用于物联网的场景,MQTT 使用消息代理在发布消息的发送者和对这些消息感兴趣的接收者之间分派消息,同一个客户端可以发布和订阅消息。
486 0
最火的物联网技术MQTT,其服务质量QoS的三个级别分别是什么意思,本文一定对您有帮助!
EMQ
|
存储 消息中间件 传感器
MQTT QoS 设计:车联网平台消息传输质量保障
在本篇文章中,我们将借助 MQTT 协议的 QoS 特性,介绍车联网场景中的 MQTT 消息 QoS 设计,保障数据传输质量。
EMQ
365 0
MQTT QoS 设计:车联网平台消息传输质量保障
|
存储 网络性能优化
我的mqtt协议和emqttd开源项目个人理解(7) - Qos==2是如何保证消息只收到一次的
我的mqtt协议和emqttd开源项目个人理解(7) - Qos==2是如何保证消息只收到一次的
660 0
|
存储 Java 数据库连接
我的mqtt协议和emqttd开源项目个人理解(3) - 客户端publish消息QoS==0的源码分析
我的mqtt协议和emqttd开源项目个人理解(3) - 客户端publish消息QoS==0的源码分析
221 0
|
2月前
|
消息中间件 C语言 RocketMQ
消息队列 MQ操作报错合集之出现"Connection reset by peer"的错误,该如何处理
消息队列(MQ)是一种用于异步通信和解耦的应用程序间消息传递的服务,广泛应用于分布式系统中。针对不同的MQ产品,如阿里云的RocketMQ、RabbitMQ等,它们在实现上述场景时可能会有不同的特性和优势,比如RocketMQ强调高吞吐量、低延迟和高可用性,适合大规模分布式系统;而RabbitMQ则以其灵活的路由规则和丰富的协议支持受到青睐。下面是一些常见的消息队列MQ产品的使用场景合集,这些场景涵盖了多种行业和业务需求。
|
2月前
|
消息中间件 Java C语言
消息队列 MQ使用问题之在使用C++客户端和GBase的ESQL进行编译时出现core dump,该怎么办
消息队列(MQ)是一种用于异步通信和解耦的应用程序间消息传递的服务,广泛应用于分布式系统中。针对不同的MQ产品,如阿里云的RocketMQ、RabbitMQ等,它们在实现上述场景时可能会有不同的特性和优势,比如RocketMQ强调高吞吐量、低延迟和高可用性,适合大规模分布式系统;而RabbitMQ则以其灵活的路由规则和丰富的协议支持受到青睐。下面是一些常见的消息队列MQ产品的使用场景合集,这些场景涵盖了多种行业和业务需求。
|
3天前
|
消息中间件
手撸MQ消息队列——循环数组
队列是一种常用的数据结构,类似于栈,但采用先进先出(FIFO)的原则。生活中常见的排队场景就是队列的应用实例。在数据结构中,队列通常用数组实现,包括入队(队尾插入元素)和出队(队头移除元素)两种基本操作。本文介绍了如何用数组实现队列,包括定义数组长度、维护队头和队尾下标(front 和 tail),并通过取模运算解决下标越界问题。此外,还讨论了队列的空与满状态判断,以及并发和等待机制的实现。通过示例代码展示了队列的基本操作及优化方法,确保多线程环境下的正确性和高效性。
9 0
手撸MQ消息队列——循环数组
|
29天前
|
消息中间件 存储 Java
【揭秘】RocketMQ内部运作大揭秘:一探究竟,原来消息队列是这样工作的!
【8月更文挑战第19天】RocketMQ是一款高性能、高可用的消息中间件,在分布式系统中至关重要。它采用发布/订阅模式,支持高吞吐量的消息传递。核心组件包括管理元数据的NameServer、存储消息的Broker以及Producer和Consumer。RocketMQ支持发布/订阅与点对点两种模型,并具备复杂的消息持久化和路由机制。通过Java API示例,可轻松实现消息的发送与接收。RocketMQ凭借其出色的特性和可靠性,成为大型分布式系统首选的消息解决方案。
49 5