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

dde*_*ele 7 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)
Run Code Online (Sandbox Code Playgroud)

以下它确实持续存在

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)
Run Code Online (Sandbox Code Playgroud)

显然,我也可以开始记账并单独保留所有失败的消息,但随后我可能最终得到QoS等级2重复(由Paho和我自己重新发布的消息).

如何对客户进行编程?

  • 是否需要根据异常代码与Paho一起做我自己的消息持久性?
  • 我是否需要考虑connectionLost回调并假设从那时起,Paho将不会在MQTT客户端重新连接之前为我保留任何内容?
  • 在发布之前,我需要检查客户端是否正确连接,如果是这样,假设Paho将保留消息?

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

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

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

小智 6

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

主要原则是:

  1. 如果客户端API未在要发送消息的位置连接(包括断开连接),则不会尝试发送消息,并且不会保留该消息.
  2. 如果客户端API当前已连接,则尝试发送消息,并在执行此操作之前保留该消息.在QoS 2交换完成之前,连接可能会失败,在客户端重新连接时将重试该消息.

但这两种情况都被报告为例外,这是无益的.

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

  1. 如果消息持久存在,则无论QoS 2交换是否完成,都会返回成功
  2. 如果客户端断开连接,则调用connectionLost回调

所以你知道如果你收到错误,你必须重试发布调用.

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

  1. 如果消息未持久,则仅抛出异常

要么

  1. 创建另一类异常,清楚地显示消息何时存在并且不存在,例如

    • MqttException超类 - 消息未持久化
    • MqttIncompleteException - 消息被保留.

请注意,我们计划在6月份发布1.2版本的"离线缓冲",这意味着当客户端未连接时,该消息可以保留.