首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >MQTT Keep Alive 参数有什么用途?

MQTT Keep Alive 参数有什么用途?

作者头像
Hello工控
发布2025-05-21 14:17:50
发布2025-05-21 14:17:50
4870
举报
文章被收录于专栏:Hello工控Hello工控

在物联网网络中,有些设备的数量少,3台到5台,也可能很庞大,成千上万台。例如,传感器,包括磁性接触传感器、功率计、椅子占用传感器等。无论客户端的数量是多少,很可能并不是所有的设备都会持续传输数据。比如,如果冰箱内的温度发生变化,冰箱的传感器会发送一条关于这个变化的消息。在其他时间,这个客户端保持“沉默”。

如果客户端因为某些原因保持沉默,MQTT 代理将会断开与它们的连接。同时,客户端可以通过通知代理它们是“活跃的”来请求不要这样做。

我们通过前期对MQTT协议的详细介绍,已经知道MQTT 协议基于 TCP 协议之上,而 TCP 是一种面向连接的协议,提供了两个连接方之间稳定有序的字节流。然而,在某些情况下,TCP 可能会出现半连接问题。半连接是指一侧的连接已经断开或未建立,而另一侧的连接仍然保持。在这种情况下,半连接的一方可能会持续发送数据,而这些数据显然从未到达另一方。为了避免由半连接引起的通信黑洞,MQTT 协议提供了一个 Keep Alive 机制,允许客户端和 MQTT 服务器检测是否存在半连接问题,并关闭相应的连接。

阅读本期的文章,其他的基础性的可以参考:

MQTT发布和订阅架构

MQTT Packet详解【04】:PINGREQ & PINGRESP心跳报文

什么是MQTT Last Will and Testament (LWT)遗嘱和遗言?

MQTT Keep Alive 是什么,为什么需要它?

MQTT 中的 Keep Alive 是一个标志,定义了一个时间间隔(以秒为单位),在此期间,客户端应当通过发送 PINGREQ 消息通知 MQTT 代理连接是活跃的。如果客户端没有发送消息,MQTT 代理会开始关注它,并在另一个指定间隔的一半后断开客户端连接。该参数可以在 MQTT CONNECT 请求的可变头部中指定如下:

在这个例子中,代理会在 300 秒没有与客户端通信后开始关注状态。它等待客户端的 PINGREQ 消息。如果客户端保持沉默,代理会在另外 150 秒后断开连接。

同样,如果代理没有对客户端的 PINGRESP 消息做出响应,客户端会关闭连接。因此,Keep Alive 允许代理检测客户端是否断开了所谓的半开连接。

启用 MQTT Keep Alive 间隔后,MQTT 代理将知道客户端的状态并保持连接或断开连接。同样,客户端也会意识到代理的故障并断开连接,因为它也可以检测到半开连接。

所以,MQTT Keep Alive 参数的主要价值在于检测代理和客户端之间的断开连接。

MQTT Keep Alive 工作机制

1.Client process 客户端进程

当客户端与代理建立连接时,它会指定一个以秒为单位的时间间隔,称为心跳间隔。该间隔定义了代理和客户端之间可能不进行任何通信的最大时间间隔。根据 MQTT 规范,Keep Alive定义如下:

Keep Alive 是客户端在发送一个控制包完成之后到开始发送下一个控制包之间允许的最大时间间隔。客户端有责任确保发送控制包之间的间隔不超过 Keep Alive 值。如果没有发送其他控制包,客户端必须发送一个 PINGREQ 包。

当客户端发送 PINGREQ 包时,代理必须返回 PINGRESP 包。如果客户端在可靠时间内未收到服务器的 PINGRESP 包,这意味着存在半连接、代理离线或网络故障,此时客户端应关闭连接。

2.Broker process Broker 进程

如果客户端在 1.5 倍的 Keep Alive 间隔内没有发送任何消息或 PINGREQ 包,代理负责断开客户端连接。同样,如果客户端在合理的时间内没有收到代理的响应,客户端应该关闭连接。

如果代理接收到客户端发送的 PINGREQ 协议包,它需要回复一个 PINGRESP 协议包以确认。

3.Client takeover mechanism客户端接管机制

当客户端重新上线,并且之前的连接保持半打开状态时,代理服务器会执行一个简单的客户端接管操作:

  • 它会关闭此客户端之前的连接。
  • 它会用这个客户端建立一个新的连接。

通过采用 Keep Alive 机制,MQTT 增强了连接的稳定性,减轻了半开连接带来的风险,并在各种网络条件下促进了代理和客户端之间的高效通信。

图片
图片

Keep Alive&LWT

Keep Alive 通常与 Will Message 一起使用,可以在设备发生意外离线事件时及时通知其他客户端。

如图所示,当该客户端连接时,Keep Alive 设置为 5 秒,并设置了一个遗嘱消息。如果服务器在 7.5 秒内(Keep Alive 的 1.5 倍)没有收到客户端的任何数据包,它将向 'Last_will' 主题发送一个包含 'offline' 载荷的遗嘱消息。

除非 keepalive 等于 0,否则如果 MQTT 代理在指定的 Keep Alive 时间间隔加上间隔的一半内没有从客户端接收到任何消息,连接将被关闭。在这种情况下,如果在建立连接时指定了 LWT(最后遗言),客户端将接收到 LWT 消息。同样,如果 MQTT 代理没有对客户端的 PINGREQ 消息以 PINGRESP 消息进行回复,客户端也会关闭连接。然而,在大多数情况下,断开连接的客户端会尝试重新连接。

重要提示:当客户端发送任何数据包时,PINGREQ-PINGRESP 交换变得无效,Keep Alive 间隔重新从 0 秒开始计算。

常见问题

Q: MQTT Keep Alive 间隔可以多长?

A: 最大 Keep Alive 间隔为 18 小时 12 分钟 15 秒。然而,在许多情况下,较长的 Keep Alive 间隔可能并不实用。

Q: 如果 MQTT Keep Alive 间隔设置得太长会发生什么?

A: 如果间隔时间过长,在网络故障或其他问题导致客户端断开连接的情况下,代理服务器识别客户端断开连接所需的时间会更长。这可能会延迟 LWT 消息的发送,并且还可能导致代理服务器维持客户端会话的时间比必要的时间更长,从而可能消耗不必要的资源。

Q: 我可以在我的 MQTT 客户端中禁用 MQTT Keep Alive 吗?

A: 是的,MQTT Keep Alive = 0 即可。你可以禁用 MQTT Keep Alive 功能,尽管这通常不被推荐。

Q: MQTT 客户端是如何通知代理它想要接管现有会话的

A: 当 MQTT 客户端想要接管现有的会话时,它会向代理发送一个 CONNECT 消息。在 CONNECT 消息中,它包含了与现有会话相同的 ClientID。

Q: 在 MQTT 系统中,有没有防止意外客户端接管的策略?

A: 是的,可以在 MQTT 系统中使用多种策略来防止意外的客户端接管,这包括使用唯一的 ClientIds、强大的身份验证和授权机制,以及应用程序级别的措施等。

Q: 当客户端接管一个 MQTT 会话时,未完成的 QoS 1 或 2 消息会发生什么?

A: 当客户端通过使用相同的 Client Identifier(客户端标识符)并在连接时将“clean session”标志设置为 0 来接管现有的会话时,代理服务器会恢复该会话,包括任何未完成的 QoS 1 或 QoS 2 消息。

Q: 如果 MQTT 客户端尝试使用不同的 ClientID 接管一个会话会发生什么?

A: 当客户端尝试使用与现有会话不同的 ClientID 进行连接时,代理会将此视为来自完全不同客户端的新连接请求。代理将为该客户端开始一个新的会话,与之前 ClientID 相关的任何订阅或消息都不会影响这个新会话。

参考链接:

  1. https://cedalo.com/blog/mqtt-keep-alive-explained/
  2. https://www.emqx.com/en/blog/mqtt-keep-alive
  3. https://www.hivemq.com/blog/mqtt-essentials-part-10-alive-client-take-over/
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2025-05-20,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Hello工控 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • MQTT Keep Alive 是什么,为什么需要它?
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档