在众多的MQTT问题中,我想知道当需要保留发送给某个主题的所有消息并排队等待新订户时,MQTT有哪些替代方案。

在我公司,我们管理着远程部署,我们希望使用MQTT进行本地数据收集。想法是将数据发送到本地本地代理(例如,在Raspberry Pi上运行),并且代理将与我们的CloudMQTT部署建立MQTT桥。如果失去连接,则消息将在本地收集,并在重新建立连接时再次同步。

典型的设置如下:



在我的示例中,左侧是在每个位置运行的许多(大约100个)MQTT本地代理,而右侧是我们要付费的CloudMQTT服务器。

当我阅读文章MQTT Essentials第8部分:保留的消息时,这一部分令人失望:


保留的消息是将保留标志设置为true的普通MQTT消息。代理存储该主题的最后保留的消息和
相应的QoS。订阅与保留邮件的主题匹配的主题模式的每个客户端在订阅后立即收到保留消息。代理
每个主题仅存储一条保留的消息。


本质上,这意味着CloudMQTT服务器上必须始终有一个订户,侦听来自所有的传入事件。我们所有的位置;否则,数据可能会丢失。

MQTT似乎仅用于保留最新消息。是否有其他软件包可以执行此本地<=>远程同步,但保留所有消息?

评论

这是因为MQTT的设计目标是轻量级,所以您正在寻找更适合您的需求的RabittMQ。参考:rabbitmq.com

#1 楼

您正在尝试使用不适合您情况的系统。

MQTT设计为:


MQTT是机器对机器( M2M)/“物联网”连接协议。它被设计为一种非常轻量级的
发布/订阅消息传送。


参考:https://mqtt.org/您需要的是,它可以部署在分布式和联合配置中。它还具有核心发行版中随附的MQTT 3.1.1插件。

参考:https://www.rabbitmq.com

#2 楼

MQTT将为您处理此问题,保留消息不是正确的事情,您需要使用较高的QOS值(1或2而不是默认的0)。您需要阅读提到的文章序列的第6部分。

保留的邮件解决了一个不同的问题,即允许新客户始终获取最新的信息。高QOS将确保所有邮件的传递。当网络中断时,代理将使所有消息排队,直到网桥返回,然后再将它们传递给云代理。

评论


感谢您的回复,我理解这一部分。我的“问题”确实来自另一端,即云代理。为了在云代理上接收所有事件,这意味着始终需要一个订户(例如,在我们的Kubernetes集群中运行的一个小程序)。如果没有,事件的历史将丢失。

–斯科特·克鲁克斯(Scott Crooks)
19年2月14日在12:40

不,不是这样,只要客户端过去已在QOS 1或2上订阅了云代理,它就会在脱机时将消息排队,并在重新连接时将其传递。唯一的要求是它已订阅一次。全新的客户只会从首次连接/订阅的那一刻收到消息。另外,您真的不希望在连接新客户时向其提供5年的历史记录,因为它将被无用的数据埋没。

– hardillb
19年2月14日在17:09

如果需要完整的历史记录,则应将其存储在某个地方的数据库中,而不是在消息传递系统中

– hardillb
19年2月14日在20:35

#3 楼

根据MQTT代理中的支持,持久会话可能会起作用。当客户端连接时,他们可以将clean session标志设置为False,然后订阅感兴趣的主题。如果客户端断开连接,则在QoS 1或2下发布到这些主题的所有消息都将排队。当客户端重新连接时,订阅将自动重新建立传递的排队消息。

确实需要对客户端进行更多思考和潜在更改才能处理排队消息。

#4 楼

另一个选择是创建自己的服务来处理它。根据您的指定,服务需要连接到本地RPi(充当本地网关)上的本地MQTT代理。本地网关通常用于提供数据过滤,但是您可以使用它来临时存储设备发送的数据。您可以使用python或任何支持MQTT客户端库的编程语言。客户端服务不过是网关上运行的另一个MQTT客户端,可以执行逻辑和数据库操作。您构建的此客户端服务将在数据到达本地网关的MQTT代理后立即接收数据,尝试将其转发到CloudMQTT。如果由于没有可用的Internet连接而无法连接到CloudMQTT,则它将数据存储到带有标志的临时数据库中,以跟踪该数据是否已发布到CloudMQTT。客户端服务(始终在后台运行)尝试从数据库中获取此数据并重新发送。如果该数据已成功发送到CloudMQTT,则该服务将在发送数据时更新该标志。稍后您可以从数据库中删除其标志值指示已将其发送到CloudMQTT的所有数据。因此,在这种情况下,运行本地代理(当然还有SQLite这样的数据库)的本地RPi计算机实际上可以充当智能网关。该解决方案应该使您能够发送所有收集的数据,即使几个小时甚至一天或更长时间都没有Internet连接,因为您拥有所有备份。