第26章 クラスター化されたデプロイメントのオプション

26.1. クラスター化シングルトンサービス

クラスター化されたシングルトンサービス (HA シングルトンとも呼ばれます) はクラスター内の複数のノードにデプロイされたサービスですが、ノードの 1 つでのみサービスを提供します。 シングルトンサービスを実行するノードは通常マスターノードと呼ばれます。
マスターノードで障害が発生する前のトポロジ

図26.1 マスターノードで障害が発生する前のトポロジ

マスターで障害が発生あるいはシャットダウンすると、 残りのノードから別のマスターが選択され、 その新しいマスターでサービスが再び起動されます。 したがって、 あるマスターが停止し、 別のマスターが引き継ぐまでの短い時間を除き、 サービスは常に 1 つのノードによって提供されます。
マスターノードで障害が発生した後のトポロジ

図26.2 マスターノードで障害が発生した後のトポロジ

26.1.1. HASingleton デプロイメントオプション

JBoss Enterprise Application Platform は、 クラスター化されたシングルトンサービのデプロイメントを容易にする複数の方法をサポートします。 この項では、 さまざまな方針について説明します。 これらすべての方法は「はじめに」で説明した HAPartition サービスの上に構築されます。 また、 HAPartition を使用してクラスター内の異なるノードが起動および停止した時に通知を行います。 これらの通知に基づいて、 クラスター内の各ノードは独自に (また一貫的に) マスターノードであるかを判断し、 サービスの提供を開始するかを決定します。

26.1.1.1. HASingletonDeployer サービス

HA シングルトンをデプロイする最も単純で最も一般的に使用されている方法は、 通常のデプロイメント (war、ear、jar やその他デプロイに通常含めるもの) を利用して、 deploy の代わりに $JBOSS_HOME/server/production/deploy-hasingleton ディレクトリにデプロイすることです。deploy-hasingleton ディレクトリは deployfarm ディレクトリに含まれないため、そのコンテンツは Enterprise Application Platform インスタンスの起動時に自動的にデプロイされません。 このディレクトリのコンテンツをデプロイするのは HASingletonDeployer bean (これ自体は deploy/deploy-hasingleton-jboss-beans.xml ファイルによってデプロイされます) という特殊なサービスです。 HASingletonDeployer サービスはそれ自体が HA シングルトンであり、マスターになった時にその提供されたサービスは deploy-hasingleton のコンテンツをデプロイし、マスターでなくなったとき (通常はサーバーのシャットダウン時) にそのサービスは deploy-hasingleton のコンテンツをアンデプロイします。
したがって、デプロイメントを deploy-hasingleton に格納することにより、デプロイメントはクラスター内のマスターノードにのみデプロイされます。マスターノードが正常にシャットダウンした場合は、シャットダウンの一部としてデプロイメントが正常にデプロイ解除されます。マスターノードで障害が発生した場合やマスターノードがシャットダウンされた場合はこのデプロイメントがマスターとして引き継いだノードにデプロイされます。
deploy-hasingleton の使用は非常に簡単ですが、以下の 2 つの欠点があります。
  • deploy-hasingleton のサービスにはホットデプロイメント機能がありません。 deploy-hasingleton にデプロイされたサービスを再デプロイするにはサーバーを再起動する必要があります。
  • マスターノードで障害が発生し、 別のノードがマスターを引き継いだ場合、 シングルトンサービスはサービスを提供する前にデプロイメントプロセス全体を経る必要があります。 サービスのデプロイメントの複雑さや実行する開始アクティビティの種類によって異なりますが、 処理にしばらく時間がかかることがあります 。処理中はサービスが提供されません。

26.1.1.2. HASingletonController を使用した POJO デプロイメント

サービスが POJO である場合 (ear、war、jar などの J2EE デプロイメントでない場合) は、 HASingletonController というサービスと共にサービスをデプロイして HA シングルトンに変えることができます。 HASingletonController は HAPartition サービスと連携してクラスターを監視し、 そのサービスのマスターノードであるかどうか確認します。 マスターノードである場合は、 サービスに対してサービスの提供を開始するメソッドが呼び出されます。 マスターノードでなくなると、 サービスに対してサービスの提供を中止するメソッドが呼び出されます。 まず、 下図を見てみましょう。
最初に HA シングルトンを作成する POJO があります。 POJO は、サービスの提供を開始する時に呼び出すことができるパブリックメソッドと、 サービスの提供を停止する時に呼び出す別のメソッドを公開する必要があります。
public interface HASingletonExampleMBean
{
   boolean isMasterNode();
}
public class HASingletonExample implements HASingletonExampleMBean
{
   private boolean isMasterNode = false; 

   public boolean isMasterNode()
   {
      return isMasterNode; 
   }

   public void startSingleton()
   { 
      isMasterNode = true;
   }

   public void stopSingleton()
   {
      isMasterNode = false; 
   }
}
上図の例では、 メソッド名が startSingletonstopSingleton になっていますが、 メソッドには任意の名前を付けることができます。
次に、制御を行うHASingletonController とサービスを共にデプロイします。通常、以下の META-INF/jboss-service.xml と共に .sar ファイルにパッケージされています。
<deployment xmlns="urn:jboss:bean-deployer:2.0">
  <!-- This bean is an example of a clustered singleton -->
  <bean name="HASingletonExample" class="org.jboss.ha.examples.HASingletonExample">
    <annotation>@org.jboss.aop.microcontainer.aspects.jmx.JMX
      (name="jboss:service=HASingletonExample", 
      exposedInterface=org.jboss.ha.examples.HASingletonExampleMBean.class)</annotation>
  </bean>

  <bean name="ExampleHASingletonController" class="org.jboss.ha.singleton.HASingletonController">
    <annotation>@org.jboss.aop.microcontainer.aspects.jmx.JMX
      (name="jboss:service=ExampleHASingletonController", 
      exposedInterface=org.jboss.ha.singleton.HASingletonControllerMBean.class, 
      registerDirectly=true)</annotation>
    <property name="HAPartition"><inject bean="HAPartition"/></property>
    <property name="target"><inject bean="HASingletonExample"/></property>
    <property name="targetStartMethod">startSingleton</property>
    <property name="targetStopMethod">stopSingleton</property>
  </bean>
</deployment>
クラスター化されたシングルトンサービスです。
deploy-ha-singleton と比較したこの方法の主な利点は、 上記の例を deploy または farm に格納できるため、 ホットデプロイメントやファームデプロイメントを実行できることです。 また、 このサービス例が複雑で時間がかかる起動要件を持っている場合、 create() メソッドまたは start() メソッドで実装することが可能です。 サービスがデプロイされると、 JBoss は即座に create() と start() を呼び出します。 ノードがマスターノードになるまで待機しないため、 コントローラーが startSingleton() を実装するまで待機すれば、サービスはすぐに利用できる状態になります。
上記の例にはありませんが、 HASingletonController は目的の起動メソッドや停止メソッドに対するオプションの引数をサポートします。 引数を指定するには、 起動メソッドの場合は targetStartMethodArgument プロパティを使用し、 停止メソッドの場合は TargetStopMethodArgument プロパティを使用します。 現在、 ストリング値のみがサポートされています。

26.1.1.3. バリアを使用した HASingleton デプロイメント

deploy-hasingleton のコンテンツがデプロイまたはデプロイ解除された時に (現在のノードがマスターになった時など)起動または停止する deploy または farm 内に通常デプロイされるサービスは、 バリアーサービス の依存関係のみを指定する必要があります。
<depends>jboss.ha:service=HASingletonDeployer,type=Barrier</depends>
この仕組みは、 BarrierController が HASingletonDeployer と共にデプロイされ、 そこから JMX 通知をリッスンします。 BarrierController はシステムの JMX 通知を受信するためにサブスクライブできる比較的単純な Mbean です。 また、 受け取った通知を使用して、動的に作成された Barrier という Mbean のライフサイクルを管理します。 BarrierController がデプロイされると、 Barrier はインスタンス化されてから登録され、 CREATE ステートになります。 その後、 一致する JMX 通知を受け取るとBarrierController が Barrier を起動または終了します。 したがって、 他のサービスは通常の <depends> タグを使用して Barrier Bean に依存するだけで良いのです。 これらのサービスは Barrier と並行して開始または停止します。BarrierController がアンデプロイされると、Barrier も破棄されます。
これにより deploy-hasingleton を使用した方法とは別の方法が提供され、deploy-hasingleton のコンテンツをすべてのノードに手動でコピーする必要がありますがファーミングを使用してサービスを分散できます。
その一方でバリアー依存のサービスはすべてのノードでインスタンス化および作成されます (つまり、任意の create() メソッドが呼び出されます) が、マスターノードでのみ開始されます。これは複数のノードのいずれかに deploy-hasingleton ディレクトリのコンテンツのみをデプロイ (インスタンス化/作成/開始) する deploy-hasingleton の方法とは異なります。
したがって、バリアーに依存するサービスは create() のステップ内で必要最低限の作業を行うか、まったく作業を行わないようにし、start() を使用して作業を行うようにする必要があります。

注記

Barrier は依存するサービスの起動や停止を制御しますが、 BarrierController が破棄あるいはデプロイ解除された時のみ発生するサービスの破棄については制御しません。 そのため、サービスの通常のデプロイ解除操作として Barrier を使用し、破棄しなければならないサービスを制御しようとしても (EJBContainer など)、 思い通りには動作しません。

26.1.2. マスターノードの決定

多くのクラスター化シングルトン管理方法は、 クラスターの各ノードが独自にクラスター内の変更へ反応し、 マスターノードであるかを正しく判断することに依存しています。 実際、 どのように実現されるのでしょうか。
クラスターの各メンバーに対して、 HAPartition サービスは現在のクラスターメンバーの順序化されたリストである CurrentView という属性を保持します。 ノードがクラスターに参加し、クラスターから離れると、 JGroups によってクラスターの残りの各メンバーが更新されたビューを受け取るようにします。 現在のビューは JMX コンソールに移動し、 jboss:service=DefaultPartition MBean の CurrentView 属性を確認します。 クラスターの各メンバーは同じビューを持ち、 メンバーの順番も同じです。
たとえば、ノード A から D までの 4 つのノードクラスターを持ち、現在のビューを {A, B, C, D} と表すことができるとします。通常、ビューのノードの順序はノードがクラスタに参加した順序を反映します (ただし、常にそうなるとは限らず、該当しない場合もあります)。
また、何らかの理由で B を除くクラスターにデプロイされた Foo という名前のシングルトンサービス (HASingletonController など) があるとします。 HAPartition サービスはどのサービスがどこにデプロイされているかをビューの順序で表すレジストリをクラスター全体で保持します。 したがって、クラスター内の各ノードでは、HAPartition サービスは Foo サービスに関するビューが {A, C, D} (B はなし) であることを認識します。
Foo サービスのクラスタートポロジに変更があると、 HAPartition サービスは Foo へのコールバックを呼び出し、 新しいトポロジについて通知します。 例えば、 Foo が D で起動した時に、 A、 C、 D で実行されているすべての Foo サービスが、 Foo の新しいビューが {A, C, D} であると通知するコールバックを受け取ったとします。 この場合、コールバックにより、各ノードが独自にマスターであるかを判断できる十分な情報をノードに提供します。 「HA シングルトンの選出ポリシー」 の通り、 各ノードの Foo サービスは HAPartitionHASingletonElectionPolicy を使用してマスターであるかを判断します。
A に障害が発生あるいはシャットダウンすると、 Foo の新しいビューが {C, D} であるというコールバックを C と D の Foo が受け取ります。 この時、 C がマスターになります。 A が再起動すると、 Foo の新しいビューが {C, D, A} であるというコールバックを A、C、D が受け取りますが、 C が引き続きマスターとなります。 A が前のマスターであっても、 再度マスターになるわけではありません。

26.1.2.1. HA シングルトンの選出ポリシー

HASingletonElectionPolicy オブジェクトは、 クラスタートポロジの変更後、 HA シングルトンの代わりに利用可能なノードのリストからマスターノードを選出します。
public interface HASingletonElectionPolicy
{
   ClusterNode elect(List<ClusterNode> nodes);
}
JBoss Enterprise Application Platform には 2 つの選出ポリシーが同梱されます。
HASingletonElectionPolicySimple
このポリシーはマスターノードを相対年代で選択します。 希望の年代は、 利用可能ノードリストのインデックスに相当する position プロパティより設定します。 position = 0 はデフォルトで最も古いノードを意味し、 position = 1 は 2 番目に古いノードを意味します。 position に負の数字を使用してノードの新しさを示すこともできます 。利用可能ノードのリストは環状リストであると考えてみてください。 position = -1 は最新のノードを意味し、 position = -2 は 2 番目に新しいノードを意味します。
<bean class="org.jboss.ha.singleton.HASingletonElectionPolicySimple">
  <property name="position">-1</property>
</bean>
PreferredMasterElectionPolicy
このポリシーは、 HASingletonElectionPolicySimple を拡張し、 希望のノードを設定できるようにします。 host:port または address:port と指定された preferredMaster プロパティは、 使用できる場合にマスターとなるべきノードを特定します。 希望のノードが使用できない場合、 選出ポリシーが前述の通り動作します。
<bean class="org.jboss.ha.singleton.PreferredMasterElectionPolicy">
  <property name="preferredMaster">server1:12345</property>
</bean>