MQTT消息ID的实际实现

MQTT消息ID的实际实现,mqtt,Mqtt,我工作的公司已经评估了MQTT,并决定将其用作大型系统的核心消息传递平台。主要原因是协议的紧凑性以及它的实际实现有多容易。不过,我对MQTT有一个问题,我正在寻找以下问题的答案: QoS1和QoS2消息需要客户端的确认。在接收PUBACK、PUBREC、PUBREL和PUBCOMP时,我知道的关于消息的唯一信息(识别它)是messageId和clientId。消息id是无符号int16,因此最大值为65535。对于长时间运行的客户来说,比如说一年,每小时发送15条QoS2消息,它似乎不够大 我不

我工作的公司已经评估了MQTT,并决定将其用作大型系统的核心消息传递平台。主要原因是协议的紧凑性以及它的实际实现有多容易。不过,我对MQTT有一个问题,我正在寻找以下问题的答案:

QoS1和QoS2消息需要客户端的确认。在接收PUBACK、PUBREC、PUBREL和PUBCOMP时,我知道的关于消息的唯一信息(识别它)是messageId和clientId。消息id是无符号int16,因此最大值为65535。对于长时间运行的客户来说,比如说一年,每小时发送15条QoS2消息,它似乎不够大


我不太确定是否有其他方法来识别该消息?我希望尽可能遵守该标准。

首先要明确的一点是,消息ID是根据每个客户机和每个方向处理的。也就是说,代理将为每个连接的客户端创建QoS>0的每个传出消息的消息ID,并且这些消息ID将完全独立于用于发布到其他客户端的相同消息的任何其他消息ID。同样,每个客户机为其发送的消息生成自己的消息ID

消息ID不必是唯一的,因此您的客户机在QoS级别为2的情况下每小时发送15条消息,可能会在某个时候溢出。真正的限制是,一次“飞行中”每个方向最多只能有65535条消息(即部分通过消息握手)。具有给定ID的消息被完全处理后,可以重用该消息ID

另一种方法是考虑如果你的客户只在一次飞行中有一个消息,不管是因为消息的传输速率还是按你处理消息的方式设计的,它是如何工作的。在这种情况下,您可以将每条消息的消息ID设置为1,因为不会有重复的消息

如果您希望支持同时传输多条消息,那么在分配新消息之前,检查是否存在重复的消息ID将相对简单

由于消息ID是针对每个客户端的,因此如果向>65535个客户端发送单个消息,则不会发生消息ID冲突。如果您一次向每个客户端发送>65535条消息,并且消息流未完成,则会出现问题

回答评论“我注意到每个MQTT代理都倾向于只传递最后一条QoS1/2消息”:


代理将只向它知道的客户端发送消息。如果您是第一次连接,则无法从过去获取消息,只有一个例外:保留的消息。如果消息设置为“保留”,则它是“最后一个已知良好”值。当一个新的客户端订阅时,它将立即被发送保留消息,这使得它对于不经常更新的东西很有用。我怀疑这就是你所指的。如果希望客户端在未连接时将消息排入队列,则必须禁用“clean session”选项以使客户端持久化。您还必须使用QoS>0订阅和QoS>0发布。当客户端重新连接(清除会话仍设置为禁用)时,将传递排队的消息。您通常可以在代理中以这种方式配置要排队的消息数量,在代理中,任何进一步的消息都将被丢弃。重要的一点是,设计不支持为以前未连接的客户端排队消息。

要在QOS1或QOS2上传递更多消息,应使用持久内存的概念。在这种情况下,当订户不可用时,消息将存储在持久内存中,并在订户连接后发送。您也可以在配置mosquitto.conf文件后在QOS0上执行此操作。

我理解这一点,顺便感谢您的回答。我注意到,每个MQTT代理都倾向于只传递最后一条QoS1/2消息。如果我想多送些呢?有什么比65535还多?我明白这是极不可能的,但这是可能的。您建议的解决方案适用于已知数量的收件人。我所面对的情况是,我不知道可能有多少受助人,他们是否还在工厂里。基本上,他们可以在那里,但永远不会进来。有一点我没有说清楚,消息ID是每个客户端和每个方向的。我已经更新了答案,包括这一点。我还回答了你的另一点。如果这还不清楚,请留下另一条评论。事实上,还有一条,当代理代表另一个客户重新发布消息时,我应该更改消息id吗?从你之前的解释来看,情况似乎是这样的。是的,这是我试图理解的关键点。您应该为每个客户端维护传入和传出消息id。