MQTT保持活动机制是MQTT协议定义的一项功能。

MQTT客户端通过向代理发送为PINGREQ报文来维持与代理的连接。

MQTT代理通过接收PINGREQ来检测客户端是否无响应或断开连接,同理MQTT客户端通过接收PINGRESP响应来判断代理是否可用。

KeepAlive

当MQTT客户端与代理建立连接时,会协商KeepAlive值大小。

KeepAlive是以秒表示的时间间隔。

MQTT客户端必须在此时间间隔内至少向代理发送一次PINGREQ报文,以表明其存在并保持连接处于活动状态

MQTT代理收到PINGREQ报文后,会返回PINGRESP报文进行响应,确认连接仍处于活动状态

MQTT KeepAlive机制对于连接监控、高效资源利用、检测网络故障、正常断开等非常重要。

MQTT是TCP之上的通信协议,因此会收到TCP半开连接的影响,而MQTT KeepAlive就是为了解决或者优化这个问题。

TCP半开连接问题

  1. TCP客户端与服务器建立起正常的TCP连接。
  2. 客户端口由于网络断开、电源掉电、系统崩溃等诸多情况导致连接断开,服务器进程不会知道(常用的select,epoll监测不到断开或错误事件)。
  3. 服务端如果不主动处理或重启系统,则会一直维持该连接,良妃服务端资源(比如文件描述符)。

在TCP中,这种不完整连接的状态称为半开连接,其中通信的一端一直不知道另一端的故障。连接端持续尝试发送消息,同时急切地等待确认。

工作原理

MQTT KeepAlive机制就是为了解决基于TCP之上的连接存在的TCP半开连接问题。

此机制保证MQTT代理和客户端之间的连接保持活动状态,并且双方都知道其连接状态。

当MQTT客户端与代理建立连接时,会协商一个以秒为单位的时间间隔,称为“保持活动持续时间”(KeepAlive值)。

此持续时间间隔用于设置MQTT客户端与代理不交换任何通信数据的最大时间间隔。换句话说,即客户端完成发送一个控制数据包与开始发送下一个控制数据包之间允许经过的最大时间间隔

客户端需要确保发送的数据报文之间的间隔不超过连接时协商的保持活动持续时间间隔(KeepAlive)。

在该时间间隔内,如果没有任何数据报文发送时,客户端必须发送PINGREQ报文,用于通知客户端可用并保持连接处于活跃状态。

如果MQTT客户端在KeepAlive间隔的1.5倍的时间内没有发送任何数据(包括PINGREQ报文),则代理负责断开客户端的连接。同理,如果客户端在合理的时间内没有收到代理的响应,则会关闭连接。

通信流程

sequenceDiagram participant 客户端 participant MQTT代理 autonumber 客户端 ->>+ MQTT代理: CONNECT(keepalive=30) MQTT代理 ->>- 客户端: CONNACK note right of 客户端: 连接建立成功 rect rgb(200, 150, 255) note over 客户端,MQTT代理: keepalive间隔内无其他通信数据 客户端 ->>+ MQTT代理: PINGREQ MQTT代理 ->>- 客户端: PINGRESP end

其中PINGREQ与PINGRESP报文内容如下所示:

PINGREQ报文用于MQTT客户端向代理表明其持续存在并处于活跃状态,PINGRESP报文用于客户端确认代理是可用状态。

说明

  1. 如果MQTT代理在指定时间范围内没有收到来自客户端PINGREQ报文或其他任何数据,则会关闭连接并转发遗嘱消息消息(如果客户端已指定)。
  2. MQTT客户端负责设置适当的KeppAlive数值。
  3. KeepAlive最大为18小时12分钟15秒,将KeepAlive设置为0可停用KeepAlive机制。