この章では、ADF Business Componentsアプリケーション・モジュール・プールの動作方式と、それらのプールをチューニングしてアプリケーションのパフォーマンスを最適化する方法について説明します。
この章の内容は次のとおりです。
アプリケーション・モジュール・プールとは、タイプが同じアプリケーション・モジュール・インスタンスの集合のことです。たとえば、SRDemoアプリケーションの中には、該当サイトにアクセスするユーザーの数に応じて、SRServiceアプリケーション・モジュールのインスタンスが1つまたは複数存在しています。一連のアプリケーション・モジュール・インスタンスから構成されるこのプールは、複数のブラウザ・クライアントによって共有されます。そして、それらのブラウザ・クライアントがあるWebページを発行してから次のWebページを発行するまでの間にいわゆる「思考時間」が存在するため、それを利用してアプリケーション・モジュールのコンポーネント数を最適化し、システム上で作業しているアクティブ・ユーザーの総数より効果的に少なくすることができます。つまり、20名のユーザーが各自のブラウザを使用して該当するWebサイトにアクセスしている場合、それらのユーザーにサービスを提供するアプリケーション・モジュール・インスタンスは、ブラウザ・ユーザーと同じ数用意しなくても、5〜10個で済ませることができます。
アプリケーション・モジュール・コンポーネントを使用すると、完全にステートレスなWebアプリケーションをサポートしたり、複数のブラウザ・ページにまたがる作業ユニットをサポートしたりできます。パフォーマンスを最適化するために、あるアプリケーション・モジュールのインスタンスが「状態管理」モードでプールに返された場合、プールは該当するアプリケーション・モジュールが特定のセッションによって参照されていることを記憶しています。該当するアプリケーション・モジュール・インスタンスは、プール内にあって利用可能な状態にありますが、このいわゆる「セッション・アフィニティ」の維持によってパフォーマンスが改善されるため、最後に使用されたものと同じセッションによって使用されることが求められることになります。
そのため、プール内のアプリケーション・モジュールのインスタンスはどの時点においても、その状態を反映して、次の3つのグループに論理的に分類されます。
無条件に利用可能
利用可能であるが、セッション・アフィニティによる再利用のためにアクティブ・ユーザー・セッションによって参照されている
Webコンテナ内のスレッドによって現在使用されているために利用不能
アプリケーション・モジュール・プールの構成パラメータおよびそれがプールの動作に与える影響については、29.3項「構成プロパティのスコープ」を参照してください。
JSFとOracle ADFを併用した場合のWebページ・リクエストのライフサイクルのシーケンス図を、図29-1に示します。
図で示したとおり、処理の基本的なフローは次のようになります。
http://yourserver/yourapp/faces/some.jsp
に対するWebリクエストが、クライアントからアプリケーション・サーバーに到着します。
ADFBindingFilter
が、HTTPセッション内でADFバインディング・コンテキストを検索し、それがまだ存在しない場合はその初期化を初めて実行します。
バインディング・コンテキストの初期化時、ADFBindingFilter
は次の処理を実行します。
CpxFileName
という名前のサーブレット・コンテキスト初期化パラメータを調べ、その値にファイル拡張子*.cpx
を付加して、バインディング・コンテキスト・メタデータ・ファイルの名前を特定します。このパラメータ値のデフォルトは"DataBindings
"であるため、DataBindings.cpx
という名前のファイルが検索されます。
バインディング・コンテキスト・メタデータ・ファイルを読み込んで、データ・コントロール定義、ページ定義ファイル名(実行時にバインディング・コンテナをインスタンス化する際に使用される)およびページ・マップ(JSPページをそのページ定義ファイルに関連付ける)を特定します。
各データ・コントロールのインスタンスと、各BindingContainerへの参照を構築します。各バインディング・コンテナのコンテンツは、ページによって初めて使用されるときに、遅延ロードされます。
ADFBindingFilter
が、該当するリクエストに関与する各データ・コントロールに対してbeginRequest()
メソッドを起動します。これにより、各データ・コントロールは各リクエストの開始時に通知を受けて、必要な設定を実行できます。
アプリケーション・モジュール・データ・コントロールがbeginRequest
の通知を使用して、アプリケーション・モジュール・プールからアプリケーション・モジュールのインスタンスを取得します。
JSF Lifecycle
クラス(各リクエストの標準的な処理フェーズの調整を行う)が、ライフサイクルの各フェーズでADFPhaseListener
クラスに通知し、JSFライフサイクルとOracle ADF Modelデータ・バインディング・レイヤーを調整するためのカスタムな処理が実行できるようにします。
注意: FacesServlet (javax.faces.webapp 内)は、JSFアプリケーションのweb.xml ファイル内で構成され、各リクエストを処理するためのJSF Lifecycle クラス(javax.faces.lifecycle 内)を最初に作成します。ただし、FacesServletは、該当する処理をすべて実行するLifecycle クラスであるため、図に示していません。 |
図29-2に示すように、ADFPhaseListener
が、各リクエストを処理するためのADF PageLifecycle
オブジェクトを作成し、該当するフェーズ前/フェーズ後メソッドをADF PageLifecycle
クラス内の対応するメソッドに委譲します。ページのバインディング・コンテナは、該当ユーザーのセッション中、以前に適切なものが使用されていない場合、作成されます。
JSF Lifecycle
が、レンダリング対象のページにコントロールを移動します。
該当するページ上の一連のUIコンポーネントが、該当ページのバインディング・コンテナ内の値バインディングおよびイテレータ・バインディングにアクセスし、フォーマット設定された出力をレンダリングしてブラウザに表示します。
ADFBindingFilter
が、該当するリクエストに関与する各データ・コントロールに対してendRequest()
メソッドを起動します。これにより、各データ・コントロールは各リクエストの終了時に通知を受けて、リソースの必要なクリーンアップを実行できます。
アプリケーション・モジュール・データ・コントロールがendRequest
の通知を使用して、アプリケーション・モジュール・プールにアプリケーション・モジュールのインスタンスを解放して戻します。
得られたページが、ユーザーのブラウザに表示されます。
ADF Business Componentsが使用する各ランタイム構成プロパティには、スコープが1つあります。各プロパティのスコープは、該当するプロパティ値が評価されるレベルと、その値が単一のJava VM内で効果的に共有される(すなわち静的である)か否かを示します。ADF Business ComponentsのPropertyManager
クラスは、サポートされているすべてのプロパティから構成されるレジストリです。定義されるのは、プロパティの名前、デフォルト値およびスコープです。このクラスにはmain()
メソッドが含まれているので、該当クラスをコマンドラインから実行して、全構成プロパティ情報のリストを表示できます。
JDEVHOMEがJDeveloper 10gのインストール・ディレクトリである場合、この一連の設定値のリストを表示するには、次のコマンドを実行します。
$ java -cp JDEVHOME/BC4J/lib/bc4jmt.jar oracle.jbo.common.PropertyManager
このコマンドを発行すると、ADF Business Componentsの構成プロパティがすべてコンソールに送られます。また、構成プロパティ値を設定できる様々なレベルおよびそれらのレベルの優先度を示す便利な参考情報もリスト表示されます。
--------------------------------------------------------------- Properties loaded from following sources, in order: 1. Client environment [Provided programmatically or declaratively in bc4j.xcfg] 2. Applet tags 3. -D flags (appear in System.properties) 4. bc4j.properties file (in current directory) 5. /oracle/jbo/BC4J.properties resource 6. /oracle/jbo/commom.jboserver.properties resource 7. /oracle/jbo/common.Diagnostic.properties resource 8. System defined default ---------------------------------------------------------------
どのプロパティも、次のいずれか1つのスコープとともにリスト表示されます。
MetaObjectManager
このスコープのプロパティは、ADF PropertyManagerが初めて初期化される際、Java VMごとに一度初期化されます。
SessionImpl
このスコープのプロパティは、ApplicationModule.prepareSession()
が起動されるたびに一度初期化されます。
Configuration
このスコープのプロパティは、アプリケーション・モジュール・プールが初めて作成され、該当するアプリケーション・モジュールの構成が初めて読み込まれるときに初期化されます。
Diagnostic
このスコープのプロパティは、ADF Business Componentsの組込み診断機能に固有なものです。
これらのどのスコープでも、一連のプロパティが初期化される際に、前述のレイヤー化された値の解決が実行されます。プロパティ値は初期化時、システム・パラメータ(解決順序のレベル3)として指定されている値より、クライアント環境(解決順序のレベル1)で指定されている値の方が優先されます。
クライアント環境は、一連の名前/値のペアから構成されるハッシュテーブルであり、プログラムによって移入することも、Configuration
オブジェクト(ロードされると、名前/値のペアとともにbc4j.xcfg
ファイルに該当エントリが含まれる)によって自動移入することもできます。つまり、MetaObjectManagerレベルでスコープの対象となるプロパティの場合は、次の両方の処理を実行するのが、該当する一連のプロパティに対し全アプリケーション・モジュールで同じデフォルト値を確実に使用するための最も信頼性の高い方法です。
該当するプロパティ値が、どのアプリケーション・モジュールのbc4j.xcfg
ファイルの構成名/値のペア・エントリにも表示されないようにする。
実行環境内のJavaシステム・プロパティを使用してプロパティ値を設定する。
MetaObjectManagerスコープのプロパティがbc4j.xcfg
ファイルに残っている場合は望ましくない動作になります。これにより、Java VMの起動後にプールが作成される最初のアプリケーション・モジュールの構成で指定されている値が採用されます。
アプリケーション・モジュール・プールの実行時動作は、適切な構成パラメータの設定により制御します。それらのパラメータは、アプリケーション・モジュールの構成で宣言的な設定を行ったり、Java Systemパラメータとして指定したり、または実行時にプログラムで設定したりできます。
パラメータの表示および設定には、図29-3で示す構成エディタの「プーリングおよびスケーラビリティ」タブを使用します。
Configuration Managerで指定した値は、アプリケーション・モジュールのXMLコンポーネント定義を基準とする./commonサブディレクトリ内のbc4j.xcfg
というXMLファイルに保存されます。同一のJavaパッケージ内の全アプリケーション・モジュールの構成はすべて、この同じファイルに保存されます。
たとえば、SRDemoアプリケーションのDataModel
プロジェクトの./oracle/srdemo/model/common
ディレクトリの中にあるbc4j.xcfg
ファイルを見ると、例29-1のように、そのSRService
アプリケーション・モジュール用に名前の付いた構成が2つあることがわかります。SRServiceLocalTesting
構成では、SRDemoアプリケーションのJUnitテストおよびビジネス・コンポーネント・ブラウザが使用するJDBC URL接続を指定しています。SRServiceLocal
は、JDBCデータソース名を指定しており、Webアプリケーションによって使用されます。
例29-1 SRServiceアプリケーション・モジュール用の構成
<BC4JConfig> <AppModuleConfigBag> <AppModuleConfig name="SRServiceLocal"> <DeployPlatform>LOCAL</DeployPlatform> <JDBCDataSource>java:comp/env/jdbc/SRDemoDS</JDBCDataSource> <jbo.project>DataModel</jbo.project> <jbo.locking.mode>optimistic</jbo.locking.mode> <AppModuleJndiName>oracle.srdemo.model.SRService</AppModuleJndiName> <jbo.security.enforce>Must</jbo.security.enforce> <ApplicationName>oracle.srdemo.model.SRService</ApplicationName> <jbo.server.internal_connection >java:comp/env/jdbc/SRDemoCoreDS</jbo.server.internal_connection> </AppModuleConfig> <AppModuleConfig name="SRServiceLocalTesting"> <DeployPlatform>LOCAL</DeployPlatform> <JDBCName>SRDemo</JDBCName> <jbo.project>DataModel</jbo.project> <AppModuleJndiName>oracle.srdemo.model.SRService</AppModuleJndiName> <jbo.locking.mode>optimistic</jbo.locking.mode> <jbo.security.enforce>Must</jbo.security.enforce> <ApplicationName>oracle.srdemo.model.SRService</ApplicationName> </AppModuleConfig> </AppModuleConfigBag> <ConnectionDefinition name="SRDemo"> <ENTRY name="JDBC_PORT" value="1521"/> <ENTRY name="ConnectionType" value="JDBC"/> <ENTRY name="HOSTNAME" value="localhost"/> <ENTRY name="DeployPassword" value="true"/> <ENTRY name="user" value="srdemo"/> <ENTRY name="ConnectionName" value="SRDemo"/> <ENTRY name="SID" value="XE"/> <ENTRY name="password"> <![CDATA[{904}05708016F4BB90FC04CFE36B6C9D2BDFE5]]> </ENTRY> <ENTRY name="JdbcDriver" value="oracle.jdbc.OracleDriver"/> <ENTRY name="ORACLE_JDBC_TYPE" value="thin"/> <ENTRY name="DeployPassword" value="true"/> </ConnectionDefinition> </BC4JConfig>
AppModuleConfigタグの子要素は、該当するプロパティ値に一致するタグ名で表示される点に注意してください。また、プロパティが現在その実行時のデフォルト値に設定されていると、Configuration Managerは該当するエントリをbc4j.xcfg
ファイルに書き込みません。これも重要な点です。
構成プロパティは、bc4j.xcfg
ファイルで指定するのみでなく、同じプロパティ名を持つJava VMシステム・パラメータとして設定することもできます。それらのシステム・パラメータは、該当するアプリケーション・モジュールのbc4j.xcfg
ファイルの中に対応するプロパティが存在しない場合にのみ使用されます。つまり、アプリケーション・モジュール構成内の構成パラメータは、Javaシステム・パラメータとして指定した同名のパラメータより優先されます。
通常、Javaシステム・パラメータは、次のようにJava VMに対するコマンドライン・フラグ-D
を使用して設定します。
java -Dproperty=value -jar yourserver.jar
また、J2EEコンテナの場合はその独自の構成ファイルの中にセクションがあり、そこではJ2EEコンテナの起動時に使用されるJavaシステム・パラメータを指定できます。
ADF構成パラメータのサイト固有のデフォルト値をJavaシステム・パラメータとして指定し、それらのパラメータに対する参照をbc4j.xcfg
ファイルに含めない(それらのグローバルなデフォルト値に対してアプリケーション・モジュール固有の例外が必要な場合は除く)というベスト・プラクティスを採用しているカスタマは多数存在しています。
OC4Jを使用する場合は、それらのパラメータを、OC4Jを起動するコマンドラインで-D
Javaシステム・パラメータとして指定したり、oc4j.properties
ファイル内で1行に1つ指定し、起動時に-properties oc4j.properties
コマンドライン・フラグをOC4Jに追加したりできます。
注意: 「アプリケーション・プール」およびデータベースの「接続プール」の「アイドル・インスタンス・タイムアウト」、「プール・ポーリング間隔」の設定値は、前述のダイアログでは秒数として表示され、秒数として編集しますが、構成ファイルにはミリ秒として保存されます。これら4つのパラメータの値をJavaシステム・パラメータとして指定する場合や、bc4j.xcfg ファイルを手作業で編集する場合は、それらの時間間隔値をミリ秒の単位で指定してください。 |
oracle.jbo.common.ampool
パッケージにEnvInfoProvider
インタフェースを実装するJavaクラスを作成すると、構成プロパティをプログラムによって設定できます。クラス内では、例29-2に示すように、getInfo()
メソッドをオーバーライドしてput()
をコールし、渡されるenvironment Hashtableに値を格納します。
例29-2 カスタムなEnvInfoProviderを使用した環境プロパティの設定
package devguide.advanced.customenv.view; import java.util.Hashtable; import oracle.jbo.common.ampool.EnvInfoProvider; /** * Custom EnvInfoProvider implementation to set * environment properties programmatically */ public class CustomEnvInfoProvider implements EnvInfoProvider { /** * Overridden framework method to set custom values in the * environment hashtable. * * @param string - ignore * @param environment Hashtable of config parameters * @return null - not used */ public Object getInfo(String string, Object environment) { Hashtable envHashtable = (Hashtable)environment; envHashtable.put("some.property.name","some value"); return null; } /* Required to implement EnvInfoProvider */ public void modifyInitialContext(Object object) {} /* Required to implement EnvInfoProvider */ public int getNumOfRetries() {return 0;} }
Configuration
クラスのcreateRootApplicationModule()
メソッドを使用してステートレスなクライアントまたはコマンドラインクライアント用のアプリケーション・モジュールを作成する場合は、カスタムなEnvInfoProviderを第2引数(オプション)として渡すことができます。カスタムなEnvInfoProviderをADF Webベース・アプリケーションで使用するには、例29-3で示すように、セッションCookieファクトリのカスタム・クラスを実装する必要があります。カスタムなセッションCookieファクトリを使用するには、構成プロパティjbo.ampool.sessioncookiefactoryclass
に、セッションCookieファクトリのカスタム・クラスの完全修飾名を設定します。
例29-3 カスタムなEnvInfoProviderをインストールするためのカスタムなSessionCookieFactory
package devguide.advanced.customenv.view; import java.util.Properties; import oracle.jbo.common.ampool.ApplicationPool; import oracle.jbo.common.ampool.EnvInfoProvider; import oracle.jbo.common.ampool.SessionCookie; import oracle.jbo.http.HttpSessionCookieFactory; /** * Example of custom http session cookie factory * to install a custom EnvInfoProvider implementation * for an ADF web-based application. */ public class CustomHttpSessionCookieFactory extends HttpSessionCookieFactory { public SessionCookie createSessionCookie(String appId, String sessionId, ApplicationPool pool, Properties props) { SessionCookie cookie = super.createSessionCookie(appId, sessionId,pool, props); EnvInfoProvider envInfoProv = new CustomEnvInfoProvider(); cookie.setEnvInfoProvider(envInfoProv); return cookie; } }
一般的なADF Webアプリケーション、アプリケーション・モジュール・プールおよびデータベース接続プールの実行時に使用されるプールは、2種類あります。ユーザー・アプリケーションで各種のプールをいくつ作成するのかを理解することが重要です。
アプリケーション・モジュール・コンポーネントは実行時、次の2つの方法で使用できます。
クライアントから直接アクセスされるアプリケーション・モジュールとして使用する
別のアプリケーション・モジュール・インスタンスの中に集約(ネスト)されている再利用可能なコンポーネントとして使用する
クライアントから直接アクセスされるアプリケーション・モジュールは、ルート・アプリケーション・モジュールといいます。ネストされたアプリケーション・モジュールは、それが含まれるアプリケーション・モジュール・インスタンスの一部として間接的にアクセスされます。同一のアプリケーション・モジュールを実行時にこれら両方の方法で使用することも可能ですが、それは一般的ではありません。ADFはルート・アプリケーション・モジュールに対してのみアプリケーション・モジュール・プールを作成するという点が重要です。
各Java VM(該当するタイプのルート・アプリケーション・モジュールがADFコントローラ・レイヤーによって使用される)内のADF Webアプリケーションによって使用されるルート・アプリケーション・モジュールごとに、アプリケーション・モジュール・プールが1つ作成されるというのが基本ルールです。
ADF Webアプリケーションは常に同一のデータベース接続プールを使用しますが、それがユーザー・アプリケーション・モジュール用に使用するデータベース接続プールはADF Webアプリケーションによる接続の定義によって次のように異なります。
JDBC URL(例: jdbc:oracle:thin:@penguin:1521:ORCL
)
データソースのJNDI名(例: java:comp/env/jdbc/YourConnectionDS
)
アプリケーション・モジュールの構成時にJDBC URL接続を指定する(JDBC URLとユーザー名情報をカプセル化するJDeveloper名前付き接続を選択する場合に発生)と、接続プールの管理にADFデータベース接続プールが使用されます。
JDBCデータソースのJNDI名を指定すると、ADFデータベース接続プールは使用されず、ADFデータベース接続プールに関連する後述の構成パラメータは使用されません。
注意: ユーザーのJ2EE WebコンテナまたはEJBコンテナ(あるいはその両方)からJNDIによってチェックされるJDBCデータソースのデータベース接続プールを構成するには、J2EEコンテナのドキュメントを参照し、プーリングに関する構成オプションとその設定方法を理解してください。 |
ADFデータベース接続プールを使用する場合、基本ルールは次のようになります。つまり、各Java VM(ADFコントローラ・レイヤーによって使用されるルート・アプリケーションから<JDBCURL,Username>の接続がリクエストされる)内の<JDBCURL,Username>の一意なペアごとにデータベース接続プールが1つ作成されます。
アプリケーション・モジュール・プールと接続プールの作成シナリオの違いについては、29.5.3.1項「Oracle Application Serverインスタンスが1つ、OC4Jコンテナが1つ、JVMが1つの場合」および29.5.3.2項「Oracle Application Serverインスタンスが複数、OC4Jコンテナが1つ、JVMが複数の場合」を参照してください。これらいずれの項でも、次の事柄が前提条件になります。
ユーザーのWebアプリケーションでHRModule
およびPayablesModule
という2つのアプリケーション・モジュールを使用する。
ユーザー・アプリケーション内で値リストをサポートするためによく使用される一連のビュー・オブジェクトがCommonLOVModule
に含まれており、HRModule
にもPayablesModule
にもよく使用されるLOVビュー・オブジェクトにアクセスするためにCommonLOVModule
のインスタンスがネストされている。
HRModule
およびPayablesModule
は、appuser
という名前の同一のJDeveloper接続定義を使用するように構成済である。
HRModule
およびPayablesModule
で、jbo.passivationstore=database
(デフォルト値)およびADF内部接続(jbo.server.internal_connection
、appuser
接続のポイント先とは異なるユーザー名をポイントする完全修飾のJDBC URLの値を状態管理の永続性のために持たせることが目的)を構成済である。
このアプリケーションにおいて、実行時のJVMが1つの場合と複数の場合でどの種類のプールがいくつ作成されるのかを見てみましょう。
Java VMを1つ持つOC4Jコンテナが1つという構成で、このアプリケーションを単一のOracle Application Serverインスタンスにデプロイすると、アプリケーション・ユーザーからのWebリクエストにサービスを提供するのに利用可能なJava VMは1つのみになります。
HRModule
およびPayablesModule
にアクセスするWebページを全ユーザーが利用するものと仮定すると、次のようになります。
HRModule
ルート・アプリケーション・モジュール用のアプリケーション・モジュール・プールは1つ
PayablesModule
ルート・アプリケーション・モジュール用のアプリケーション・モジュール・プールは1つ
appuser
接続用のDB接続プールは1つ
状態管理を目的とする内部接続用JDBC URLのDB接続プールは1つ
Java VMが1つであるこの場合は、全部でアプリケーション・モジュール・プールが2つとデータベース・プールが2つになります。
注意: 再利用可能なCommonLOVModule のネストされたインスタンスに対して、アプリケーション・モジュール・プールは存在しません。CommonLOVModuleのインスタンスは、HRModule およびPayablesModule のインスタンスにより、それぞれのアプリケーション・モジュール・プール内でラップされます。 |
次は、Java VMが複数関与するデプロイ環境を考えてみます。フロントエンドとしてハードウェア・ロードバランサを設け、Oracle Application Server 10g(バージョン9.0.4)を2台の異なる物理マシンにインストールしてあるものとします。これらのいずれのマシンでも、Oracle Application Serverのインスタンスは、JVMが2つあるOC4Jコンテナを1つ持つように構成されているものとします。アプリケーションのユーザーがアプリケーションにアクセスすると、そのリクエストはこれら2つのOracle Application Serverインスタンスによって共有され、各Oracle Application Serverインスタンスの中では該当するOC4Jコンテナから利用可能な2つのJVMによって共有されます。
この場合も、HRModule
およびPayablesModule
にアクセスするWebページを全ユーザーが利用するものと仮定すると、次のようになります。
HRModule
のアプリケーション・モジュール・プールは4つ(4つの各JVMごとに1つ)
(1つのHRModule
ルート・アプリケーション・モジュール)×(2つのOracle Application Serverインスタンス)×(2つのOC4J JVM)
PayablesModule
のアプリケーション・モジュール・プールは4つ(4つの各JVMごとに1つ)
(1つのPayablesModule
ルート・アプリケーション・モジュール)×(2つのOracle Application Serverインスタンス)×(2つのOC4J JVM)
appuser
のDB接続プールは4つ(4つの各JVMごとに1つ)
(1つのappuser
DB接続プール)×(2つのOracle Application Serverインスタンス)×(2つのOC4J JVM)
内部接続JDBC URLのDB接続プールは4つ(4つの各JVMごとに1つ)
(1つの内部接続JDBC URLのDB接続プール)×(2つのOracle Application Serverインスタンス)×(2つのOC4J JVM)
この場合は、全部で8つのアプリケーション・モジュール・プールと8つのDB接続プールが4つのJVMに存在することになります。
29.6項「アプリケーション・モジュール・プールのパラメータ」でアプリケーション・モジュール・プールの構成パラメータをいろいろと確認する場合、それらのパラメータは1つのJVM内で指定した単一のアプリケーション・モジュールの特定の1つのアプリケーション・モジュール・プールに適用されることに注意してください。
ロード・バランシングにより、ADFが動作している複数のJVMに渡ってユーザー・リクエストが分散されると、各JVM内の個々のアプリケーション・モジュール・プールでサポートする必要のあるユーザー負荷はN
分の1になります(N
は、それらのユーザー・リクエストにサービスを提供するために利用可能なJVMの数)。アプリケーション・モジュール・プールおよびDB接続プールに適した値は、Java VMの数を念頭に置いて設定する必要があります。
アプリケーション・モジュール・プールの構成パラメータは、プールの動作、プールのサイズ指定およびプールのクリーンアップ動作に関連する3つの論理的カテゴリに分類されています。
アプリケーション・モジュール・プールの動作に影響を与えるアプリケーション・モジュール構成パラメータを、表29-1に示します。
表29-1 プールの動作に関するアプリケーション・モジュール構成パラメータ
プール構成パラメータ | 説明 |
---|---|
管理された解放時にトランザクションの状態をフェイルオーバー ( |
アプリケーション・モジュールが「状態管理」モードでプールに解放されるたびに、保留中のトランザクション状態の積極的な受動化が有効になります。詳細は、28.2.3項「オプションのフェイルオーバー・モードを有効にしたときの受動化の変化」を参照してください。 この機能はデフォルトでは無効( |
解放時にアプリケーション・モジュールを切断(接続プーリングを使用) ( |
アプリケーション・モジュールがプールに解放されるたびに、アプリケーション・モジュール・プールは使用中のJDBC接続を解放するように強制されます。詳細は、29.8項「データベースとアプリケーション・モジュール・プールの連携」を参照してください。 この機能はデフォルトでは無効( |
動的JDBC資格証明をサポート ( |
該当するアプリケーション・モジュールの使用を新しいユーザー・セッションが開始するたびに、データベース資格証明(ユーザー名/パスワード)の変更を開発者作成コードに許可する別のプーリング・ライフサイクル・イベントが有効になります。 この機能はデフォルトで有効( |
管理されていない解放時に非トランザクション状態をリセット ( |
アプリケーション・モジュールが非管理モード、すなわち「ステートレス」モードでプールに解放されたとき、ビュー・オブジェクトの実行時設定、JDBCプリコンパイル文、バインド変数値のような非トランザクション状態をすべてリセットするように強制します。 この機能はデフォルトで有効( |
アプリケーション・モジュール・プーリングを使用可能にする ( |
アプリケーション・モジュール・プーリング機能が有効になります。アプリケーション・テストのルーチン部としてこの機能を無効にするよう推奨されている場合の詳細は、28.8項「アプリケーション・モジュールの能動化が安全であることの確認テスト」を参照してください。 この機能はデフォルトでは有効( |
アプリケーション・モジュール・プールのサイズ指定に影響を与えるアプリケーション・モジュール構成パラメータを、表29-2に示します。
表29-2 プールのサイズ指定に関するアプリケーション・モジュール構成パラメータ
プール構成パラメータ | 説明 |
---|---|
プールの初期サイズ ( |
プールの初期化時に作成されるアプリケーション・モジュール・インスタンスの数。 デフォルト値は、 |
最大プール・サイズ ( |
プールで割り当てることができるアプリケーション・モジュール・インスタンスの最大数。 プールでは、この限界値を超える数のアプリケーション・モジュール・インスタンスを作成しません。デフォルト値は、 |
参照プール・サイズ ( |
状態管理モードでアプリケーション・モジュール・インスタンスをプールに解放する直前にそれらのアプリケーション・モジュール・インスタンスを使用していたセッションによる次のリクエストのためにセッション・アフィニティを維持しようとする、プール内のアプリケーション・モジュール・インスタンスの最大数。 このパラメータ値は常に、「最大プール・サイズ」の値以下である必要があります。デフォルトでは |
インスタンスの最大有効時間 ( |
この時間(ミリ秒)を超えると、プール内のインスタンス数がminavailablesize未満になるかどうかには関係なく、プール内のアプリケーション・モジュール・インスタンスが、次のリソース・クリーンアップ時に削除の候補とみなされます。 デフォルト値は3600000ミリ秒(3600秒または1時間)です。 |
Java VMごとに1つのアプリケーション・モジュール・プール・モニターがバックグラウンド・スレッドで動作し、しばしばウェイクアップしてリソースの再生を実行します。プール・モニターが各リソース・クリーンアップ・パスを実行するときのリソースの再生処理に影響を与えるパラメータを、表29-3に示します。
注意: アプリケーション・モジュール・プール・モニターはJava VMごとに1つしか存在しないため、最初に作成されるアプリケーション・モジュール・プールによって読み込まれるアプリケーション・モジュール構成内の値が、アプリケーション・モジュール・プール・モニターのポーリング間隔として使用される実際の値になります。この値を常識的な方法で確実に設定するには、すべてのアプリケーション・モジュールで同一のプール・ポーリング間隔の値を使用するよう設定するのがベスト・プラクティスです。 |
表29-3 リソースの管理に関するアプリケーション・モジュール構成パラメータ
プール構成パラメータ | 説明 |
---|---|
プール・ポーリング間隔 ( |
プール・リソース・クリーンアップの時間間隔(ミリ秒)。 プール内のアプリケーション・モジュール・インスタンスの数が最大プール・サイズを超えないかぎり、プールから削除される候補のインスタンスは、アプリケーション・モジュール・プール・モニターが次回ウェイクアップしてそのジョブを実行するまで、クリーンアップされることはありません。アプリケーション・モジュール・プール・モニターは、デフォルトでは |
使用可能な最大サイズ ( |
負荷が異常でない場合に理想的な、プール内のアプリケーション・モジュール・インスタンスの最大数。 プール・モニターは、ウェイクアップしてリソースのクリーンアップを実行する場合、利用可能なアプリケーション・モジュール・インスタンスを削除して、利用可能なインスタンスの総数をこの理想的な最大値まで減らそうとします。アイドル・インスタンスのタイムアウトより長い期間使用されていないインスタンスは常に、その時点でクリーンアップされます。その後、利用可能なインスタンスの数をこのサイズまで下げるために必要な場合は、利用可能なインスタンスがさらに削除されます。デフォルト値は、 |
使用可能な最小サイズ ( |
リソースのクリーンアップ処理時にプール・モニターがプールに残す必要のある、利用可能なアプリケーション・モジュール・インスタンスの最小数。すべてのインスタンスがアイドル・タイムアウトより長い期間アイドルである場合に、プールにインスタンスが1つも含まれないようにするには、ゼロ( デフォルト値は、 |
アイドル・インスタンス・タイムアウト ( |
この時間(ミリ秒)を超えると、プール内の非アクティブなアプリケーション・モジュール・インスタンスは、次回のリソース・クリーンアップ時に削除の候補とみなされます。 デフォルト値は、600000ミリ秒(600秒または10分)です。 |
インスタンスの最大有効時間 ( |
この時間(ミリ秒)を超えると、プール内のインスタンス数がminavailablesize未満になるかどうかには関係なく、プール内の接続モジュール・インスタンスが、次のリソース・クリーンアップ時に削除の候補とみなされます。 デフォルト値は3600000ミリ秒(3600秒または1時間)です。 |
接続情報としてJDBC URLを使用しADFデータベース接続プールを使用する場合は、表29-4の構成パラメータを使用すると、データベース接続プールの動作をチューニングすることができます。Java VMごとに1つのデータベース接続プール・モニターがバックグラウンド・スレッドで動作し、しばしばウェイクアップしてリソースの再生を実行します。プール・モニターが各リソース・クリーンアップ・パスを実行するときのリソースの再生処理に影響を与えるパラメータを、表29-3に示します。
注意: データベース接続プーリング用の構成パラメータは、MetaObjectManagerスコープを持ちます(前述の29.3項「構成プロパティのスコープ」を参照)。つまり、それらの設定値はグローバルで、アプリケーション内で最初のアプリケーション・モジュール・プールが作成されるときに設定されます。予測可能な動作を保証するには、「プーリングおよびスケーラビリティ」タブの「接続プール」セクションにある該当パラメータをデフォルト値のままにしておき(該当するエントリをbc4j.xcfg ファイルに書き込まない)、それらのデータベース接続プーリング・チューニング用パラメータの望ましい値をJ2EEコンテナのJava Systemパラメータとして設定してください。 |
表29-4 データベース接続プールのパラメータ
プール構成パラメータ | 説明 |
---|---|
プールの初期サイズ ( |
プールの初期化時に作成されるJDBC接続インスタンスの数。 デフォルト値は |
最大プール・サイズ ( |
プールで割り当てることができるJDBC接続インスタンスの最大数。 この限界値を超える数のJDBC接続がプールによって作成されることはありません。デフォルト値は、 |
プール・ポーリング間隔 ( |
プール・リソース・クリーンアップの時間間隔(ミリ秒)。 プール内のJDBC接続インスタンスの数が最大プール・サイズを超えないかぎり、プールから削除される候補のインスタンスは、JDBC接続プール・モニターが次回ウェイクアップしてそのジョブを実行するまで、クリーンアップされることはありません。デフォルト値は、 |
使用可能な最大サイズ ( |
負荷が異常でない場合に理想的な、プール内のJDBC接続インスタンスの最大数。 プール・モニターは、ウェイクアップしてリソースのクリーンアップを実行する場合、利用可能なJDBC接続インスタンスを削除して、利用可能なインスタンスの総数をこの理想的な最大値まで減らそうとします。アイドル・インスタンスのタイムアウトより長い期間使用されていないインスタンスは常に、その時点でクリーンアップされます。その後、利用可能なインスタンスの数をこのサイズまで下げるために必要な場合は、利用可能なインスタンスがさらに削除されます。デフォルト値は、 |
使用可能な最小サイズ ( |
リソースのクリーンアップ処理時にプール・モニターがプールに残す必要のある、利用可能なJDBC接続インスタンスの最小数。すべてのインスタンスがアイドル・タイムアウトより長い期間アイドルである場合に、プールにインスタンスが1つも含まれないようにするには、ゼロ( デフォルトでは、利用可能な最小サイズを |
アイドル・インスタンス・タイムアウト ( |
この時間(ミリ秒)を超えると、プール内の非アクティブなJDBC接続インスタンスは、次回のリソース・クリーンアップ時に削除の候補とみなされます。 デフォルト値は、 |
データベース接続プールの場合は経験則的なセッション・アフィニティが実装されません。そのため、参照プール・サイズを制御するための構成パラメータがありません。
前のクリーンアップサイクルがまだ実行中のときにプール・モニターの次回のウェイクアップが発生する可能性がある(クリーンアップ対象のアプリケーション・モジュール・プールの数が多い場合)ので、jbo.ampool.monitorsleepinterval
(アプリケーション・モジュール・プールの場合)またはjbo.poolmonitorsleepinterval
(DBプールの場合)の時間間隔を短くしすぎないでください。10分(600000
ミリ秒)というデフォルト値が妥当な値です。その値を10秒(10000
ミリ秒)などに設定すると、トラブルが発生する可能性があります。
ADFアプリケーション・モジュール・プールがデータベース接続プールを使用する方法は、アプリケーション・モジュール構成パラメータjbo.doconnectionpooling
の設定によって異なります。図29-3のConfiguration Managerのパネルでは、「解放時にアプリケーション・モジュールの切断」チェック・ボックスを使用してこのパラメータを設定します。
注意: 関連する構成パラメータ名(jbo.doconnectionpooling )より、プールへの解放時にアプリケーション・モジュールを「切断する」という概念の方が、実際の機能に即しています。jbo.doconnectionpooling=false と設定しても、データベース接続プーリングが実行されないわけではありません。これは、アプリケーション・モジュール・プールに戻されるときのチェックインの際、アプリケーション・モジュールがそのJDBC接続から切断されないという意味です。 |
jbo.doconnectionpooling=false
というデフォルト値の場合、アプリケーション・モジュール・インスタンスがいずれかのプール内で作成されるとき、該当する接続プール(ADFの場合はJDBC URLに基づきます。JNDIデータ・ソース名の場合は基礎となるJDBCデータ・ソース実装のプールから)からJDBC接続を取得します。該当するアプリケーション・モジュール・インスタンスは、該当するプールから取得したJDBC接続オブジェクトを、自分がアプリケーション・モジュール・プールから削除されるまで保持します。そのアプリケーション・モジュール・インスタンスは、存続期間中、多数の異なるユーザーにサービスを提供する可能性があります。そのため、ADFでは、様々なユーザーによって保留中のデータベース状態が複雑化しないように、データベース接続上でのロールバック実行が懸念される可能性があります。各アプリケーション・モジュール・インスタンスは、JDBC接続を保持することにより、クライアントによる以降のアクセス全体に渡ってそのJDBC PreparedStatementをオープンで使用可能な状態に維持し、最良のパフォーマンスを実現することができます。
jbo.doconnectionpooling=true
の場合は、ユーザー・セッションがアプリケーション・モジュールの使用を終える(通常は各HTTPリクエストの終了時)たびに、アプリケーション・モジュール・インスタンスが該当するリクエストで使用していたJDBC接続を切断し、そのJDBC接続をJDBC接続プールに返します。該当するアプリケーション・モジュール・インスタンスは、ユーザー・セッションによって次回使用されるとき、JDBC接続プールからJDBC接続を再度取得し、該当するアプリケーション・モジュールがアプリケーション・モジュール・プールからチェックアウトされている期間(この場合も、通常は1つのHTTPリクエストの期間)、そのJDBC接続を使用します。アプリケーション・モジュール・インスタンスは、PreparedStatement(現在のHTTPリクエストに対するサービスの提供時に使用された可能性がある)の作成に使用したJDBC接続オブジェクトから自分自身を切断するので、それらのPreparedStatementは次のHTTPリクエストで使用することができません(PreparedStatementは、自身が作成された接続オブジェクトのコンテキスト内でのみ有効であるため)。そのため、今の場合のように接続プーリング・モードを有効にして使用する場合は、データベース接続の総数が少なくなるかわりに、JDBCを毎回セットアップするオーバーヘッドが少し増えます。
アプリケーション接続のために、基礎となる同一のデータベース・ユーザーを多数のアプリケーション・モジュール・プールがすべて使用する場合、違いが顕著になります。
50個の異なるアプリケーション・モジュール・プールがそれぞれアプリケーション・モジュール・インスタンスを内部に1つだけ持つ場合、jbo.doconnectionpooling=false
という条件では、50個のJDBCアプリケーション接続が使用されます。jbo.ampool.minavailablesize=0
と設定し、適切なインスタンス・アイドル・タイムアウトが経過した後にアプリケーション・モジュール・プールを0
インスタンスまで減らせるようにアプリケーション・モジュール・プーリングのパラメータを設定すると、アプリケーション・モジュールは保持していた接続をそのプールから削除されるときに元に戻します。
一方、50個の異なるアプリケーション・モジュール・プールがそれぞれアプリケーション・モジュール・インスタンスを内部に1つだけ持つ場合、jbo.doconnectionpooling=true
という条件では、使用されるJDBC接続の数は別々のクライアントによって同時に使用されるアプリケーション・モジュールの個数に依存します。アプリケーション・モジュール・インスタンスは、プール内にあってユーザー・セッションにより使用されていない場合、jbo.doconnectionpooling=true
という条件があるため、そのJDBC接続を接続プールに解放します。そのアプリケーション・モジュール・インスタンスは、別のユーザーによって再度必要とされるかアプリケーション・モジュール・プール・モニターによって最終的にクリーンアップされるまでプール内で待機している間、JDBC接続には接続されていません。
パフォーマンスを最大にするには、アプリケーション・モジュール・プールへのチェックインのたびにアプリケーション・モジュール・インスタンスをそのデータベース接続から切断しないでください。構成パラメータjbo.doconnectionpooling
のデフォルト値がfalse
になっているのは、このためです。リソースの使用方法を最適化するための効果的な方法として、アプリケーション・モジュール・インスタンスのプーリングは実績があります。また、プールに解放された後、関連付けされているJDBC接続からアプリケーション・モジュール・インスタンスを毎回切断する必要がないのであれば、Oracle ADFの実行時の効率が向上します。JDBC接続に1対1で関連付けされているアプリケーション・モジュールをプーリングすれば、ほとんどのWebアプリケーションに最適なデータベース接続のプーリングを実現できます。
デフォルトの推奨事項とは異なりますが、アプリケーション・モジュール・プールの数が多数で、それらのすべてにおいて基礎となる同一のアプリケーション・ユーザーのデータベース接続をデータベース・レベルで使用する必要がある場合は、データベース接続プーリングを使用するのが適していることがあります。この場合、多数のアプリケーション・モジュール・プールでは、それぞれ効率のロスはあるものの、JDBC接続の基礎となる同一のデータベース接続プールを共有することにより、データベース・セッションの総数を節約することができると思われます。ただし、これが有効なのは、すべてのデータベース・セッションの優先度が最大の場合のみです。
現在のユーザー・セッションに関連するデータベース状態を初期化するために、ストアド・プロシージャの起動が必要な場合もあります。その初期化を実行するには、アプリケーション・モジュールのprepareSession()
メソッドをオーバーライドして行うのが正しい方法です。
jbo.doconnectionpooling
のデフォルト値はfalse
です。つまり、アプリケーション・モジュール・インスタンスは、アプリケーション・モジュール・プールの中にあるとき、そのJDBC接続に接続されていません。アプリケーション・モジュールは、そのJDBCプリコンパイル文をアプリケーション・モジュールの一連のチェックアウト/チェックインに渡ってオープン状態に維持できるので、これが最も効率的な設定です。アプリケーション・モジュール・インスタンスは、新しいユーザー・セッションによる使用が開始されるたびに、そのprepareSession()
メソッドをトリガーします。
jbo.doconnectionpooling
をtrue
に設定すると、アプリケーション・モジュールがプールからチェックアウトされるたびに、アプリケーション・モジュール・プールはデータベース接続プールからJDBC接続を取得し、現在のリクエストの期間中、それを使用します。該当リクエストの終了時、アプリケーション・モジュールがアプリケーション・モジュール・プールに解放されるとき、アプリケーション・モジュール・プールは使用していたJDBC接続をデータベース接続プールに解放します。
jbo.doconnectionpooling
がtrue
に設定されているので、プール内のアプリケーション・モジュール・インスタンスはその後、プールからチェックアウトされるたびにまったく異なるJDBC接続を持つ可能性があります。この場合は、該当するアプリケーション・モジュールがプールからチェックアウトされるたびにprepareSession()
メソッドが起動され、ユーザーはデータベース状態を初期化しなおすことができます。
SRDemoアプリケーションには、ユーザーごとにデータベース状態を設定する簡単な例が含まれています。そこで使用される次のPL/SQLパッケージでは、現在認証されているWebアプリケーション・ユーザーの名前が格納されているパッケージレベル変数の設定および取得を実行します。
例29-4 SRDemo CONTEXT_PKG PL/SQLパッケージ
create or replace package context_pkg as procedure set_app_user_name(username varchar2); function app_user_name return varchar2; end context_pkg;
このデモ内のServiceHistories
ビュー・オブジェクトのWHERE句では、context_pkg.app_user_name
関数を参照して、各ユーザーの状態がアプリケーション問合せによってどのように参照されるのかを示します。
注意: 実際は、通常、データベースCONTEXT ネームスペースを作成し、それとPL/SQLプロシージャを関連付けた後、SQL関数SYS_CONTEXT() を使用してコンテキストの値を参照します。ただし、SRDemoアプリケーションのインストールをさらに複雑にすることなく、ユーザー状態の設定および参照のメカニズムを説明するには、前述の簡単なPL/SQLパッケージで十分です。このデモの作成者は、デモをわかりやすくするためにこのようなシンプルなアプローチを採用したと思われます。 |
FrameworkExtensions
プロジェクトのフレームワーク拡張クラスSRApplicationModuleImpl
には、25.5.2項「IN引数のみのストアド・プロシージャの呼出し」で示したものと同様のヘルパー・メソッドcallStoredProcedure()
が含まれています。SRServiceImpl
アプリケーション・モジュール・クラスは、このクラスを拡張し、例29-5で示すヘルパー・メソッドsetCurrentUserInPLSQLPackage()
(callStoredProcedure()
メソッドを使用してストアド・プロシージャcontext_pkg.set_app_user_name()
を起動し、現在認証されているユーザーの値をパラメータ値として渡す)を定義します。
例29-5 ストアド・プロシージャContext_Pkg.Set_App_User_Nameをコールするメソッド
// In SRServiceImpl.java public void setCurrentUserInPLSQLPackage() { String user = getUserPrincipalName(); callStoredProcedure("context_pkg.set_app_user_name(?)",new Object[]{user}); }
このヘルパー・メソッドを使用し、SRServiceImpl
クラスでは例29-6に示すように、prepareSession()
メソッドをオーバーライドします。