Skip to content

メッセージロスのトラブルシューティング方法

メッセージロスは通常、注意深い検討と追跡が必要な2つの状況に関係しています。

EMQXでサブスクライブされていない場合のメッセージドロップ

この状況は、メッセージがすでにEMQXに到達しているものの、サブスクライバーが存在しないためにメッセージがドロップされる場合に発生します。具体的なドロップ統計は、デプロイメントコンソールの「Messages」セクション内の「Unsubscribed Message Count」で確認できます。

サブスクライブされていない場合のドロップメトリクス

これらのドロップされたメッセージを追跡するには、イベントトピック $events/message_dropped を使用できます。メッセージがドロップされるたびにイベントがトリガーされ、関連するメッセージ情報がこのイベントトピックに送信されます。これにより、メッセージドロップイベントをサードパーティのシステムに送信して記録し、後の問題調査に役立てることが可能です。

メッセージ配信中にEMQXがメッセージをドロップする場合

この状況は、メッセージがサブスクライバーに受信されているものの、さまざまな理由で正常に配信されない場合を指します。理由としては、クライアントがClean SessionをFalseに設定し長時間オフラインであったり、クライアントのメッセージ処理能力が不足していることなどが挙げられます。以下はメッセージ配信失敗を引き起こす可能性のあるシナリオです。

a. クライアントがClean SessionをFalseに設定し、長時間のオフラインによりメッセージロスが発生する場合

この場合、クライアントがオフラインでもEMQXはメッセージの送信を試みます。配信に失敗したメッセージはクライアントのメッセージキューに蓄積され、クライアントの再接続を待ちます。クライアントのオフライン期間が長すぎる(MQTT v3プロトコルではデフォルト2時間、MQTT v5プロトコルではsession_expiry_intervalの値で決定)か、クライアントがこれらのメッセージを迅速に処理できない場合、メッセージがドロップされる可能性があります。

このシナリオの対策としては、クライアントが再接続時に大量のオンライン/オフラインメッセージが蓄積されないように、Clean SessionをTrueに設定することが推奨されます。Clean SessionをFalseに設定する場合は、クライアントの長時間のダウンタイムを防ぐために自動再接続機能を実装してください。また、ランダムなクライアントIDの使用は避けてください。ランダムなクライアントIDを使用しClean SessionをFalseに設定すると、クライアント再接続時にセッションが変わり、メッセージロスが発生する可能性があります。

b. クライアントのメッセージ処理能力が不足している場合

具体的には、クライアントが複数のトピックからメッセージをサブスクライブしている場合、これらのメッセージは固定長のメッセージキュー(デフォルトは1,000)を共有します。あるトピックのメッセージが過剰に蓄積しキュー長の制限を超えると、メッセージロスが発生します。したがって、クライアント側のメッセージ処理能力不足により、一部のメッセージがサブスクライバーに正常に配信されないことがあります。

このシナリオの対策としては以下が挙げられます。

  • クライアントコードを最適化してサブスクライブのパフォーマンスを向上させる。
  • 共有サブスクリプションを試す。共有サブスクリプションの詳細は共有サブスクリプションのドキュメントをご参照ください。

関連する統計は、デプロイメントコンソールの「Metrics」内「Dropped Messages」セクションで確認できます。

メッセージキュー満杯によるドロップメトリクス

さらに、デプロイメントログでエラータイプを「Message」に選択すると、「[Session] Dropped msg due to mqueue is full: Message」などの類似レコードを検索でき、より詳細な情報を得られます。

メッセージキュー満杯によるドロップログ

c. QoS 0メッセージのストレージが無効になっている場合

クライアントがオフライン期間中にパブリッシュされたQoS 0メッセージを再接続後に受信しない場合、そのセッションが保持・再開されているかを確認してください。QoS 0メッセージは、セッションでQoS 0メッセージストレージが有効になっている場合にのみキューイングされます。

設定をサポートするデプロイメントでは、Deployment Settings -> MQTT Settings -> Session に移動し、Store QoS 0 Message を確認してください。設定の動作や制限についてはセッション設定を参照してください。配信ドロップ理由が qos0_msg の場合はセッションでQoS 0メッセージストレージが無効、queue_full はキューが満杯であることを示します。キュー長を増やしても、無効化されたQoS 0メッセージストレージによるドロップは解決しません。

これらのメッセージロスイベントを追跡するには、イベントトピック $events/delivery_dropped を使用できます。メッセージ配信に失敗するたびにイベントがトリガーされ、関連情報がこのイベントトピックに送信されます。さらに、メッセージ配信失敗イベントをサードパーティシステムに送信して記録し、後の問題調査に活用可能です。

まとめると、関連イベントをフィルタリングするために以下のSQLルールを使用できます。

sql
SELECT 
*

FROM "$events/message_dropped", "$events/delivery_dropped"

WHERE topic =~ 'xxx'

このSQLルールは、特定のトピック(例:'xxx')に関連するメッセージドロップイベントをフィルタリングし、さらなる分析や対応に役立てます。メッセージスループットが高い場合は、クライアントIDなどの追加フィルタリングフィールドを加えることを検討してください。利用可能なフィルタリングフィールドについては、イベントトピック - メッセージイベントを参照してください。