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

时间:2015-01-24 13:28:06

标签: mqtt paho

我有许多QoS2级别的消息,这些消息在MQTT代理或客户端出现问题时会导致问题。这些问题可以包括

  • 客户端开始查看服务器超时
  • 客户端已经失去与代理的连接(互联网连接断开,经纪人问题,......)一段时间并重新连接。

通常,当MQTT客户端开始从代理接收超时或其他错误时,该消息将存储在持久性存储中(正在进行中的消息),并最终将重新发布。

但是,如果Paho客户端失去与经纪人的连接,则不会再在飞行中考虑消息,Paho也不会存储消息。此时,似乎应用程序负责持久保存这些消息(在paho之外)并重新发布它们。

我是否正确地说,当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会保留该消息吗?

以下是Paho的一些例外和持久性行为

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

Paho有哪些最佳做法?

2 个答案:

答案 0 :(得分:6)

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

主要原则是:

  1. 如果客户端API未在发送消息的位置连接(包括断开连接),则不会尝试发送消息,并且不会保留该消息。
  2. 如果客户端API当前已连接,则尝试发送消息,并在执行此操作之前保留该消息。在QoS 2交换完成之前,连接可能会失败,在客户端重新连接时将重试该消息。
  3. 但这两种情况都被报告为例外,这是无益的。

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

    1. 如果消息持久存在,则无论QoS 2交换是否完成,都会返回成功
    2. 如果客户端断开连接,则调用connectionLost回调
    3. 所以你知道如果你收到错误,你必须重试发布电话。

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

      1. 仅在邮件未持久存在时抛出异常
        1. 创建另一类异常,清楚地显示消息何时存在且不存在,如

          • MqttException超类 - 消息未保留
          • MqttIncompleteException - 消息被保留。
        2. 请注意,我们计划在6月发布1.2版本的“离线缓冲”,这意味着当客户端未连接时,该消息可以保留。

答案 1 :(得分:0)

确保离线缓冲至少在使用Android客户端时是一个胜利。我已经重新使用了paho android服务中的sqlite,该服务在单独保留服务时保留消息,以便在客户端断开连接并保持良好的结果时保留消息。在考虑更广泛的平台解决方案时,我不知道未来的决定是什么,也许只是在客户端断开连接时允许消息在QOS2中保留在文件/内存持久存储中?不确定这会在累积大型消息队列时如何影响,必须发送。