MQTT QoS 工作流程

发布时间 2023-10-18 08:54:18作者: aimigi
  • MQTT 根据此处定义的服务质量 (QoS) 级别传送应用程序消息。
  • 传送协议是对称的,在下面的描述中,客户端和服务器各自可以充当发送者或接收者的角色。 传送协议仅涉及将应用程序消息从单个发送方传送到单个接收方。
  • 当服务器向多个客户端传递应用程序消息时,每个客户端都会被单独处理。
  • 用于向客户端传送出站应用程序消息的 QoS 级别可能与入站应用程序消息的 QoS 级别不同。

1. QoS 0 最多一次传递,不保证收到

该级别消息接收方没发送响应,发送方也不会重试。消息要么到达被接收一次,要么没有到达。

该消息PUBLISH 数据包 QoS=0 DUP=0

Sender 数据包方向 Receiver
PUBLISH QoS 0, DUP=0 ---->
----> 收到消息,以QoS0 转发

2. QoS 1 最少一次传递,确保收到,但是会重复

使用QoS 1 级别发送时,发送方必须:

  1. 每次由新消息要发布时,必须分配一个未使用的数据包标识符 Packet Identifier
  2. PUBLISH 数据包中的 QoS 设置为 1,DUP=0
  3. 必须将PUBLISH 数据包视为 未确认,直到收到接收方的PUBACK 数据包

一旦收到PUBACK 数据包,PacketIdentifier 就可以重复使用了。发送放可以在等待接收确认时发送具有不同PacketIdentifier 的更多的数据包。

接收方必须:

  1. 使用来自传入的PUBLISH 数据包的PacketIdentifier 标识PUBACK 数据包
  2. 发送PUBACK数据包后,接收方必须将任何包含相同数据包标识符的传入PUBLISH包视为新的发布,无论其DUP 设置如何(服务端重复接收)

交互流程:

Sender 数据包方向 Receiver
本地存储消息
发送 PUBLISH QoS1,DUP=0 消息 --->
得到消息所有权,准备转发或者发出PUBLISHACK
<--- Send PUBACK(PacketIdentifier= Sender PacketId)
丢弃消息

3. QoS 2 精确收到一次,不会重复。

  • 这是最高质量的服务,适合在消息丢失或重复均不可接受的情况下使用。 与这种服务质量相关的开销会增加。
  • QoS 2 PUBLISH 数据包的接收方通过两步确认过程来确认接收

使用 QoS 2 级别时,发送方必须:

  1. 为消息分配一个未被使用的PacketIdentifier
  2. PUBLISH数据包必须设置OoS=1,DUP=0,并在本地将数据包存储,并视为“未确认”,直到收到PUBREC数据包。
  3. 当发送方收到PUBREC时,必须发送PUBREL数据包,且PacketIdentifier 与原始PUBLISH 数据包相同。在收到PUBCOMP 数据包前,PUBREL 数据包(需要本地存储)必须被视为“未确认”。
  4. 一旦发送了相应了PUBREL 数据包,就不能重新发送PUBLISH 数据包。

注意:

  • 一旦发送方收到了 PUBCOMP 数据包,PacketIdentifier就可以重用

此时,接收方必须:

  1. 收到PUBLISH包后,立即发送PUBREC 数据包,保持PacketIdentifier一致。并得到消息所有权。
  2. 收到相应的 PUBREL数据包前,接收方必须通过发送 PUBREC 来确认具有相同PacketIdentifier 的任何后续PUBLISH数据包。这种情况下,不能将重复消息转发给任何其他接收方。
  3. 必须通过发送PUBCOMP 来响应 PUBREL 数据包(PacketIdentifier相同)
  4. 发送完PUBCOMP数据包后 ,接收方将任何包含该PacketIdentifier 的PUBLISH数据包视为新的发布。

3.1 交互流程

Sender 数据包方向 Receiver
存储消息
发送PUBLISH QoS 2,DUP=0 --->
处理方法1 存储消息,持有消息所有权
或者处理办法2.存储PacketIdentifier,然后开始转发消息
PUBREC
<---
丢弃消息,存储PacketIdentifier
发送 PUBREL(相同PaketIdentifier)
--->
处理方式1:启动转发,然后丢弃消息 .或处理方式2 丢弃PacketIdentifier
发送PUBCOMP 消息
<---
丢弃存储的PacketIdentifier

4. 消息重发

当客户端在CleanSession 设置为0 的情况下重新连接时,客户端和服务端都愮使用原始数据包标识符 PacketIdentifier重新发送任何未确认的PUBLISH 数据包和PUBREL 数据包。

5. 消息回执 Message receipt

当服务器获得传入应用程序消息的所有权时,它必须将其添加到具有匹配订阅的那些客户端的会话状态中。

在正常情况下,客户端会收到响应其创建的订阅的消息。 客户端还可能收到与其任何显式订阅都不匹配的消息。 如果服务器自动向客户端分配订阅,则可能会发生这种情况。 客户端还可以在取消订阅操作正在进行时接收消息。 客户端必须根据适用的 QoS 规则确认其收到的任何发布数据包,无论其是否选择处理其中包含的应用程序消息

6. 消息顺序

客户端在实现协议时需要遵循以下规则:

  1. 当它重新发送任何PUBLISH 数据包时,必须按照原始PUBLISH数据包的发送顺序重新发送消息(适用于QoS1 和QoS2)
  2. 必须按照接收相应的PUBLISH数据包的顺序发送PUBACK 数据包(QoS1)
  3. 必须按照接收相应的PUBLISH 数据包的顺序发送PUBREC数据包(QoS2)
  4. 必须按照接收相应的PUBREC数据包的顺序发送PUBREL数据包(QoS2)
    默认情况下,服务器将每个主题视为“有序主题”。可以提供管理机制允许一个或多个主题被视为“无序主题"
    当服务器处理已发布到有序主题的消息时,它在向每个订阅者传递消息时必须遵循上面列出的规则。 此外,它必须按照从任何给定客户端接收到的顺序将 PUBLISH 数据包发送给消费者(对于相同的主题和 QoS)