7

MQTT ブローカーまたはクライアントに問題がある場合、シナリオで問題を引き起こしている QoS2 レベルのメッセージが多数あります。これらの問題には、

  • クライアントがサーバーのタイムアウトを認識し始める
  • クライアントがしばらくの間ブローカーとの接続を失い (インターネット接続のダウン、ブローカーの問題など)、再接続します。

通常、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) : メッセージは永続化されています
  • クライアントが接続されていません (32104) : paho によってメッセージが失われました

ここでの Paho のベスト プラクティスにはどのようなものがありますか?

4

2 に答える 2

6

私は Java クライアントを設計したわけではありませんが、この動作がどのようにして生じたのか、また混乱を招く可能性があることは理解できます。ここで同期クライアントについて話していると思いますか? そして、発行を呼び出すときにこれらすべての例外が発生することはありますか?

主な原則は次のとおりです。

  1. メッセージが送信される時点でクライアント API が接続されていない (切断を含む) 場合、メッセージの送信は試行されず、保持されません。
  2. クライアント API が現在接続されている場合、メッセージの送信が試行され、送信前に保持されます。QoS 2 交換が完了する前に接続が失敗する可能性があり、クライアントが再接続したときにメッセージが再試行されます。

ただし、これらの状況はどちらも例外として報告されるため、役に立ちません。

C クライアントでは、次のルールに従います。

  1. メッセージが永続化されている場合、QoS 2 交換が完了したかどうかに関係なく、成功が返されます。
  2. クライアントが切断されると、connectionLost コールバックが呼び出されます。

エラーが発生した場合は、発行呼び出しを再試行する必要があることがわかります。

Java クライアントの場合、次の方法で状況を改善できます。

  1. メッセージが永続化されていない場合にのみ例外をスローします

また

  1. メッセージが永続化されたときと永続化されなかったときを明確に示す別のクラスの例外を作成します。

    • MqttException スーパークラス - メッセージが永続化されていません
    • MqttIncompleteException - メッセージが永続化されました。

6 月にリリース 1.2 の「オフライン バッファリング」を計画していることに注意してください。これは、クライアントが接続されていないときにメッセージを永続化できることを意味します。

于 2015-01-25T13:52:45.107 に答える
0

確かに、少なくとも Android クライアントを使用する場合は、オフライン バッファリングが有利になります。クライアントが切断されたときにメッセージを永続化するために、サービスが放置されているときにメッセージを永続化する paho android サービスから sqlite を再利用しました。より広範なプラットフォーム ソリューションを検討する際に、将来的にどちらが決定されるかはわかりません。クライアントが切断されたときに QOS2 のファイル/メモリ永続ストレージにメッセージを永続化できるようにするだけでよいでしょうか? 大きなメッセージ キューが蓄積され、送信する必要がある場合に、これがどのように影響するかはわかりません。

于 2015-06-20T08:01:17.557 に答える