MQTT QoS 工作流程
- 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 级别发送时,发送方必须:
- 每次由新消息要发布时,必须分配一个未使用的数据包标识符 Packet Identifier
- PUBLISH 数据包中的 QoS 设置为 1,DUP=0
- 必须将PUBLISH 数据包视为 未确认,直到收到接收方的PUBACK 数据包
一旦收到PUBACK 数据包,PacketIdentifier 就可以重复使用了。发送放可以在等待接收确认时发送具有不同PacketIdentifier 的更多的数据包。
接收方必须:
- 使用来自传入的PUBLISH 数据包的PacketIdentifier 标识PUBACK 数据包
- 发送PUBACK数据包后,接收方必须将任何包含相同数据包标识符的传入PUBLISH包视为新的发布,无论其DUP 设置如何(服务端重复接收)
交互流程:
Sender | 数据包方向 | Receiver |
---|---|---|
本地存储消息 | ||
发送 PUBLISH QoS1,DUP=0 消息 | ---> | |
得到消息所有权,准备转发或者发出PUBLISHACK | ||
<--- | Send PUBACK(PacketIdentifier= Sender PacketId) | |
丢弃消息 |
3. QoS 2 精确收到一次,不会重复。
- 这是最高质量的服务,适合在消息丢失或重复均不可接受的情况下使用。 与这种服务质量相关的开销会增加。
- QoS 2 PUBLISH 数据包的接收方通过两步确认过程来确认接收
使用 QoS 2 级别时,发送方必须:
- 为消息分配一个未被使用的PacketIdentifier
- PUBLISH数据包必须设置OoS=1,DUP=0,并在本地将数据包存储,并视为“未确认”,直到收到PUBREC数据包。
- 当发送方收到PUBREC时,必须发送PUBREL数据包,且PacketIdentifier 与原始PUBLISH 数据包相同。在收到PUBCOMP 数据包前,PUBREL 数据包(需要本地存储)必须被视为“未确认”。
- 一旦发送了相应了PUBREL 数据包,就不能重新发送PUBLISH 数据包。
注意:
- 一旦发送方收到了 PUBCOMP 数据包,PacketIdentifier就可以重用
此时,接收方必须:
- 收到PUBLISH包后,立即发送PUBREC 数据包,保持PacketIdentifier一致。并得到消息所有权。
- 收到相应的 PUBREL数据包前,接收方必须通过发送 PUBREC 来确认具有相同PacketIdentifier 的任何后续PUBLISH数据包。这种情况下,不能将重复消息转发给任何其他接收方。
- 必须通过发送PUBCOMP 来响应 PUBREL 数据包(PacketIdentifier相同)
- 发送完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. 消息顺序
客户端在实现协议时需要遵循以下规则:
- 当它重新发送任何PUBLISH 数据包时,必须按照原始PUBLISH数据包的发送顺序重新发送消息(适用于QoS1 和QoS2)
- 必须按照接收相应的PUBLISH数据包的顺序发送PUBACK 数据包(QoS1)
- 必须按照接收相应的PUBLISH 数据包的顺序发送PUBREC数据包(QoS2)
- 必须按照接收相应的PUBREC数据包的顺序发送PUBREL数据包(QoS2)
默认情况下,服务器将每个主题视为“有序主题”。可以提供管理机制允许一个或多个主题被视为“无序主题"
当服务器处理已发布到有序主题的消息时,它在向每个订阅者传递消息时必须遵循上面列出的规则。 此外,它必须按照从任何给定客户端接收到的顺序将 PUBLISH 数据包发送给消费者(对于相同的主题和 QoS)