MQTT messageId实际实现

时间:2012-06-20 08:12:44

标签: mqtt

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

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

我不太确定是否还有其他方法来识别邮件?我希望尽可能符合标准。

2 个答案:

答案 0 :(得分:21)

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

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

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

如果您希望支持一次性处理多条消息,那么在分配新消息之前检查没有消息ID重复是相对简单的。

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

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

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

答案 1 :(得分:0)

要在QOS1或QOS2上传递更多消息,您应该使用持久存储器的概念。在此期间,当订户不可用时,消息被存储在持久存储器中并且一旦订户被连接就传送。在配置mosquitto.conf文件后,您也可以在QOS0上执行此操作。