MQTT 无限保活

Unlimited keepalive in MQTT

目前正在开发类似 "smart home" 的东西,我家里几乎没有其他设备。他们都通过 MQTT 连接到 OpenHab。我出于我的目的使用 Paho MQTT library (Python)。

一般MQTT有"keepalive"属性。 属性 描述了当订阅的主题没有更新时,我的客户端将连接到 MQTT 服务器的时间(据我所知,它将 ping 发送到服务器)。

但是这里我遇到了一个大问题。需要的主题可以每小时更新一次,甚至可以每隔几个 days/months 更新一次。假设这是室内警报。 如何避免保持活动超时或忽略该字段?可以无限吗?

您没有理解 keepalive 值代表什么。

MQTT 客户端即使不发布或接收任何消息也可以无限期保持连接。但是代理需要跟踪哪些客户端仍处于连接状态,以便它知道何时为客户端发送 Last Will and Testament (LWT) 消息。为此,它使用 keepalive 时间。

客户端每次发送或接收消息时,代理都会重置一个计时器,如果此计时器超过 keepalive 时间值的 1.5 倍,则代理将客户端标记为断开连接并处理轻重量。为了防止消息速率非常低的客户端断开连接,这样的客户端可以随时(很可能在 keepalive 值超时时)向 server/broker 发送一个 PINGREQ 数据包。服务器收到 PINGREQ,用 PINGRESP 数据包应答,它会将 keepalive 计时器重置为零并使客户端保持连接状态。

请参阅 MQTT 标准的保持活动部分:(http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html#_Toc385349238)

The Client can send PINGREQ at any time, irrespective of the Keep Alive value, and use the PINGRESP to determine that the network and the Server are working. If the Keep Alive value is non-zero and the Server does not receive a Control Packet from the Client within one and a half times the Keep Alive time period, it MUST disconnect the Network Connection to the Client as if the network had failed

从客户端发送初始 MQTT CONNECT 消息时,您可以提供可选的“keep-alive”值。该值是一个时间间隔,以秒为单位,在此期间代理期望客户端发送消息,例如 PUBLISH 消息。如果在间隔期间没有消息从客户端发送到代理,代理将自动关闭连接。请注意,您指定的 keep-alive 值乘以 1.5,因此设置 10 分钟 keep-alive 实际上会导致 15 分钟的间隔。

查看 MQTT specificationKeep Alive 部分:

A Keep Alive value of 0 has the effect of turning off the Keep Alive mechanism. If Keep Alive is 0 the Client is not obliged to send MQTT Control Packets on any particular schedule. v5 spec source

因此,将keep alive 设置为0,客户端就不必经常发送keep alive 信号了。服务器应该尊重这个与客户端的连接(例如从去年开始)应该仍然连接,但不能保证(当服务器关闭时客户端可能会断开连接)。