代理超时/客户端断开连接时Paho MQTT客户端行为

代理超时/客户端断开连接时Paho MQTT客户端行为,mqtt,paho,Mqtt,Paho,我有许多QoS2级别的消息,它们在MQTT代理或客户机出现问题时会导致场景中出现问题。这些问题包括 客户端开始看到服务器超时 客户端与代理失去连接(internet连接中断,代理出现问题等)一段时间后重新连接 通常,当MQTT客户机开始从代理接收超时或其他错误时,消息存储在持久性存储器(正在运行的消息)中,并最终重新发布 但是,如果Paho客户端失去与代理的连接,消息将不再被视为在传输中,也不会被Paho存储。在这一点上,应用程序似乎负责持久化这些MSG(在泛美卫生组织之外)并重新发布它们

我有许多QoS2级别的消息,它们在MQTT代理或客户机出现问题时会导致场景中出现问题。这些问题包括

  • 客户端开始看到服务器超时
  • 客户端与代理失去连接(internet连接中断,代理出现问题等)一段时间后重新连接
通常,当MQTT客户机开始从代理接收超时或其他错误时,消息存储在持久性存储器(正在运行的消息)中,并最终重新发布

但是,如果Paho客户端失去与代理的连接,消息将不再被视为在传输中,也不会被Paho存储。在这一点上,应用程序似乎负责持久化这些MSG(在泛美卫生组织之外)并重新发布它们

当MQTT代理变得不可用时,Paho MQTT客户机不能帮助我保证这些QoS2级别的消息将被重新传递,我这样说对吗

因此,我如何区分以下情况,其中client.publish导致了一个MqttException,其中Paho没有在飞行中持久化消息

Client is currently disconnecting (32102)
    at org.eclipse.paho.client.mqttv3.internal.ClientComms.shutdownConnection(ClientComms.java:297)
    at org.eclipse.paho.client.mqttv3.internal.CommsSender.handleRunException(CommsSender.java:154)
    at org.eclipse.paho.client.mqttv3.internal.CommsSender.run(CommsSender.java:131)
    at java.lang.Thread.run(Thread.java:745)
下面是它在飞机上持续存在的地方

Timed out waiting for a response from the server (32000)
    at org.eclipse.paho.client.mqttv3.internal.Token.waitForCompletion(Token.java:94)
    at org.eclipse.paho.client.mqttv3.MqttToken.waitForCompletion(MqttToken.java:50)
    at org.eclipse.paho.client.mqttv3.MqttClient.publish(MqttClient.java:315)
    at org.eclipse.paho.client.mqttv3.MqttClient.publish(MqttClient.java:307)
显然,我也可以开始做簿记并分别保存所有失败的消息,但随后我可能会得到QoS级别2的副本(Paho和我自己都重新发布了消息)

客户端应该如何编程

  • 是否需要基于异常代码与Paho一起执行我自己的消息持久性
  • 我是否需要考虑connectionLost回调,并假设从那时起,Paho将不会为我保留任何内容,直到MQTT客户机重新连接
  • 在发布之前,我是否需要检查客户端是否正确连接,如果正确连接,则假设Paho将保留该消息
以下是泛美卫生组织的一些例外情况和持久性行为

  • 连接丢失(32109):消息由paho保留
  • 客户端当前正在断开连接(32102):paho丢失消息
  • 等待服务器响应超时(32000):消息被持久化
  • 客户端未连接(32104):paho丢失消息

Paho的一些最佳实践是什么?

我没有设计Java客户机,但我可以看到这种行为是如何产生的,而且可能会令人困惑。我假设我们在这里讨论的是同步客户机?调用publish时会遇到所有这些异常

主要原则是:

  • 如果在要发送消息的点未连接(包括断开连接)客户端API,则不会尝试发送消息,也不会持久化消息
  • 如果客户端API当前已连接,则尝试发送消息,并在发送之前将其持久化。在QoS 2交换完成之前,连接可能会失败,在这种情况下,当客户端重新连接时,将重试消息
  • 但这两种情况都被报告为例外,这是无益的

    在C客户机中,我遵循以下规则:

  • 如果消息被持久化,则无论QoS 2交换是否完成,都将返回成功
  • 如果客户端断开连接,则调用connectionLost回调
  • 因此,您知道如果出现错误,必须重试发布调用

    对于Java客户端,我们可以通过以下方式改善这种情况:

  • 仅在消息未持久化时引发异常
  • 创建另一类异常,清楚地显示消息何时被持久化,何时未持久化,如

    • MqttException超类-消息未持久化
    • MqttIncompleteException-消息已持久化

  • 请注意,我们计划在6月份推出1.2版的“离线缓冲”,这意味着当客户端未连接时,消息可以持久化。

    可以肯定,离线缓冲至少在使用android客户端时是一个胜利。我重用了pahoandroid服务中的sqlite,该服务在不使用服务时保留消息,在客户端断开连接时保留消息,效果非常好。我不知道在考虑更广泛的平台解决方案时,哪一个将是未来的决定,当客户端断开连接时,可能只允许消息在QOS2中的文件/内存持久存储中持久化?不确定当大消息队列累积且必须发送时,这将如何影响