MQTTの再配信でスマートホームのシーンが異なる順序で完了するのはなぜですか?

エヴァ・ウォン は テクニカルライター であり ZimaSpaceの常駐ティンカーでもあります。 生涯のオタクであり、 ホームラボとオープンソースソフトウェアに情熱を持っています。彼女は複雑な技術的概念をわかりやすく、 実践的なガイドに翻訳することを専門としています。エヴァはセルフホスティングは楽しくあるべきで、怖がるものではないと信じています。彼女のチュートリアルを通じて、コミュニティが ハードウェアのセットアップを解明する手助けをしています。初めてのNAS構築からDockerコンテナの習得まで。

スマートホームのシーンは、MQTTが保持する配信順序が限定的であり、再配信、並行処理、デバイスの実行によって別々のタイムラインが生じるため、異なる順序で完了することがあります。

シーンでは、Wi-Fiが中断する前に照明、ブラインド、スピーカー、サーモスタットへのコマンドを発行することがあります。再接続後、未確認のQoSメッセージが再び配信される一方で、後続のコマンドや別のトピックが異なるキューを通じて処理される場合があります。最終的に家庭内で観測される順序は、ブローカーの順序、サブスクライバーの並行処理、保持状態、重複処理、そして各デバイスの物理的な完了時間によって決まります。

MQTTがパケットの順序を保証するのは限定されたプロトコル範囲内

TCPは1つの接続上でバイト列の順序を保持し、MQTTは特定のQoSや処理中メッセージの条件下で、フローの順序どおりの処理を定義します。しかし、パブリッシャー、トピック、ブローカーのルート、サブスクライバー、デバイスコントローラーをまたぐ単一のグローバルな順序を作るわけではありません。

MQTT Receive Maximumは、MQTT 5のReceive Maximumが、確認応答されていないQoS 1およびQoS 2のパブリッシュをどのように制限するかを説明しています。ウィンドウを1に設定すると、接続上での順序どおりの処理が強化されます。一方、より大きなウィンドウではスループットが向上し、処理中の作業をより多く並行して実行できます。

したがって、複数のトピックにまたがるシーンでは、パブリッシュ呼び出しを順番に実行したというだけで普遍的な順序が保証されるわけではありません。あるサブスクライバーは逐次処理し、別のサブスクライバーはコールバックを並行して実行することがあります。また、確認応答が示すのはメッセージの転送であり、物理的な動作の完了ではありません。

再配信によって、以前のコマンドが後の状態に再び入り込む

QoS 1は少なくとも1回の配信を提供するため、未確認のPUBLISHは再接続後に重複フラグ付きで再び現れることがあります。QoS 2は受信アプリケーションに1回だけ配信するためのハンドシェイクを追加しますが、セッションの喪失やアプリケーションレベルの再試行によって、新しい論理コマンドが生成されることはあります。

少なくとも1回の配信では、QoS 0、1、2を比較し、確認応答のやり取りがスループットと配信保証のトレードオフになる仕組みを示しています。シーンにおける重要な点は、信頼性レベルがメッセージ転送を左右するのであって、デバイス操作が現在の状態に適合しているか、繰り返し安全に実行できるかを保証するものではないということです。

コマンドAが、コマンドBによってすでにデバイスの状態が変更された後に再配信されると、最終状態が後戻りする可能性があります。コマンドにはシーンID、ステップID、目標状態のバージョン、有効期限、冪等性のある適用処理を持たせ、遅れて到着した重複を新しい意図として実行するのではなく、認識できるようにする必要があります。

デバイスの完了順序はメッセージ到着順序とは別のもの

電球はすぐに確認応答を返すかもしれませんが、ブラインドの動作には20秒かかり、サーモスタットブリッジは内部で処理をキューに入れることがあります。並行するサブスクライバー、プロトコルブリッジ、スリープ中のデバイス、レート制限によって、MQTTの配信が完全に逐次化されていても、完了順序は入れ替わることがあります。

永続セッションのキューでは、クライアントがオフラインの間もブローカーがサブスクリプションとQoSの状態を保持し、メッセージをキューに入れられるようにする永続セッションについて説明しています。復旧によって継続性は向上しますが、アプリケーションが有効期限とバージョンの意味論を付与しない限り、キューに入れられた処理は古い目標状態を表す可能性があります。

問題の境界は、MQTTだけに厳密なグローバル順序を要求することです。すべてのメッセージを逐次化すればプロトコル上の順序の入れ替わりは減らせますが、物理デバイスを同期したり、古いコマンドを取り消したりすることはできません。シーンエンジンは、トランスポート層より上位で目標状態と完了条件を追跡する必要があります。

切断と再配信をまたいで1つのシーンを追跡する

1つのトピックに番号付きのコマンドをまとめたシーンをパブリッシュし、次に複数のトピックに分けてパブリッシュします。確認応答の前に切断し、異なるReceive Maximum値で再接続します。そのうえで、サブスクライバーを逐次モードと並行モードで実行し、パケットID、重複フラグ、シーンのバージョン、到着、確認応答、デバイスの完了を記録します。

スマートホームのイベント時刻で示されるイベント時刻の区別を使い、ブローカーの順序、サブスクライバーの順序、物理的な完了順序を比較します。有効期限と冪等性を追加し、遅れて到着した重複によって古い目標状態が復元されないことを確認します。この区別は、その後の家庭内テストでも確認できます。

依存関係上、本当に必要なステップに限ってグローバルな順序を要求します。独立したデバイスでは並行性を維持してシーン完了バリアを定義し、依存するステップでは、トランスポートのQoSがワークフローエンジンであると想定せず、単一の信頼できる状態機械を使用します。

テック&AIハブ

もっと読む

Get More Builds Like This

Stay in the Loop

Get updates from Zima - new products, exclusive deals, and real builds from the community.

Stay in the Loop preferences

We respect your inbox. Unsubscribe anytime.