VerneMQ 单一发布消息在客户端离线时丢失

VerneMQ single publish messages lost when client is offline

我对 MQTT 和代理很陌生,但我遇到了 VerneMQ 无法向客户端发送离线消息的问题。这是我的设置。我有一个用 Python 编写的后端,它使用 Paho Eclipse MQTT 库的 single() 方法将消息发送到连接的客户端。客户端,我开发站的一个虚拟机,有一个用go-lang写的客户端,使用paho.mqtt.golang连接到broker并订阅。

后端对 single() 的调用如下所示:

def send_message(device_id, payload):
    token = get_jwt('my_token').decode()
    mqtt.single(
       f'commands/{device_id}',
       payload=payload,
       qos=2,
       hostname=MESSAGING_HOST,
       port=8080,
       client_id='client_id',
       auth={'username': 'username', 'password': f'Bearer {token}'},
       transport='websockets'
   )

在客户端,使用以下选项建立会话:

func startListenerRun(cmd *cobra.Command, args []string) {
//mqtt.DEBUG = log.New(os.Stdout, "", 0)
mqtt.ERROR = log.New(os.Stdout, "", 0)
opts := mqtt.NewClientOptions().AddBroker(utils.GetMessagingHost()).SetClientID(utils.GetClientId())
opts.SetKeepAlive(20 * time.Second)
opts.SetDefaultPublishHandler(f)
opts.SetPingTimeout(5 * time.Second)
opts.SetCredentialsProvider(credentialsProvider)
opts.SetConnectRetry(false)
opts.SetAutoReconnect(true)
opts.willQos=2
opts.SetCleanSession(false)

我没有展示所有代码,但希望足以说明会话的设置方式。

我是 运行 VerneMQ 作为 docker 容器。我们使用以下环境变量来更改 Dockerfile 中的默认配置:

ENV DOCKER_VERNEMQ_PLUGINS.vmq_diversity on
ENV DOCKER_VERNEMQ_VMQ_DIVERSITY.myscript1.file /etc/vernemq/authentication.lua
ENV DOCKER_VERNEMQ_VMQ_ACL.acl_file /etc/vernemq/vmq.acl
ENV DOCKER_VERNEMQ_PLUGINS.vmq_acl on
ENV DOCKER_VERNEMQ_RETRY_INTERVAL=3000

只要客户端与代理有活动连接,服务器发布的消息就会无缝到达。但是,如果我手动关闭客户端与代理的​​连接,然后在后端向该客户端发布一条消息,当客户端的连接重新打开时,代理不会重新发送该消息。正如我所说,我是 MQTT 的新手,所以我可能需要配置其他选项,但到目前为止我还没有确定是哪个。任何人都可以阐明我的设置可能会导致无法发送离线消息的情况吗?感谢您提供任何信息。

正如评论中所讨论的那样

消息只会排队等待 QOS 大于 0 的离线客户端

可以找到更多详细信息here

您需要根据您的要求将 QOS 设置为 1 或 2,您也可以使用 --retain 标志,这非常有用。保留标志将确保最后一条消息将被传递,而不管任何失败。您可以知道设备的最后状态。检查这个 http://www.steves-internet-guide.com/mqtt-retained-messages-example/