RabbitMQのトラブルシューティング:コマンドでキューとメッセージの問題を診断する

`rabbitmqctl`コマンドラインユーティリティを習得して、RabbitMQのトラブルシューティングを迅速に行いましょう。このガイドでは、過剰なキューバックログ、スタックしたメッセージ、コンシューマ接続ゼロ、誤ったエクスチェンジバインディングなどの一般的な問題を診断するための実用的で即効性のあるコマンドを提供します。UIだけに頼らずにメッセージフローを迅速に復元するための必須診断方法を学びます。

RabbitMQのトラブルシューティング:コマンドでキューとメッセージの問題を診断する

RabbitMQのキューがスタックしているように見える場合、最悪の最初の対応は通常、キューをパージすることです。2番目に悪い対応は、ブローカーを再起動して問題が解決することを願うことです。ほとんどのキューの問題には痕跡が残ります:準備完了メッセージ、未確認メッセージ、コンシューマの欠如、ブロックされたパブリッシャー、ルーティング不能なメッセージ、静かに溜まっていくデッドレターキュー、または接続されているが何も確認応答しないコンシューマなどです。

このガイドでは、RabbitMQコマンドを使用して、ターミナルから問題を絞り込みます。ブローカー側の状態を確認するにはrabbitmqctlを、メッセージの安全なサンプリングなどの管理API操作が必要な場合にはrabbitmqadminを使用します。例では、-p <vhost>オプションが示されていない限り、デフォルトの仮想ホストを想定しています。実際のシステムでは、常にvhostを含めてください。多くの誤診は、誰かが/をチェックしている間にアプリケーションがpaymentsprodを使用しているために発生します。

rabbitmqctlについて

rabbitmqctlコマンドは、RabbitMQ管理レイヤーと対話するためのコマンドラインインターフェース(CLI)として機能します。これにより、ユーザー、権限、エクスチェンジ、キュー、バインディングを管理でき、最も重要なトラブルシューティングとして、ブローカーのランタイム統計を調査できます。

実行に関する注意: ほとんどのコマンドはroot権限が必要か、コマンドを実行するユーザーがrabbitmqグループのメンバーである必要があります。またはsudoを使用する必要がある場合もあります。

キューバックログとスタックしたメッセージの診断

最も一般的な問題の1つは、キューが増大していることです。これは、メッセージが消費されるよりも速く生成されているか、コンシューマが処理を停止したことを示しています。

キューから始めるが、適切な列を要求する

デフォルトのlist_queues出力はトラブルシューティングには情報が不足しています。「配信待ち」と「配信済みだが未確認」を区別する列を要求してください。

rabbitmqctl -p / list_queues name messages_ready messages_unacknowledged messages consumers state

次のように読み取ります:

症状 考えられる意味
messages_readyが増加、consumers0 アクティブなコンシューマがキューにサブスクライブしていません。デプロイメント、認証情報、vhost、キュー名を確認してください。
messages_readyが増加、コンシューマが存在 コンシューマが遅すぎる、ブロックされている、またはプリフェッチがワークロードに対して低すぎます。
messages_unacknowledgedが高く安定 コンシューマはメッセージを受信したが、確認応答していません。スタックしたハンドラまたは高すぎるプリフェッチ値を探してください。
staterunningではない キューが利用不可、同期中、またはノードの問題の影響を受けている可能性があります。クラスターとキューのリーダー状態を確認してください。

クォーラムキューの場合は、リーダーとメンバーシップの列を追加します:

rabbitmqctl -p / list_queues name type leader members online messages_ready messages_unacknowledged consumers state

これは重要です。なぜなら、キューがあるノードに正常なコンシューマを持ちながら、リーダーが別の場所にある場合や、クォーラムキューが十分なメンバーがオンラインになるのを待っている場合があるからです。

リストが長い場合は、標準のシェルツールでフィルタリングします:

rabbitmqctl -p / list_queues name messages_ready messages_unacknowledged consumers state \
  | awk '$2 > 0 || $3 > 0 || $4 == 0'

ブローカーがパブリッシャーをブロックしているか確認する

rabbitmqctl status
rabbitmq-diagnostics alarms

メモリとディスクのアラームはキューが誤って設定されていることを意味しませんが、「何も動かない」インシデントの多くを説明します。RabbitMQがメモリまたはディスク空き容量アラームを発生させると、パブリッシング接続をブロックする可能性があります。コンシューマはメッセージを消費し続ける可能性があるため、目に見える症状は不均一になることがあります:一部のキューは縮小し、他のキューは新しい作業の受信を停止し、パブリッシャーはタイムアウトします。

また、リスナーとノードの健全性を確認します:

rabbitmq-diagnostics ping
rabbitmq-diagnostics listeners
rabbitmq-diagnostics check_running
rabbitmq-diagnostics check_local_alarms

推測せずにコンシューマを検査する

list_connectionsは誰が接続しているかを示します。list_channelsは、それらの接続がチャネルを開いたかどうか、そしてどれだけの作業を保持しているかを示します。

rabbitmqctl list_connections name user peer_host peer_port state channels recv_oct send_oct
rabbitmqctl list_channels connection name number consumer_count messages_unacknowledged prefetch_count state

有用なパターンは単純です:

  • 期待されるホストからの接続がない:アプリケーションがダウンしている、ブローカーを解決できない、認証できない、または別の環境に接続している。
  • 接続は存在するが、チャネルがない:クライアントは接続したが、宣言または消費する前に失敗した。
  • チャネルは存在するが、consumer_count0:アプリケーションは公開のみを行っているか、コンシューマのサブスクリプションが失敗した。
  • 1つのチャネルでmessages_unacknowledgedが高い:そのコンシューマはメモリ内に作業を保持しており、迅速に確認応答を返していない。

名前付き接続を使用する場合は、クライアント設定にconnection_nameを含めてください。10.42.8.17:52344 -> 10.42.1.20:5672のような行よりも、billing-worker-7の方が役立ちます。

コンシューマを非難する前にバインディングを確認する

キューが空であるにもかかわらず、アプリケーションがメッセージを公開したと言っている場合、次に確認すべきはルーティングです。

rabbitmqctl -p / list_exchanges name type durable auto_delete internal arguments
rabbitmqctl -p / list_bindings source_name source_kind destination_name destination_kind routing_key arguments

ダイレクトエクスチェンジでは、ルーティングキーが完全に一致する必要があります。トピックエクスチェンジでは、1語に*、0語以上に#を使用します。ファンアウトエクスチェンジはルーティングキーを無視します。エクスチェンジに一致するバインディングがなく、代替エクスチェンジもない場合、メッセージはルーティング不能です。どこかに密かに待機しているわけではありません。

パブリッシャー側の確認には、必須パブリッシングを使用し、クライアントで返されたメッセージを処理します。ブローカー側では、管理UIとメトリクスが通常rabbitmqctlよりもレートの確認に適していますが、list_bindingsは一般的な間違い(間違ったvhost、間違ったエクスチェンジ、ルーティングキーのスペルミス、デプロイ後に古いエクスチェンジにバインドされたキュー)をキャッチするのに十分です。

メッセージを安全にサンプリングする

現代のRabbitMQには、一般的なrabbitmqctl queue_getコマンドはありません。管理プラグインをrabbitmqadminまたはHTTP APIを通じて使用してください。注意して行ってください:確認応答モードによっては、メッセージを取得すると削除または再キューイングされる可能性があります。

rabbitmqadmin -V / get queue=orders.pending count=3 ackmode=ack_requeue_true

これを使用して、ペイロードが有効なJSONか、メッセージタイプがコンシューマの期待通りか、必要なヘッダーが欠落していないか、ルーティングキーがプロデューサーチームの言った通りかを確認するなど、限定的な質問に答えてください。ビジーな本番キューで一括検査ツールとして使用しないでください。

デッドレターの動きを確認する

遅延処理は、デッドレターキューが静かに増大していることで現れることがよくあります。

rabbitmqctl -p / list_queues name messages_ready messages_unacknowledged arguments policy
rabbitmqctl -p / list_bindings source_name destination_name routing_key arguments \
  | grep -E 'dead|dlx|retry|parking'

x-dead-letter-exchangex-dead-letter-routing-keyx-message-ttlx-max-lengthx-overflowなどのキュー引数は、メッセージが期限切れ、拒否、または長さ制限に達したときにどこに移動するかを変更します。アプリケーションが遅延キューを介してデッドレタリングによって再試行する場合、誤ったバインディングがループを引き起こす可能性があります。症状は「遅延メッセージ」のように見えますが、実際の問題は、メッセージが最終処理キューやパーキングロットキューに到達する代わりに、キュー間を循環していることです。

実用的なコマンドシーケンス

誰かが「注文がスタックしている」と報告した場合、通常は次のシーケンスを実行します:

rabbitmq-diagnostics ping
rabbitmq-diagnostics check_local_alarms
rabbitmqctl -p orders list_queues name type messages_ready messages_unacknowledged consumers state
rabbitmqctl list_connections name user peer_host state channels
rabbitmqctl list_channels connection consumer_count messages_unacknowledged prefetch_count state
rabbitmqctl -p orders list_bindings source_name destination_name routing_key arguments

messages_readyが高くconsumersがゼロの場合、コンシューマのデプロイメントを確認します。messages_unacknowledgedが高い場合、コンシューマのログとプリフェッチ設定を確認します。キューが空だがパブリッシャーが成功を報告している場合、バインディングとパブリッシャー確認を調査します。アラームがアクティブな場合、アプリケーションロジックを追う前にブローカーのリソースプレッシャーを修正します。これにより、調査はブローカーが実際に行っていることに基づいて行われます。