![]() |
![]() |
|
|
| |
プログラミングの考慮事項
以下の節では、WebLogic Server で使用するための RMI のプログラミングで用いる WebLogic RMI の機能について説明します。
WebLogic RMI コンパイラ
WebLogic RMI コンパイラ(weblogic.rmic
) は、クライアントサイドでカスタム リモート オブジェクト インタフェースのための動的プロキシを生成し、サーバサイド オブジェクトにホット コード生成を提供します。RMI オブジェクトがデプロイされている場合は、rmic
を実行すると、実行時にホット コード生成機能によってバイトコードが動的に生成されます。
注意: クラスタ対応クライアントまたは IIOP クライアントの場合は、明示的に rmic
を実行するだけです(WebLogic RMI over IIOP を使用すると、クライアントは、Internet Inter-ORB Protocol(IIOP)を介して RMI リモート オブジェクトにアクセスできるため、RMI プログラミング モデルが拡張されます)。RMI over IIOP の使用方法の詳細については、『WebLogic RMI over IIOP プログラマーズ ガイド』を参照してください。
動的プロキシ クラスは、クライアントに渡されるシリアライズ可能クラスです。ホット コード生成は、バイトコードを生成する RMI の機能です。このバイトコードは、クライアントの動的プロキシからの要求を処理するサーバサイド クラスです。クラスの実装は、Weblogic Server の RMI レジストリ内の名前に関連付けられます。
クライアントは、レジストリでクラスをルックアップすることによって、そのクラスのプロキシを取得します。クライアントは、あたかもローカルなクラスであるかのようにプロキシのメソッドを呼び出します。プロキシは、要求をシリアライズして WebLogic Server に送ります。動的に生成されたバイトコードはクライアント要求をデシリアライズし、実装クラスに対して実行します。次に結果をシリアライズしてクライアントのプロキシへ送り返します。
動的プロキシとバイトコード
WebLogic Server 6.1 より前のバージョンでは、rmic
を実行すると、クライアントにはスタブが、サーバサイドにはスケルトン コードが生成されました。今回のバージョンでは、rmic は実行時にロードされる XML デプロイメント記述子を生成します。スタブの代わりに、クライアントは動的プロキシを使用してリモート オブジェクトと通信します。スケルトン クラスは必要時にメモリ内に作成されます。これにより、クラスの生成が不要になりました。
バージョン 6.1 より前の WebLogic RMI オブジェクトをバージョン 6.1 以降の WebLogic Server で実行できるようにするには、それらのオブジェクトに対して rmic
を再度実行します。これにより、デプロイ済みの RMI オブジェクトを有効にする、必要なプロキシおよびバイトコードが生成されます。
リモート オブジェクトが EJB の場合は、weblogic.ejbc
を再度実行すると、バージョン 6.1 より前の WebLogic Server オブジェクトがバージョン 6.1 以降で動作するようになります。weblogic.ejbc
の使用方法の詳細については、『ebLogic エンタープライズ JavaBeans プログラマーズ ガイド』を参照してください。
リモート オブジェクトに対して weblogic.rmic
または weblogic.ejbc
を再度実行すると、そのオブジェクトのデプロイメント記述子ファイルが生成されます。
WebLogic RMI コンパイラのオプション
WebLogic RMI コンパイラは、Java コンパイラがサポートしているオプションをすべて受け入れます。たとえば、コマンド ラインのコンパイラ オプションに -d \classes examples.hello.HelloImpl
を追加できます。ほかにも、Java コンパイラがサポートしているすべてのオプションを使用でき、これらのオプションは直接 Java コンパイラに渡されます。
次の表に、java weblogic.rmic
オプションを示します。これらのオプションは、java weblogic.rmic
の後、リモート クラス名の前に入力します。
表2-1 WebLogic RMI コンパイラのオプション
オプション |
説明 |
---|---|
|
|
|
そのサービスをクラスタ化可能(WebLogic クラスタ内の複数のサーバがホストできる)として指定する。各ホスティング オブジェクト、またはレプリカは、共通名でネーミング サービスにバインドされる。そのサービス プロキシがネーミング サービスから取り出される場合、それはレプリカのリストを保持するレプリカ対応参照を含み、レプリカ間のロード バランシングやフェイルオーバを行う。 |
|
注釈を出力する。 |
|
サービスが WebLogic Server の実行スレッドを取得するために使う、コンフィグレーション済みの実行キューを指定する。詳細については、「実行キューによるスレッド使用の制御」を参照。 |
|
オプションの説明を表示する。 |
|
リモート インタフェース用の IDL を生成する。 |
|
既存の IDL ファイルを上書きする。 |
|
IDL情報についての冗長な情報を表示する。 |
|
OMG 規格に従って IDL を生成する。 |
|
valuetype のファクトリ メソッドを生成しない。 |
|
IDL ファイルを作成するディレクトリを指定する(デフォルトはカレント ディレクトリ)。 |
|
サーバから IIOP プロキシを生成する。 |
|
IIOP プロキシ クラスが作成されるディレクトリを指定する。 |
|
WebLogic RMI コンパイラを実行するときに、生成したプロキシ クラスとバイトコードのソースを保持できる。 |
|
|
|
|
|
コンパイル時にリモート クラスに固有のプロキシが作成される。 |
|
|
|
|
|
バージョン情報を出力する。 |
表2-2 クラスタ固有の WebLogic RMI コンパイラ オプション
クラスタにおけるスタブのレプリケーション
レプリケートされないスタブをクラスタ内に生成することもできます。このようなスタブは、「固定」サービスと呼ばれています。これらのスタブは登録されたホストからのみ使用可能であり、透過的なフェイルオーバやロード バランシングは提供しません。
weblogic.rmic
でクラスタ化オプションを使用して RMI オブジェクトをコンパイルし、3 ノードのサーバ クラスタ(A、B、C)の 2 つのノード(A および B)にオブジェクトをデプロイし、バインドを 3 つのノードすべてにレプリケートする場合、各サーバから同じビューが得られます。3 つのノードすべてに対して JNDI ルックアップを行うと同じスタブが得られ、メソッド呼び出しを行うと、サーバは最初の 2 つのノード間でロード バランシングを実行します。
したがって、クラスタ化可能オプションを指定して RMI オブジェクトをコンパイルし、バインド セットのレプリケーションを「false」に設定してそれらのオブジェクトを JNDI ツリーにバインドする場合、JNDI ルックアップを行うと次の結果が得られます。
サーバ A に対してリモート呼び出しを行い、サーバが使用不可になっていることによって呼び出しが失敗する場合、クラスタ化可能スタブは再ルックアップを実行し、呼び出しのルーティング先に応じて次のいずれかの結果が発生します。
クラスタ非対応の RMI オブジェクトを、バインド セットのレプリケーションを false
に設定して JNDI ツリーにバインドする場合、JNDI ルックアップを行うと、固定スタブが返されフェイルオーバは行われません。固定サービスは、レプリケートされたクラスタ全体の JNDI ツリーにバインドされるため、クラスタ全体で利用可能です。ただし、固定サービスのホストである個別のサーバで障害が発生すると、クライアントは別のサーバへのフェイルオーバを行うことができません。
クラスタ非対応の RMI オブジェクトを、バインド セットのレプリケーションを true
に設定して JNDI ツリーにバインドすると、バインドは失敗します。その理由は、オブジェクトがクラスタ非対応であり、クラスタ内でクラスタ非対応のサービスを提供できるのは 1 つのサーバに限られるためです。
WebLogic RMI フレームワーク
WebLogic RMI はクライアントとサーバのフレームワークに分けられています。実行時のクライアントはサーバのソケットを持たないため、接続をリスンしていません。クライアントはサーバを介して接続を取得します。サーバだけがクライアントのソケットを認識します。このため、クライアントにあるリモート オブジェクトをホストする場合、クライアントは WebLogic Server に接続していなければなりません。WebLogic Server はクライアントへのリクエストを処理して、クライアントへ情報を渡します。つまり、クライアントサイドの RMI オブジェクトには、クラスタ内であっても単一の WebLogic Server を介してのみアクセスできます。クライアント サイドの RMI オブジェクトが JNDI ネーミング サービスにバインドされている場合、そのオブジェクトへのアクセスは、そのバインドを実行したサーバにアクセスできる場合に限り可能です。
WebLogic RMI コンパイラのその他の機能
WebLogic RMI コンパイラには、他にも以下のような機能があります。
RemoteException
を送出する必要がありません。
RuntimeException
にマッピングできます。
RMI の動的プロキシ
動的プロキシまたはプロキシは、リモート オブジェクトのクライアントが使用するクラスです。このクラスは、作成されるときに、実行時に指定されたインタフェースのリストを実装します。
RMI では、動的に生成されたバイトコードとプロキシ クラスが使用されます。プロキシ クラスは、クライアントの Java 仮想マシン(JVM)で呼び出されるインスタンスです。プロキシ クラスは、呼び出されたメソッド名とその引数をマーシャリングして、リモートの JVM に転送します。リモート呼び出しが終了して返された後に、プロキシ クラスはクライアント上でその結果のマーシャリングを解除します。生成されたバイトコードはリモート JVM に存在し、リモート JVM 上で呼び出されたメソッドと引数のマーシャリングを解除し、リモート オブジェクトのインスタンスのメソッドを呼び出した後、結果をマーシャリングしてクライアントに返します。
WebLogic RMI コンパイラとプロキシの使い方
WebLogic RMI コンパイラは、デフォルトの動作により、リモート インタフェース用のプロキシと、そのプロキシを共有するリモート クラス用のプロキシを作成します。プロキシは、リモート オブジェクトのクライアントが使用するクラスです。RMI では、動的に生成されたバイトコードとプロキシ クラスが使用されます。
たとえば、WebLogic RMI コンパイラでは、example.hello.HelloImpl
と counter.example.CiaoImpl
は、一対のプロキシ クラスとバイトコード、つまりリモート オブジェクト(このサンプルでは example.hello.Hello
)によって実装されたリモート インタフェースに適合するプロキシで表わされます。
リモート オブジェクトが複数のインタフェースを実装する場合、プロキシの名前とパッケージは 1 組のインタフェースをエンコードすることによって決定されます。WebLogic RMI コンパイラの -nomanglednames
というオプションを使って、デフォルトの動作をオーバーライドできます。このオプションを使用すると、コンパイル時にリモート クラスに固有のプロキシが作成されます。クラス固有のプロキシが検出された場合は、そのプロキシはインタフェース固有のプロキシに優先します。
さらに、WebLogic RMI のプロキシ クラスでは、プロキシは final ではありません。同じ場所に配置されたリモート オブジェクトへの参照は、プロキシではなくオブジェクトそのものへの参照です。
ホット コード生成
rmic
を実行すると、WebLogic Server のホット コード生成機能により、メモリ内にサーバ クラス用のバイトコードが自動生成されます。バイトコードは、リモート オブジェクトの必要に応じて、動的に生成されます。現在のバージョンの WebLogic Server では、weblogic.rmic
を実行しても、オブジェクトのスケルトン クラスは生成されません。
WebLogic RMI レジストリ
WebLogic Server は、RMI レジストリのホストとなり、RMI クライアント用のサーバ インフラストラクチャを提供します。レジストリ トラフィックは JDBC などのトラフィックと同じ接続で多重化されるので、RMI レジストリとサーバの通信オーバーヘッドは最小限に抑えられます。クライアントは RMI 用に単一のソケットを使用します。このため、WebLogic 環境での RMI クライアントのスケーラビリティは直線的です。
WebLogic RMI レジストリは WebLogic Server の起動時に作成され、新しいレジストリを作成するための呼び出しを行うだけで既存のレジストリの位置を見つけることができます。レジストリにバインドされているオブジェクトには、標準の rmi:// のほかに、http:// や https:// などのクライアント プロトコルを使ってアクセスできます。実際のところ、すべてのネーミング サービスで JNDI が使用されます。
WebLogic RMI 実装の機能
一般に、java.rmi
パッケージに含まれているすべてのメソッドと同じ機能のメソッドが WebLogic RMI で提供されています(RMIClassLoader
内のメソッドと java.rmi.server.RemoteServer.getClientHost()
メソッドを除く)。
他のすべてのインタフェース、例外、およびクラスは WebLogic RMI でサポートされています。以下の節に、特定の実装に関する注意事項を示します。
JNDI
WebLogic RMI では、オブジェクトのネーミングの望ましいメカニズムとして、Java Naming and Directory Interface(JDNI)を使用します。JNDI は、Java アプリケーションにネーミング サービスを提供するアプリケーション プログラミング インタフェース(API)です。JNDI は、Sun Microsystems の Java 2 Enterprise Edition(J2EE)技術の不可欠なコンポーネントです。ネーミング サービスは名前をオブジェクトに関連付けて、指定された名前に基づいてオブジェクトを見つけます(RMI レジストリは、ネーミング サービスの一例です)。
RMI で JNDI を使用すると、より効率的に分散プログラミングを行うことができます。ただし、リモート クライアントとサーバ間の往復回数には注意する必要があります。クライアントとサーバ間で JNDI ルックアップが繰り返されると、パフォーマンス上の問題が発生する場合があります。
rmi.RMISecurityManager
rmi.RMI SecurityManager
は非最終クラスとして実装され、すべてのパブリック メソッドが WebLogic RMI でサポートされます。制約のある JavaSoft 参照実装とは異なり、まったく制約がありません。WebLogic RMI のセキュリティはより大きな WebLogic 環境の重要な一部で、SSL (Secure Socket Layer)と ACL (アクセス制御リスト)がサポートされています。
rmi.registry.LocateRegistry
rmi.registry.LocateRegistry
は最終クラスとして実装され、すべてのパブリック メソッドがサポートされます。ただし、LocateRegistry.createRegistry
(int port
) を呼び出すと、レジストリが同じ場所に作成されるのではなく、JNDI を実装するサーバサイド インスタンスへの接続が試みられます。JNDI には属性によってホストとポートが指定されます。WebLogic RMI では、クライアントは、このメソッドを呼び出して WebLogic Server 上の JNDI ツリーを検索できます。
注意: デフォルト(rmi
)以外のプロトコルを使うことも可能で、次に示すように方式、ホスト、およびポートを URL として使うこともできます。
LocateRegistry.getRegistry(https://localhost:7002);
この例では、標準 SSL WebLogic プロトコルを使用してローカル ホスト上のポート 7002 にある WebLogic Server レジストリの位置を検索します。
rmi.server クラス
rmi.server.LogStream
は、write
(byte[]
) メソッドが WebLogic Server のログ ファイルを通してメッセージを記録する点で JavaSoft 参照実装とは異なります。
rmi.server.RemoteObject
は、UnicastRemoteObject
と同じ型を保存するために WebLogic RMI に実装されますが、その機能は WebLogic RMI の基本クラスである proxy
によって提供されます。
rmi.server.RemoteServer
は、rmi.server.UnicastRemoteObject
の抽象スーパークラスとして実装され、getClientHost() を除くすべてのパブリック メソッドが WebLogic RMI でサポートされています。
rmi.server.UnicastRemoteObject
は、リモート オブジェクトの基本クラスとして実装され、このクラスのすべてのメソッドは WebLogic RMI の基本クラスである Proxy
という名前で実装されます。この結果、プロキシは final ではない Object
メソッドをオーバーライドでき、実装についてまったく条件を付けずにこれらのメソッドを実装したのと同じ状態になります。
WebLogic RMI では、呼び出し側のオブジェクトが RMI オブジェクトと同じ Java 仮想マシン(JVM)内に存在しない場合、メソッド パラメータはすべて値渡しです。存在する場合、メソッド パラメータは参照渡しです。
注意: WebLogic RMI は、クライアントからのクラスのアップロードをサポートしません。つまり、リモート オブジェクトに渡されるどのクラスも、サーバの CLASSPATH
内に存在しなければなりません。
setSecurityManager
setSecurityManager()
メソッドは、コンパイルの互換性を保持するためだけに WebLogic RMI に組み込まれています。WebLogic RMI は WebLogic Server 内のより一般的なセキュリティ モデルに依存しているため、このメソッドにはセキュリティは関連付けられていません。セキュリティ マネージャを設定する場合、1 つしか設定できません。セキュリティ マネージャを設定する前に、セキュリティ マネージャが既に設定されているかどうかをテストする必要があります。セキュリティ マネージャを重複して設定しようとすると、例外が送出されます。次に例を示します。
if (System.getSecurityManager() == null)
使用されないクラス
System.setSecurityManager(new RMISecurityManager());
以下のクラスは、実装されていますが、WebLogic RMI では使用されません。
rmi.dgc.Lease
rmi.dgc.VMID
rmi.server.ObjID
rmi.server.Operation
rmi.server.RMIClassLoader
rmi.server.RMISocketFactory
rmi.server.UID
RMI と T3 プロトコル
WebLogic Server における RMI 通信では、T3 プロトコルが使用されます。T3 は、WebLogic Server とそれ以外の Java プログラム (クライアントや他の WebLogic Server など) の間でのデータ転送に用いられる最適化されたプロトコルです。 サーバ インスタンスは、接続先の各 Java 仮想マシン (JVM) の動作を追跡し、JVM のすべてのトラフィックを伝送するための T3 接続を 1 つだけ作成します。
たとえば、Java クライアントが WebLogic Server 上のエンタープライズ Bean や JDBC 接続プールにアクセスする場合、WebLogic Server の JVM とクライアントの JVM との間に単一のネットワーク接続が確立されます。T3 プロトコルでは、単一接続上のパケットが目に見えない形で多重化されるため、あたかも専用のネットワーク接続を独占的に使用しているかのように、EJB サービスや JDBC サービスを記述することができます。
有効な T3 接続が確立された任意の 2 つの Java プログラム (たとえば、2 つのサーバ インスタンスや、サーバ インスタンスと Java クライアント) では、ポイント ツー ポイントの定期的な「ハートビート」を使用して、自分が引き続き利用可能であることの通知や、相手が利用可能かどうかの判断を行います。各エンドポイントでは、ピア (通信相手) に定期的にハートビートを送ると共に、ピアから引き続きハートビートを受信しているかどうかでピアがまだ利用可能かどうかを判断します。
サーバ インスタンスがハートビートを出す頻度は、ハートビート間隔で決まります。デフォルトでは 60 秒です。
ピアから何回ハートビートが届かなかったらピアが利用できないとサーバ インスタンス側が判断するかは、ハートビート タイムアウト期間で決まります。デフォルトでは 4 です。
したがって、各サーバ インスタンスでは、ピアからメッセージ (ハートビートかそれ以外の通信) がない場合、最大 240 秒間すなわち 4 分間待ってから、ピアが到達不能と判断します。
タイムアウトのデフォルト設定を変更することはお勧めしません。
![]() |
![]() |
![]() |