![]() ![]() ![]() ![]() |
可能な最大のパフォーマンスを得るためにポートレットを最適化するプロセスは、開発のすべての段階にまたがります。パフォーマンスを継続的にモニタし、適切な調整を行う必要があります。
この章では、ポートレットの開発時に組み込むことのできるパフォーマンスの最適化について説明します。
ポータルのパフォーマンスに影響を与える最も重要な変数の 1 つは、ポータル フレームワーク コントロールです。ポータル フレームワークのコントロール (ページ、ポートレット、ボタンなど) が多くなると、コントロール ツリーが大きくなります。
ポータルがインスタンス化されるときに、分類、すなわちポータル リソース (デスクトップ、ブック、ページ、ポートレットなど) の階層が生成されます。各リソースは、図 11-1 のようにコントロール ツリーのノードとして表されます。
この例では、1 つのポータルに 1 つのメイン ブックがあり、その中に 6 つのサブブックが含まれています。各サブブックにはそれぞれ 2 つのページがあり、各ページはそれぞれ 2 つのポートレットを含みます。これだけでも、このポータルのコントロールは少なくとも 42 になります。ボタン、ウィンドウ、メニュー、およびレイアウトを含めると、ポータルのコントロール数は大幅に増加します。
注意 : | この例は、極めて単純化したものです。エンタープライズ ポータルに含まれるコントロールは数千に及ぶことがあります。 |
コントロール ツリーが構築され、すべてのインスタンス変数がコントロールに設定されたら、ポータル全体を表示する前に、ツリーが各コントロールのライフサイクルを実行する必要があります。ライフサイクル メソッドは、深さ優先順で呼び出されます。つまり、各コントロールの init()
メソッドがすべて呼び出されてから、各コントロールの loadState()
メソッドが呼び出されるというように続きます。順序は、ポータルの分類における各コントロールの位置によって決まります。たとえば、図 11-2 のコントロール ツリーに示される分類は、ブック (B1)、ブックに含まれる 2 つのページ (P1 および P2)、各ページに含まれる 2 つのポートレット (p1 - p4) で構成される単純なポータルです (p2 にはさらにサブブック、ページ、ポートレットの階層も含まれています)。
このポータルが表示されるとき、init()
メソッド (_nfpb=true
の場合は handlePostBackData()
も) が各コントロールで最初に呼び出されます。順序は、B1、P1、p1、p2、B2、P3、p5、p6、P2、p3、p4 です。次に、loadState()
メソッドが同じ順序で呼び出されます。同様に、saveState()
まですべてのライフサイクル メソッドが呼び出されます。
注意 : | コントロールのライフサイクル メソッド preRender() 、render() 、および dispose() は、表示されるコントロールのみで呼び出されます。 |
ライフサイクルを通して各コントロールを実行するには、オーバーヘッドの処理時間が必要になります。コントロールが数千に及ぶポータルであれば、処理時間も比例して長くなります。このように、ポータルのコントロール ツリーが大きくなると、パフォーマンスへの影響も増大することがわかります。
ポータルの柔軟性を損なわずにコントロール ツリーのサイズを制限する最も単純な方法は、ポータルを複数のデスクトップに分割することです。ポータルの分類では、デスクトップは、別のポータルに埋め込まれたポータルとして扱われます。デスクトップは、ポータルに備わっているすべての機能を活用することができ、その中に別のデスクトップを含むことができます。
複雑なポータルを複数のデスクトップに分割すると、コントロールがそれぞれのデスクトップに分散されます。コントロール ツリーは個々のポータルに相当し、デスクトップはポータルと同様の動作をします。このため、各デスクトップが独自のツリーを持ち、そのツリーのコントロールはそのデスクトップが開かれたときにのみ構築されます。このように、大きなコントロール ツリーを持つ複雑なポータルを複数のデスクトップに分割することで、ツリーのコントロール数が、アクティブなデスクトップで必要な数にまで削減されます。つまり、ポータルを 1 つのデスクトップとして表示するために必要な時間が短縮し、ポータルのパフォーマンスが向上します。
ポータルが表示されるとき、処理時間の 15% はコントロール ツリーの構築に使用されます。ライフサイクル メソッドの実行には 70%、ガベージ コレクション (ヒープから不要なオブジェクトを消去して、新しいオブジェクトのために領域を解放するプロセス) には 15% が使用されます。構築とガベージ コレクションは常に実行されますが、ライフサイクル メソッドの実行は表示されるコントロール (デスクトップ上に見えているコントロール) についてのみです。したがって、複数のデスクトップの使用は、オーバーヘッドを大幅に節約し、システムのパフォーマンスの向上につながります。
たとえば、図 11-1 に示すコントロール ツリーの例は、42 のコントロールを含む 1 つのポータルを表します。このポータルを図 11-3 のように複数のデスクトップに分割した場合、ポータル全体でのコントロール ツリー数は増加しますが、各ツリーの大きさは約 3 分の 2 に縮小し、処理時間もおよそ 3 分の 2 になり、ポータルの表示に必要な時間が大幅に短縮されます。
図 11-4 は、図 11-3 の例を開いたときにどのように表示されるかを示します。
これらの例が示すように、複雑なポータルを複数のデスクトップに分割すると、パフォーマンスの向上の面では非常に効果的です。ただし、複数のデスクトップに分割する追加作業を考慮した場合、必ずしもすべてのポータルで有効な手段であるとは言えません。複数のデスクトップを使用してポータルを実装する前に、設計上の重要な決定事項について考慮する必要があります。次に例を示す。
デスクトップの作成の詳細については、「デスクトップ」を参照してください。
ツリー最適化の意味は、名前が示すとおりです。コントロール ツリーを表示するときに、システムのオーバーヘッドを最小限に抑えながらも、ユーザがポータル インスタンスを正常に使用するために必要なすべてのポータル コントロールを提供するようにします。
注意 : | ポートレットの非同期表示は、コントロール ツリーの最適化と共に使用できます。ポートレットの非同期表示の詳細については、『ポートレット開発ガイド』を参照してください。 |
コントロール ツリーの最適化を有効にするには、コード リスト 11-1 に示すように、.portal
ファイルの treeOptimizationEnabled
フラグを true に設定します。
<desktop> element:
<netuix:desktop definitionLabel="defaultDesktopLabel"
markupName="desktop"treeOptimizationEnabled="true"
markupType="Desktop" title="SimplePortal"><netuix:lookAndFeel
definitionLabel="defaultLookAndFeel">
<netuix:desktop/>
注意: | .portal ファイルに treeOptimizationEnabled= が含まれない場合、ポータルはデフォルトで treeOptimizationEnabled=false になります。 |
このフラグを true
に設定すると、ポータル フレームワークによってコントロール ツリーの全体ではなく一部が生成されます。この部分的なツリーは、表示されてアクティブになるコントロールだけで構成されます。このように、表示する必要があるコントロールが減るため、処理時間とコストを大幅に削減できます。
ポータルについて、このフラグを有効にするには、図 11-5 のように Workshop for WebLogic のプロパティ ビューで [ツリー最適化] を true に設定します。
注意 : | 新しいデスクトップのデフォルト値は treeOptimizationEnabled="true" です。 |
フラグが実際に機能するためには、コード リスト 11-2 のように、ファイル beehive-url-template-config.xml
(Portal_Web_Project/
webAppName/WEB-INF
にある) で <url-template>
要素に {url:currentPage}
が設定されていることが必要です。
注意 : | Workshop for WebLogic で新しいプロジェクトを作成すると、currentPage が自動的に追加されます。ただし、以前のバージョンの WebLogic Portal から移行している場合は、beehive-url-template-config.xml を手動で更新する必要があります。 |
<!-- URL templates -->
<url-template name="default">
{url:scheme}://{url:domain}:{url:port}/{url:path}?{url:queryString}
{url:currentPage}
</url-template>
<url-template name="proxyurl">
{url:scheme}://{url:domain}:{url:port}/{url:prefix}/{url:path}?
{url:queryString}{url:currentPage}
</url-template>
<url-template name="finurl">
https://fin.domain.com:7004/{url:prefix}/{url:path}?{url:queryString}
{url:currentPage}
&dept=finance
</url-template>
<url-template name="default-complete">
{url:scheme}://{url:domain}:{url:port}/{url:prefix}/{url:path}?
{url:queryString}{url:currentPage}
</url-template>
<url-template name="jpf-default">
http://{url:domain}:{url:port}/{url:path}?{url:queryString}
{url:currentPage}
</url-template>
<url-template name="jpf-action">
http://{url:domain}:{url:port}/{url:path}?{url:queryString}
{url:currentPage}
</url-template>
ポータル サーブレットはリクエスト (マウスのクリック) を受け取ると、キャッシュを読み込んで、コントロール ツリー ファクトリが存在するかどうかを判断します。存在しない場合は、controlTreeFactoryBuilder
を呼び出し、.portal
ファイルから XML を渡します。このクラスがコントロール ツリー ファクトリをサーブレットに返し、サーブレットがリクエストを CreateUIControlTree
クラスに渡します。
_pageLabel
と treeOptimizationEnabled="true"
が設定されている場合、CreateUIControlTreeFactory
が PartialUIControlTreeCreator()
メソッドを呼び出し、このメソッドは、指定のページ ラベルおよびアクティブなページとブックのラベルのセットで識別されるコントロールのみで構成されるコントロール ツリーを返します。これが、部分的なコントロール ツリーです。
たとえば、図 11-4 のポータルでツリー最適化が有効になっている場合、リクエストを発行する (マウスをクリックする) と、図 11-7 のようにアクティブなコントロールのみが表示されます。
saveState()
ライフサイクル メソッドの実行時に、このセッションでアクティブなページとブックのラベルのセットが格納されて、構築するコントロールが PartialUIControlTreeCreator
() に通知されます。これらのコントロールのみが構築され、ポータルのそれ以外のコントロールは無視されます。結果として、コントロール ツリーを最適化すると、構築する必要のあるコントロールが減少するため、処理オーバーヘッドが大幅に削減され、パフォーマンスが大いに向上します。
大規模なポータルの場合、単一レベル メニューを使用すると、複数レベル メニューを使用する場合よりも大幅にパフォーマンスを向上できます。環境によって条件は異なりますが、40 のブックで構成される大規模なポータルで、各ブックに 10 ページ、各ページに 10 のポートレットがあり (合計 4000 ポートレット) 、通常のユーザ負荷が 2000 同時ユーザになる場合を考えます。
この例の場合、単一レベル メニューを有効にすると、複数レベル メニューを使用するポータルよりも、システムの応答時間は少なくとも 2 倍速くなります。これは、コントロール ツリーの最適化がオンになっているかどうかに関係なく、複数レベル メニューではコントロール ツリーを走査してメニューの構築が可能である必要があるためです。複数レベル メニューを使用してコントロール ツリーを最適化する方法にも利点はありますが、この場合、システムのパフォーマンスが主な目的ではありません。
大量のコントロールを必要とする複雑なポータルを作成する場合に最適なポータル パフォーマンスを実現する最も簡単な方法は、ツリーを最適化することです。現在のポータル インスタンスでアクティブでないコントロールは構築されないので、時間とオーバーヘッドが大幅に減少します。ただし、ツリー最適化によってポータルの動作が少し変化することや、ポータルの実装によってはツリー最適化を使用することが有効であるとは限らないことに注意してください。以下に例を示します。
DesktopBackingContext、BookBackingContext、および PageBackingContext では、次のメソッドがアクセスしようとしたページ、ブック、またはポートレットが部分的なツリーに含まれないと、null が返されます。
public BookBackingContext getBookBackingContextRecursive(String definitionLabel)
public PageBackingContext getPageBackingContextRecursive(String definitionLabel)
public PortletBackingContext getPortletBackingContextRecursive(String instanceLabel)
public PortletBackingContext[] getPortletsBackingContextRecursive(String definitionLabel)
DesktopPresentationContext
、BookPresentationContext
、および PagePresentationContext
で次のメソッドのプレゼンテーション バージョンを使用した場合も、同じ動作が発生することがあります。
public BookPresentationContext getBookPresentationContextRecursive(String definitionLabel)
public PagePresentationContext getPagePresentationContextRecursive(String definitionLabel)
public PortletPresentationContext getPortletPresentationContextRecursive(String instanceLabel)
public PortletPresentationContext[] getPortletsPresentationContextRecursive(String definitionLabel)
メニューがアクティブなブックにある場合、そのメニューからアクセスできるすべてのコントロールは、ポータルが完全に表示される前に作成されることが必要です。このため、オーバーヘッドが増加し、パフォーマンスに大きく影響します。ただし、複数レベル メニューによって骨組みコントロール ツリーが作成されるため、目的の場所にナビゲートするために必要なリクエスト サイクル数が減少し、ナビゲーションを完了するために必要な合計オーバーヘッドは減少します。
通常、大規模なポータルの場合、単一レベル メニューを使用すると、複数レベル メニューを使用する場合よりも大幅にパフォーマンスを向上できます。環境によって条件は異なりますが、40 のブックで構成される大規模なポータルで、各ブックに 10 ページ、各ページに 10 のポートレットがあり (合計 4000 ポートレット)、通常のユーザ負荷が 2000 同時ユーザになる場合を例に取ります。この例の場合、単一レベル メニューを有効にすると、複数レベル メニューを使用する同じポータルよりも、システムの応答時間が少なくとも 2 倍速くなります。
この問題に対処するには、次のいずれかを実行します (優先順位が高い方から示しています)。
.portal ファイル内の「ツリー最適化」フラグがオンになっている場合、指定されたリクエストで一部の非表示ポートレットが処理されないことがあります(非表示ポートレットとは、指定されたリクエストに対して表示されないページ上に存在するポートレット)。これは、ポートレットの非アクティブ化イベント (onDeactivation
) を捕捉しようとした場合に問題になることがあります。ポートレットは非アクティブ化されると非表示になるので、システムがポートレットの非アクティブ化イベントを開始するためにポートレットを処理することはありません。推奨する解決策は、問題のポータルに対してツリー最適化を false に設定することです。ただし、ツリーの最適化が必要な場合は、裏技を使用できます。非アクティブ化イベントを捕捉する各ポートレットについて、ダミーのイベント ハンドラを定義します (たとえば、event = "[任意の文字列]" を指定してカスタム イベント ハンドラを作成し、"Only If Displayed" プロパティを false に設定します)。これによって、ポートレットは非表示かどうかにかかわらず、システムで処理されます。
これらの条件に十分に注意し、必ず事前にポータルで完全なリグレッション テストを実行してから、treeOptimizationEnabled
を true
に設定してください。上記のいずれかの問題が発生した場合は、ポータルの設計を再考するか、ツリー最適化を完全に無効にする必要があります。
これまで説明したように、コントロール ツリーの最適化はほとんどのポータルに効果的ですが、場合によっては動作の制約があるために無効にする必要があります。最適化を無効にすると、リクエストのたびにポータルによってコントロール ツリー全体が作成されます。このとき大規模なポータルではパフォーマンスに大きな影響が出ることに注意してください。予期されるパフォーマンスの低下が、機能の向上で埋め合わせられるかを判断する必要があります。
1 インスタンスのみでツリー最適化を無効にする場合は、リクエストのパラメータに nfto="false"
を含めます。URL はフレームワーク クラス GenericURL
および PostbackURL
を使用して生成されるため、パラメータを URL にプログラムによって追加する必要があります。これらのクラスの詳細については、WebLogic Portal「Javadoc」を参照してください。
PostbackURL url = PostbackURL.createPostbackURL(request, response);
url.addParameter(GenericURL.TRE_OPTIMIZATION_PARAM, "false");
WebLogic Portal では、コントロール ツリーを効果的に使用してポータルの分類を管理する他にも、パフォーマンスを向上させる方法があります。これらのソリューションはすべて、複数のデスクトップやコントロール ツリーの最適化と組み合わせて使用でき、ポータルの優れたパフォーマンスを実現します。この節では、WebLogic Portal で提供される最も効果の高いパフォーマンス向上ソリューションについて説明します。
資格によって、ポータル アプリケーション内のリソースにどのユーザがアクセスできるか、そのリソースに対してユーザが何をできるかが決定されます。このアクセスはアプリケーションの訪問者に割り当てられているロールに基づいており、これによって柔軟なリソース管理が可能になります。たとえば、「従業員レビュー」というポートレットがある場合、「マネージャ」という訪問者の資格ロールを作成してポートレットに割り当てると、ログインしたユーザのうち、そのロールに属するユーザのみがポートレットを表示できます。
アプリケーションを訪問するユーザには、ユーザ名、ユーザが属するグループ、日時、またはユーザのプロファイルの特徴などを含む条件式に基づいて、ロールが割り当てられます。たとえば、マイレージ サービスの参加者で前年に 50,000 マイル以上搭乗したユーザに「ゴールド メンバー」ロールを割り当てることなどができます。このロールは、ユーザがサイトにログインしたときに動的に割り当てられます。
ポータルの最適なパフォーマンスを実現するために、資格は慎重に使用してください。資格が多すぎると、パフォーマンスに大きく影響します。資格エンジンは、処理の表示段階で呼び出され、システムのオーバーヘッドとルールをチェックする必要があるためです。このチェックによってさらにシステムのオーバーヘッドが増加するため、ポータルでチェックが頻繁に必要になると、パフォーマンスが低下します。また、資格エンジンは管理タスクの管理も行うため、これによってもオーバーヘッドが増加し、パフォーマンスが低下します。
デフォルトで、資格は LDAP ではなくデータベースに格納されます。その場合でも、資格が多すぎるとパフォーマンスの低下につながる可能性があることに常に注意する必要があります。
資格を慎重に使用するための、簡単な推奨事項を以下に示します。
<control-resource-cache-size=
nn
>
属性の値を設定します。値には、ポータルで使用するデスクトップ数、ブック数、ページ数、ポートレット数、ボタン数 ([最大化]、[最小化]、[ヘルプ]、[編集] ボタン) の合計を指定します。使用可能なメモリ容量に懸念がある場合は、デフォルト値を使用します。
ポータル訪問者が変更できる対象を 1 ページまたは数ページのセットだけに制限し、残りのページは管理者が管理することをお勧めします。
ユーザがページをカスタマイズすると、ユーザはそのページのユーザ独自のインスタンスを取得します。カスタマイズされていない他のすべてのページは、元のライブラリ インスタンスを指します。管理者がページに変更を加えた場合、そのページをカスタマイズした各ユーザに対してその変更を繰り返し処理する必要があります。多くのユーザがそのページを変更した場合は、データベース処理が必要であるため、変更を伝播するのに時間がかかります。
レプリケートされたクラスタ環境では、ポータルでページ フロー ポートレットを使用すると、パフォーマンスの問題が発生することがあります。これらのポートレットに追加するリクエスト属性が、ページ フロー ポートレットの状態のコンポーネントとしてセッションに永続化されることがあるためです。追加するリクエスト属性が増えると、セッションのサイズが大きくなり、パフォーマンスが厳しく制約される可能性があります。
ページ フロー ポートレットは、ポータル フレームワーク内で、スコープ サーブレット環境によってホストされます。この環境は、サーブレット コンテナとして効果的に機能しますが、その動作のために、ページ フロー状態を永続化するコンテナ クラス内で、リクエスト属性のスコープがセッションに設定されます。これが特に望ましくないのは、大容量のデータ (このようなページ フロー ポートレットのリクエスト属性を含む) がクラスタ上でレプリケートされる場合です。
WebLogic Portal には、ページ フロー ポートレットにリクエスト属性の永続性 (requestAttrPersistence
) プロパティが用意されています。このプロパティは .portlet
ファイルに含まれており、Workshop for WebLogic のプロパティ ビューで設定できます。
session
: 既存の動作です (デフォルト)。デフォルトでは、すべての既存のページ フロー ポートレットで変更の必要がありません。transient-session
: 永続ページ フロー状態オブジェクトの、シリアライズ不可のラッパー クラスをセッションに挿入します。これらのポートレットの動作は、既存のポートレットと同じです。ただし、フェイルオーバの場合は例外です。永続リクエスト属性は、サーバへのフェイルオーバが発生すると消失します。この場合、転送 JSP を作成してこのような不測の事態を適切に処理する必要があります。そのためには、少なくとも、特定のリクエスト属性が設定されていることを前提とせず、自動的にリクエスト属性を再設定するメカニズムを用意するか、最後のアクションを再実行してリクエスト属性を再設定するためのリンクをユーザに表示するのが理想的です。フェイルオーバがない場合、リクエスト属性は永続化され、非ポストバック ポートレットに対してデフォルトの session
永続性ポートレットに匹敵するパフォーマンスが実現される。セッション メモリについては負荷が残りますが、永続リクエスト属性のための、追加のクラスタ レプリケーションの負荷は発生しません。none
: 永続性操作を実行しません。このようなポートレットには、更新要求時に使用できるリクエスト属性がありません。そのため、リクエスト属性が使用できないことを前提に転送 JSP を作成する必要があります。このオプションは、フレームワークによって発生する、永続リクエスト属性のためのセッション メモリのロードを完全になくす場合に役立ちます。
ページ フロー ポートレットについてリクエスト属性の永続性の属性を設定するには、図 11-8 のように、プロパティ ビューで [ページ フロー コンテンツ] グループの下の [リクエスト属性の永続性] ドロップダウンを開き、必要な値を選択します。
ポータルには、ファイルベースとストリーミングの 2 種類があります。ファイルベースのポータル (「ライト ポータル」とも呼ばれる) は、名前のとおりユーザのファイル システムからすべてのリソースを取得します。これに対して、ストリーミング ポータルは、リソースを 1 つ以上のデータベースから導出します。
ファイルベース ポータルとストリーミング ポータルの主な相違点は、複数のポートレット インスタンスの作成および管理に使用するメソッドです。ストリーミング ポータル (WebLogic Portal Administration Console を使って管理) を使用すると、ポートレットの単一のインスタンスを管理して、それをさまざまな場所で再利用できます。また、大量のポートレット インスタンスを容易に作成して、各インスタンスに異なるコンフィギュレーションを行うこともできます。ファイルベース ポータルを使用する場合、.portal ファイル内に個別のソース ポートレットを作成する必要があります。
ストリーミング ポータルでは、Administration Console の管理機能を利用することもできます。たとえば、ポートレットを無効にする場合には、Administration Console から簡単に操作することができます。Administration Console を使用しない場合には、プロダクション サーバに直接アクセスして .portal ファイルを変更する必要があります。また、Administration Console を使うと、ブックやページ コンテンツの管理、およびリソースの各種インスタンスに対する訪問者の資格や委託管理の機能を利用することもできます。
単純な静的ポータルでは、ファイル システムからリソースを導出するため、パフォーマンスが向上し、次の利点が得られます。
ファイルベース ポータルは、ストリーミング ポータルと比較してパフォーマンスが向上しますが、機能は限られます。たとえば、データベースを使用しないため、ユーザ カスタマイズや資格などの機能は利用できません。この他にファイルベース ポータルにない機能を以下に示します。
さらに、ほとんどのケースにおいて、ファイルベース ポータルの使用によるパフォーマンスの向上は、これらの制限の埋め合わせになるとは言えません。
この方法は実行時のパフォーマンス向上に直接はつながりませんが、アプリケーションをプロダクション環境に伝播する前にアプリケーションの実行の様子を確認することができます。開発時にプロダクション ドメインを作成することで、プロダクション環境でのポータルのパフォーマンスをシミュレートおよび評価できます。その後、必要な調整を行ってから、実際にポータルをデプロイすることができます。問題が発生する場合、またはパフォーマンスが最適ではない場合は、エンド ユーザに届く前にそのような状況を修正できます。
プロダクション ドメインを作成するには、起動スクリプトを更新します。WLS_PRODUCTION_MODE=
フラグを true
に設定し、次のフラグを false に設定します。
また、threadcount と JDBCConnectionPool のサイズにはデフォルト値を設定する必要があります。ポートレットをスレッド化 (forkable=true
を使用) する場合、config.xml
ファイルで portalRenderQueue
や portalPreRenderQueue
をコンフィグレーションし、フォークされたポートレットが WebLogic スレッド プールではなく独自のスレッド プールを使用するようにします。次のコード例は、スレッド数を適切に設定する方法を示します。
<ExecuteQueue Name="default" ThreadCount="15"/>
<ExecuteQueue Name="portalRenderQueue" ThreadCount="5"/>
ポータルでポートレットのパフォーマンスを最適化するには、以下のような方法を使用します。
上記の方法の詳細については、『ポートレット開発ガイド』を参照してください。
![]() ![]() ![]() |