Table Of Contents

Previous topic

8. アプリケーションのインクルード

Next topic

10. リリース

This Page

9. 分散アプリケーション

9.1. 定義

複数のErlangのノードに分散したシステムにおいても、分散して動作しているアプリケーションを制御のできなければなりません。もし特定のアプリケーションがダウンした場合には、他のノードから再起動させてもらう必要があります。

このようなアプリケーションは、 分散アプリケーション と呼ばれます。ここでは、分散したアプリケーションの制御について述べています。例えば、他のノードのサービスを利用するという意味では、すべてのアプリケーションが分散アプリケーションです。

分散されたアプリケーションは、ノード間で移動する可能性があるため、現在実行されているノードがどれであろうと、他のアプリケーションでアドレッシングできるような仕組みが必要です。この問題はここでは触れませんが、この目的で、カーネルモジュールの global と、STDLIBモジュールの pg が使用できます。

9.2. 分散アプリケーションの記述

分散アプリケーションは、アプリケーションコントローラと、分散アプリケーションコントローラの dist_ac の両方から制御されます。どちらのプロセスも、 kernel アプリケーションの一部です。そのため、分散アプリケーションの記述は、次の設定パラメータを使用して、 kerneall アプリケーションの設定を通じて行います。(kernel(6)参照)

distributed = [{Application, [Timeout,] NodeDesc}]

.. Specifies where the application Application = atom() may execute.
   NodeDesc = [Node |    {Node,...,Node}] is a list of node names in priority
   order. The order between nodes in a tuple is undefined.

``Application = atom()`` には、実行されるアプリケーションを設定します。 ``NodeDesc = [Node | {Node,...,Node}]`` は、優先順位順のノード名のリストです。タプル内のノードの順序は未定義です。

.. Timeout = integer() specifies how many milliseconds to wait before
   restarting the application at another node. Defaults to 0.

``Timeout = integer()`` には、他のノードからアプリケーションを再起動させるまでに、何ミリ秒待つか、を設定します。デフォルトは0です。

アプリケーションの分散が適切に動作しているのであれば、分散アプリケーションが実行されているノードはお互いに連絡をとりあって、どこでアプリケーションを実行するかのネゴシエーションを行います。次のカーネル設定パラメータを使用して、これの設定を行います。

sync_nodes_mandatory = [Node]

立ち上がる必要があるノードはどれか(sync_nodes_timeout で指定されたタイムアウト時間内に)を設定します。

sync_nodes_optional = [Node]

立ち上げられてもよいノードはどれか(sync_nodes_timeout で指定されたタイムアウト時間内に)を設定します。

sync_nodes_timeout = integer() | infinity

他のノードが立ち上がるときにどのぐらい待つかの時間(ミリ秒)を設定します。

起動すると、ノードは sync_nodes_mandatorysync_nodes_optional で指定されたすべてのノードが立ち上がってくるのを待ちます。すべてのノードが立ち上がり、 sync_nodes_timeout で指定された時間が経過すると、すべてのアプリケーションが起動します。もし、すべての義務的(mandatory)なノードが立ち上がっていない場合には、ノードは終了します。

例えば、 cp1@cave というノードで myapp アプリケーションを起動しなければならないとシます。もしこのノードがダウンした場合には、 myappcp2@cave か、 cp3@cave で再起動しなければなりません。 cp1@cave のための設定ファイル cp1.config は次のようになります。

[{kernel,
  [{distributed, [{myapp, 5000, [cp1@cave, {cp2@cave, cp3@cave}]}]},
   {sync_nodes_mandatory, [cp2@cave, cp3@cave]},
   {sync_nodes_timeout, 5000}
  ]
 }
].

cp2@cave ノードと、 cp3@cave ノードの設定ファイルもほぼ同じですが、義務的な(mandatory)ノードがそれぞれ、 cp2@cave 向けが [cp1@cave, cp3@cave]cp3@cave 向けが [cp1@cave, cp2@cave] になります。

Note

すべての関連ノードの distributedsync_nodes_timeout の値は同じにしてください。異なる値が設定されている場合の動作は未定義です。

9.3. 分散アプリケーションの起動と停止

すべての(義務的な)ノードが起動したら、これらのすべてのノードで application:start(Application) を呼び出すと、分散アプリケーションを起動させることができます。

もちろん、ブートスクリプト(リリース 参照)を使うと、自動でアプリケーションを起動させることができます。

distributed 設定パラメータので定義された最初のノードでアプリケーションが起動すると、実行が始まります。アプリケーションは通常と同じようにスタートします。アプリケーションマスターが作成され、アプリケーションのコールバック関数が呼ばれます。

Module:start(normal, StartArgs)

例: 前のセクションの例の続きを説明します。システム設定ファイルで指定された3つのノードを起動します。

> erl -sname cp1 -config cp1
> erl -sname cp2 -config cp2
> erl -sname cp3 -config cp3

すべてのノードが起動されると、 myapp がスタートします。すべての3つのノードで application:start(myapp) を呼ばれます。 cp1 で起動した状態が、次の図の通りです。

../_images/situation1.png

アプリケーション myapp - 状態1

9.4. フェイルオーバー

アプリケーションを実行しているノードがダウンした場合には、指定された時間のタイムアウト後に、 distributed 設定パラメータで指定されたように、最初のノード上でアプリケーションが再起動します。これをフェイルオーバーと呼びます。

アプリケーションが新しいノード上で正常に起動する場合には、アプリケーションマスターが次のように呼びます。

Module:start(normal, StartArgs)

例外: もし、 start_phases キーが定義されたアプリケーション(アプリケーションのインクルード 参照)の場合には、次のように呼ばれます。

Module:start({failover, Node}, StartArgs)

この Node は終了したノードです。

例: もし cp1 がダウンすると、システムは他のノード(cp2cp3)のうち、起動しているアプリケーション数がもっとも少ないノードを調べます。ただし、 cp1 が再起動するまで5秒間待ちます。もし cp1 が再起動せず、 cp2 で起動しているアプリケーションが cp3 よりも少ない場合、 myappcp2 上で起動します。

../_images/situation2.png

アプリケーション myapp - 状態2

同じようにして cp2 がダウンし、5秒間待っても再起動しなければ、 myapp は、 cp3 上で再起動します。

../_images/situation3.png

アプリケーション myapp - 状態3

9.5. テイクオーバー

もしノードが起動したときに、そのノードが、現在分散アプリケーションを実行しているノードよりも distributed 設定上で高い優先順位を持っていた場合に、新しいノードでアプリケーションを起動しなおして、古いノードのアプリケーションを止めることがあります。これをテイクオーバーと呼びます。

アプリケーションは次のように、アプリケーションマスターから呼ばれます。

Module:start({takeover, Node}, StartArgs)

Node は古いノードです。

例: もし myappcp3 で起動している時に、 cp2 が再起動したとすると、 myapp の再起動は行われません。 cp2 と、 cp3 の間の優先順位が未定義だからです。

../_images/situation4.png

アプリケーション myapp - 状態4

しかし、 cp1 が再起動したとすると、このアプリケーションに関しては cp1 の方が cp3 よりも優先順位が高いため、 application:takeover/2 関数が myappcp1 に移動します。この場合、アプリケーションを cp1 で起動するために、 Module:start({takeover, cp3@cave}, StartArgs) が実行されます。

../_images/situation5.png

アプリケーション myapp - 状態5

Copyright (c) 1991-2009 Ericsson AB