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」のような類似レコードを検索でき、より詳細な情報を取得できます。

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

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

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

sql
SELECT 
*

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

WHERE topic =~ 'xxx'

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