2016-01-29 7 views
6

私が制御しようとしているIoTデバイスがあるとします(例えば、温度の読み取り値を収集する)。 MQTTが適切であると思われます。私はそれを制御するためにデバイスにメッセージを公開することができ、デバイスはブローカに温度の読み取り値を報告するメッセージを発行することができました。ここまでは順調ですね。クラウドベースのシステムを介してMQTTを介してIoTデバイスに渡されるメッセージの順序を設定する方法(API設計の問題)

デバイスを制御するAPIを設計しようとすると、問題が発生し始めます。

デバイスに2つのトピックをサブスクライブ当日ます:その後、私はこれらのメッセージをパブリッシュ

  • /デバイスID /制御/オフ
  • に/

    • /デバイスID /コントロールをいくつかの順番で話題になります。しかし、メッセージングは​​通常非同期プロセスであるため、デバイスが受信するメッセージの順序は保証されません。

      1. /デバイスID /制御/
      2. /デバイスID /コントロールON/OFF

      彼らは可能性:だから場合には2つのメッセージは、次の順序で公開されている

      を逆の順序で受信して、デバイスの電源を入れたままにしておくと、状況に応じて劇的な結果を招く可能性があります。例えばそこにただ一つのトピック

      1. /デバイスID /制御

      ことができ、個々のメッセージのペイロードを運ぶAPIは、他の方法で設計することができるもちろん

      個々のメッセージの意味(オン/オフ)。したがって、メッセージがこのトピックに所定の順序で公開される場合、メッセージはデバイス上で全く同じ順序で受信されることが期待されます。

      しかし、個々のトピックへの公開順序を保証できない場合はどうすればよいですか? IoTデバイスのためのシステムの次のアーキテクチャを考える:システムの

           /control service \ 
      application -> broker -> control service -> broker -> IoT device 
               \ control service/
      

      コンポーネントは次のとおり効果ブローカ

    • 典型的なメッセージにメッセージを発行することによって装置を制御

      • アプリケーションブローカー
      • いくつかのビジネスロジックと制御サービス

      importanほとんどの現代の分散システムと同様に、制御サービスは、一度にアプリケーションからの複数の制御メッセージを処理することができる分散型のマルチインスタンスエンティティです。したがって、アプリケーションによって発行されるメッセージの順序は、IoTデバイスに配信されるときに完全に混在する可能性があります。

      ほとんどのMQTTブローカーはQoS0とQoS1を実装していますが、QoS2を実装していないという事実を考慮すると、このような制御メッセージは複数回配信される可能性があります(QoS1 - https://stackoverflow.com/a/30959058/1776942参照)。

      私の主張は、制御メッセージのための別々のトピックは悪い考えです。単一のトピックについても同じことが言えます。どちらの場合も、メッセージ配信順序保証はありません。

      この特定の問題の唯一の解決策は、最新のバージョンプロパティを持つ別のメッセージの後に配信される古い(古い)メッセージを単にスキップできるように、メッセージのバージョン管理です。

      • 何か不足していますか?
      • この問題の唯一の解決方法はメッセージのバージョン管理ですか?

    答えて

    1

    状態が変更された場合は、新しい状態を直ちに、その後、定期的にx秒ごとに送信します。このソリューションを使用すると、一時的にネットワークから切断されても(低バッテリ)、しばらくするとシステムが希望の状態になります。

    ところで、あなたは何も見逃しませんでした。

    1

    ほとんどのブローカーがQOS2をサポートしていないというコメントは別として(おそらく、AmazonのAWS IoTサービスなど、サービス提供のブローカーがQOS2をサポートしていないと思われる)ポイント。

    メッセージの順序が本当に重要である場合は、メッセージのペイロードに何らかの形式のマーカーを挿入する必要があります。これはカウンタまたはタイムスタンプです。

    4

    何か不足していますか?

    最も確実です。あなたが育てた例は、いくつかのメッセージ指向スキームに添付されている汎用コントロールシステムです。メッセージベースのアーキテクチャを参照するときに使用できるパターンはいくつかあります。 コマンド

    • イベント

    コマンドの挙動の最も一般的なパターンは、状態を測定し、その後、コマンドを発行することです:マイクロソフトによってThis articleは、2つの主要なクラスにメッセージパターンを分類しますコマンドが実行されたことを確認するためにシステムの確認するのを忘れた場合、システムには開ループがあります。このようなオープンループは(残念ながら)忘れやすいため、ITシステムではよくあります。また、前述のようなバグやその他の悪い行為を招くことがよくあります。だから、コマンドを処理するための適切な方法は次のとおりです。

    1. コマンドを発行し、システムの状態によう
    2. に問い合わせる
    3. を評価し、次のアクション

    イベント、一方で、単に発砲されます。イベントの出版社として、誰がイベントを受け取ったか、どのような順序で受け取るかなどを心配するのは私のビジネスではありません。現在、まともなメッセージブローカー(例えば、RabbitMQ)の使用は、メッセージが最初に発行された順序で配信されることを強く保証することが一般的に指摘されるべきである。 Note that this does not mean they will be processed in order.

    したがって、コマンドをイベントとして扱うと、システムは遅かれ早かれ動作することが保証されます。

    メッセージのバージョン管理はこの問題の唯一の解決方法ですか?

    メッセージのバージョン管理は、通常、クラスの特定のインスタンスではなく、メッセージクラス自体のプロパティを参照します。メッセージベースのAPIの複数のバージョンが存在し、相互に下位互換性がある必要がある場合によく使用されます。

    代わりにあなたが指しているのは、一意のメッセージ識別子です。 Guidsは、各メッセージが固有のIDを持つことを確認するのに特に便利です。しかし、私は、メッセージベースのアーキテクチャにおける重複排除は反パターンであると主張します。メッセージングを使用することの結果の1つは、重複が可能であるため、システムの動作をステートレスにするように設計してください。idempotentこれが不可能な場合は、メッセージングが必要に応じた適切な通信ソリューションでない可能性があります。一例として、コマンド・イベントの二分法を使用して

    、次のトランザクションを実行できます。

    1. コントローラは、コマンドを発行し、コマンドに固有の識別子を割り当てます。
    2. 制御システムがコマンドを受信して​​オンになります。
    3. 制御システムは、ライトをオンにするために使用されたコマンドの一意のIDを含む「ライトオン」イベント通知を発行します。
    4. コントローラーは通知を受信し、元のコマンドに関連付けます。

    コントローラがタイムアウト後に通知を受信しない場合、コントローラはコマンドを再試行できます。 "ライトオン"は、複数の呼び出しが同じ効果を持つという点で、冪等のコマンドであることに注意してください。

    +0

    ありがとうございました。非常に面白いです、私は間違いなくそれを詳しく見ていきます。それにもかかわらず、私はこの問題にもっと価値あるアプローチがあるかどうかを確かめるために、しばらく質問を残しておきます。 –

    関連する問題