欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

MQTT的秘密武器:心跳机制(Keep Alive)详解

最编程 2024-08-08 22:01:28
...

在这篇文章中,我们将讨论MQTT的Keep Alive功能以及为什么此功能对移动网络特别重要。

正文

TCP连接半开问题

MQTT 基于传输控制协议 (TCP)。该协议确保数据包以“可靠、有序和错误检查”的方式通过互联网传输。然而,通信双方之间的传输有时会不同步。例如,如果一方崩溃或传输错误。在 TCP 中,这种不完全连接的状态称为半开连接。要记住的重要一点是,通信的一侧继续运行,而不会通知另一侧的故障。仍然连接的一侧不断尝试发送消息并等待确认。

正如安迪·斯坦福-克拉克(MQTT 协议的发明者)所指出的,半开连接的问题在移动网络中越来越多:

“虽然理论上 TCP/IP 会在套接字中断时通知您,但实际上,特别是在移动和卫星链接等事物上,它们通常通过空中“伪造”TCP 并在每一端放回标头,TCP 很有可能会话到“黑洞”,即它似乎仍然打开,但实际上只是将您写入的任何内容倾倒在地板上。”

安迪·斯坦福-克拉克 (Andy Stanford-Clark) 关于“为什么需要保持活动状态?” 来源

MQTT Keep Alive

MQTT 包含一个保持活动功能,该功能为半开连接问题提供了一种解决方法(或至少可以评估连接是否仍然打开)。

保持活动确保代理和客户端之间的连接仍然打开,并且代理和客户端知道正在连接。当客户端建立到代理的连接时,客户端以秒为单位向代理传送时间间隔。此时间间隔定义了代理和客户端不能相互通信的最大时间长度。

MQTT 规范说明如下:

“Keep Alive ... 是客户端完成传输一个控制数据包的时间点和它开始发送下一个数据包的时间点之间允许经过的最大时间间隔。确保时间间隔是客户端的责任”

只要消息交换频繁并且没有超过keep-alive间隔,就不需要发送额外的消息来建立连接是否仍然打开。

如果客户端在保活期间没有发送消息,它必须向代理发送一个 PINGREQ 数据包以确认它可用并确保代理仍然可用。

代理必须断开在保持活动间隔的一倍半内未发送消息或 PINGREQ 数据包的客户端。同样,如果客户端在合理的时间内没有收到来自代理的响应,则期望客户端关闭连接。

  • Keep Alive功能使用两个数据包:
    PINGREQ
image.png

PINGREQ 由客户端发送,并指示代理客户端还活着。如果客户端不发送任何其他类型的数据包(例如,PUBLISH 或 SUBSCRIBE 数据包),则客户端必须向代理发送 PINGREQ 数据包。客户端可以随时发送 PINGREQ 数据包,以确认网络连接仍然有效。PINGREQ 数据包不包含有效载荷。

PINGRESP

image.png

当代理收到 PINGREQ 数据包时,代理必须回复一个 PINGRESP 数据包以向客户端表明它仍然可用。PINGRESP 数据包也不包含有效载荷。

注意

  • 如果代理没有收到来自客户端的 PINGREQ 或任何其他数据包,代理将关闭连接并发送最后的遗嘱(Last Will and Testament)(如果客户端指定了 LWT)。
  • MQTT 客户端有责任设置适当的保持活动值。例如,客户端可以将保活时间间隔调整为其当前信号强度。
  • 最大保活时间为 18 小时 12 分 15 秒。
  • 如果保活时间间隔为 0,则保活机制被停用。

通常,断开连接的客户端会尝试重新连接。有时,代理仍然为客户端提供半开连接。在 MQTT 中,如果代理检测到半开连接,它会执行“client take-over”。代理关闭与同一客户端的先前连接(由客户端标识符确定),并与客户端建立新连接 。此行为可确保半开连接不会阻止断开连接的客户端重新建立连接。