鱒身(Masu_mi)のブログ

知った事をメモする場所。

RabbitMQ設定 (クラスタリング, ミラーリング)

RabbitMQ では環境変数・設定ファイル・ランタイムパラメタとポリシーの3つの経路で設定される。 以下の2つについては設定ファイルと相性が悪い。

  • クラスタ内のノード全体で共有すべき事
  • 実行時に動的に変化しがちな内容

これらの項目をRabbitMQではパラメターと呼びrabbitmqctlコマンドやmanagement pluginのHTTP API経由で操作する

分散構成の説明

RabbitMQを複数ノードで構成したい場合がある。方法は3通りあるようで紹介されている。 クラスタリング、フェデレーション、シャベルと呼ばれる。それぞれ違いは以下の様になっている。

クラスタリング

クラスタリングの主なモチベーションは高可用性・スループットの向上。

複数のノードが論理的に単一のbrokerを構成する。 クラスタ内の各ノードはErlangのメッセージパッシングで通信しており各ノードはErlangのバージョン・RabbitMQのメジャー・マイナーバージョン(X.Y.*)の一致が要求される。

vhost, exchange, user, permissionが全台にミラーリングされるがqueueは設定しない限り単一ノードに存在する。 ただしqueueの識別子は全ノードに公開されるためクライアントはどのノードに繋いでも問題は起きない。

フェデレーション

フェデレーションの主なモチベーションは広域なマルチキャスト(インターネットをまたぐPub/Sub)・複雑なルーティング・キューサイズのバランシング。

フェデレーションでは別ブローカー上のexchangeやqueueにpublishされたメッセージを受け取れるqueueやexchangeを使えるようにする。 フェデレーションの通信ではAMQP(with optional SSL)が利用される。

シャベル

シャベルはフェデレーションと同様のインターネットをまたいだキューイングで利用される。 しかしより詳細なコントロールが必要な場合に選ばれる。単純で他ブローカーからメッセージを消費し別のブローカーに再発行する事で実現される。

クラスタリングを試してみる

クラスタリング可能な条件

ErlangCookieが統一されている

cookieの位置は下にあり中身は任意の文字列となる。 クラスタを構成するErlangノードは互いの認証のために共通のCookieを持つ必要があるので事前に準備する必要がある。 特に設定せずに起動すると自動でランダムな文字列を含むCookieが作成される。

/var/lib/rabbitmq/.erlang.cookie
${HOME}/.erlang.cookie

クラスタリングする方法

全部で4つあるrabbitmqctlコマンドで手作業、設定ファイルで定義する。 プラグインのサポートを得る方法が2つ(autocluster, clusterer)

コマンドで手作業してみる

はじめにrabbitmq-serverでサーバーを稼働させる。そのあとrabbitmqctlで設定をいじる。 同一ホストで稼働させる場合はポート番号に注意する。特にマネジメントプラグインが有効だと15672で衝突しやすい。

rabbitmq-server

はじめにrabbitmq-serverを使ってノードを立ち上げる。

$ sudo RABBITMQ_NODENAME=apple rabbitmq-server -detached
apple としてrabbitmq nodeを立ち上げる

apple としてrabbitmq nodeを立ち上げる

orange としてrabbitmq nodeを立ち上げる

orange としてrabbitmq nodeを立ち上げる

rabbitmqctl

rabbitmqctl は管理用コマンドで様々な操作を実行できる。-n オプションで実行対象のノード名を指定できる。

rabbitmqctl -n ${node_name} ${subcommand} ${attr}

クラスタ操作サブコマンド(TODOサブコマンドって用語が正しいか?)

join_cluster 対象ノードと同一のクラスタに所属する
cluster_status 現在のクラスタステータスを確認する
reset クラスタ情報を初期化する
forget_cluster_node 対象ノード情報を削除する

試してみた。

../../../_images/join_cluster_requires_stop_app.png ../../../_images/effect_of_join_clusters.png ../../../_images/forget_cluster_require_running_node.png ../../../_images/effect_of_forget_cluster.png

サブコマンドの実行条件は下の様になる。

サブコマンド 実行ノード(-nオプション) 相手ノード(サブコマンド引数)
join_cluster stop_app start_app
reset stop_app start_app
forget_cluster_node start_app stop_app

Disk or Ram

–ramオプションを使う事で対象ノード永続化をRAMにしてパフォーマンス向上を図る事が出来る。 RAMなのでDISKよりもデータの耐久性は落ちる。

$ rabbitmqctl -n ${node_name} join_cluster --ram ${target_node}

設定ファイル

クラスタリングの設定項目は以下になる。

cluster_nodes
join_clusterする対象ノード名一覧, nodeタイプ(disc, ram) のタプル
cluster_partition_handling
可用性モードの設定(ネットワーク分断時の挙動選択)
cluster_keepalive_interval
keepaliveメッセージを他ノードへ送る間隔[msec]
net_ticktime
クラスタ内で互いの存在確認のメッセージ間隔[msec]

cluster_partition_handling

詳細はClustering and Network Partitions を見ておく。 ネットワーク障害時のハンドリングを4つの選択肢から選んで可用性/一貫性の具合を決められる。

ignore
何もしない
pause_minority
少数派パーティションが停止
pause_if_all_down
指定ノードのどこにも辿り着けなくなったノードが停止 分断から回復する時の挙動にautoheal, ignore を選択できる
autoheal
ネットワーク回復時に多数派を決定しそれ以外のノードを再起動

net_ticktime

詳細はnettickに記載されている。 Erlangのkernel_app が実際には関わっているらしい。

キューをミラーリングする

Highly Available QueuesでQueueのミラーリングについて書かれている。 キューをノード間でミラーリングするにはpolicyの設定が必要になる。 policyなのでパラメータして動的に指定する。

下みたいな感じで設定する。変数名で概要, デフォルト値でサンプル値を書いたので察して欲しい。

$ sudo rabbitmqctl -n apple set_policy ${rule_name:-"mirroring_all_queueu"} ${pattern:-'^.*'} ${policy:-'{"ha-mode": "all"}' -p ${vhost:-"/"}'}