RabbitMQクラスタリング:セットアップ、設定、ベストプラクティス

RabbitMQクラスタリングで、スケーラブルで回復力のあるメッセージングの力を引き出しましょう。このガイドでは、ノードタイプ、ネットワークパーティション、データ同期などの重要な概念をカバーします。RabbitMQクラスタのセットアップ、ポリシーを使用した高可用性(HA)キューの設定、堅牢なデプロイと管理のためのベストプラクティスの実装方法をステップバイステップで学びます。フォールトトレラントなメッセージ駆動型アプリケーションを構築したい開発者や運用者に最適です。

RabbitMQクラスタリング:セットアップ、設定、ベストプラクティス

RabbitMQクラスタリングはしばしば誤解されます。クラスタは、複数のErlangノードからなる1つの論理ブローカーを提供します。ユーザー、vhost、交換機、バインディング、ポリシー、その他のメタデータをそれらのノード間で共有します。すべてのキューのメッセージがどこでも利用可能になるわけではありません。キューの可用性は、キューのタイプとそのレプリケーション設定に依存します。

その違いは本番環境で重要です。クラスタは管理とルーティングを容易にし、高可用性キューをサポートできますが、魔法のパフォーマンススイッチではありません。すべてのホットキューを1つのノードに配置すると、そのノードがすべての作業を行います。レプリケーションなしのクラシックキューを使用し、キューのリーダーノードが消失した場合、そのノードが戻るまでキューは利用できません。実際に実行するキューに基づいてクラスタを設計してください。

クラスタが共有するものとしないもの

RabbitMQクラスタのメタデータはレプリケートされます。あるノードで交換機を宣言すると、他のノードもそれを認識します。ユーザーやポリシーを追加すると、クラスタはその定義を保存します。クライアントアプリケーションは任意のノードに接続し、同じトポロジを使用できます。

メッセージは異なります。キューにはリーダーがいます。クラシックキューの場合、メッセージはそのキューをホストするノードに存在します(古いミラーリングキューを使用しない限り)。クォーラムキューの場合、RabbitMQはコンセンサスプロトコルを使用してノードグループ全体にキューデータをレプリケートします。ストリームの場合、データはストリーム設定に従ってレプリケートされます。現代のRabbitMQデプロイメントでは、クォーラムキューは通常、レプリケートされた耐久性のあるワークキューのためのより安全な選択肢です。

古い記事では「HAキュー」が現代のデフォルトであるかのように語られることがよくあります。RabbitMQの用語では、これは通常、ポリシーによって設定されたクラシックミラーリングキューを意味します。これらは一部のインストール環境にまだ存在しますが、新しい耐久性のあるレプリケートキュー設計ではクォーラムキューを検討すべき方向性です。既存のワークロードを移行する前に、常にRabbitMQのバージョンと環境の運用上の制約を確認してください。

ノードを参加させる前に行うこと

まずは退屈なチェックを先に行ってください:

  • ノードは互いのホスト名を一貫して解決できる必要があります。
  • Erlang分散ポートとRabbitMQポートはノード間で到達可能である必要があります。
  • RabbitMQとErlangのバージョンはクラスタ全体で互換性がある必要があります。
  • すべてのノードが同じErlangクッキーを共有している必要があります。
  • 時間同期は適切である必要があります(特に監視とTLSがそれに依存する場合)。

ErlangクッキーはErlangノードが使用する共有秘密です。多くのLinuxパッケージでは、/var/lib/rabbitmq/.erlang.cookieにあり、所有者はrabbitmqユーザー、モードは600です。

sudo systemctl stop rabbitmq-server
sudo install -o rabbitmq -g rabbitmq -m 600 .erlang.cookie /var/lib/rabbitmq/.erlang.cookie
sudo systemctl start rabbitmq-server

実行中のクラスタでクッキーを軽率に再生成しないでください。1つのノードが異なるクッキーを持つと、他のノードと通信できなくなり、エラーメッセージは必ずしも親切ではありません。

ノードの参加

rabbit@rmq-aがすでに実行中で、rabbit@rmq-bがそれに参加すると仮定します。rmq-bで:

sudo rabbitmqctl stop_app
sudo rabbitmqctl reset
sudo rabbitmqctl join_cluster rabbit@rmq-a
sudo rabbitmqctl start_app

その後、任意のノードから確認:

rabbitmqctl cluster_status
rabbitmq-diagnostics cluster_status

resetは参加前にローカルノードのRabbitMQデータベースを削除します。これは通常、新しい空のノードに必要な操作です。重要なキューを所有するノードで軽率に実行するものではありません。

3ノードの場合、rmq-cから同じプロセスを繰り返します。rmq-brmq-cの両方をrmq-aに参加させることができます。参加後、人々が時々想像するようなメタデータの永続的な「マスターノード」は存在しません。

クライアントを安定したエンドポイントの背後に配置する

アプリケーションは、ノードメンテナンスを想定する場合、1つのハードコードされたブローカーホストを持つべきではありません。ロードバランサー、DNS戦略、またはクライアントライブラリの接続リストを使用してください。ロードバランサーは、RabbitMQアプリケーションが実行中かどうかを確認する必要があります(ポート5672が開いているかどうかだけではありません)。

単純なTCPチェックでは、アラームでブロックされているか完全に参加していないノードにクライアントを送信する可能性があります。より厳格な環境では、管理プラグインを通じて公開されるヘルスチェック、またはrabbitmq-diagnostics -q pingを実行する小さなローカルチェックを使用してください。

キュータイプを意図的に選択する

耐久性のあるレプリケートワークロードには、クォーラムキューがしばしば良いデフォルトです:

rabbitmqadmin declare queue name=orders.pending durable=true arguments='{"x-queue-type":"quorum"}'

またはアプリケーション宣言を通じて:

channel.queue_declare(
    queue='orders.pending',
    durable=True,
    arguments={'x-queue-type': 'quorum'}
)

クォーラムキューは、より強力なレプリケーション動作と引き換えに、スループットとレイテンシの一部を犠牲にします。すべてのキューに対する無料のアップグレードではありません。一時的な応答キュー、短命なファンアウトサブスクライバー、または価値の低い一時的なワークには、クラシックキューで十分かもしれません。ノード損失に耐えなければならないビジネスイベントには、レプリケートされたキューを使用し、フェイルオーバーをテストしてください。

ネットワークパーティションは運用上のイベントであり、チェックボックスではない

ネットワークパーティションとは、クラスタノードが互いに通信できないことを意味します。RabbitMQにはパーティション処理戦略がありますが、どれも壊れたネットワークを健全なものに変えるわけではありません。適切な対応は、パーティションがまれで、可視性があり、慎重に回復されるようにクラスタを設計することです。

ほとんどの本番クラスタでは、クォーラムベースのワークロードには奇数のノードを使用し、信頼性の低いリンクをまたいで小さなクラスタを拡張しないでください。レイテンシが許容できる場合、3つのアベイラビリティゾーンにまたがる3ノードはうまく機能します。2つのサイトに分割された2ノードは、リンクが切れた場合に過半数がないため、苦しい決定の一般的な原因です。

パーティションが疑われる場合、確認:

rabbitmqctl cluster_status
rabbitmq-diagnostics alarms
rabbitmq-diagnostics check_running
rabbitmqctl list_queues name type leader members online state

キューリーダーが移動したりメンバーがオフラインになった場合、接続が回復したからといってアプリケーションが正常であると想定しないでください。パブリッシャー確認、コンシューマーエラーレート、未承認メッセージを監視してください。

クラスタの驚きを防ぐメンテナンス習慣

可能な場合は、ノードを停止する前に接続をドレインしてください。クライアントをロードバランサーの背後に配置している場合、ノードをローテーションから外し、クライアントが他の場所に再接続するのを待ってからRabbitMQを再起動してください。

定期的にキューの分布を確認:

rabbitmqctl list_queues name type leader messages consumers

すべてのホットキューのリーダーが1つのノードに集中している場合、そのワークロードに対してクラスタはバランスが取れていません。キューを再宣言するか、ポリシーを見直すか、RabbitMQのバージョンに適したキューリーダーロケーター設定を使用する必要があるかもしれません。

ポリシーをソース管理下に置いてください。キュータイプ、デッドレタリング、最大長、ミラーリング動作を変更するポリシーは、UIの微調整ではなく、本番インフラです。

バックアップは依然として重要です。クラスタリングは、定義のエクスポート、インフラ自動化、または災害復旧計画の代わりにはなりません。トポロジ変更後に定義をエクスポート:

rabbitmqadmin export rabbitmq-definitions.json

最後に、生き残れると思っている障害をテストしてください。キューリーダーを保持するノードを停止してください。未承認メッセージがある状態でコンシューマーを強制終了してください。ステージング環境でディスクアラーム中にパブリッシャーをブロックしてください。RabbitMQクラスタは、3つのノードが描かれた図ではなく、退屈なリハーサルを通じて信頼を得ます。