web-dev-qa-db-ja.com

ネットワーク障害後にRabbitMQクラスターが再接続されない

本番環境に2つのノードがあるRabbitMQクラスターがあり、クラスターが次のエラーメッセージで壊れています。

=エラーレポート==== 2011年12月23日:: 04:21:34 ===
** Node rabbit @ rabbitmq02が応答しません**
**(タイムアウト)接続の削除**

=情報レポート==== 2011年12月23日:: 04:21:35 ===
ノードrabbit @ rabbitmq02が「rabbit」を失った

=エラーレポート==== 2011年12月23日:: 04:21:49 ===
Mnesia(rabbit @ rabbitmq01):**エラー** mnesia_eventが{inconsistent_database、running_partitioned_network、rabbit @ rabbitmq02}を取得しました

「tcpkill」を使用して2つのノード間の接続を切断することで問題をシミュレートしようとしましたが、クラスターが切断されました。驚くべきことに、2つのノードは再接続を試みていません。

クラスターが壊れた場合でも、haproxyロードバランサーは両方のノードをアクティブとしてマークし、クラスター内にない場合でも両方にリクエストを送信します。

私の質問:

  1. ノードがクラスターとして機能するように構成されている場合、ネットワーク障害が発生したときに、ノードが再接続を試みないのはなぜですか?

  2. 壊れたクラスターを特定し、ノードの1つをシャットダウンするにはどうすればよいですか? 2つのノードを別々に操作すると、一貫性の問題が発生します。

14
Ranch

この種の障害から回復するもう1つの方法は、RabbitMQが永続化メカニズムとして使用するデータベースであるMnesiaを使用することです。これにより、RabbitMQインスタンス(およびマスター/スレーブステータス)の同期が制御されます。詳細については、次のURLを参照してください。 http://www.erlang.org/doc/apps/mnesia/Mnesia_chap7.html

ここに関連するセクションを追加します。

Mnesiaが、通信障害のためにネットワークが分割されていることを検出する場合がいくつかあります。

1つは、Mnesiaがすでに稼働していて、Erlangノードが再び接続を取得したときです。次に、Mnesiaは他のノードのMnesiaに接続して、ネットワークがしばらくの間パーティション化されていると考えているかどうかを確認します。両方のノードのMnesiaが相互にmnesia_downエントリをログに記録している場合、Mnesiaは{inconsistent_database、running_partitioned_network、Node}というシステムイベントを生成し、Mnesiaのイベントハンドラーおよびその他の可能なサブスクライバーに送信します。デフォルトのイベントハンドラーは、エラーロガーにエラーを報告します。

Mnesiaが通信障害のためにネットワークが分割されたことを検出する可能性がある別の機会は、起動時です。 Mnesiaは、ローカルノードと別のノードの両方が相互にmnesia_downを受信したことを検出すると、{inconsistent_database、starting_partitioned_network、Node}システムイベントを生成し、上記のように動作します。

アプリケーションは、データベースの不整合を引き起こした可能性のある通信障害が発生したことを検出した場合、関数mnesia:set_master_nodes(Tab、Nodes)を使用して、各テーブルがロードされる可能性のあるノードを特定できます。

起動時に、Mnesiaの通常のテーブルロードアルゴリズムがバイパスされ、ログ内の潜在的なmnesia_downエントリに関係なく、テーブルに定義されたマスターノードの1つからテーブルがロードされます。ノードには、テーブルにレプリカがあるノードのみを含めることができ、テーブルが空の場合、特定のテーブルのマスターノード回復メカニズムがリセットされ、次回の再起動時に通常のロードメカニズムが使用されます。

関数mnesia:set_master_nodes(Nodes)は、すべてのテーブルのマスターノードを設定します。テーブルごとに、レプリカノードを決定し、ノードリストに含まれているレプリカノードを使用してmnesia:set_master_nodes(Tab、TabNodes)を呼び出します(つまり、TabNodesはノードとテーブルのレプリカノードの共通部分です)。交差点が空の場合、特定のテーブルのマスターノード回復メカニズムがリセットされ、次回の再起動時に通常のロードメカニズムが使用されます。

関数mnesia:system_info(master_node_tables)およびmnesia:table_info(Tab、master_nodes)を使用して、潜在的なマスターノードに関する情報を取得できます。

通信障害後に保持するデータを決定することは、Mnesiaの範囲外です。 1つのアプローチは、どの「島」にノードの過半数が含まれているかを判別することです。重要なテーブルに{majority、true}オプションを使用すると、「マジョリティアイランド」の一部ではないノードがそれらのテーブルを更新できないようにすることができます。これは、マイノリティノードでのサービスの低下を構成することに注意してください。これは、より高い一貫性の保証を支持するトレードオフになります。

関数mnesia:force_load_table(Tab)を使用すると、アクティブ化されているテーブルロードメカニズムに関係なく、テーブルを強制的にロードできます。

これは、このような障害から回復するためのより長く複雑な方法です..ただし、最終的なマスターノードで使用できるデータの粒度と制御が向上します(これにより、データの量を減らすことができますRabbitMQマスターを「マージ」するときに発生する可能性のある損失)

RabbitMQクラスターは、信頼性の低いネットワークではうまく機能しません(RabbitMQドキュメントの一部)。したがって、(2ノードクラスターで)ネットワーク障害が発生すると、各ノードはそれがマスターであり、クラスター内の唯一のノードであると見なします。 2つのマスターノードは、状態が自動的に同期されないため、自動的に再接続しません(RabbitMQスレーブの場合でも-実際のメッセージ同期は行われません-メッセージがキューから消費され、メッセージが増えると、スレーブは「追いつく」だけです追加されます)。

壊れたクラスターがあるかどうかを検出するには、次のコマンドを実行します。

rabbitmqctl cluster_status

クラスターの一部を形成する各ノードで。クラスターが壊れている場合は、ノードが1つだけ表示されます。何かのようなもの:

Cluster status of node rabbit@rabbitmq1 ...
[{nodes,[{disc,[rabbit@rabbitmq1]}]},{running_nodes,[rabbit@rabbitmq1]}]
...done.

このような場合、元のクラスターの一部を形成したノードの1つで次の一連のコマンドを実行する必要があります(クラスター内の他のマスターノード(rabbitmq1など)にスレーブとして参加するため)。

rabbitmqctl stop_app

rabbitmqctl reset

rabbitmqctl join_cluster rabbit@rabbitmq1

rabbitmqctl start_app

最後に、クラスターのステータスをもう一度確認します。今回は、両方のノードが表示されます。

注:仮想IPを使用してHA構成にRabbitMQノードがある場合(およびクライアントがこの仮想IPを使用してRabbitMQに接続している場合)、マスターにする必要があるノードは、仮想IPを持つノードである必要があります。

14

RabbitMQは、ネットワークパーティションを自動的に処理する2つの方法も提供します。pause-minorityモードとautohealモードです。 (デフォルトの動作は無視モードと呼ばれます)。

マイノリティ一時停止モードでは、RabbitMQは、他のノードがダウンしたことを確認した後、マイノリティ(つまり、ノードの総数の半分以下)にあると判断したクラスターノードを自動的に一時停止します。したがって、CAP定理から可用性よりもパーティションの許容範囲を選択します。これにより、ネットワークパーティションが発生した場合でも、1つのパーティション内の最大でノードが引き続き実行されます。

自動修復モードでは、パーティションが発生したと見なされた場合、RabbitMQは勝者のパーティションを自動的に決定します。勝者のパーティションにないすべてのノードを再起動します。勝者のパーティションは、最も多くのクライアントが接続されているパーティションを自動的に処理するパーティションです(または、これが引き分けを生成する場合は、最も多くのノードを持つパーティションです。それでもドローが発生する場合は、パーティションの1つが不特定の方法で選択されます)。

構成ファイル内のrabbitアプリケーションの構成パラメーターcluster_partition_handlingpause_minorityまたはautohealに設定することにより、どちらのモードも有効にできます。

どのモードを選ぶべきですか?

RabbitMQがネットワークパーティションを自動的に処理できるようにしても、問題が少なくなるわけではないことを理解することが重要です。ネットワークパーティションは常にRabbitMQクラスターに問題を引き起こします。どのような問題が発生するかについては、ある程度の選択が必要です。はじめに述べたように、一般的に信頼性の低いリンクを介してRabbitMQクラスターを接続する場合は、 federationプラグインまたはshovelプラグイン を使用する必要があります。

そうは言っても、次のようにリカバリモードを選択することをお勧めします。

  • ignore:あなたのネットワークは本当に信頼できます。すべてのノードはラック内にあり、スイッチで接続されており、そのスイッチは外界へのルートでもあります。他の部分に障害が発生した場合(または2ノードクラスターがある場合)にクラスターがシャットダウンするリスクを冒したくありません。

  • pause_minority:ネットワークの信頼性が低い可能性があります。 EC2の3つのAZにまたがってクラスター化し、一度に1つのAZのみが失敗すると想定します。そのシナリオでは、残りの2つのAZが引き続き機能し、障害が発生したAZのノードが、AZが戻ってきたときに大騒ぎせずに自動的に再結合するようにします。

  • autoheal:ネットワークが信頼できない可能性があります。データの整合性よりもサービスの継続性に関心があります。 2ノードのクラスターがある場合があります。

この回答は、rabbitmqドキュメントからの参照です。 https://www.rabbitmq.com/partitions.html より詳細な説明が表示されます。

9
NewPtone