piroor
null+****@clear*****
Fri Sep 26 19:25:24 JST 2014
piroor 2014-09-26 19:25:24 +0900 (Fri, 26 Sep 2014) New Revision: 43cfd1f7d09ebc7cf0fe3950915383c813fc4094 https://github.com/droonga/wikipedia-search/wiki/Droonga%E3%83%8E%E3%83%BC%E3%83%89%E3%81%AE%E6%AD%BB%E6%B4%BB%E7%AE%A1%E7%90%86%E3%82%92Serf%E3%81%A7%E8%A1%8C%E3%81%86%E6%89%8B%E9%A0%86/43cfd1f7d09ebc7cf0fe3950915383c813fc4094 Message: Updated Droongaノードの死活管理をSerfで行う手順 (markdown) Modified files: Droongaノードの死活管理をSerfで行う手順.md Modified: Droongaノードの死活管理をSerfで行う手順.md (+228 -228) =================================================================== --- Droongaノードの死活管理をSerfで行う手順.md 2014-09-26 19:24:44 +0900 (b026ccc) +++ Droongaノードの死活管理をSerfで行う手順.md 2014-09-26 19:25:24 +0900 (49a73e0) @@ -1,229 +1,229 @@ -[[実験環境(仮想環境)の構築]]に基づいて、以下の3ノードがセットアップ済みであると仮定する。 - - * node0: 192.168.100.50 - * node1: 192.168.100.51 - * node2: 192.168.100.52 - -## Serfのインストール - -各ノード上で行う。 - - 1. [ダウンロードページ](http://www.serfdom.io/downloads.html)からバイナリを入手し、パスの通ったディレクトリに実行ファイルを設置する。 - - % wget https://dl.bintray.com/mitchellh/serf/0.5.0_linux_amd64.zip - % unzip 0.5.0_linux_amd64.zip - % sudo mv serf /usr/local/bin/ - - -## Serfの挙動について - -### Serfの起動 - - 1. 各ノードでサービスを起動する。ノード名とバインド先IPアドレスは、自分自身を指す値とする。 - ここではポート番号の指定を省略しており、Serf既定のポート`7946`が使われる。 - - (node0) - % serf agent -node=node0 -bind=192.168.100.50 \ - -event-handler=/path/to/command \ - -log-level=debug - ---- - (node1) - % serf agent -node=node1 -bind=192.168.100.51 \ - -event-handler=/path/to/command \ - -log-level=debug - ---- - (node2) - % serf agent -node=node2 -bind=192.168.100.52 \ - -event-handler=/path/to/command \ - -log-level=debug - - * この時、各ノードではイベントハンドラに以下の情報が渡される(以下はnode0の場合)。 - * $SERF_EVENT: `member-join` - * stdin: `node0 192.168.100.50` - -### クラスタへの明示的な参加 - - 1. サービスを起動したコンソールとは別のコンソールで、他のノードのIPアドレスを指定して`serf join`を実行する。 - - (node0) - % serf join 192.168.100.51 - % serf join 192.168.100.52 - ---- - (node1) - % serf join 192.168.100.50 - % serf join 192.168.100.52 - ---- - (node2) - % serf join 192.168.100.50 - % serf join 192.168.100.51 - - * join先は、クラスタを構成する自分以外のノードであれば誰でも構わない。 - (実際の運用時は、catalog.jsonからIPアドレスを収集してくることになる?) - * 複数回joinしても問題ない。 - (ただし、既にjoin済みの場合はエラーのイベントが発生するようなので、あるノードへのjoinに失敗したら次のノードにjoinを試みる、といった形でfallbackするのがよさそう。) - * この時、各ノードではイベントハンドラに以下の情報が渡される(以下はnode0の場合)。 - * $SERF_EVENT: `member-join` - * stdin: `node1 192.168.100.51\nnode2 192.168.100.52` - 2. クラスタへの参加に成功したかどうか、`serf members`コマンドで確認する。 - - % serf members - node0 192.168.100.50:7946 alive - node1 192.168.100.51:7946 alive - node2 192.168.100.52:7946 alive - -### クラスタからの明示的な離脱と再参加 - - 1. どれか1つのノード(例えばnode1)でSerfのプロセスを終了してみる。 - するとイベントが自動的にメンバーに通知されて、各メンバーが持つメンバーリストが更新される。 - * `serf leave`を実行しても、自動的にプロセスが終了する。 - * この時、クラスタに残されたノードではイベントハンドラに以下の情報が渡される(以下はnode0の場合)。 - * $SERF_EVENT: `member-leave` - * stdin: `node1 192.168.100.51` - 2. 他のノード(node0かnode2)で`serf members`してみる。 - - (node0) - % serf members - node0 192.168.100.50:7946 alive - node1 192.168.100.51:7946 left - node2 192.168.100.52:7946 alive - - leftとなっているのが、離脱中のノードである。 - 3. 離脱したノードで再度Serfを起動する。 - - (node1) - % serf agent -node=node1 -bind=192.168.100.51 \ - -event-handler=/path/to/command \ - -log-level=debug - - この時点ではまだ、このノードはクラスタに復帰していない。 - - (node0) - % serf members - node0 192.168.100.50:7946 alive - node1 192.168.100.51:7946 left - node2 192.168.100.52:7946 alive - ---- - (node1) - % serf members - node1 192.168.100.51:7946 alive - - 4. 再度クラスタに参加する。node1から他のノードへ`serf join`する。 - - (node1) - % serf join 192.168.100.50 - - * この時、クラスタに残っていたノードではイベントハンドラに以下の情報が渡される(以下はnode0の場合)。 - * $SERF_EVENT: `member-join` - * stdin: `node1 192.168.100.51` - 5. クラスタへの参加に成功したかどうか、`serf members`コマンドで確認する。 - - % serf members - node0 192.168.100.50:7946 alive - node1 192.168.100.51:7946 alive - node2 192.168.100.52:7946 alive - -### 障害によるクラスタからの離脱と再参加(すぐに再接続できるパターン) - - 1. どれか1つのノード(例えばnode1)で、serfのプロセスを強制終了してみる。 - すると、残ったノードに対してイベントが自動的に通知されて、各メンバーが持つメンバーリストが更新される。 - * この時、クラスタに残されたノードではイベントハンドラに以下の情報が渡される(以下はnode0の場合)。 - * $SERF_EVENT: `member-failed.` - * stdin: `node1 192.168.100.51` - 2. 他のノード(node0かnode2)で`serf members`してみる。 - - (node0) - % serf members - node0 192.168.100.50:7946 alive - node1 192.168.100.51:7946 failed - node2 192.168.100.52:7946 alive - - failedとなっているのが、障害発生により暗黙的に離脱中のノードである。 - 3. 離脱したノードのserfをもう一度起動する。 - * この時、クラスタに残っていたノードでは一定時間ごとのポーリングによりノードの復帰が検知され、自動的に、イベントハンドラに以下の情報が渡される(以下はnode0の場合)。 - * $SERF_EVENT: `member-join` - * stdin: `node1 192.168.100.51` - * serfを起動し直したノードでは、「自分がjoin」のイベントが発生した後、しばらく経ってから「クラスタに残っていたほか野ノードがjoin」のイベントが発生する。 - 5. クラスタへの復帰に成功したかどうか、`serf members`コマンドで確認する。 - - % serf members - node0 192.168.100.50:7946 alive - node1 192.168.100.51:7946 alive - node2 192.168.100.52:7946 alive - - -### 障害によるクラスタからの離脱と再参加(重篤な障害のパターン) - - 1. どれか1つのノード(例えばnode1)のVMをリセットしてみる。 - すると、残ったノードに対してイベントが自動的に通知されて、各メンバーが持つメンバーリストが更新される。 - * この時、クラスタに残されたノードではイベントハンドラに以下の情報が渡される(以下はnode0の場合)。 - * $SERF_EVENT: `member-failed.` - * stdin: `node1 192.168.100.51` - 2. 他のノード(node0かnode2)で`serf members`してみる。 - - (node0) - % serf members - node0 192.168.100.50:7946 alive - node1 192.168.100.51:7946 failed - node2 192.168.100.52:7946 alive - - failedとなっているのが、障害発生により暗黙的に離脱中のノードである。 - 3. 離脱したノードのVMを再開し、`serf agent`を実行してサービスを起動する。 - * この時、クラスタに残っていたノードでは一定時間ごとのポーリングによりノードの復帰が検知され、自動的に、イベントハンドラに以下の情報が渡される(以下はnode0の場合)。 - * $SERF_EVENT: `member-join` - * stdin: `node1 192.168.100.51` - * 復帰したノードの側でも、クラスタに残っていたノードからのメッセージにより`serf join`が自動的に実行される。 - 4. クラスタへの復帰に成功したかどうか、`serf members`コマンドで確認する。 - - % serf members - node0 192.168.100.50:7946 alive - node1 192.168.100.51:7946 alive - node2 192.168.100.52:7946 alive - - -### クラスタ全体への任意のメッセージの通知 - - 1. クラスタに参加中のノードからイベントを送る。 - - (node0) - % serf event "my-event" "my-data" - - * この時、クラスタに所属しているノードではイベントハンドラに以下の情報が渡される(以下はnode0の場合)。 - * $SERF_EVENT: `user` - * $SERF_USER_EVENT: `my-event` - * stdin: `my-data` - * 他のノードだけでなく、自分自身にも同時に通知される。 - -### 特定ノードへの任意のメッセージの通知 - - 1. クラスタに参加中のノードからイベントを送る。 - - (node0) - % serf query -node=node1 "my-event" "my-data" - - * この時、`-node` オプションで指定されたノードではイベントハンドラに以下の情報が渡される(以下はnode1の場合)。 - * $SERF_EVENT: `query` - * $SERF_USER_QUERY: `my-event` - * stdin: `my-data` - * 自分自身にも通知できる。 - * 関係ないノードには通知されない。 - -## Droonga Engineとの連携プラン - - * Serfのインストールと起動はChefで自動化しておくのが望ましいか? - * 誰かが作ったChef cookbookはある。 https://github.com/bbaugher/serf - * Serfのイベントハンドラとして機能するコマンドをDroonga Engineの `bin/droonga-handle-serf-event` として含める。 - このコマンドの働きは以下の通りとする。 - * `member-join`, `member-leave`, `member-failed`イベントの受信時:liveなノードのリスト(ファイル)を更新する。 - * `user`, `query`イベントの受信時:ノードの死活状態の変更に関するものであった場合、liveなノードのリスト(ファイル)を更新する。 - * ノードのリストのファイルの位置は、以下のようにしてコマンドライン引数で指定する。 - `serf agent -event-handler="droonga-handle-serf-event --list=/path/to/list-file"` - * イベントを受信した際は、内部で`serf members`を実行し、完全な情報を元にその都度完全なリストを生成することにする。 - * Serfのノード名は、Droonga Engineのボリュームの`address`の`host:port/tag.db`における`host`の部分に揃える。 - * Droonga Engineは、初期状態で、catalog.jsonに記述されているすべてのノードがliveであると想定したliveなノードのリストを持つ。 - * Droonga Engineは、メッセージを配送する必要が生じた時は、メモリ上にあるliveなノードのリストに基づいて配送先を決定する。 - * Droonga Engineは、liveなノードのリスト(ファイル)が書き換えられたことを何らかの方法で検知して、メモリ上にあるliveなノードのリストを破棄し、ファイルから最新のliveなノードのリストを読み込む。 - * Serfが起動した時点で「自分しかノードがいないクラスタに参加した」という事を意味するイベントを受信するが、それをトリガーとして、初期状態のliveなノードのリストはすぐに破棄され、自分だけが生きているという内容のliveなノードのリストがメモリ上に保持された状態となる。 - * SerfとDroonga Engineは、互いにliveなノードのリスト(ファイル)のみを通じて連携しあう。お互いがお互いのプロセスを直接起動するということはない。 - * これは、依存関係を可能な限り断ち切り、自動テストを容易に行えるようにするために、有効な方針である。 - * Droonga Engineは、[guard/listen](https://github.com/guard/listen)を使ってファイルの変更を監視する。 +[実験環境の構築手順](http://droonga.org/ja/tutorial/virtual-machines-for-experiments/)に基づいて、以下の3ノードがセットアップ済みであると仮定する。 + + * node0: 192.168.100.50 + * node1: 192.168.100.51 + * node2: 192.168.100.52 + +## Serfのインストール + +各ノード上で行う。 + + 1. [ダウンロードページ](http://www.serfdom.io/downloads.html)からバイナリを入手し、パスの通ったディレクトリに実行ファイルを設置する。 + + % wget https://dl.bintray.com/mitchellh/serf/0.5.0_linux_amd64.zip + % unzip 0.5.0_linux_amd64.zip + % sudo mv serf /usr/local/bin/ + + +## Serfの挙動について + +### Serfの起動 + + 1. 各ノードでサービスを起動する。ノード名とバインド先IPアドレスは、自分自身を指す値とする。 + ここではポート番号の指定を省略しており、Serf既定のポート`7946`が使われる。 + + (node0) + % serf agent -node=node0 -bind=192.168.100.50 \ + -event-handler=/path/to/command \ + -log-level=debug + ---- + (node1) + % serf agent -node=node1 -bind=192.168.100.51 \ + -event-handler=/path/to/command \ + -log-level=debug + ---- + (node2) + % serf agent -node=node2 -bind=192.168.100.52 \ + -event-handler=/path/to/command \ + -log-level=debug + + * この時、各ノードではイベントハンドラに以下の情報が渡される(以下はnode0の場合)。 + * $SERF_EVENT: `member-join` + * stdin: `node0 192.168.100.50` + +### クラスタへの明示的な参加 + + 1. サービスを起動したコンソールとは別のコンソールで、他のノードのIPアドレスを指定して`serf join`を実行する。 + + (node0) + % serf join 192.168.100.51 + % serf join 192.168.100.52 + ---- + (node1) + % serf join 192.168.100.50 + % serf join 192.168.100.52 + ---- + (node2) + % serf join 192.168.100.50 + % serf join 192.168.100.51 + + * join先は、クラスタを構成する自分以外のノードであれば誰でも構わない。 + (実際の運用時は、catalog.jsonからIPアドレスを収集してくることになる?) + * 複数回joinしても問題ない。 + (ただし、既にjoin済みの場合はエラーのイベントが発生するようなので、あるノードへのjoinに失敗したら次のノードにjoinを試みる、といった形でfallbackするのがよさそう。) + * この時、各ノードではイベントハンドラに以下の情報が渡される(以下はnode0の場合)。 + * $SERF_EVENT: `member-join` + * stdin: `node1 192.168.100.51\nnode2 192.168.100.52` + 2. クラスタへの参加に成功したかどうか、`serf members`コマンドで確認する。 + + % serf members + node0 192.168.100.50:7946 alive + node1 192.168.100.51:7946 alive + node2 192.168.100.52:7946 alive + +### クラスタからの明示的な離脱と再参加 + + 1. どれか1つのノード(例えばnode1)でSerfのプロセスを終了してみる。 + するとイベントが自動的にメンバーに通知されて、各メンバーが持つメンバーリストが更新される。 + * `serf leave`を実行しても、自動的にプロセスが終了する。 + * この時、クラスタに残されたノードではイベントハンドラに以下の情報が渡される(以下はnode0の場合)。 + * $SERF_EVENT: `member-leave` + * stdin: `node1 192.168.100.51` + 2. 他のノード(node0かnode2)で`serf members`してみる。 + + (node0) + % serf members + node0 192.168.100.50:7946 alive + node1 192.168.100.51:7946 left + node2 192.168.100.52:7946 alive + + leftとなっているのが、離脱中のノードである。 + 3. 離脱したノードで再度Serfを起動する。 + + (node1) + % serf agent -node=node1 -bind=192.168.100.51 \ + -event-handler=/path/to/command \ + -log-level=debug + + この時点ではまだ、このノードはクラスタに復帰していない。 + + (node0) + % serf members + node0 192.168.100.50:7946 alive + node1 192.168.100.51:7946 left + node2 192.168.100.52:7946 alive + ---- + (node1) + % serf members + node1 192.168.100.51:7946 alive + + 4. 再度クラスタに参加する。node1から他のノードへ`serf join`する。 + + (node1) + % serf join 192.168.100.50 + + * この時、クラスタに残っていたノードではイベントハンドラに以下の情報が渡される(以下はnode0の場合)。 + * $SERF_EVENT: `member-join` + * stdin: `node1 192.168.100.51` + 5. クラスタへの参加に成功したかどうか、`serf members`コマンドで確認する。 + + % serf members + node0 192.168.100.50:7946 alive + node1 192.168.100.51:7946 alive + node2 192.168.100.52:7946 alive + +### 障害によるクラスタからの離脱と再参加(すぐに再接続できるパターン) + + 1. どれか1つのノード(例えばnode1)で、serfのプロセスを強制終了してみる。 + すると、残ったノードに対してイベントが自動的に通知されて、各メンバーが持つメンバーリストが更新される。 + * この時、クラスタに残されたノードではイベントハンドラに以下の情報が渡される(以下はnode0の場合)。 + * $SERF_EVENT: `member-failed.` + * stdin: `node1 192.168.100.51` + 2. 他のノード(node0かnode2)で`serf members`してみる。 + + (node0) + % serf members + node0 192.168.100.50:7946 alive + node1 192.168.100.51:7946 failed + node2 192.168.100.52:7946 alive + + failedとなっているのが、障害発生により暗黙的に離脱中のノードである。 + 3. 離脱したノードのserfをもう一度起動する。 + * この時、クラスタに残っていたノードでは一定時間ごとのポーリングによりノードの復帰が検知され、自動的に、イベントハンドラに以下の情報が渡される(以下はnode0の場合)。 + * $SERF_EVENT: `member-join` + * stdin: `node1 192.168.100.51` + * serfを起動し直したノードでは、「自分がjoin」のイベントが発生した後、しばらく経ってから「クラスタに残っていたほか野ノードがjoin」のイベントが発生する。 + 5. クラスタへの復帰に成功したかどうか、`serf members`コマンドで確認する。 + + % serf members + node0 192.168.100.50:7946 alive + node1 192.168.100.51:7946 alive + node2 192.168.100.52:7946 alive + + +### 障害によるクラスタからの離脱と再参加(重篤な障害のパターン) + + 1. どれか1つのノード(例えばnode1)のVMをリセットしてみる。 + すると、残ったノードに対してイベントが自動的に通知されて、各メンバーが持つメンバーリストが更新される。 + * この時、クラスタに残されたノードではイベントハンドラに以下の情報が渡される(以下はnode0の場合)。 + * $SERF_EVENT: `member-failed.` + * stdin: `node1 192.168.100.51` + 2. 他のノード(node0かnode2)で`serf members`してみる。 + + (node0) + % serf members + node0 192.168.100.50:7946 alive + node1 192.168.100.51:7946 failed + node2 192.168.100.52:7946 alive + + failedとなっているのが、障害発生により暗黙的に離脱中のノードである。 + 3. 離脱したノードのVMを再開し、`serf agent`を実行してサービスを起動する。 + * この時、クラスタに残っていたノードでは一定時間ごとのポーリングによりノードの復帰が検知され、自動的に、イベントハンドラに以下の情報が渡される(以下はnode0の場合)。 + * $SERF_EVENT: `member-join` + * stdin: `node1 192.168.100.51` + * 復帰したノードの側でも、クラスタに残っていたノードからのメッセージにより`serf join`が自動的に実行される。 + 4. クラスタへの復帰に成功したかどうか、`serf members`コマンドで確認する。 + + % serf members + node0 192.168.100.50:7946 alive + node1 192.168.100.51:7946 alive + node2 192.168.100.52:7946 alive + + +### クラスタ全体への任意のメッセージの通知 + + 1. クラスタに参加中のノードからイベントを送る。 + + (node0) + % serf event "my-event" "my-data" + + * この時、クラスタに所属しているノードではイベントハンドラに以下の情報が渡される(以下はnode0の場合)。 + * $SERF_EVENT: `user` + * $SERF_USER_EVENT: `my-event` + * stdin: `my-data` + * 他のノードだけでなく、自分自身にも同時に通知される。 + +### 特定ノードへの任意のメッセージの通知 + + 1. クラスタに参加中のノードからイベントを送る。 + + (node0) + % serf query -node=node1 "my-event" "my-data" + + * この時、`-node` オプションで指定されたノードではイベントハンドラに以下の情報が渡される(以下はnode1の場合)。 + * $SERF_EVENT: `query` + * $SERF_USER_QUERY: `my-event` + * stdin: `my-data` + * 自分自身にも通知できる。 + * 関係ないノードには通知されない。 + +## Droonga Engineとの連携プラン + + * Serfのインストールと起動はChefで自動化しておくのが望ましいか? + * 誰かが作ったChef cookbookはある。 https://github.com/bbaugher/serf + * Serfのイベントハンドラとして機能するコマンドをDroonga Engineの `bin/droonga-handle-serf-event` として含める。 + このコマンドの働きは以下の通りとする。 + * `member-join`, `member-leave`, `member-failed`イベントの受信時:liveなノードのリスト(ファイル)を更新する。 + * `user`, `query`イベントの受信時:ノードの死活状態の変更に関するものであった場合、liveなノードのリスト(ファイル)を更新する。 + * ノードのリストのファイルの位置は、以下のようにしてコマンドライン引数で指定する。 + `serf agent -event-handler="droonga-handle-serf-event --list=/path/to/list-file"` + * イベントを受信した際は、内部で`serf members`を実行し、完全な情報を元にその都度完全なリストを生成することにする。 + * Serfのノード名は、Droonga Engineのボリュームの`address`の`host:port/tag.db`における`host`の部分に揃える。 + * Droonga Engineは、初期状態で、catalog.jsonに記述されているすべてのノードがliveであると想定したliveなノードのリストを持つ。 + * Droonga Engineは、メッセージを配送する必要が生じた時は、メモリ上にあるliveなノードのリストに基づいて配送先を決定する。 + * Droonga Engineは、liveなノードのリスト(ファイル)が書き換えられたことを何らかの方法で検知して、メモリ上にあるliveなノードのリストを破棄し、ファイルから最新のliveなノードのリストを読み込む。 + * Serfが起動した時点で「自分しかノードがいないクラスタに参加した」という事を意味するイベントを受信するが、それをトリガーとして、初期状態のliveなノードのリストはすぐに破棄され、自分だけが生きているという内容のliveなノードのリストがメモリ上に保持された状態となる。 + * SerfとDroonga Engineは、互いにliveなノードのリスト(ファイル)のみを通じて連携しあう。お互いがお互いのプロセスを直接起動するということはない。 + * これは、依存関係を可能な限り断ち切り、自動テストを容易に行えるようにするために、有効な方針である。 + * Droonga Engineは、[guard/listen](https://github.com/guard/listen)を使ってファイルの変更を監視する。 * guard/listenは、ファイルの変更を監視するコマンドラインツールとして知られるguardが内部的に使用しているライブラリである。 \ No newline at end of file -------------- next part -------------- HTML����������������������������... Download