WebSphere Application Server V6.1 での EJB 呼び出しの動作を理解する

多くのアプリケーションで、IBM® WebSphere® Application Server の EJB (Enterprise JavaBeans™) コンテナーにデプロイされた EJB が使われています。これらの EJB コンポーネントと通信するためには、IIOP (Internet Inter-ORB Protocol) 通信や JNDI ルックアップ、ワークロード管理などの概念を使う必要があります。このやり取りは複雑であり、多くの WebSphere ユーザーにとってはブラックボックスであることが多いものです。この記事では、WebSphere Application Server のコンテキストで EJB の通信がどのように行われるか、その基本部分を説明します。また、ORB (Object Request Broker) に対する送受信を取り上げると同時に、WebSphere Application Server の EJB コンテナーにデプロイされた EJB コンポーネントを呼び出す際に関係する基本的な呼び出しパターンとコンポーネントの定義についても説明します。この記事を読む前提として、J2EE™ の基本を理解していること、また WebSphere Application Server の管理に関する一般的な知識が必要です。

John Pape, WebSphere Application Server SWAT Team, IBM

Author photoJohn Pape は現在 WebSphere SWAT Team に所属し、WebSphere Application Server と WebSphere Portal Server、そして WebSphere Extended Deployment を利用するユーザーのための CRITSIT サポートを担当しています。この業務には細部に注目する能力と、たえず枠にとらわれない斬新な発想をすることが求められ、それによって可能な限り最高のサポートを IBM のユーザーに保証しています。


developerWorks 貢献著者レベル

Dr. Mahesh Rathi, WebSphere Application Server SWAT Team, IBM

Mahesh Rathi 博士は WebSphere Application Server 製品が始まった時からこの製品を扱っています。彼はセキュリティー開発チームのリーダーをした後 L2 Support チームに加わり、2005年に SWAT チームに加わりました。彼は厳しい要求をするユーザーが直面している問題に対処することを心の底から楽しんでおり、また重圧をものともしません。彼は Purdue University でコンピューター・サイエンスの博士号を取得しており、IBM に入社する前には Wichita State University でソフトウェア・エンジニアリングを教えていました。



2008年 7月 30日

はじめに

多くの WebSphere ユーザーにとって、EJB の通信はブラックボックスです。つまり私達は、メソッド「X」を呼び出すと EJB のビジネス・ロジックから所望の結果が返される、と理解しています。正常な動作条件の下では、通常は ORB (Object Request Broker) の内部動作を理解する必要がないため、こうした理解で十分かもしれません。しかしパフォーマンスの問題やロード・バランシングの問題が発生した場合には、ORB を詳しく理解していると、問題判別作業の効率を大幅に高められ、問題解決に要する時間も大幅に短縮することができます。また、すべての WebSphere コンポーネントの場合と同様に、ORB を操作するためのメカニズムやそれに関連する通信プロトコルを理解しておくことで、トラブルシューティングを行う際に高度な専門知識を活かせるようになります。


ORB

ORB は、オブジェクト指向の分散アプリケーションにおいて、リモート・オブジェクトをローカル・オブジェクトと同じように使えるようにすることを目的とした技術であり、CORBA (Common Object Request Broker Architecture) の中心を成すものです。ORB を使うと、分散アプリケーションでオブジェクトを実装するために使われている特定のプラットフォームや手法、言語にかかわらず、これらのオブジェクト同士を通信させることができます。

CORBA はオープンでベンダーに依存しない、分散コンピューティングのための仕様であり、オープンで標準化されたインターフェースを推進するために 600 社を超えるソフトウェア・ベンダーなどの会社で構成されているコンソーシアム、OMG (Object Management Group) によって作成されたものです。CORBA と CORBA の IDL (Interface Definition Language) はオブジェクトを表現するための共通のフォーマットであり、これらのオブジェクトが Java™、C、C++ その他の言語で作成され、さまざまなオペレーティング・システムやマシンで実行されるアプリケーションに配布されます。

ORB は、アプリケーション・サーバーのランタイムに欠かせないものであり、JVM (Java Virtual Machine) の一部として実装されます。IBM WebSphere Application Server には ORB インスタンスを扱うために追加できるコード (通常は拡張 ORB と呼ばれます) が含まれており、またオブジェクト・サービス (セキュリティーなど) のためのプラグイン・フレームワークが提供されています。この IBM による ORB の実装は Sun™ の ORB とは同じではなく、コード・ベースがまったく異なります。IBM による ORB 実装のコード・ベースとなっているのは、EJB コンテナーが Java RMI (Remote Method Invocation) による対話動作の通信を仲介する際のベースとなるコードです。

RMI は Java でリモート通信を行うために従来からある方法であり、標準化されていない JRMP (Java Remote Method Protocol) というプロトコルを使って Java オブジェクト間の通信を行います。最も基本的なレベルでは、RMI は Java のオブジェクト指向版の RPC (Remote Procedure Call) にすぎません。WebSphere Application Server は ORB を使ってクライアント・サーバー間の RMI 通信を実現し、またコンポーネント間の通信を行っています。

ORB は、EJB コンポーネントなどのリモート Java オブジェクトに対するインバウンド・リクエストとアウトバウンド・リクエストを処理します。ORB はクライアントがサーバー上の EJB を見つけるための、また EJB がローカルにあるかのように EJB の操作を呼び出すための仕組みです。(この概念はローカルとリモートの透過性と呼ばれます。) ORB と EJB コンテナーとの関係は、図 1 のように表すことができます。

図 1. ORB と EJB コンテナー
ORB と EJB コンテナー

ORB 間の通信

ORB 間の通信は、GIOP (General Inter-ORB Protocol) 抽象リファレンス仕様を具体的に実装した IIOP (Internet Inter-ORB Protocol) によって実現されます。IOR (Interoperable Object Reference) は CORBA または RMI-IIOP のオブジェクト参照を ORB が理解できるフォーマットでストリングとして表現したものにすぎません。IOR は日常的なコーディングの中で使われる通常の Java オブジェクト参照と考えることができます。IIOP によって GIOP が TCP/IP 通信スタックにマッピングされます。

GIOP プロトコルはいくつか異なるタイプのメッセージを規定しています。例えば request、reply、locate request、locate reply、そして fragment などがあります。request メッセージと reply メッセージは自明であり、クライアント・アプリケーションとサーバー・アプリケーションの間でのリクエストとレスポンスのやり取りを処理します。locate request と fragment というメッセージ・タイプは、以下の用途で使われますが、問題を解決するために GIOP の仕様全体を詳しく読む必要があった人以外にはなじみがないかもしれません。

locate request メッセージ・タイプは、要求されたリモート・オブジェクトを ORB が理解しているかどうか、またそのオブジェクトを格納しているかどうかを検証するために使われます。locate request メッセージの中で要求されたオブジェクトを ORB が理解できない場合、その ORB は、クライアントがその要求されたオブジェクトをどこで見つければよいかに関する詳細 (例えば、そのオブジェクトを実際に格納しているサーバーを指す OBJECT_FORWARD など) を提供しようと試みます。

  • fragment メッセージは、その前にその ORB に送信されたメッセージの続きです。
  • 大規模な GIOP メッセージを処理する場合、ORB で問題が起きる可能性があります。GIOP メッセージは、処理を容易かつ高速に行えるような断片に分割することができます。メッセージを分割する場合の正確なサイズ (あるいはそもそもメッセージを分割するかどうか) を指定するカスタムのプロパティーは、WebSphere Application Server の中で設定することができます。WebSphere Application Server はデフォルトで GIOP メッセージを 1024 バイトに分割します。

最も基本的な対話動作のシナリオでは、クライアント ORB とサーバー ORB は互いに直接通信を行い、リモート・リソースに対するアプリケーションの要求を満足させます。しかしもっと複雑な対話動作 (ワークロード管理機能を持つクラスター化されたサーバーなど) では、(この記事で説明するように) NodeAgent プロセスの中にクライアントとサーバー以外のプロセスが関係してくる場合があります。

各アプリケーション・サーバーには、送られてくるリクエストをリッスンする ORB があります。ORB には 3 つ以上のポート (ORB リスナー・ポートとブートストラップ・ポート、そしてセキュリティー・ポート) が関連付けられています。ORB リスナー・ポートは、(ORB のセキュリティーが有効ではない場合に) 送られてくる IIOP リクエストを ORB がリッスンする実際のポートです。ブートストラップ・ポートは常時アクティブな、よく知られているポートであり、必ずセキュアなリスナー・ポートとセキュアではないリスナー・ポートを含む間接 IOR を返すポートです。適切に構築されたクライアントからリモート・リソースが存在するサーバーに接続するときには、必ずブートストラップ・ポートにアクセスしなければなりません (あるいは、クラスターにリソースが存在する場合には、そのクラスターを構成する複数のホストを指定する URL のにブートストラップ・ポートにアクセスしなければなりません。ORB とセキュリティーに関連するポートは他に 3 つ (CSIv2 Client Authentication SSL ポートと CSIv2 SSL ポート、そして SAS SSL ポート) あります (これらのポートの詳細はこの記事の範囲外のため、ここでは説明しません)。ORB リスナー・ポートはデフォルトでは、実行時にプラットフォームの一時ポートの範囲から動的に決定されますが、その一方で、ファイアーウォールのルールやビジネス・ポリシーなどのさまざまな理由から、特定の静的ポートに設定することもできます。

ORB クライアントがリモート・オブジェクトに対する参照を要求すると、リモート ORB はIOR を使って応答します。IOR は CORBA や RMI-IIOP のオブジェクト参照を ORB が理解できるフォーマットでストリングとして表現したものにすぎず、非常に基本的なレベルでは、当該オブジェクトが存在するサーバーのホスト情報とポート情報を含んでいます。IOR は日常的なコーディングで使用される典型的な Java オブジェクト参照と考えることができます。


NodeAgent はどのように関係するのか

まず、NodeAgent プロセスは WebSphere Application Server Network Deployment 製品の中で ORB のトランザクションのみに関係し、ベースとなるアプリケーション・サーバーのオファリングの中には存在しません。NodeAgent プロセスはロケーション・サービス・デーモンと呼ばれるサービスを含んでおり、アプリケーション・サーバーはこのサービスを利用して、アプリケーション・サーバーが提供するサービスやリモート・オブジェクトを登録することができます (そのためにはそのアプリケーション・サーバーを指すダイレクト IOR をこのデーモンに提供します)。その後、ロケーション・サービス・デーモンは locate request を受信すると、この登録情報を使って、登録されたアプリケーション・サーバーの ORB リスナー・ポートを指すダイレクト IOR をクライアントに返します。この登録情報と IOR 情報は、このデーモンが使用する一種のルーティング・テーブルと考えることができます (デーモンは特定の NodeAgent が管理するさまざまなアプリケーション・サーバー上にある EJB や他のリソースを、この情報を使って見つけ出します)。

管理対象のアプリケーション・サーバーが適切に起動するには、そのノードのローカルに NodeAgent が存在していなければなりません。NodeAgent プロセス (実際にはロケーション・サービス・デーモンによるサービス) への依存関係がなくなるように、アプリケーション・サーバーを構成することもできますが、そのように設定するためには IIOP リクエストに対して静的なルーティングを実行する必要があります。すると、それによって WebSphere Application Server のワークロード管理サービスが使えなくなってしまいます。本当に必要でない限り、こうした静的ルーティングを設定することは避ける必要があります。(この判断を自分で下す前に IBM Support にご相談ください。)

EJB がデプロイされているノードと同じノード上にあるアプリケーション・サーバーの動作中に NodeAgent プロセスが異常終了してしまった場合や、NodeAgent プロセスを削除する必要がある場合、あるいは NodeAgent プロセスを再起動する必要がある場合、NodeAgent が利用できなくなった時点でサーバー・ログに例外がスローされるかもしれません。こうした例外メッセージがスローされるのは、NodeAgent が NodeAgent プロセスから削除されると IIOP 通信は両方の ORB (クライアント ORB とサーバー ORB) が適切に通信できなくなるように変更されることによあるものです。しかしクライアントが自分にとって必要なサーバーへのダイレクト IOR を既に持っており、自分の EJBHome オブジェクトを既に作成してあり、そしてその EJB に対するリモート呼び出しを行っている限り、NodeAgent が利用できなくなった後で NodeAgent が IIOP 通信に関係することはあり得ません。

理想的な状態では、ロケーション・サービス・デーモンに向けられた、EJB 関連のオブジェクトに関する locate request は、ある特定ノード上のすべてのアプリケーション・サーバーが NodeAgent のロケーション・サービス・デーモンへの登録を完了するまで受信されません。まだ登録されていないサーバー上、あるいは一時的にダウンしている (従ってもはや登録されていない) サーバー上にあるオブジェクトに対して locate request が送られてくると、そのクライアントには CORBA.OBJECT_NOT_EXIST 例外が返されます。この場合には、アプリケーション・サーバーの状態をチェックし、それらのサーバーが適切に実行されているかどうか、またそれらのサーバーがロケーション・サービス・デーモンに登録されているかどうかを確認する必要があります。


ORB の呼び出しパターンを理解する

上位レベルのアプリケーション機能 (EJB コンポーネントなど) が動作するためには、ORB 間で通信が行われる必要があります。基本的なシナリオには次の 2 つがあります。

  • スタンドアロンのアプリケーション・サーバー (Network Deployment を利用しない WebSphere Application Server)
  • WebSphere Application Server Network Deployment 環境でのクラスター化されたアプリケーション・サーバー

以下のセクションでは、これらのシナリオについて説明します。

WebSphere Application Server のベース・インスタンス

このシナリオでは、EJB コンポーネントとそのクライアントは別々のアプリケーション・サーバーに含まれています。呼び出しを行うクライアントのコードは以下のようなコードです。

リスト 1
Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY,"com.ibm.websphere.naming
.WsnInitialContextFactory");
env.put(Context.PROVIDER_URL,"corbaloc::isador:2810");
Context ctx = new InitialContext(env);
TestEJBHome home = (TestEJBHome)
PortableRemoteObject.narrow(ctx.lookup("ejb/ejbs/TestEJBHome"),
	TestEJBHome.class);
TestEJB bean = home.create();

太字で強調されているコードはリモート ORB 呼び出しを行うための行です。実際の動作としてのイベント・シーケンスは図 2 のようになります (この図では上から下の順でイベントの一覧を示してあります)。

図 2. ベース・インスタンスでの ORB イベントの呼び出し
ベース・インスタンスでの ORB イベントの呼び出し

図 2 は 3 つの部分に分けることができ、それぞれの部分がリスト 1 の Java コードの太字の各部分に対応しています。

  • 一番上のセクションには、クライアントで InitialContext を作成した結果発注するイベントが含まれています。
  • 中段のセクションには、InitialContext.lookup() メソッドを実行した結果発注するイベントが含まれています。
  • 一番下のセクションには、EJB インスタンスを作成した結果発注するイベントが含まれています。

この図を見ると、サーバーから初期コンテキストを取得するためのプロセスでは ORB のブートストラップ・ポートにある ORB (この場合はクライアント ORB とサーバー ORB は同じ) に locate request メッセージを送信することがわかります。その結果としての reply メッセージには、要求されたオブジェクトを含むサーバーをクライアントに示す、(ホスト、TCP/IP、SSL ポートの情報を持つ) ダイレクト IORが含まれています。次に、クライアントは別の locate request メッセージを発行しますが、この場合は ORB のリスナー・ポートに対してメッセージを発行します。これが終わると、クライアントは初期コンテキストを確立するための情報を ORB に要求します。

InitialContext の値が取得できると、クライアント・コードは JNDI 名前空間の中でルックアップを行い、対象のリモート・オブジェクト (WLMTestEJB) に対する参照を取得するための方法を判断します。これを実現するために、クライアントは ORB のリスナー・ポートに対して、また別の locate request を発行します。ORB は、確かにそのオブジェクトがローカルに含まれていることを伝える locate reply メッセージでクライアントに応答します。次にクライアントはこの locate reply への応答として、ORB がそのオブジェクトを解決し、ある参照を返すように要求します。表面的には見えませんが、背後では ORB が tie クラスを使って、その ORB に送られて来たリクエストと実際の Java オブジェクトとを結びつけています。クライアントはその参照を取得すると、narrow メソッドを呼び出して、ORB から返された一般オブジェクトを所望のオブジェクト・タイプにマーシャリングします。

最後にこのコードはリモート EJB のインスタンスを作成しています。このプロセスを完了するために、クライアントはリモート ORB に対して locate request を発行します。これに対してその ORB は、そのオブジェクトが存在することを伝える locate reply で応答します。すると最後に、クライアントはリモート・オブジェクトの create() メソッドを呼び出します。このプロセスが ORB の中で完了すると、ORB はレスポンスをマーシャリングしてクライアントに返します。ORB に送られてくる、あるいは ORB から送られるすべてのデータ (メソッド・パラメーターやメソッドの戻り値など) は、CDR (common data representation) と呼ばれるフォーマットを使ってシリアライズ/デシリアライズされます。そのため、ORB に渡されるすべての値はシリアライズ可能なインターフェースを実装する必要があります。

このベース・アプリケーション・サーバーのシナリオで使われている locate request メッセージは単純な locate request であり、ORB そのものによって処理されます。これは次に示すシナリオとは異なります。次のシナリオでは、locate request に応答するためのメッセージを (ORB インスタンスに接続されている) ロケーション・サービス・デーモン・プラグインが処理します。

WebSphere Application Server Network Deployment によってクラスター化されたインスタンス

このシナリオでの主な違いは、クライアント ORB とサーバー ORB がほとんど常に 2 つの異なる JVM インスタンスであり、多くの場合は完全に別のホスト上に存在している点です。このプロセスも先ほどの例とほとんど同じように見えますが、このシナリオには NodeAgent に含まれるロケーション・サービス・デーモン・サーバーが関係していることに気付くと思います。リスト 2 は、この呼び出しに関係するコードを示しています。

リスト 2
Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY,"com.ibm.websphere.naming
.WsnInitialContextFactory");
env.put(Context.PROVIDER_URL,"corbaloc::boris:9811,:natasha
:9812");
Context ctx = new InitialContext(env);
TestEJBHome home = (TestEJBHome)
PortableRemoteObject.narrow(ctx.lookup("ejb/ejbs/TestEJBHome"),
	TestEJBHome.class);
TestEJB bean = home.create();

このコードは先ほどの例から 1 ヵ所 (アプリケーション・サーバー環境を表す Hashtable オブジェクトの PROVIDER_URL キーの値) を変更しただけです。この場合、開発者は複数の corbaloc URL を含めており、それぞれが別々のサーバーのブートストラップ・ポートを指しています。この変更によって、このコードでは InitialContext オブジェクトを取得できるパスが 2 つになったため、プロセスにフォルト・トレランス機能とフェイルオーバー機能が追加されたことになります。先ほどのシナリオの場合と同じく、太字のコードによってリモート ORB リクエストが生成されます。図 3 は、このシナリオのイベント・シーケンスを先ほどの例と同じフォーマットで示しています。

図 3. クラスター化されたインスタンスでの ORB イベントの呼び出し
クラスター化されたインスタンスでの ORB イベントの呼び出し

一番上のセクションでの InitialContext オブジェクトの作成については、このシナリオと最初のシナリオとの間に明確な違いは何もありません。しかし WebSphere Application Server のワークロード管理機能を追加したことにより、わずかな違いが生じています。

第 1 に、(一番上のセクションで) InitialContext を作成する際、そのセルのロケーション・サービス・デーモン・クラスターのそれぞれを指す IOR のリストが用意され、対話動作の getProperties() の期間中にクライアント ORB に返されます。クライアント ORB がさらにサーバー ORB の呼び出しを行うと、クライアント側のワークロード管理プラグインがリストに対して繰り返し処理を行い、resolve_complete_info リクエストを発行します。この最初のリクエストは NodeAgent のロケーション・サービス・デーモン・サービスにルーティングされ (中段のセクションの最初の呼び出しとして示されています)、このサービスで、必要なクラスターのデータが、宛先サーバーを指すダイレクト IOR の形でクライアントに返送されます。

図 3 の一番下のセクションを見ると、最初のシナリオで発行された locate request メッセージが必要なく、その代わり即座に create() メソッドが呼び出されており、別の locate request を処理する必要もないことがわかります。これはワークロード管理が既に適切なアプリケーション・サーバーを「見つけて (locate)」いるからです。


まとめ

この記事ではまず ORB について明らかにし、クライアントが EJB サーバーにリモート・リクエストを行う上で必要な重要機能をアプリケーション・サーバーのランタイムに提供する方法を説明しました。さらに、クライアントとサーバーの間での ORB による通信という部分で NodeAgent が果たす役割について説明するとともに、ORB 間の通信を構成する上位レベルのイベント・シーケンスも示しました。

これらの話題に関しては、さらに多くの情報があります。続けて他の資料を読みたい場合は、以下の事項を調べてみるとよいでしょう。

  • GIOP プロトコル
  • ORB/EJB コンテナーに関する問題判別
  • RMI over IIOP
  • JNDI (Java Naming and Directory Interface)
  • EJB クラスタリング
  • WLM (WebSphere workload management)
  • CORBA と OMG.

謝辞

この記事で取りあげた話題に関して指導いただき、また不明点を明確にしてくださった Paul Bullis と Claudia Barrett の両氏に感謝いたします。

参考文献

コメント

developerWorks: サイン・イン

必須フィールドは(*)で示されます。


IBM ID が必要ですか?
IBM IDをお忘れですか?


パスワードをお忘れですか?
パスワードの変更

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


お客様が developerWorks に初めてサインインすると、お客様のプロフィールが作成されます。会社名を非表示とする選択を行わない限り、プロフィール内の情報(名前、国/地域や会社名)は公開され、投稿するコンテンツと一緒に表示されますが、いつでもこれらの情報を更新できます。

送信されたすべての情報は安全です。

ディスプレイ・ネームを選択してください



developerWorks に初めてサインインするとプロフィールが作成されますので、その際にディスプレイ・ネームを選択する必要があります。ディスプレイ・ネームは、お客様が developerWorks に投稿するコンテンツと一緒に表示されます。

ディスプレイ・ネームは、3文字から31文字の範囲で指定し、かつ developerWorks コミュニティーでユニークである必要があります。また、プライバシー上の理由でお客様の電子メール・アドレスは使用しないでください。

必須フィールドは(*)で示されます。

3文字から31文字の範囲で指定し

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


送信されたすべての情報は安全です。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=WebSphere, SOA and web services
ArticleID=337089
ArticleTitle=WebSphere Application Server V6.1 での EJB 呼び出しの動作を理解する
publish-date=07302008