MQTT遗嘱(Last Will and Testament, LWT),允许客户端指定一条消息,在发生意外断开连接时,代理自动发布该消息到已订阅的其他客户端。

MQTT遗嘱 (LWT) 功能对于确保高效通信和在客户端意外断开时保持系统完整性至关重要。

遗嘱消息

在网络不可靠的场景中,MQTT客户端有两种断开连接的类型,分别是正常断开(会发送DISCONNECT报文)和异常断开连接

由于MQTT采用的是发布/订阅模式,消息的订阅者和发布者完全解耦,不能互相确定是否连接正常。当消息发布者意外掉线之后,订阅者并不知道这个情况,并且还在订阅主题等待接收消息。

针对这种情况,MQTT LWT为客户端提供了一种解决方案,可以有效响应不正常的断开连接并确保正确处理此类事件。

MQTT LWT允许消息发布者通知其他订阅者其意外断开连接。

工作流程

  1. 发布者连接到MQTT代理,并指定遗嘱消息。该遗嘱消息遵循常规MQTT消息结构,包括主题、保留标志、服务质量 (QoS) 和负载。
  2. 代理会存储该遗嘱消息。
  3. 代理通过keepalive检测连线状态:
    1. 如果发布者与代理异常断开连接,则向相应主题的所有订阅客户端广播该遗嘱消息。
    2. 如果发布者发送DISCONNECT报文正常断开连接,代理将丢弃存储的该遗嘱消息。

DISCONNECT报文没有负载,内容如下:

客户端配置

MQTT客户端在建立连接时可以指定遗嘱消息,将其包含在CONNECT报文中。

CONNECT报文结构如下: 遗嘱消息和MQTT普通消息结构一致,包含4部分,分别是主题、保留标志、服务质量 (QoS) 和负载。

代理何时转发

根据 MQTT 3.1.1 规范,代理在以下情况下发送客户端的遗嘱和遗嘱 (LWT) 消息:

代理一般在以下情况转发客户端设置的遗嘱消息:

  1. I/O错误或网络故障:网络接口的输入/输出流错误或者网络连接失败。
  2. KeepAlive超时:KeepAlive时间范围内没有任何数据交互(PING或用户数据)。
  3. 任何客户端关闭连接且不发送DISCONNECT的情况

使用方式

LWT对于向订阅客户端发出有关客户端突然断开连接的警报非常有用。

当与保留消息结合使用时,其将成为存储和传达特定主题的客户端状态的强大工具。

判断设备状态场景

  1. MQTT客户端client1在连接时设置遗嘱消息为topic=client1/status, payload=offline, retained=1
  2. 设备连接成功后发布消息为topic=client1/status, payload=online, retained=1,此时该消息为遗嘱主题的保留消息,新订阅客户端订阅该主题时会收到client1 online的保留消息
  3. 如果client1意外断开连接,MQTT代理会发布遗嘱消息给已订阅的客户端,并将该遗嘱消息作为最新的保留消息,确保在client1离线期间新订阅的客户端收到client1 offline的保留消息