我们在介绍MQTT简史的文章中,有朋友留言:
我们这期就针对LWT详细介绍和说明,大家看完有任何建议和指导留言区留言讨论哈!!!
Last Will and Testament (LWT) 是 MQTT 中的一个强大功能,允许客户端指定一条消息,当客户端发生意外断开连接时,代理会自动发布这条消息。它提供了一种可靠的通信方式,并确保客户端在断开连接时能够优雅地处理,避免主题处于不一致的状态。当客户端必须通知其他人其不可用或在意外断开连接时传达重要信息时,这一功能尤其有价值。
简单来说,MQTT 客户端只是告诉代理,“如果我因某些原因意外断开连接,请将此消息发布到此主题。”
在现实世界中,一个人可以立下遗嘱,说明其资产应如何分配以及去世后应采取什么行动。当他去世后,遗嘱执行人将遗嘱公布并执行遗嘱中的指示。
在 MQTT 中,客户端在连接时可以向服务器注册一个遗嘱消息(Will Message)。类似普通消息,我们可以设置遗嘱消息的主题、负载以及其他字段。一旦代理检测到连接中断,它会发布一条预定义的消息,称为 lastWillMessage,到预定义的主题 lastWillTopic,从而使订阅者得知断开连接的消息。因此,这些接收方可以及时采取行动,例如发送用户通知或切换到备用设备。
MQTT LastWill
是一组参数,用于向特定主题的订阅者通知某个特定客户端的异常断开情况。当客户端意外断开连接时无法发送消息,因此它请求代理服务器代为发送。
注意:根据 MQTT 5.0 规范和 3.1.1 版本,这一组参数 simply 被称为 Last Will:遗愿消息(Will Message)、遗愿主题(Will Topic)、遗愿质量等级(Will QoS)和遗愿保留(Will Retain)。
MQTT Last Will 参数主要包括:
lastWillMessage
– 如果客户端重新连接,将发送给特定主题订阅者的消息。lastWillTopic
– 一个 MQTT 主题,用于发布遗愿消息。
lastWillRetain
– 一个布尔值,表示是否保留 Last Will 消息。如果保留,Last Will 消息将被发送给 lastWillTopic
的所有新订阅者。如果不保留,新订阅者将不会收到 Last Will 消息。
lastWillQoS
– 在发送遗嘱消息时使用的 MQTT 服务质量级别。
MQTT Last Will 的主要思想,也被称为 MQTT 遗言或 LWT,是为了提供一种适当的机制来通知客户端意外断开连接。
发送给订阅者的 Last Will 消息表示客户端的连接意外断开,即客户端没有发送 MQTT DISCONNECT 消息。这些信息允许你相应地应对物联网系统的需求或需求。我们将在下面的例子中观察 MQTTLast Will 的价值。但在那之前,让我们看看它是如何工作。
通常,如果你想让客户端断开连接,你可以简单地调用 disconnect()函数。但如果客户端在函数未执行的情况下断开连接,你还想要知道这一点的话,而这就是 Last Will & Testament 的作用。
它是如何工作的呢?我们这里分三步详细说明:
Step 01:
客户端在连接到代理之前设置LWT消息负载和主题名称。像普通消息一样,我们可以为遗嘱消息设置主题(遗嘱主题)、保留标志(遗嘱保留)、属性(遗嘱属性)、服务质量(遗嘱服务质量)和负载(遗嘱负载)。
这些字段的使用方式与在普通消息中相同。唯一的区别是,遗嘱消息可用的属性与普通应用消息略有不同。以下表格列出了它们的具体差异:
遗愿消息总是在客户端“死亡”后发布。从某种意义上说,这也是客户端发送的最后一条消息。因此,在遗愿消息中,主题别名没有意义。
此外,遗愿消息还具有一种独有的属性:遗愿延迟间隔。这是由 MQTT 5.0 引入的重要改进,我们稍后会讨论这一点。
Step 02:
代理会在断开连接函数被调用之前存储 LWT 消息。如果调用了断开连接函数,代理会丢弃 LWT 消息。
Step 03:
如果客户端意外断开连接,代理会将 LWT 消息发布到 LWT 主题。
如果客户端在连接时指定了遗嘱消息,那么服务器将在相应的会话中存储此遗嘱消息,直到满足以下任一条件以发布它:
简而言之,我们可以总结为只要没有发送带有 Reason Code 0x00 的 DISCONNECT 数据包就关闭网络连接,服务器就需要发送遗嘱消息。
当客户端完成工作并主动登出时,它可以发送一个带有 Reason Code 0x00 的 DISCONNECT 数据包,然后关闭网络连接,以防止服务器发布遗嘱消息。
为什么没有发布遗嘱消息?
在MQTT5.0中,还增加了 Will Delay Interval 属性用于 Last Will 消息,该属性确定在网络连接关闭后服务器将在多长时间内延迟发布 Last Will 消息,单位为秒。
延迟发布和取消遗嘱消息使得订阅者是否会接收到遗嘱消息变得有些复杂。下图已经考虑了所有可能的情况,以帮助您更好地理解:
如果连接意外关闭且 Will Delay Interval 等于 0,当网络连接关闭时,Last Will 消息将立即发布。
在遗嘱延迟间隔或会话过期间隔到期之前:
客户端指定 Clean Start 为 0 以恢复连接,遗嘱消息将不会发布。
客户端指定 Clean Start 为 1 以恢复连接,遗嘱消息将立即发布,因为现有会话结束。
如果现有的网络连接尚未关闭,但客户端使用相同的 Client ID 建立新的连接,服务器将向现有网络连接发送一个 Reason Code 为 0x8E(会话接管)的 DISCONNECT 包,然后关闭该连接。这种情况很可能发生在网络条件较差时,也被认为是意外断开连接。
现在考虑这个问题:如果现有的网络连接的会话过期间隔等于 0,并且遗愿延迟间隔大于 0,当客户端将 Clean Start 设置为 0 以启动新的网络连接时,服务器是否会发送遗愿消息?
答案是,当现有的网络连接断开时,遗愿消息将立即被发布。
当服务器关闭现有的网络连接时,会话会立即结束,因为会话过期间隔为 0。虽然 Clean Start 设置为 0,但服务器会在新的网络连接中创建一个新的会话。因此,由于会话结束,遗愿消息将被发布。
Demo示例
我们还是使用MQTTX来和大家演示,我们首先与免费公共 MQTT 代理建立客户端连接。在该连接中,我们指定了一个遗嘱消息,主题为 mqttx_ee260cd0/status ,负载为 offline,并将遗嘱延迟间隔设置为 5 秒,会话过期间隔设置为 300 秒。使用 Client ID 作为主题的前缀可以有效避免与公共服务器上其他用户使用的主题重复:
创建一个新的客户端连接,连接到公共 MQTT 服务器,然后订阅主题 mqttx_ee260cd0/status 以接收遗嘱消息:
接下来,我们让第一个客户端发送一个带有空主题但设置了主题别名的消息。由于我们尚未建立主题和主题别名之间的映射,这将导致服务器认为客户端的行为不符合协议规则并关闭连接,然后发送遗嘱消息:
由于设置了遗嘱延迟间隔,在发送消息 5 秒后,我们将看到遗嘱消息到达订阅者:
实际验证上述测试,没有出现offline的消息,可以尝试断开模拟电脑的网络,再次连接的时候,willsub这个客户端就出现上图的will消息。
总结来说,要确保您不会错过任何设备断开连接的情况,那么就要使用和Will(LWT)。
参考链接:
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有