rabbitmqctlを使用したRabbitMQノードの状態と接続の監視方法

この記事では、`rabbitmqctl`コマンドラインユーティリティを使用してRabbitMQノードの状態とアクティブな接続を監視するための包括的なガイドを提供します。ノードの健全性を確認し、接続、チャネル、コンシューマを検査し、その出力を解釈してRabbitMQメッセージングシステムが最適かつ効率的に動作するようにするための重要なコマンドを学びます。

rabbitmqctlを使用したRabbitMQノードの状態と接続の監視方法

RabbitMQは通常、キューがバックアップしたり、コンシューマがメッセージの確認応答を停止したり、デプロイによって数百もの余分な接続が作成された後にのみ注目されます。rabbitmqctlは、ブローカーがノード内部から何を見ているかを確認する最も速い方法の1つです。Prometheus、管理UI、ログレビューに取って代わるものではありませんが、サーバー上で迅速に回答が必要な場合に、信頼性の高いコマンドラインビューを提供します。

rabbitmqctlについて

rabbitmqctlスクリプトは、RabbitMQノードと対話するための主要なコマンドラインインターフェースです。管理者は、ブローカーの起動と停止から、ユーザー、権限、交換機、キュー、そしてこの記事で重要なノードの動作状況とネットワークアクティビティの監視まで、幅広いタスクを実行できます。

RabbitMQノードの状態を確認する

接続の詳細に入る前に、RabbitMQノードが起動して実行されていることを確認することが不可欠です。statusコマンドは、ノードの現在の状態に関する包括的な概要を提供します。

rabbitmqctl statusコマンド

このコマンドは、次のような豊富な情報を出力します。

  • ノード名: RabbitMQノードの名前。
  • 実行中のアプリケーション: 実行中のErlangアプリケーションを一覧表示します。RabbitMQ自体が重要な指標です。
  • メモリ使用量: メモリの割り当てと使用量の詳細。パフォーマンスチューニングに不可欠です。
  • ディスク容量: 利用可能なディスク容量に関する情報。メッセージの永続性に影響を与える可能性があります。
  • ファイル記述子: 開いているファイル記述子の数。重要なシステムリソースです。
  • ネットワーク情報: ネットワークインターフェースとポートの詳細。
  • クラスタステータス: ノードがクラスタの一部であるかどうか、およびその接続性に関する情報。
  • リスナー: RabbitMQがさまざまなプロトコル(AMQP、管理UIなど)でリッスンしているポート。

使用例:

rabbitmqctl status

出力の解釈: リソースの枯渇(高メモリ、低ディスク容量、高ファイル記述子使用量)の兆候を探し、rabbitなどの重要なアプリケーションが実行されていることを確認します。listenersセクションは、RabbitMQが期待されるポートでアクセス可能であることを確認するために重要です。

接続、チャネル、コンシューマの監視

クライアントがRabbitMQノードとどのように対話しているかを理解することは、トラブルシューティングとパフォーマンス分析の鍵です。rabbitmqctlは、これらのエンティティを一覧表示して検査するためのコマンドを提供します。

接続の一覧表示 (rabbitmqctl list_connections)

このコマンドは、RabbitMQノードへのすべてのアクティブなクライアント接続を表示します。各接続は、正常に接続されたクライアントアプリケーション(プロデューサーまたはコンシューマ)を表します。

コマンド:

rabbitmqctl list_connections

出力列(一般的なもの):

  • pid: 接続のErlangプロセス識別子。
  • node: 接続が確立されているノード。
  • name: 接続の名前(多くの場合、クライアントプロパティを反映)。
  • port: クライアントが接続したポート。
  • host: クライアントが接続したホスト。
  • user: 認証に使用されたユーザー名。
  • vhost: 接続が関連付けられている仮想ホスト。
  • ssl: 接続がSSL/TLSを使用しているかどうかを示します。
  • protocol: 使用されるプロトコル(例:amqp0-9-1)。

例:

rabbitmqctl list_connections name host port user vhost protocol

これにより、どのユーザーがどこから接続し、どの仮想ホストを使用しているかを確認できます。

チャネルの一覧表示 (rabbitmqctl list_channels)

各接続は複数のチャネルを持つことができます。チャネルは、単一のTCP接続を介した軽量で多重化された接続であり、AMQP操作に使用されます。

コマンド:

rabbitmqctl list_channels

出力列(一般的なもの):

  • connection: 親接続のpid
  • node: チャネルがあるノード。
  • channel_pid: チャネルのErlangプロセス識別子。
  • vhost: チャネルが関連付けられている仮想ホスト。
  • name: チャネルの名前(クライアントによって設定された場合)。
  • consumer_count: このチャネルでアクティブなコンシューマの数。
  • messages_unacknowledged: このチャネル上の未確認メッセージの数。
  • messages_ready: このチャネルで配信準備ができているメッセージの数。

例:

rabbitmqctl list_channels connection vhost consumer_count messages_ready messages_unacknowledged

messages_unacknowledgedmessages_readyを監視することは、コンシューマが追いつくのに苦労している可能性のある潜在的なボトルネックを特定するために重要です。

コンシューマの一覧表示 (rabbitmqctl list_consumers)

コンシューマは、メッセージを受信して処理するためにキューにサブスクライブするプロセスです。

コマンド:

rabbitmqctl list_consumers

出力列(一般的なもの):

  • vhost: コンシューマがいる仮想ホスト。
  • queue: コンシューマが接続されているキューの名前。
  • consumer_tag: コンシューマの一意の識別子(クライアントによって設定)。
  • delivery_tag: 現在処理中のメッセージの配信タグ。
  • redelivered: メッセージが再配信されたかどうか。
  • message_count: このコンシューマに配信されるのを待っているメッセージの数。
  • ack_required: このコンシューマに配信されたメッセージに対して確認応答が必要かどうかを示します。

例:

rabbitmqctl list_consumers vhost queue consumer_tag message_count ack_required

このコマンドは、どのキューにアクティブなコンシューマがいるか、それらに配信待ちのメッセージがいくつあるか、確認応答が正しく設定されているかを理解するのに役立ちます。

特定のコンポーネントの検査(オプションの引数)

ほとんどのlist_*コマンドは、表示するフィールドを指定するための引数を受け入れ、出力をより管理しやすくします。また、grepsortなどの標準的なシェルユーティリティを使用して出力をフィルタリングおよび並べ替えることもできます。

例: 特定のユーザーからの接続を見つける:

rabbitmqctl list_connections | grep 'my_user'

例: 未確認メッセージがあるキューのみを表示する:

rabbitmqctl list_channels | awk '$4 > 0 { print }'

監視のベストプラクティス

  • 定期的なチェック: rabbitmqctl statusの定期的なチェックを実装して、問題が本番環境に影響を与える前に特定します。
  • 自動化: スクリプトを使用してこれらのチェックを自動化し、プロアクティブなアラートのために監視システム(例:Prometheus、Nagios)と統合することを検討します。
  • コンテキストが重要: 環境の典型的な値を理解します。未確認メッセージの突然の急増や新しい予期しない接続は、調査が必要です。
  • 管理UIとの組み合わせ: rabbitmqctlはスクリプト作成や直接アクセスに強力ですが、RabbitMQ管理UIは同じ情報を監視するための視覚的でインタラクティブな方法を提供します。
  • リソース監視: 完全な全体像を把握するために、rabbitmqctlの出力を常にシステムレベルのリソース監視(CPU、RAM、ディスクI/O)と関連付けます。

キューがバックアップした場合の便利なトリアージフロー

キューが増大し始めたら、RabbitMQを再起動することから始めないでください。再起動すると回復が遅くなり、必要な証拠が隠れてしまう可能性があります。まずは4つの質問に答えてください。

まず、ノードはクライアントにサービスを提供できるほど健全ですか?

rabbitmqctl status

メモリアラーム、ディスクアラーム、ファイル記述子の使用状況、リスナーを確認します。RabbitMQにはメモリとディスクの空き容量に関する安全機構があります。ノードがアラーム状態になると、パブリッシャーがブロックされる可能性があります。これは外部からはアプリケーションの問題のように見えるかもしれませんが、実際にはブローカーが自分自身を保護しています。

次に、コンシューマは接続されていますか?

rabbitmqctl list_consumers vhost queue consumer_tag ack_required active

キューにコンシューマがいない場合、キューの深さはRabbitMQのパフォーマンス問題ではありません。キューから消費するはずのアプリケーションがダウンしているか、設定が間違っているか、間違った仮想ホストに接続しているか、パブリッシャーが使用するものとは異なるキュー名から消費しています。

3番目に、コンシューマはメッセージを受信しているが確認応答していませんか?

rabbitmqctl list_queues name messages_ready messages_unacknowledged consumers

messages_readyはメッセージがキューで待機していることを意味します。messages_unacknowledgedはメッセージがコンシューマに配信されたがまだ確認応答されていないことを意味します。未確認数の多さは、多くの場合、ハンドラーの遅さ、コンシューマ内の長時間のデータベース呼び出し、プリフェッチ値が高すぎる、またはメッセージ受信後にコンシューマがクラッシュしたことを示しています。

4番目に、接続またはチャネルが多すぎませんか?

rabbitmqctl list_connections name user host state channels send_pend recv_cnt send_cnt
rabbitmqctl list_channels connection number consumer_count messages_unacknowledged prefetch_count

正常なクライアントは通常、接続を再利用し、制御された数のチャネルを開きます。すべてのリクエストが新しい接続を開くと、ブローカーは接続のチャーンに多くの時間を費やす可能性があります。単一の接続に非常に多くのチャネルがある場合は、クライアントライブラリの動作とデプロイメントサイズを調査します。

接続状態の解釈

list_connectionsは、特定の列を要求するとより便利です。インシデント発生時にスキャンしやすいコンパクトなコマンドは次のとおりです。

rabbitmqctl list_connections name user host state channels protocol ssl

state列は、通常のトラフィックと不審な動作を区別するのに役立ちます。running状態の接続はアクティブです。フロー制御またはブロック状態でスタックしている接続が多数ある場合は注意が必要です。TLSが期待される場所でsslがfalseの場合、クライアントが間違ったリスナーまたは古い設定を使用している可能性があります。

クライアント名はアプリケーションコードで設定する価値もあります。多くのRabbitMQクライアントライブラリでは、接続名を設定できます。これがないと、ホストとポートの詳細しか表示されず、負荷を引き起こしているサービスを特定するのが難しくなります。billing-worker-prod-3のような名前は、匿名のTCP接続よりもはるかに便利です。

チャネルとプリフェッチの問題

チャネルはTCP接続と比較すると安価ですが、無料ではありません。一般的な本番環境の問題は、チャネルを作成して閉じないワーカープロセスです。もう1つは、プリフェッチ値が高く、多くのメッセージを受信し、それらをゆっくり処理し、他のコンシューマをアイドル状態のままにするコンシューマです。

以下を使用します。

rabbitmqctl list_channels connection number consumer_count messages_unacknowledged prefetch_count

1つのチャネルに大量のmessages_unacknowledgedがある場合は、そのコンシューマを調査します。おそらく、低速なHTTP呼び出しを行っているか、データベースロックを待っているか、プリフェッチではるかに多くのメッセージを予約できるようにしながらメッセージを1つずつ処理しています。プリフェッチを下げると公平性が向上する可能性がありますが、魔法のようなパフォーマンス修正ではありません。ハンドラーが遅い場合は、ハンドラーを修正する必要があります。

接続チェックの隣に配置するキュー・チェック

この記事はノードの状態と接続に焦点を当てていますが、キューの状態が全体像を完成させます。

rabbitmqctl list_queues name durable auto_delete messages messages_ready messages_unacknowledged consumers memory state

永続メッセージを持つ永続キューは、ディスクに負荷をかける可能性があります。consumers0に設定されているキューは、アプリケーションのチェックが必要です。準備完了メッセージが多くアクティブなコンシューマがいるキューは、スループットの不一致を示しています。未確認メッセージが多いキューは、コンシューマ側の処理または確認応答動作を示しています。

シェルフィルターを使用する場合は、列の位置に注意してください。要求するフィールドを変更すると、古いawkスニペットが静かに間違った列をフィルタリングする可能性があります。繰り返し可能なチェックには、固定フィールドを要求し、出力にラベルを付けるスクリプトを優先します。

クラスタに関する注意事項

クラスタでは、関心のあるノードに対してコマンドを実行するか、サポートされている場合はノードを指定します。

rabbitmqctl -n rabbit@node1 status

クラスタのメンバーシップとパーティションを確認します。

rabbitmqctl cluster_status

ネットワークパーティションとノードの不一致は、混乱を招く症状を引き起こす可能性があります。クライアントは1つのノードに正常に接続する一方で、キューやメタデータは他の場所で異常です。問題が1つのアベイラビリティゾーンまたは1つのブローカーホストにのみ影響する場合は、クラスタ全体の設定を変更する前に、ノード間でstatuslist_connectionslist_queuesを比較します。

自動化すべきこと

小規模な環境では、いくつかのスクリプト化されたチェックで明らかな問題をキャッチできます。ノードダウン、ディスクアラーム、メモリアラーム、重要なキューにコンシューマがいない、準備完了メッセージが通常のしきい値を超えている、未確認メッセージが上昇し続けている、接続数がベースラインをはるかに超えているなどです。

大規模なシステムでは、RabbitMQ Prometheusプラグインまたは別のメトリクスパイプラインを使用し、rabbitmqctlは直接調査用に保持します。アラートは、ユーザーが気にする動作に関連付ける必要があります。バッチジョブ中にキューが一時的に上昇するのは正常な場合があります。コンシューマが接続されていて未確認メッセージも上昇している間にキューが15分間上昇する場合は、より良いページです。

時間を節約する運用習慣

rabbitmqctlは、正しいOSユーザーとして、またはインストールで期待されるサービスアカウントを介して実行します。権限の問題は、急いでいるときにブローカーの問題のように見えることがあります。コマンドがノードに接続できない場合は、ノード名、Erlang Cookie、およびRabbitMQサービスがそのホストで実際に実行されているかどうかを確認します。

重要なキューとその期待されるコンシューマの小さなリストを保持します。インシデント中に「キューにコンシューマがゼロ」という情報は、そのキューに常にコンシューマがいるべきかどうかを知っている場合にのみ役立ちます。一部の遅延、デッドレター、またはバッチキューは、長期間アイドル状態であることが期待されます。

最後に、ダッシュボードを緑色にするためだけにキューをクリアしないでください。メッセージが設計上使い捨て可能でない限り、キューのパージはデータ損失です。メッセージがスタックしている場合は、まずそれらが待機中、未確認、拒否、デッドレター、または欠落しているコンシューマによってブロックされているかどうかを確認します。

rabbitmqctl statuslist_connectionslist_channelslist_consumerslist_queuesは、「メッセージが遅延している」から考えられる原因への実用的なコマンドラインパスを提供します。コツはそれらを一緒に読むことです。ノードリソース、クライアント接続、チャネル動作、コンシューマの存在、キューの深さはすべて、同じストーリーの異なる部分を伝えています。