第21章 クラスター化 JNDI サービス

JNDI はアプリケーションサーバーによって提供される最も重要なサービスの 1 つです。 JBoss HA-JNDI (高可用性 JNDI) サービスにより以下の機能が JNDI に提供されます。
  • ネーミング処理の透過的なフェイルオーバー。 HA-JNDI ネーミングコンテキストは特定の JBoss Enterprise Application Platform インスタンス上の HA-JNDI サービスに接続され、 サービスは失敗するか、 シャットダウンされます。 HA-JNDI クライアントは別の Enterprise Application Platform インスタンスに透過的にフェイルオーバーできます。
  • ネーミング処理の負荷分散。 HA-JNDI ネーミングコンテキストはクラスター内のすべての HA-JNDI サーバーで要求を自動的に負荷分散します。  
  • HA-JNDI サーバーの自動クライアント検出 (マルチキャストを使用)
  • クラスター全体の JNDI ツリーの統合ビュー。 クライアントはクラスター内の任意のノードで実行されている HA-JNDI サービスに接続し、 他のノードの JNDI でバインドされたオブジェクトを検索できます。 これは以下の 2 つのメカニズムによって実現されます。
    • クラスター間ルックアップ。 クライアントはルックアップを実行でき、 サーバー側 HA-JNDI サービスはクラスタ内のノードにある通常の JNDI でバインドされたものを検索できます。
    • 複製されたクラスター全体のコンテキストツリー。 HA-JNDI サービスにバインドされたオブジェクトは、 クラスター全体で複製され、 そのオブジェクトのコピーはクラスターの各ノードの VM で利用できます。
JNDI は、 他の多くのインターセプタベースのクラスタリングサービスに対する主要なコンポーネントです。 これらのサービスはそれ自体を JNDI に登録し、 クライアントがプロキシをルックアップしてそのサービスを使用できるようにします。 HA-JNDI はクライアントがこれらのプロキシをルックアップする高可用な方法を持つようにします。 ただし、 HA-JNDI の使用 (または非使用) はルックアップされるオブジェクトのクラスタリングの動作にまったく影響を及ぼしません。
  • EJB がクラスター対象として設定されていない場合は、 HA-JNDI を使用して EJB をルックアップしても、EJB にクラスタリング機能 (EJB 読み出しの負荷分散、 透過的なフェイルオーバー、 状態レプリケーション) が追加されません。
  • EJB がクラスター対象として設定された場合は、 HA-JNDI の代わりに通常の JNDI を使用して EJB をルックアップしても、 Bean プロキシのクラスタリング機能は削除されません。

21.1. 仕組み

JBoss のクライアント側の HA-JNDI ネーミングコンテキストは、 クライアント側のインターセプタのアーキテクチャが基になっています (はじめにとクイックスタートの章を参照)。 クライアントは HA-JNDI プロキシオブジェクトを取得し ( InitialContext オブジェクトより)、 プロキシよりリモートサーバーの JNDI ルックアップサービスを呼び出します。 クライアントは InitialContext オブジェクトによって使用されるネーミングプロパティを設定し、 HA-JNDI プロキシを要求します。 この詳細は 「クライアントの設定」 で取り上げています。 InitialContext に適切なネーミングプロパティが提供されていることを確認する必要がある以外は、 ネーミングコンテキストが HA-JNDI を使用していることはクライアントに対して透過的です。
サーバー側では、 HA-JNDI サービスはクラスター全体のコンテキストツリーの管理を行います。 クラスター全体のツリーはクラスター内にノードが 1 つ存在していれば常に使用することができます。 クラスター内の各ノードもノード自体のローカル JNDI コンテキストツリーを管理します。 各ノードの HA-JNDI サービスはローカル JNDI コンテキストツリーにバインドされたオブジェクトを検索でき、 他のノード上のローカルツリーにバインドされたオブジェクトを検索するためクラスター全体の RPC を作成することができます。 アプリケーションはオブジェクトをいずれかのツリーにバインドできますが、 実際はほとんどのオブジェクトがローカルの JNDI コンテキストツリーへバインドされます。このアーキテクチャーの設計原理は次の通りです。
  • すでに JNDI 実装がローカルであることを前提としていたので、アプリケーションに伴う移行関連の問題を回避し、設定ファイルを少し調整するだけでそのまますぐクラスタリングを機能するようにしたかったこと。
  • 同種のクラスターでは、 この構成によってネットワークトラフィック量が軽減され、同じタイプのオブジェクトが各ノードの同じ名前にバインドされること。
  • このような設計により、 基礎となるすべてのクラスターコードが新しい InitialContext を使用してバインディングをルックアップしたり作成するため、 HA-JNDI サービスは任意のサービスとなります。
サーバー側では、 new InitialContext() の呼び出しによって取得されたネーミングコンテキストがローカル専用のクラスタワイドでない JNDI コンテキストにバインドされます。 このため、 すべての EJB ホームなどはクラスター全体の JNDI コンテキストにはバインドされませんが、各ホームはローカルの JNDI にバインドされます。
リモートクライアントが HA-JNDI を使用してルックアップを行う時、 グローバルなクラスター全体のコンテキスト内にオブジェクトが見つからない場合 HA-JNDI はローカル JNDI コンテキスト委譲します。 詳細なルックアップルールは次の通りです。
  • クラスタ全体の JNDI ツリーにバインディングがある場合はそれを返します。
  • クラスター全体のツリーにバインディングがない場合、 ルックアップのクエリをローカルの JNDI サービスに委任して受信した応答があればそれを返信します。
  • 応答を受信しなかった場合、 HA-JNDI サービスはクラスター内の他すべてのノードに対しローカルの JNDI サービスがそのようなバインディングを持っているか問い合わせ、 受信するセットからの応答を返します。
  • バインディングを持つローカルの JNDI サービスがない場合、 最終的にはNameNotFoundException が発行されます。
実際には、オブジェクトはクラスター全体の JNDI ツリーにほとんどバインドされず、 ローカルの JNDI ツリーにバインドされます。 たとえば、 EJB がデプロイされた場合、 そのプロキシは常に HA-JNDI ではなくローカルの JNDI にバインドされます。 したがって、 HA-JNDI を使用して行われた EJB ホームルックアップは常にローカルの JNDI インスタンスに委任されます。

注記

異なる Bean (同じタイプでも異なるクラスタに参加している) が同じ JNDI 名を使用する場合、 各 JNDI サーバーは同じ名前の論理的に異なる「ターゲット」バインドを持つことになります (ノード 1 の JNDI は Bean A のバインディング、 ノード 2 の JNDI は同じ名前で Bean B のバインディングを持つ)。 必然的に、 クライアントがこの名前で HA-JNDI クエリを実行すると、このクエリはクラスターの任意の JNDI サーバーで呼び出され、 ローカルでバインドされたスタブを返します。しかし、 このスタブはクライアントが求めるスタブとは異なる可能性があります。 したがって、 常にクラスター全体で論理的に異なるバインディングに異なる名前を使用することがベストプラクティスとなります。

注記

クラスターの少数のノードでのみバインディングが使用できる場合 (例えば、クラスターにおける小さいサブセットのノードのみに Bean がデプロイされた場合)、 このバインディングを所有しない HA-JNDI サーバーをルックアップする可能性が高くなるため、 クラスターにあるすべてのノードにルックアップを転送する必要があります。 したがって、 ローカルでバインディングが使用できる場合よりもクエリにかかる時間が長くなります。そのため、 JNDI クエリの結果はできる限りクライアントでキャッシュするようにしてください。

注記

HA-JNDI を使用したい場合、 現在非 JNP JNDI 実装 (例:LDAP) をローカルの JNDI 実装として使用することはできません。 しかし、 ExternalContext MBean を用いる JNDI フェデレーションを使用すると、 非 JBoss INDI ツリーを JBoss JNDI の名前空間へバインドすることができます。 また、 クラスター全体やHA-JNDI やJNP のスクラップに 1 つの集中 JNDI サーバーを使用することもできます。