4.3 Quality of Service levels and protocol flows 服务质量水平和协议流程
MQTT根据此处定义的服务质量(QoS)级别提供应用程序消息。传递协议是对称的,在下面的描述中,客户端和服务器都可以扮演发送者或接收者的角色。传递协议仅涉及从单个发送方向单个接收方传递应用程序消息。当服务器向多个客户端提供应用程序消息时,将独立处理每个客户端。用于向客户端传送出站的应用程序消息的QoS级别可能与入站应用程序消息的QoS级别不同。
以下部分中的非规范流程图旨在显示可能的实现方法。
4.3.1 QoS 0:At most once delivery 最多一次交付
根据底层网络的功能传递消息。接收方未发送响应,发送方不执行重试。消息一次到达接收器或根本不到达接收器。
在QoS 0传递协议中,发送者
·必须发送QoS = 0,DUP = 0 [MQTT-4.3.1-1] 的PUBLISH数据包。
在QoS 0传送协议中,接收器
·接收PUBLISH数据包时接受消息的所有权。
发件人行动 | 控制包 | 接收者行动 |
发布QoS 0,DUP = 0
|
|
|
| ----------> |
|
|
| 向适当的转发收件人发送应用程序消息 |
4.3.2 QoS 1:At least once delivery 至少一次交付
这种服务质量确保消息至少到达接收器一次。QoS 1 PUBLISH分组在其可变报头中具有分组标识符,并由PUBACK分组确认。第2.3.1节提供了有关数据包标识符的更多信息。
在QoS 1传递协议中,发送者
·每次要发布新的应用程序消息时,必须分配一个未使用的数据包标识符。
·必须发送包含此数据包标识符的PUBLISH数据包,其QoS = 1,DUP = 0。
·必须将PUBLISH数据包视为“未确认”,直到它从接收方收到相应的PUBACK数据包。有关未确认消息的讨论,请参见第4.4 节。
[MQTT-4.3.2-1]。
一旦发送方收到PUBACK数据包,数据包标识符就可以重用。
请注意,允许发件人在等待接收确认时发送具有不同数据包标识符的其他PUBLISH数据包。
在QoS 1传送协议中,接收器
- 必须使用包含来自传入的PUBLISH数据包的数据包标识符的PUBACK数据包进行响应,并接受应用程序消息的所有权
- 在发送PUBACK数据包之后,接收方必须将包含相同数据包标识符的任何传入PUBLISH数据包视为新发布,而不管其DUP标志的设置如何。
[MQTT-4.3.2-2]。
发件人行动 | 控制包 | 接收者行动 |
存储消息 |
|
|
发送PUBLISH QoS 1,DUP 0, | ----------> |
|
|
| 启动应用程序消息1的继续交付 |
| <---------- | 发送PUBACK <数据包标识符> |
丢弃消息 |
|
|
1在发送PUBACK之前,接收方无需完成应用程序消息的传递。当其原始发送方收到PUBACK数据包时,应用程序消息的所有权将传输到接收方。
4.3.3 QoS 2: Exactly once delivery 确保一次交付
这是最高质量的服务,用于既不接受丢失也不重复消息的情况。与此服务质量相关的开销增加。
QoS 2消息在其变量头中具有分组标识符。第2.3.1节提供了有关数据包标识符的更多信息。QoS 2 PUBLISH数据包的接收方通过两步确认过程确认收到。
在QoS 2传递协议中,发送者
- 当有新的应用程序消息要发布时,必须分配一个未使用的数据包标识符。
- 必须发送包含此数据包标识符的PUBLISH数据包,其QoS = 2,DUP = 0。
- 必须将PUBLISH数据包视为“未确认”,直到它从接收方收到相应的PUBREC数据包。有关未确认消息的讨论,请参见第4.4 节。
- 必须在从接收器接收PUBREC数据包时发送PUBREL数据包。该PUBREL分组必须包含与原始PUBLISH分组相同的分组标识符。
- 必须将PUBREL数据包视为“未确认”,直到它从接收方收到相应的PUBCOMP数据包。
- 一旦发送了相应的PUBREL数据包,就不能重新发送PUBLISH。
[MQTT-4.3.3-1]。
一旦发件人收到PUBCOMP数据包,数据包标识符就可以重用了。
请注意,允许发件人在等待接收确认时发送具有不同数据包标识符的其他PUBLISH数据包。
在QoS 2传送协议中,接收器
- 必须使用包含来自PUBLISH数据包的数据包标识符的PUBREC进行响应,并接受应用程序消息的所有权。
- 在收到相应的PUBREL数据包之前,接收方必须通过发送PUBREC来确认具有相同数据包标识符的任何后续PUBLISH数据包。在这种情况下,它不得导致重复的邮件传递给任何转发收件人。
- 必须通过发送包含与PUBREL相同的包标识符的PUBCOMP包来响应PUBREL包。
- 在发送了PUBCOMP之后,接收方必须将包含该数据包标识符的任何后续PUBLISH数据包视为新发布。
[MQTT-4.3.3-2]
发件人行动 | 控制包 | 接收者行动 |
存储消息 |
|
|
PUBLISH QoS 2,DUP 0 |
|
|
| ----------> |
|
|
| 方法A,存储消息 |
|
| PUBREC <数据包标识符> |
| <---------- |
|
丢弃消息,Store PUBREC收到<Packet Identifier> |
|
|
PUBREL <数据包标识符> |
|
|
| ----------> |
|
|
| 方法A,启动应用程序消息1的继续传递, 然后丢弃消息 |
|
| 发送PUBCOMP <数据包标识符> |
| <---------- |
|
丢弃存储状态 |
|
|
1在发送PUBREC或PUBCOMP之前,接收方无需完成应用程序消息的传送。当其原始发送方接收到PUBREC数据包时,应用程序消息的所有权将传输到接收方。
图4.3 显示接收器可以通过两种方法处理QoS 2。它们在消息可用于向前传递的流程中的不同点。方法A或方法B的选择是特定于实现的。只要实现选择这些方法中的一种,这不会影响QoS 2流的保证。
4.4 Message delivery retry 消息传递重试
当客户端重新连接CleanSession设置为0时,客户端和服务器必须使用其原始数据包标识符 [MQTT-4.4.0-1] 重新发送任何未确认的PUBLISH数据包(其中QoS> 0)和PUBREL数据包。 这是客户端或服务器需要重新传递消息的唯一情况。
非规范性注释
历史上需要重新传输控制数据包以克服某些旧TCP网络上的数据丢失。对于要在此类环境中部署MQTT 3.1.1实现的问题,这可能仍然是一个问题。
4.5 Message receipt 留言收据
当服务器获取传入的应用程序消息的所有权时,它必须将其添加到具有匹配的订阅的那些客户端的会话状态。匹配规则在第4.7 节[MQTT-4.5.0-1] 中定义。
在正常情况下,客户端会收到消息以响应他们创建的订阅。客户端还可以接收与其任何显式订阅都不匹配的消息。如果服务器自动为客户端分配了订阅,则会发生这种情况。在UNSUBSCRIBE操作正在进行时,客户端也可以接收消息。客户端必须根据适用的QoS规则确认它收到的任何发布数据包,无论它是否选择处理它包含的应用程序消息 [MQTT-4.5.0-2]。
4.6 Message ordering 消息排序
在实现本章其他地方定义的协议流时,客户端必须遵循这些规则:
- 当它重新发送任何PUBLISH数据包时,它必须按发送原始PUBLISH数据包的顺序重新发送它们(这适用于QoS 1和QoS 2消息) [MQTT-4.6.0-1]
- 它必须按照接收相应PUBLISH数据包的顺序发送PUBACK数据包(QoS 1消息) [MQTT-4.6.0-2]
- 它必须按照接收相应PUBLISH数据包的顺序发送PUBREC数据包(QoS 2消息) [MQTT-4.6.0-3]
- 它必须按照接收相应PUBREC数据包的顺序发送PUBREL数据包(QoS 2消息) [MQTT-4.6.0-4]
默认情况下,服务器必须将每个主题视为“有序主题”。它可以提供管理或其他机制,允许将一个或多个主题视为“无序主题” [MQTT-4.6.0-5]。
当服务器处理已发布到有序主题的消息时,它必须在向每个订户发送消息时遵循上面列出的规则。此外,它必须按照从任何给定客户端 [MQTT-4.6.0-6] 收到的顺序向用户发送PUBLISH数据包(对于相同的主题和QoS)。
非规范性评论
上面列出的规则确保在发布消息流并使用QoS 1订阅时,订阅者收到的每条消息的最终副本将按照它们最初发布的顺序排列,但可能会导致消息重复的可能性重新发送在其后续消息之一后收到的早期消息。例如,发布者可以按1,2,3,4的顺序发送消息,订阅者可以按1,2,3,2,3,4的顺序接收消息。
如果客户端和服务器都确保在任何时间只有一个消息“在飞行中”(通过在其前任已被确认之前不发送消息),那么在任何后续消息之后将不会收到任何QoS消息 - 例如,订户可能按顺序1,2,3,3,4但不是1,2,3,2,3,4接收它们。将飞行中窗口设置为1还意味着即使发布者在同一主题上发送具有不同QoS等级的消息序列,也将保留订单。