J2EEアプリケーションのデータアクセスにおける
パフォーマンスとスケーラビリティのための構成

Oracleテクニカル・ホワイトペーパー
2002年7月

目次

はじめに

Webベースのアプリケーションでは、大量のクライアントに対してストレスのないサービスを提供することが期待されます。多くの場合、このような機能を提供するJ2EEアプリケーションでもっともパフォーマンス上考慮すべきポイントはデータアクセスです。データベースへのアクセスおよび処理を行うロジックを不用意にコーディングすると、その影響は直接パフォーマンスに影響してきます。

オラクルでは、データベースにかかわるコンサルティングのなかで長年培われたノウハウから、J2EEデザイン・パターンでも提示されている手法をとりいれたJ2EEデータアクセス・フレームワーク(Business Components for Java)を提供しています。このフレームワークには、アプリケーションのパフォーマンスとスケーラビリティの強化を目的に設計された幾つもの機能があります。

このホワイトペーパーではこのような機能について、その動作、構成方法および構成の効果を説明します。HTMLクライアントで使用するWebモジュールとして配布されるアプリケーションを中心に説明します。

また、この資料の最後に、オラクル社のiLearningアプリケーションの事例について、実際に経験したパフォーマンス上の問題をいくつか示し、これらがどのように対処されたか、また結果はどうなったかを解説します。

 

データアクセス・アプリケーションの配布構成

データアクセスを行うJ2EEアプリケーションの構成方法にはいくつかのパターンが考えられます。

以下ではこれらのパターンとそれが適しているアプリケーション・タイプを明確化しています。

Javaアプリケーションのためのローカル配布

この配布構成では、Javaクライアントとデータアクセス・コンポーネントはどちらもローカルのクライアント・マシン上で実行されます。この種の配布形態は、複雑でアクセス頻度の高いGUIアプリケーションの場合に有効です。この環境では、アプリケーションにアクセスする各ユーザーごとにクライアント・ソフトウェアをインストールし、高度に洗練されたユーザー・インタフェースと高速実行が重要視されます。またこの配布形態は、ユーザーがオフラインで作業するような切断状態の可能性がある場合にも利用できます。つまり、データベースを含む完全なアプリケーションをクライアント・マシン上にインストールすることもできるためです。

図1: Javaクライアントのためのローカル配布

注意: ダウンロード時間を考慮すると、ローカル配布はアプレットには適していません。アプレットには分散オブジェクト・モードでの配布が適しています。
なお、Java UI クライアントを実現する手段として、Java Web Startと呼ばれる新しいアプリケーション構成も存在します。これについては後述します。

Webモジュール配布

この配布構成は、中間層のWebサーバーで実行されるサーブレットまたはJavaServer Pages(JSP)クライアントと、ブラウザ・クライアントからアプリケーションをリモートにアクセスするエンド・ユーザーで構成されています。

図2: HTMLクライアントのためのWebモジュールの配布

JSPページまたはサーブレット・アプリケーションのWebモジュールとしての配布

Webモジュールの配布は、データアクセス・コンポーネントがJSPページまたはサーブレットと同じJava仮想マシンで実行されるので、一種のローカル配布であるといえます。 この配布構成は、一般に、JSPまたはサーブレット・ベースのデータアクセス・アプリケーションの配布に最適です。配布とメンテナンスが容易で、以下のような理由から最大のパフォーマンスを得られるためです。

リモート階層によるオーバーヘッドの回避とそれに対するトレードオフ

この構成は、JSPページやサーブレットといったJavaクライアントにとって、データアクセス・コンポーネントがローカルで実行されるためリモート階層が不要であり、したがってリモート・アクセスによるオーバーヘッドが問題になることはありません。 そのかわり、Webサーバー上で永続性、トランザクション、同時接続性およびリソース・プーリングを管理する必要があります。

リモート配布

この配布構成は、データアクセス・コンポーネントを中間層に配布して、リモート・クライアントからアクセスします。次のような例が考えられます。

このリモート階層に対するクライアントには、JSPやサーブレットが実行されるWebサーバーや、個々のクライアント・マシン上のJavaアプリケーションやアプレットなどが考えられます。この構成でも、Webモジュール配布と同様、永続性、トランザクション、同時接続性およびリソース・プーリングを管理する必要があります。ただし、EJBサーバーを利用する場合、EJBコンテナがそれらの機能を負担してくれるため、その分の開発コストは軽減されます。それでも、依然としてパフォーマンスを考慮して(特にWebサーバーとEJBサーバーとの間の)ネットワーク・トラフィックやEJBサーバー上のリソースを最小限で抑えられるよう設計する必要があります。

図3: EJBとしてのリモート配布

Java Web Start

Java UI クライアントが必要なケースでは、もう一つの選択オプションがあります。それが Java Web Start です。
Java Web Startベースのアプリケーションの場合、Web ページのリンクをクリックしたときに、ローカルマシンにアプリケーションが存在しない場合、必要なファイルがすべて自動的にダウンロードされ、その後起動されます。すでにダウンロード済みの場合は、バージョン・チェックが行われ、最新であることが確認されると起動されます(ダウンロード済みファイルが最新でない場合は、再び自動的にダウンロードが行われます)。常にアプリケーションがダウンロードされるわけではなく、しかしながら常に最新のアプリケーションであることが保証されるため、JavaアプレットとJavaアプリケーションの両方の利点を兼ね備えているといえます。

このアプリケーション構成によるデータアクセス・アプリケーションを選択する場合、前述の「ローカル配布」と「リモート配布」のどちらかを利用できます。ローカル配布構成のJava Web Startアプリケーションのほうがリモート配布構成に比べてダウンロードされるファイル量は多くなりますが、実行時にリモート階層を必要としないため、その分のオーバーヘッドは発生しません。

図4: Java Web Startを利用したローカル/リモート配布

Java Web Startについてもっと知りたい場合は、以下のサイトを参照ください。

Java Web Start: http://java.sun.com/products/javawebstart/ja/index_ja.html

Business Components for Javaとは

Business Components for Java(BC4J)は、オラクルが提唱するデータアクセスのための各種コンポーネントの集まり(データアクセス・フレームワーク)です。BC4Jは、その特性を活かしてデータベースにまつわるJDBCなど低レベルな層を制御するためのコード作成を自動化します。開発者は煩雑でメンテナンスの難しいデータベースまわりのコーディングをする必要がなくなり、ビジネスルールの実装に集中できます。

BC4Jフレームワークの利用は以下の利点があります:

このように、これまでJavaからのデータアクセスでは当然のように記述されていたJDBCコーディングが完全にパラメータ設定で制御できるようになり、かつ、開発前でなく開発した後から配布形態を自由に選択できるようになります。


最大のパフォーマンスとスケーラビリティを得るために

BC4Jフレームワークにおけるデータアクセス・アプリケーション・サービスは、"アプリケーション・モジュール"と呼ばれます。アプリケーション・モジュールには、パフォーマンスとスケーラビリティを考慮した数多くのチューニング手法が提供されています:

アプリケーション・モジュールの構成プロパティ

アプリケーション・モジュールに対して、その動作や配布形態を制御するために、構成プロパティ・セット(構成プロファイル)を設定できます(BC4Jフレームワークには、これらの構成情報を格納・管理するGUIツールが用意されています)。1つのアプリケーション・モジュールに対して複数の構成プロファイルを作成できますので、今まで述べてきたような多彩な配布形態を1つのアプリケーション・モジュールに対して複数設定することが可能です。

それぞれのプロファイルに対しては、配布先プラットフォーム、接続情報、および接続プーリングやログなどのランタイム・プロパティを定義することができます。これらの構成プロパティは、構成プロファイル管理ツールを用いて構成プロファイルとして設定でき、ファイルbc4j.xcfgにXMLメタデータとして格納されます。

実行時に構成プロファイルを指定する方法

設定された構成プロファイルは、構成名によって指定できます。
JSPページからBC4Jコンポーネントを利用する方法として、BC4Jデータ・タグがあります。BC4Jデータ・タグは、BC4Jフレームワークの機能のひとつとして提供されるタグ・ライブラリです。これによってJSPからのデータアクセスを完全にタグだけで制御できるようになります。このBC4Jデータ・タグでは ApplicationModule タグを使ってJSPからアプリケーション・モジュールへのアクセスを実現しますが、 その configname属性に構成名を与えるだけで構成プロファイルを指定できます。

参考 : JSPからのBC4Jデータタグの利用例

アプリケーション・モジュール・プーリング

アプリケーション・モジュール・プーリングは、中間層におけるアプリケーション・サービスを再利用するための仕組みです。これを使用すると、少量のリソースではるかに多くのリクエストに対してサービスを提供できるようになるため、スケーラビリティが要求されるアプリケーションにとっては基本的な機能だといえます。また、アプリケーション・モジュール・プーリングにより、クライアントが要求のたびに新しいインスタンスを作成するのではなく、既存のアプリケーション・モジュール・インタンスを再利用できるためにアプリケーションのパフォーマンスも向上します。

アプリケーション・モジュール・プーリングを使用しないアプリケーションの場合

アプリケーション・モジュール・プーリングを使用しない場合にどうなるかを、図4に示します。クライアントがデータアクセスを行うコンポーネントを要求すると、JDBC接続を含む新規アプリケーション・モジュール・インスタンスが作成されます。この場合、各クライアントの要求ごとに専用のアプリケーション・モジュール・インスタンスが必要なため、クライアント数が増加するとすぐにリソースが限界が達してしまうでしょう。また、クライアントの要求のたびに新規データベース接続が行われるため、パフォーマンスもよいものとはいえません。

図5: プーリング技術がない場合

アプリケーション・モジュール・プーリング

図6は、接続プーリングを使用しないアプリケーション・モジュール・プーリングを示します(接続プーリングに関しては後述します)。この場合、各アプリケーション・モジュールごとにデータベース接続が1つあり、存続期間中はこの同じ接続を保持します。クライアントはアプリケーション・モジュールに接続することにより、間接的にそれぞれ(中間層に)専用のJDBC接続をもつことになります。

図6: アプリケーション・モジュール・プーリングだけの利用

クライアントがデータアクセスを行うコンポーネントを要求すると、アプリケーション・プールはインスタンス・プールからアプリケーション・モジュールを取り出して使用します。その後、そのインスタンスが必要なくなったとき(たとえば、HTTPセッションが期限切れになったとき)に解放してプールに戻します。使用可能なインスタンスがない場合は、プールが新しいインスタンスを作成します。アプリケーション・モジュール・プーリングを使用すると、クライアントがアプリケーションにアクセスするたびに新規アプリケーション・モジュールをインスタンス化する必要がないため、クライアントのためのサーバー側リソース・コストが少なくてすみます。
BC4Jデータ・タグを使用している場合、アプリケーション・モジュールのタイプごとに1つのアプリケーション・モジュール・プールがあり、JVMインスタンス1つにつき1つのプール・マネージャがあります。

デフォルトでは、プールは必要なときに新規アプリケーション・モジュール・インスタンスを作成します。アプリケーション・モジュール・インスタンスの数に上限はありません。これにより、アプリケーションがスケーラブルになり、クライアント数はビジネス・コンポーネント・フレームワークの制約を受けません。実際には、アプリケーションが適切にサポートできる同時クライアントの数はシステム・リソースにより制限され、プール内のアプリケーション・モジュールの数にも上限を設けることが普通です。プールに未使用のインスタンスが多数含まれている場合、プールのサイズを小さくすることが必要なこともあります。これを行うには、独自のアプリケーション・モジュール・プールを実装する必要があります。

アプリケーション・モジュール・プーリングの利用と設定

HTMLクライアントからのアプリケーション・モジュール・プーリングの利用

BC4Jデータ・タグを使用してJSPからのデータアクセスを行う場合、ApplicationModule タグを使ってアプリケーション・モジュールを指定するだけで自動的にアプリケーション・モジュール・プーリングが使用されます。

参考 : JSPからのBC4Jデータタグの利用例

クライアントがサーブレットの場合や、独自のカスタム・タグ・ハンドラからアプリケーション・モジュールにアクセスする場合は、アプリケーション・モジュール・プーリングを使用するために、次のことを行う必要があります。

参考 : サーブレットからの利用例

この時に使用するアプリケーション・モジュール・プールをデフォルトのものではなく、独自のクラスで制御したい場合は構成プロファイルの中で指定します(PoolClassName プロパティ)。
アプリケーション・モジュール・プールの実装

アプリケーション・モジュール・プールのデフォルトの実装クラスは、ApplicationPoolImpl です。デフォルト実装クラスを使用するだけでなく、ApplicationPoolImpl を継承して拡張したり、ApplicationPool インタフェースを実装したりすることによって、独自のプールを実装することもできます。

アプリケーション・モジュール・プーリングに関連するクラスとインタフェースは、すべて oracle.jbo.common.ampool パッケージに用意されています。

図7: アプリケーション・モジュール・プーリングに関わるパッケージ、クラスとその関連性

プール再利用しきい値の設定

デフォルトでは、アプリケーション・モジュール・プールの再利用しきい値は10です。これは、プールが各クライアントのリクエストに応答して新規アプリケーション・モジュール・インスタンスを作成し、10個のインスタンスを作成したときに、アクティブでないインスタンスの中から再利用できるものを探し始めるということを意味します。プール再利用しきい値を変更するには、 jbo.recyclethreshold パラメータを使用します。

再利用しきい値が低い数値に設定されていると、プールが大きくなりすぎる可能性が低いため、リソースの限界に達することなく処理できるといえます。ただし、あまりに再利用しきい値が低すぎると、アプリケーションはアプリケーション・モジュール状態を保存してアクティブにすることに時間を費やすため、パフォーマンスに影響します。

接続プーリングを使用したアプリケーション・モジュール・プーリング

アプリケーション・モジュール・プーリングに加えて、さらに接続プーリングを利用することができます。図8はこの方法を示します。

図8: アプリケーション・モジュール・プーリング + JDBC接続プーリング

アプリケーション・モジュール・インスタンスがデータベース接続を必要とする場合は、接続プール・マネージャがプールから接続を割り当てます。使用可能なインスタンスがない場合、プールは新しいインスタンスを作成します。アプリケーション・モジュール・インスタンスが切断すると、その接続はプールに戻されます。接続URLのそれぞれに対して1つの接続プールが用意されます。つまり、ユーザー名、パスワードおよびデータベースの一意の組合せに対して接続プールがそれぞれ1つあります。このため、各ユーザーが別々のユーザー名とパスワードでデータベースに接続している場合は、接続プーリングが特に役立つわけではありません。

JDBC接続プーリングを使用可能または使用不可にするには、構成プロパティのひとつであるjbo.doconnectionpooling プロパティを設定します。デフォルトでは、ステートフル・モードでJDBC接続プーリングを使用しないという設定になっています。つまり、ステートフル・モードでアプリケーション・モジュール・インスタンスを解放した場合、その接続は接続プールに戻らないということです。ステートレス・モードで解放すると、接続は常に接続プールに戻り、jbo.doconnectionpooling の値は無視されます。

JDBC接続プーリングを使用したアプリケーション・モジュール・プーリングを選ぶ場合

データベース接続数を制限したい場合には接続プーリングを使用します。特に、アプリケーションで同一ユーザー名およびパスワードを使用して同一データベースに多数のユーザーを接続するときは有効です。複数のアプリケーション・モジュール・プール間でJDBC接続を共有するときも、JDBC接続プーリングを使用できます。

接続プールの構成

接続プールに関して、次のオプションを使用できます。

アプリケーション・モジュール・インスタンスの解放モード

従来より、大量アクセスが見込まれるインターネット・アプリケーションはステートレスにする必要がありました。なぜなら、セッション状態(ステート)を保つためにはクライアントとHTTPサーバー間に専用の接続が必要で、このような場合、ユーザー数が増えるとすぐにサーバー・リソースを使い切ってしまうからです。しかしながら、ステートレス・アプリケーションの弱点は、要求のたびにユーザーのセッションのステートを再作成する必要があるということで、これがパフォーマンスに悪影響を及ぼしていました。

JSPまたはサーブレット・アプリケーションの場合、3つのモードのいずれかでアプリケーション・モジュール・インスタンスを解放できます。

ステートレス・モード

ステートレス・モードでは、アプリケーション・モジュール・インスタンスが解放されるとすぐに、アプリケーション・モジュールのステートが元に戻されます。次に、アプリケーション・モジュール・インスタンスは再利用可能としてマークされ、他のクライアントがすぐに使用できるようになります。

図9: ステートレス・モード
次のチェックアウト時にどのインスタンスが使用されるかわからない

ステートレス・モードを選択する場合
一連のセッションの終わりにアプリケーション・モジュールをステートレス・モードで解放することは、理にかなっています。たとえば、ショッピング・カート・アプリケーションでは、ユーザーが買物をしている最中はアプリケーション・モジュールをステートフル・モードまたはリザーブ・モードで解放し、ユーザーが注文を送付したときにステートレス・モードで解放します。

リザーブ・モード

リザーブ・モードでは、アプリケーション・モジュールがチェックインされたときに、アプリケーション・モジュールのステートとデータベースのステートが保たれます。これは、ユーザーには常に同一アプリケーション・モジュール・インスタンスに接続することが保証されるということです。この解放モードは、ほかのモードに比べてメモリ・リソースの消費量が大きいため、リクエスト間ではアプリケーション・モジュール・インスタンスを解放する方が得策です。

リザーブ・モードではJDBC接続を保持するため、JDBC接続プーリングを使用したアプリケーション・モジュール・プーリングを使用している場合にリザーブ・モードでの解放を使用しても意味がありません。

図10: リザーブ・モード
インスタンスを"予約"してしまう

リザーブ・モードを選択する場合
リザーブ・モードではパフォーマンスは向上しますが、フェイルオーバーが使用できないためスケーラビリティと信頼性は下がります。このモードは、一連のリクエストを高いパフォーマンスで実行するときに役立ちます。データベース・ステートを維持する必要がある場合(たとえば、データベースへのデータの転送とそのコミットが別々のリクエストで行われる場合)にも役立ちます。

ステートフル・モード

ステートフル・モードでは、HTTPリクエスト間でアプリケーション・モジュールのステートが保たれ、アプリケーション・インスタンスをリサイクルできます。

ステートフル・モードの動きとしては、ブラウザがJSPページまたはサーブレットから1ページを取り出して表示するとすぐに、BC4Jランタイムがアプリケーション・モジュール・インスタンスをアプリケーション・モジュール・プールにチェックインし、そのステートを保存します(注意: ステート保存のタイミングは、後述するフェイルオーバー機能が使用禁止になっている場合は異なります)。クライアントが次に同じアプリケーション・モジュールを要求した場合、アプリケーション・モジュール・プールは、クライアントが以前にチェックインしたインスタンスを(そのインスタンスがリサイクルされていない限り)返します。インスタンスがリサイクルされてしまった場合は、プールが別のアプリケーション・モジュール・インスタンスをチェックアウトし、保存されているステートを使用してそのステートを設定します。クライアントには違いはわかりません。

アプリケーション・モジュールのステートを保存することを非活性化(パッシべーション)と呼びます。保存されているステートを取り出し、プールされているアプリケーション・モジュール・インスタンスにこのステートを割り当てることを活性化(アクティベーション)と呼びます。

図11: ステートフル・モード
保存されたステートが再度適用されるため、インスタンスが異なってもステートは保たれる

アプリケーション・モジュールのステートを保存するオプション
アプリケーション・モジュールのステートは、ファイル内またはデータベース内に保存できます。これには構成プロパティである jbo.passivationstore プロパティを設定します。このプロパティには2つの値があります。
ステートフル・モードを選択する場合

JSPおよびサーブレット・アプリケーションには、通常、ステートフル・モードが最善の選択肢です。これは、セッションのステートを保存し、かつ、アプリケーション・モジュール・インスタンスをリサイクルできるためです。データベース・ステートはアプリケーション・モジュールのステートとともにはメンテナンスされないため、要求と要求との間でデータベース・ステートを保つ必要がある場合(たとえば、即時ロックや発行されたがコミットされていない変更に関する情報を保持する必要がある場合)は、ステートフル・モードを使用しないでください。

アプリケーション・モジュール・プールに対するクッキーの有効期間の設定

ステートフル・モードでは、アプリケーション・モジュールのステートはクッキーに保存されます。デフォルトでは、このクッキーはユーザーがブラウザを閉じたときに削除されます。このクッキーの有効期間は構成プロパティのjbo.maxpoolcookieageプロパティを使用して変更できます。

解放モードの指定

アプリケーション・モジュールの解放モードは、次の方法で指定されます。

パフォーマンスとスケーラビリティに関連するその他の機能

アプリケーション・モジュールのフェイルオーバー

BC4Jフレームワークでは、マシンやネットワークの障害などの予期できない状態が発生した場合にアプリケーションのステートを保護するために、アプリケーション・モジュール・インスタンスに対してフェイルオーバーの機能を提供します。フェイルオーバーはデフォルトではオンです。これは構成プロパティの jbo.dofailover プロパティを設定して変更できます。このプロパティには2つの値があります。 アプリケーション・モジュールのフェイルオーバーは、ステートフルな解放モードに対してのみ適用されます。フェイルオーバーを使用禁止にすると、パフォーマンスは向上しますが信頼性は下がります。

SQLベースのビュー・オブジェクトと順方向限定のビュー・オブジェクト

データを更新しない場合や、検索された結果セット内での移動(結果セット内でデータの次へまたは前へ進む、といった操作)が必要ないようなアプリケーションの場合など、状況に応じて、検索オブジェクト("ビュー・オブジェクト")のオプション設定を行って機能を限定することで、さらなるパフォーマンスを実現できます。

実行時にBC4Jフレームワークを利用した問合せが実行されると、更新時のトランザクションにおけるデータ整合性のために、結果のデータをキャッシュに保存・管理します(トランザクションがコミットされると、そのキャッシュ内のデータが検査され、データベースに転送されます)。しかしながら、更新処理の必要がないアプリケーションの場合は、このようなキャッシングおよび検査などの処理は不要です(この、トランザクション管理のためにデータ・キャッシュや調整を行うオブジェクトを、BC4Jフレームワークでは"エンティティ・オブジェクト"と呼びます)。
このような場合にSQLベースのビュー・オブジェクトを使用します。SQLベースのビュー・オブジェクトは、SQL問合せ文から直接定義されるもので、そのベースとしてエンティティ・オブジェクトを使用しません。つまり、それらに伴うオーバーヘッドを回避するためパフォーマンスが上がります。一方で、SQLベースのビュー・オブジェクトは、データベース内のデータの更新には使用できません。アプリケーションの要件としてデータが決して更新されることがないという場合は、このSQLベースのビュー・オブジェクトとして作成するのがよいでしょう。

もうひとつのパフォーマンス向上の手段が、検索された結果の行セットに対する順方向限定(forward-only)モードの利用です。順方向限定(forward-only)モードでは、行セット内のデータは更新できず、順方向にのみ移動できるだけです。順方向限定(forward-only)の行セットは、通常の行セットと比べて高速でリソースの消費も少なくてすみます。このモードに設定するには、行セットに対してsetForwardOnlyMode()を呼び出します。
順方向限定(forward-only)ビュー・オブジェクトは更新できませんが、そのベースとしてエンティティ・オブジェクトを使用している場合は、同じオブジェクトをベースとする他のビュー・オブジェクトからのデータ更新内容は反映されます。

図12: 更新可能なビュー・オブジェクト(EmployeeView)からの更新内容は、
ベースのエンティティ・オブジェクトが同じビュー・オブジェクト(EmployeeList)にも伝播される

キャッシュされたデータのスピルオーバー

中間層で多数のトランザクション処理が行われると、そこでキャッシュされるデータ行が大量になるため、メモリ不足にならないようにする必要があります。そのために、行数が特定のサイズに達すると行が「オーバーフロー」してディスクに格納されるように指定することができます。この機能は、行のスピルオーバーと呼ばれます。

行のスピルオーバーが使用可能になっている場合、行はノードに格納されます。スピルオーバーのために、メモリ内の最大ノード数と各ノードに入れられる最大行数を指定します。アプリケーション内のアクティブな行数が指定された最大値を超えたときに、使用されていない行がデータベースに格納され、そのデータ整合性管理のために中間層にキャッシュされていたデータも解放されます(つまり、その分のメモリが解放されます)。行は要求に応じてメモリに戻されます。

注意: 行のスピルオーバーがサポートされているのは、Oracle8i 以上に対するデータアクセスのときのみです。

 

事例: Oracle iLearningでのパフォーマンスのチューニング

この項では、Oracle iLearning(ホスト・オンライン学習サービス)で、JSPクライアントによるWebモジュールとして配布されているBC4Jアプリケーションのパフォーマンスとスケーラビリティをどのようにチューニングしたかを説明します。

パフォーマンス・ボトルネック

iLearningプロジェクト・チームでは、システムで必要なリソース見積りのために、パフォーマンスとスケーラビリティに関する広範なテストを実施しました。典型的なパフォーマンス・ボトルネックである次のような要因を考慮し調査しました。

パフォーマンス・テストでは、前述の要因の1つを変更し、この要因がパフォーマンスに影響するかどうかを確認しました。テスト結果の詳細を以下に説明します。

データベース
Oracleデータベースはユーザー数による負荷が増大してもスケーラビリティは極めて良好です。

SQL問合せ
新しい索引付けとSQLチューニングにより、データベース問合せのパフォーマンスは著しく向上しました。

JVM数
リソースが十分にある場合は、マシンで実行するJVMの数の増加に従ってパフォーマンスが向上する可能性があります。ただし、1つのJVMが実行するスレッド数が25を超えると、パフォーマンスが低下し始めます。

メモリ
中間層のアプリケーション・サーバー上のメモリが、ユーザー数の増加を制約する主なリソース要因でした。使用可能なメモリが十分な場合、アプリケーションのスケーラビリティは線形でした。

アプリケーション・モジュールの数
CPUごとのアプリケーション・モジュールの数は、メモリおよびプロセッサ速度に依存します。また、各アプリケーション・モジュールが中間層への1ユーザーの接続を表しているため、中間層サーバーが受け入れられる最大接続数によっても制限されます。さらに、各アプリケーション・モジュールは1つのデータベース接続も表しているため、中間層サーバーが実行できるデータベース接続数によっても制限されます。iLearningアプリケーションは、アプリケーション・モジュール・プールからJDBC接続をプールしないため、アプリケーション・モジュール数がデータベース接続数より多くなることはありません。

パフォーマンス結果

iLearningは次の構成を使用して、51,000人の登録ユーザーをサポートし、同時ユーザーとして約8,000人をサポートできます。

まとめ

この項では、アプリケーションのパフォーマンスとスケーラビリティの向上のためにこの資料で説明した推奨事項をまとめます。

付録

この資料内で紹介したBC4J構成プロパティの一覧

構成プロパティ名 説明 デフォルト値
jbo.recyclethreshold プール再利用しきい値 10
jbo.doconnectionpooling JDBC接続プーリングを使用可能または使用不可にする false
+ jbo.initpoolsize 接続プールの初期サイズ 0
+ jbo.maxpoolsize 接続プールの最大サイズ 231-1
+ jbo.poolrequesttimeout 接続プールの待機タイムアウトの設定 30
jbo.passivationstore アプリケーション・モジュールのステートの保存先の指定 database
jbo.maxpoolcookieage アプリケーション・モジュール・プールに対するクッキーの有効期間 -1
jbo.dofailover アプリケーション・モジュールのフェイルオーバーを行うかどうか true

 

JSPからのBC4Jデータ・タグの利用例

   <!-- BC4Jのアプリケーション・モジュールを利用したデータの取り出し-->
   <%@ taglib uri="/webapp/DataTags.tld" prefix="jbo" %>
   <%@ page contentType="text/html;charset=Shift_JIS"%>
<HTML> <HEAD> <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=Shift_JIS"> <TITLE>BC4J Sample</TITLE> </HEAD> <!-- アプリケーション・モジュール"demo.Bc4jModule"を 構成名"Bc4jModuleLocal"で定義された構成で宣言 -->
<jbo:ApplicationModule id="Bc4jModule" configname="demo.Bc4jModule.Bc4jModuleLocal" releasemode="Stateful" /> <!-- 指定されたアプリケーション・モジュール(appid)内の データソース(ビュー・オブジェクト)を指定する --> <jbo:DataSource id="emp" rangesize="8" appid="Bc4jModule" viewobject="EmployeesView" /> <BODY> <!-- 指定されたデータソースのデータを表形式で表示--> <jbo:DataTable datasource="emp" /> </BODY> </HTML> <!-- アプリケーション・モジュールの開放--> <jbo:ReleasePageResources />

サーブレットからの利用例

import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
import java.util.Properties;

import oracle.jbo.common.ampool.SessionCookie;

import oracle.jbo.ApplicationModule;
import oracle.jbo.ViewObject;

import oracle.jbo.http.HttpContainer;
import oracle.jbo.http.HttpSessionCookieFactory;

public class AMPoolSample extends HttpServlet 
{
  private static final String CONTENT_TYPE = "text/html; charset=Shift_JIS";
  public static final String APPLICATION_ID = "1";

  public void init(ServletConfig config) throws ServletException
  {
    super.init(config);
  }

  public void doGet(HttpServletRequest request, HttpServletResponse response)
  throws ServletException, IOException
  {
    response.setContentType(CONTENT_TYPE);
    PrintWriter out = response.getWriter();
    out.println("<html>");
    out.println("<head><title>AMPoolSample</title></head>");
    out.println("<body>");
                
    out.println( getQueryResult(request, response) );

    out.println("</body></html>");
    out.close();
  }

  private String getQueryResult(HttpServletRequest request, HttpServletResponse response)
  {
    String configName    = "Bc4jModuleLocal"; //構成名
    String configPackage = "demo"; //パッケージ名

    // SessionCookie の取得
    SessionCookie cookie = findSessionCookie(request, request.getSession(true),
                           APPLICATION_ID, configPackage, configName);

    ApplicationModule am = null;

    String result = new String();
    try
    {
       am = cookie.useApplicationModule();

       // ブラウザのクッキーとして値を記述する
       cookie.writeValue(response);
   
       ViewObject empsVO = am.findViewObject("EmpView");
       empsVO.reset();
       while (empsVO.hasNext())
       {
          result += (empsVO.next().getAttribute("Ename") + "<br>");
       }
                
       //ステートフルで解放
       cookie.releaseApplicationModule(true, true);
       //二つのパラメータは( <チェックインするか>, <ステートを保持するか> ) を表す
       //ステートレスの場合(true, false)
       //リザーブの場合(false, true)
    }
    catch (Exception ex)
    {
       ex.printStackTrace();
       throw new RuntimeException();
    }

    return result;
  } 

  private SessionCookie findSessionCookie(
     HttpServletRequest request
     , HttpSession session
     , String applicationId
     , String configPackage
     , String configName)
  {
     Properties cookieProps = new Properties();
     // 以下のプロパティは必ず指定する
     cookieProps.put(HttpSessionCookieFactory.HTTP_SERVLET_REQUEST, request);
                 
     Properties poolProps = new Properties();
     // このプロパティで構成プロファイルの設定を上書きできる。例えば、使用する
     // プール・クラスを変更するには、以下のようにする
     // poolProps.put(PropertyConstants.ENV_POOL_CLASS_NAME, "<カスタム・プール・クラス名>");
     
     SessionCookie cookie = HttpContainer.findSessionCookie(
        session
        , applicationId
        , configName // この構成名をそのままプールの名前として使用する
        , configPackage
        , configName
        , poolProps
        , cookieProps);

    return cookie;
  }
}


Oracle Corporation
World Headquarters
500 Oracle Parkway
Redwood Shores, CA 94065
U.S.A.
世界共通窓口
+1.650.506.7000
Fax +1.650.506.7200
http://www.oracle.com/
版権(C) Oracle Corporation 2000
無断転載を禁ず  

このドキュメントはあくまでも参考資料であり、記載されている情報は予告なしに変更されることがあります。
万一、誤植などにお気づきの場合は、オラクル社までお知らせください。
オラクル社は本ドキュメントの内容に関していかなる保証もしません。
また、本ドキュメントの内容に関連したいかなる損害についても責任を負いかねます。

Oracleは、米国オラクル社の登録商標です。他のすべての企業名と製品名は、
識別のためにのみ掲載されており、それぞれの所有者の商標です。