如何在 eclipse-mosquitto 中使用 QoS MQTT 接收离线客户端的消息?
How to recieve messages for offline clients using QoS MQTT in eclipse-mosquitto?
我的 mosquitto.conf 是(这是整个 conf 文件,因为其他所有内容都被注释掉了)
log_dest file /mosquitto/log/mosquitto.log
log_type all
connection_messages true
log_timestamp true
log_timestamp_format [%H:%M:%S]
persistence true
persistence_location /mosquitto/data/
listener 1883
listener 9001
protocol websockets
然后我运行
docker exec -it ecs-Eclipse_mosquitto_MQTT-11-Eclipse-mosquitto-MQTT-eafxxxxxxx mosquitto_pub -t presence -m hellothere -q qos=2
(注意我还没有在线的活跃订阅者)
导航到 /mosquitto/data
,确实有一个名为 mosquitto.db
的文件
所以我可以推断出我的消息 hellothere
存储在 mosquitto.db
然后我运行命令
docker exec -it ecs-Eclipse_mosquitto_MQTT-11-Eclipse-mosquitto-MQTT-eafxxxxxxx mosquitto_sub -t presence -q qos=2
我期待什么
用于 MQTT 代理发送存储的消息,因为订阅者现在在线
实际发生了什么
无限期等待消息
也许我遗漏了什么?
我认为 mqtt spec 的相关位是:
When a Server takes ownership of an incoming Application Message it
MUST add it to the Session state of those clients that have matching
Subscriptions.
在您的情况下,当消息发布时,没有具有匹配订阅的客户端(因为此时您还没有 运行 mosquitto_sub
),因此它什么也不做。
如果您希望为某个客户端存储消息,您必须首先作为该客户端连接并订阅相关主题(QOS>0 且 CleanSession=0)。这样做之后,客户端离线时收到的任何消息都将在重新连接时存储和传递(只要 CleanSession=0)。
注意:要使用 mosquitto_sub
执行上述操作,您需要使用 --id
参数来设置客户端 ID(消息只会为订阅了相关内容的特定客户端排队话题)。您还需要 -c
标志来禁用 'clean session' 标志。
所以步骤如下(我已经删除了额外的 docker 位 - 您可以将它们添加回去):
mosquitto_sub -c --id subscriber1 -t presence -q 2
这将订阅然后等待任何消息;您可以安全地关闭它(这是需要发生的订阅位)。接下来发布您的消息:
mosquitto_pub -t presence -m hellothere -q 2
现在您可以再次开始 mosquitto_sub
以检索存储的消息:
mosquitto_sub -c --id subscriber1 -t presence -q 2
警告:当您这样订阅时,经纪人将存储您离线时收到的任何消息。如果您正在测试处理大量消息的代理(因为存储所有消息需要 space),这可能会成为一个问题。这里可能不是问题,因为你只是在测试,但要记住一些事情...... 运行 mosquitto_sub
没有 -c
将清除任何订阅 - mosquitto 配置中也有选项允许您限制保留消息的数量和保留时间。
MQTT 不是这样工作的。
消息只为之前连接过的客户端排队,它是一个pub/sub系统而不是消息队列系统。
客户端需要在过去连接并订阅了相关消息的主题。然后,在将 cleanSession 标志设置为 false 并使用相同的客户端 ID 发布消息后,它需要重新连接。
您可以在 HiveMQ 博客上阅读更多相关信息 here
我的 mosquitto.conf 是(这是整个 conf 文件,因为其他所有内容都被注释掉了)
log_dest file /mosquitto/log/mosquitto.log
log_type all
connection_messages true
log_timestamp true
log_timestamp_format [%H:%M:%S]
persistence true
persistence_location /mosquitto/data/
listener 1883
listener 9001
protocol websockets
然后我运行
docker exec -it ecs-Eclipse_mosquitto_MQTT-11-Eclipse-mosquitto-MQTT-eafxxxxxxx mosquitto_pub -t presence -m hellothere -q qos=2
(注意我还没有在线的活跃订阅者)
导航到 /mosquitto/data
,确实有一个名为 mosquitto.db
所以我可以推断出我的消息 hellothere
存储在 mosquitto.db
然后我运行命令
docker exec -it ecs-Eclipse_mosquitto_MQTT-11-Eclipse-mosquitto-MQTT-eafxxxxxxx mosquitto_sub -t presence -q qos=2
我期待什么
用于 MQTT 代理发送存储的消息,因为订阅者现在在线
实际发生了什么
无限期等待消息
也许我遗漏了什么?
我认为 mqtt spec 的相关位是:
When a Server takes ownership of an incoming Application Message it MUST add it to the Session state of those clients that have matching Subscriptions.
在您的情况下,当消息发布时,没有具有匹配订阅的客户端(因为此时您还没有 运行 mosquitto_sub
),因此它什么也不做。
如果您希望为某个客户端存储消息,您必须首先作为该客户端连接并订阅相关主题(QOS>0 且 CleanSession=0)。这样做之后,客户端离线时收到的任何消息都将在重新连接时存储和传递(只要 CleanSession=0)。
注意:要使用 mosquitto_sub
执行上述操作,您需要使用 --id
参数来设置客户端 ID(消息只会为订阅了相关内容的特定客户端排队话题)。您还需要 -c
标志来禁用 'clean session' 标志。
所以步骤如下(我已经删除了额外的 docker 位 - 您可以将它们添加回去):
mosquitto_sub -c --id subscriber1 -t presence -q 2
这将订阅然后等待任何消息;您可以安全地关闭它(这是需要发生的订阅位)。接下来发布您的消息:
mosquitto_pub -t presence -m hellothere -q 2
现在您可以再次开始 mosquitto_sub
以检索存储的消息:
mosquitto_sub -c --id subscriber1 -t presence -q 2
警告:当您这样订阅时,经纪人将存储您离线时收到的任何消息。如果您正在测试处理大量消息的代理(因为存储所有消息需要 space),这可能会成为一个问题。这里可能不是问题,因为你只是在测试,但要记住一些事情...... 运行 mosquitto_sub
没有 -c
将清除任何订阅 - mosquitto 配置中也有选项允许您限制保留消息的数量和保留时间。
MQTT 不是这样工作的。
消息只为之前连接过的客户端排队,它是一个pub/sub系统而不是消息队列系统。
客户端需要在过去连接并订阅了相关消息的主题。然后,在将 cleanSession 标志设置为 false 并使用相同的客户端 ID 发布消息后,它需要重新连接。
您可以在 HiveMQ 博客上阅读更多相关信息 here