原文:www.hivemq.com/blog/mqtt-e…
本篇文章在翻译过程中,对相关内容进行了一些删减,比如文字超链接
作者: HiveMQ Team
发布时间: February 2, 2015
更新于: 2023年6月20日
欢迎来到MQTT基础课程的第四部分,基础课程共分10部,涵盖MQTT协议的核心特性,概念,优势。本篇文章我们将深入研究MQTT中的发布、订阅和取消订阅。如果您对发布/订阅模型还不熟悉,我们建议您在继续之前阅读我们早期关于发布/订阅模式基础的文章。在本系列的第三部分中,我们讨论了在 MQTT客户端和代理服务器之间建立连接的过程。现在,我们将进一步讨论如何使用MQTT发送和接收消息。
MQTT的发布消息指的是什么?
在MQTT中,当客户端连接到了代理服务器,它就可以立即发布消息。消息可以被通过主题进行筛选,每个消息必须包含一个主题,代理服务器可以通过该主题将消息转发给感兴趣的客户端。每条消息负载体包含的数据都是以字节格式进行传输,客户端可以选择发送任何类型的数据,包括文本、数字、图像、二进制数据,甚至成熟的XML或JSON。
消息负载格式
MQTT不感知数据类型的,这意味着有效负载可以根据客户端使用场景对进行结构化。有效负载是消息的主要内容,也是客户端订阅、接收和处理的内容。
MQTT中的PUBLISH消息会受到几个属性影响的,如:包标识符、主题名称、服务质量、保留标志、有效负载和 DUP 标志。我们逐个看一下。
MQTT的包标识符指的是什么?
数据包标识符(PacketId)是MQTT中的一个基本属性。它被用于标识消息,并确保消息按照发送的顺序传递,特别是当QoS大于0时。数据包ID由客户机分配,PackedID会出现在PUBLISH、 PUBREL、 PUBREC和PUBCOMP消息中。当代理服务器接收到PUBLISH消息时,它为消息分配一个PacketId,并向客户端发送一个PUBACK消息。客户端使用PUBACK消息来确认代理已经收到该消息。
在MQTT协议中,与发布和ACK相关的消息被分为几个阶段:
1.发布 (PUBLISH) : 发布消息第一阶段,客户端先发一个PUBLISH消息到代理服务器,消息会包含一个主题和一个消息负载体。 2.发布接收 (PUBREC) : 发布消息第二阶段,代理服务器接收到PUBLISH消息后,会给客户端发一个PUBREC消息,代表它已经收到了PUBLISH消息。
4.发布释放 (PUBREL) : 发布消息第三阶段,一旦客户端接收到PUBREC,它会回复PUBREL消息给代理服务器,告知代理服务器可以内存中的消息了。
5.发布完成 (PUBCOMP) : 发布消息第四阶段,代理服务器最后会发一个PUBCOMP消息,告知客户端它已经成功接收并处理完消息了。
这四条消息是MQTT协议的服务质量(Quality of Service,QoS)机制的一部分,它们确保可靠的消息传递。QoS级别决定客户端和代理服务器之间交换的消息数量。
值得注意的是,当消息在客户端和代理服务器交互时,数据包标识符可以标识消息的唯一性。数据包标识符只会在QoS>0时生效。数据包标识符不仅适用于PUBLISH,而且适用于 SUBSCRIBE、 UNSUBSCRIBE 和 CONNECT 消息。
客户端MQTT库或者代理服务器都可以设置这个MQTT数据包标识符。当使用用数据包QoS>0级别时,客户端必须等待代理服务器的 PUBACK 或 PUBREC 消息,然后才能发送下一条消息。客户端还应该跟踪它已经发送和接收的数据包标识,以确保消息不会丢失或重复。总的来说,数据包标识符对MQTT的可靠性机制至关重要,并有助于确保正确和高效地传递消息。
MQTT主题名字指的是什么?
MQTT使用主题名作为基本概念。它使用正斜杠作为分隔符以层级结构构造这个名称,并创建一个简单的字符串。类似于URL路径,但是没有协议和域组件。MQTT主题用于标记消息,并为客户端提供订阅特定消息的方法。
例如,测量温度的设备可以把读取到数据发布到"sensors/temperature/livingroom"
这个主题。对这个主题感兴趣客户端可以订阅它,并且可更新他们收到数据。
MQTT提供两种订阅主题的通配符类型:
- "+" 用于匹配一个层级结构。例如,订阅
"sensors/+/livingroom"
这个主题,它能匹配到"sensors/temperature/livingroom"
和"sensors/humidity/livingroom"
,但不能匹配到"sensors/temperature/kitchen"
- "#" 用于匹配多层级结构。例如,订阅
"sensors/#"
这个主题,它能匹配"sensors/temperature/livingroom"
,"sensors/temperature/livingroom"
和"sensors/power/meter1"
这些主题
订阅大量主题可能会对代理服务器性能产生重大影响。这是因为发布到客户端订阅的每条主题消息都必须传递给该客户端。如果许多客户订阅了许多主题,很快就会给代理服务器带来沉重的负担。
使用通配符单独订阅多个主题也会影响性能。当客户端使用通配符订阅主题时,代理服务器必须评估发布到匹配主题的每条消息,并确定是否将其转发给客户端。如果匹配的主题数量很大,这会使代理的资源变得紧张。
为了避免性能问题,有效地使用主题订阅非常重要。一种方法是尽可能使用更具体的主题过滤器,而不是依赖于通配符。另一种方法是使用共享订阅,它允许多个客户端共享对一个主题的单个订阅。这有助于减少代理必须处理的订阅和消息的数量。最后,监视代理的性能并根据需要调整其配置对于确保最佳性能非常重要。
For more best practices on MQTT Topicname and wildcards, see Part 5 of MQTT Essentials.
MQTT中的QoS指的是什么?
在MQTT协议的介绍-MQTT基础:第一部分这篇文章中,我们接触到了QoS. QoS使用0到2来表示它值。每个值会提供不同级别的消息传递可靠性
- QoS 0(最多一次) : 这个级别对消息传递是没有任何保障的。消息仅仅会发送一次。如果消息丢失了或者没有被收到,这个消息也不会重发。
- QoS 1(至少一次) : 这个级别能保证消息至少被发送一次, 但在网络原因或者其他失败情况下,会发送多次
- QoS 2(精准一次) : 此级别为消息传递提供最高级别的保证。消息保证只传递一次,但是这个级别需要发送方和接收方之间进行更多的通信,这会增加延迟和网络流量。
选择适当的 QoS 级别取决于特定的场景。例如,QoS0可能适合于非关键数据,而 QoS2可能对于需要高可靠性水平的关键数据是必需的。
需要注意的是,QoS级别会影响代理服务器和网络的性能,因此建议针根据场景选择使用适当的级别。有关更多信息,请阅读我们的文章 MQTT 服务质量(QoS)0、1和2或其他资源,如 MQTT 5要点。
MQTT的Retain Flag指的是什么?
保留标志(Retain Flag)是一个重要特性,它决定了代理服务器是否保存指定主题的最新一次的消息数据。当保留的标志设置为true时,代理服务器将保存与指定主题匹配的最新消息,而不管是否有客户端订阅。
当新客户端订阅了保留的消息主题时,代理服务器将最后一条保留的消息(关于该主题)发送给客户端。这允许客户端可以接收到最近一条与主题相关的消息,即使他们以前没有订阅过该主题。
需要注意的是,像许多其他元素一样,使用保留消息也会影响代理服务器的性能,特别是在有许多保留消息的情况下。此外,如果保留的消息经常更新,则可能导致网络流量增加,并可能影响网络性能。
有关保留消息和如何有效使用 MQTT 保留标志的更多信息,请参阅MQTT Retained Messages - MQTT Essentials: Part 8。
MQTT的Payload指的是什么?
有效负载(payload)是消息的实际内容,可以包含任何类型的数据。MQTT是不感知数据类型的,这意味着它可以处理不同的数据类型,包括图像、任何编码中的文本、加密数据和二进制数据。但是,需要注意的是,有效负载大小会影响客户端和代理服务器的网络性能和内存使用。因此,建议尽可能减少有效负载,特别是在高频率发布消息时。
MQTT的DUP标识指的是什么?
MQTT DUP标志表明消息是重复的,并且由于预期的接收方(客户端或代理服务器)没有确认原始消息而被重新发送。它只与QoS>0的消息相关。当客户端或代理服务器收到设置了DUP标志的消息时,如果它已经收到具有相同消息ID的消息,则应该忽略该消息。如果客户端或代理服务器以前没有收到消息,那么它们应该正常处理该消息。
MQTT 协议(MQTT客户端库或代理服务器)有自动处理重发和重复机制,但是需要注意的是,这会影响网络性能并增加网络流量。有关 MQTT dUP 标志的更多信息,请阅读我们的文章 MQTT 服务质量(QoS)0、1和2-MQTT 要点: 第6部分。
MQTT 如何处理来自客户端的消息?
当客户端发布一条消息到代理服务器,代理服务器会启动一些任务,让其按照客户端指定的QoS级别来分发消息。流程如下:
- 消息接收: 代理服务器读取客户端发送的消息,验证它的语法和格式。
- 确认: 代理服务器给客户端发送确认消息,以便客户端确认消息已发布成功。确认消息依赖客户端请求的QoS值。
- 处理中: 代理服务器判断哪些客户端订阅了消息的主题,并向每个客户端发送消息的副本。代理服务器还可以将消息保留为该主题的最后一条有效消息,具体取决于Retain标志。
- 反馈: 发布客户端收到来自代理服务器的确认消息,表示客户端已成功发布消息。但是,客户端不会收到关于有多少订阅者收到消息或是否有人对此感兴趣的反馈。
MQTT 的 PUBLISH 消息流程
发布消息的客户端只关心将PUBLISH消息传递给代理服务器。一旦代理服务器接收到PUBLISH消息,代理服务器就有责任将该消息传递给所有订阅者。发布消息的客户端不会获得任何下列的反馈,是否有人对发布的消息感兴趣,或者有多少客户端收到了来自代理服务器的消息。
如何订阅MQTT主题?
如果没有人收消息,那么发布消息就没有意义。这就是订阅发挥作用的地方。一旦客户端向MQTT代理服务器发布消息,消息就必须传递给感兴趣的客户端。希望接收感兴趣主题的消息客户端需要向代理服务器发送一条 SUBSCRIBE 消息。SUBSCRIBE 消息很简单,包含唯一的包标识符和订阅列表。
MQTT SUBSCRIBE 消息包结构
包标识: 数据包标识符是唯一的,并在客户端和代理服务器之间传递消息时标识该消息。客户端库或代理服务器负责设置MQTT包标识符。
订阅列表: SUBSCRIBE 消息可以包含客户端的多个订阅信息。每个订阅信息都包含一个主题和一个 QoS 级别。SUBSCRIBE 消息中的主题可以包含通配符,从而可以订阅主题表达式而不是特定主题。如果一个客户端有重叠的订阅,代理服务器将为该主题提供具有最高 QoS 级别的消息。
总的来说,MQTT允许客户端订阅特定的主题,接收发布到这些主题的消息,并根据特定的规则处理有效负载。SUBSCRIBE消息中的包标识符和QoS级别确保消息以适当的质量级别可靠地传递。
MQTT的Suback指的是什么?
一旦客户端向代理服务器发送一条带有主题和相应QoS级别的SUBSCRIBE消息,代理服务器就会通过向客户端发送一条 SUback 消息来确认订阅请求。SUBack消息确认收到SUBSCRIBE消息,表示代理代理服务器是否已接受或拒绝订阅。
MQTT SUBACK 包结构
包标识: SUBACK消息包含与客户端SUBSCRIBE消息中相同的包标识符,这使客户端能够将确认与原始请求匹配。
返回码: SUBACK 消息还包括一个返回码。返回码是二进制值,表示代理服务器是否已允许或拒绝订阅请求。
各QoS下的返回码如下:
- QoS 0: 这意味着在QoS 0时已经允许了订阅请求。代理服务器在消息可用且没有质量保证的情况下立即将其交付给客户端。
- QoS 1: 这意味着在QoS 1时已经允许了订阅请求。代理服务器至少传递一次消息,这意味着代理至少向客户端发送一次消息。客户端在接收到消息后向代理服务器发送一条PUBACK消息,表示已确认收到消息。
- QoS 2: 这意味着在QoS 2时已经允许了订阅请求。代理服务器需精准传递一次消息,即代理服务器需要保障消息精准的传给客户端一次,并且被客户端确认收到。在客户端收到消息时,客户端会通过发送PUBREC消息告知代理服务器已收到消息,代理服务器在收到PUBREC时,会发送一条PUBREL消息给客户端,客户端在接收到PUBREL后,会回复一条PUBCOMP消息。
如果代理服务器拒绝了任何订阅,SUBACK消息会包含一个表示失败的返回码。失败的原因可能是客户端没有足够的权限订阅主题、主题格式不正确或其他原因。
失败返回代码由0x80表示,表示代理服务器不接受订阅。如果客户端没有足够的权限订阅主题、主题格式不正确或订阅请求有其他问题,就会发生这种情况。当客户端收到故障返回代码时,它应该使用不同的主题或 QoS 级别重试订阅,或者采取适当的操作来解决订阅请求中的问题。
Return Code | Return Code Response |
---|---|
0 | 成功 - Maximum QoS 0 |
1 | 成功 - Maximum QoS 1 |
2 | 成功 - Maximum QoS 2 |
128 | 失败 |
MQTT中的SUBSCRIBE,PUBLISH和SUBACK工作流程
SUBACK消息是一种从代理服务器发送到客户端的确认消息,用于表示订阅是否被允许或拒绝。数据包标识符使客户端能够将确认与原始请求匹配,而返回代码指示代理授予订阅的 QoS 级别。
SUBACK代表着服务器对客户端确认了订阅已经被允许或者拒绝。包标识能保障客户端匹配原始请求和返回是同一消息。返回码能表示代理服务器允许订阅的QoS级别。
客户端订阅了感兴趣的主题并收到这些主题的消息之后,可能最终需要取消订阅。现在让我们研究 SUBSCRIBE消息、UNSUBSCRIBE消息以及确认取消订阅的相应 UNSUBack 消息的对应部分。
如何在MQTT中使用UNSUBSCRIBE来撤销订阅?
In MQTT, clients can unsubscribe from the topics they have subscribed to by sending an UNSUBSCRIBE message to the broker. Similar to SUBSCRIBE, this message includes a packet identifier to uniquely identify it and a list of topics to unsubscribe from.
MQTT UNSUBSCRIBE包结构
包标识: 与SUBSCRIBE消息类似,UNSUBSCRIBE消息中的包标识符用作客户端和代理服务器之间消息流的内部MQTT标识符。它确保客户端和代理服务器可以跟踪消息及其相应的确认消息。
主题列表: UNSUBSCRIBE消息中的主题列表可以包含客户端希望取消订阅的一个或多个主题。不需要指定QoS级别,因为代理服务器将取消对主题的订阅,而不管它最初订阅的是什么QoS级别。
MQTT的UNSUBACK指的是什么?
接收到UNSUBSCRIBE消息后,代理服务器会发送一个UNSUBACK来确认客户端的订阅已被移除。这个消息包含包标识,并用作确认代理服务器已成功地从客户端的订阅列表中删除了主题。
MQTT UNSUBACK包结构
包标识: UNSUBACK消息中的包标识符与相应的UNSUBSCRIBE消息中的包标识符相同。这确保了客户端可以识别确认消息并将其与原始UNSUBSCRIBE消息关联。
返回码: UNSUBACK消息包含每个已解除订阅主题/QoS对的返回码列表。返回码0表示成功删除,而返回代码17表示由于无效或格式不正确的主题而不成功删除。还可以针对不同的错误情况指定其他返码。
UNSUBACK工作流程
从代理服务器接收到UNSUBACK之后,客户端可以假定已删除了UNSUBSCRIBE消息中的订阅主题。
这些详细信息已经全面让大家理解了,客户端如何解除主题的订阅,代理服务器如何通过通过 UNSUBSCRIBE和UNSUBACK消息来移除订阅消息。
总结
这就是我们的MQTT基本课程系列的第四部分的结尾。下面是一个快速回顾: MQTT提供了一种灵活的、与数据无关的方式在客户端和代理服务器之间来进行消息传递。通过使用主题来过滤消息,客户端可以快速轻松地订阅感兴趣的内容。可以定制每个消息的有效负载以满足每个客户端的特定需求,MQTT对各种数据类型的支持使其成为许多用例的通用解决方案。此外,理解PUBLISH消息的属性,比如QoS级别和保留标志,可以帮助客户端和代理服务器确保消息的有效性和可靠性。