この章では、Oracle Human Workflowをチューニングして最適なパフォーマンスを得る方法について説明します。Oracle Human Workflowは、次の分野のチューニングが可能です。
Oracle Human Workflowは、Oracle SOAサービス・インフラストラクチャ内で稼働するサービス・エンジンです。これを使用すると、対話型の人的プロセスを実行できます。ヒューマン・ワークフローは、プロセスの内部または外部で行われる承認処理、却下処理、再割当て処理といった人間のやり取りに対応しています。Human Workflowサービスは、ビジネス・プロセスと人間とのやり取りの様々な側面を処理する多くのサービスからなります。
詳細は、『Oracle Fusion Middleware Oracle SOA Suite開発者ガイド』のヒューマン・ワークフロー・サービス・コンポーネントの使用に関する項を参照してください。
Oracle Human WorkflowのWebサイト(http://www.oracle.com/technology/products/soa/hw/index.html
)も参照してください。
サイクル・タイム、その他の統計を監視して、負担の大きいグループや完了まで時間がかかるグループのスタッフを増員することができます。このように、レポートを効果的に使用すれば、ワークフローの完了を確実に迅速化できます。不参加タスク・レポートを確認して、長期間キューに入っているタスクを特定のユーザーに割り当てることができます。
監視および予防的な問題解決を容易にするワークフロー・レポート(および対応するビュー)がいくつか用意されています。これらのレポートのごく一部を次に示します。
不参加タスク・レポート: まだユーザーが獲得して処理していないため、注意が必要なグループ・タスクのリストです。
タスクのサイクル・タイム・レポート: 特定のタイプのワークフローが完了するまでの時間を把握できます。
タスクの生産性レポート: 様々なユーザーのタスクのインフローおよびアウトフローを示します。
割当て先時間分布レポート: 各ユーザーがタスクのライフ・サイクルの中で費やした時間(タスクがユーザーによって獲得されるまで待機したアイドル時間を含む)を詳細にドリルダウンできます。
監視の詳細は、「Oracle Fusion Middlewareの監視」を参照してください。
この項では、パフォーマンスの問題に対応するための様々な方法について説明します。
ワークフロー・クライアント・アプリケーションが対話型の場合、クライアント側の最適なレスポンス時間を維持することが重要です。レスポンス時間に影響を与える要素としては、サービス・コールのパフォーマンスの影響、リクエストに該当するタスク・セットを特定するための問合せ時間、該当タスクごとに取得される追加情報の量などがあります。
ワークフロー・サービスは、主にSOAPクライアントとEJBクライアントの2種類のクライアントをサポートしています。EJBクライアントは、さらにローカルEJBクライアントとリモートEJBクライアントに分けられます。
クライアント・アプリケーションが.Netテクノロジをベースとしている場合は、SOAPワークフロー・サービスしか使用できません。一方、クライアント・アプリケーションがJava EEテクノロジをベースとしている場合は、ユースケース・シナリオを基に、使用するクライアントを検討してください。選択肢を次に示します。
リモート・クライアント: ほとんどの場合、パフォーマンスの点ではこれが最善の選択肢です。クライアントがワークフロー・サービスと同じJVMで稼働している場合(soa-infraアプリケーション)、APIコールはリモート・メソッド呼出し(RMI)の必要がないように最適化されます。クライアントが別のJVMに存在する場合は、RMIが使用されます。このとき、APIメソッド間でデータのシリアライズおよびデシリアライズが行われるため、パフォーマンスに影響が出ることがあります。
SOAPクライアント: Webサービスに基づいた標準化を行うにはこの選択肢のほうが望ましいのですが、リモート・クライアントでリモート・メソッド呼出し(RMI)を使用する場合と比べて、パフォーマンス面の考慮事項が増えます。Webサービス・テクノロジによって追加の処理が行われるため、XML間でAPIメソッド引数の整列化および非整列化が発生します。
詳細は、『Oracle Fusion Middleware Oracle SOA Suite開発者ガイド』を参照してください。
厳密なフィルタを使用することは、レスポンス時間を短縮するうえで最も重要な要素の1つです。タスク・リストを取得する際に、データベース・レベルで最大限のフィルタ処理を行えるよう、問合せをできるだけ厳密なものにする必要があります。
たとえば、ユーザーの受信ボックス表示がリクエストされた場合、タスクは主に、現在のユーザーまたはユーザーの属するグループに割り当てられているかどうかを基準にフィルタ処理されます。受信ボックス表示に述語フィルタを追加指定すれば、該当するタスクの数が減るため、問合せの総レスポンス時間を短縮できます。
あるいは、述語フィルタを指定してビューを定義することもできます。こうすれば、該当するタスクの数が減るため、ビューの総レスポンス時間は短くなります。問合せAPIに渡される述語(またはビューで定義された述語)はすべて、データベース・レベルのSQL問合せに直接プッシュされます。この情報を基に、データベース・オプティマイザが最善の索引を使用して最適な実行計画を作成します。追加するフィルタは、タスクの属性に基づくものでも、プロモートされたフレックスフィールドに基づくものでもかまいません。たとえば、発注承認タスクをすべてリストするかわりに、優先度、日付、カテゴリ、金額範囲のいずれかに基づいてユーザーにタスクを提示するようビューを定義できます。
例: 優先度=1のユーザーに割り当てられたタスクをすべて取得するには、次のAPIコールを使用します。
Predicate pred = new Predicate(TableConstants.WFTASK_STATE_COLUMN, Predicate.OP_EQ, IWorkflowConstants.TASK_STATE_ASSIGNED); pred.addClause(Predicate.AND, TableConstants.WFTASK_PRIORITY_COLUMN, Predicate.OP_EQ, 1); List tasks = querySvc.queryTasks(ctx, queryColumns, null, ITaskQueryService.AssignmentFilter.MY ITaskQueryService.AssignmentFilter.MY, null, pred, null, startRow, endRow);
前の項で説明したように、特定の条件に合せてタスク・リストを絞り込んだら、今度はユーザーに提示するタスクの数を基準に、次のレベルのフィルタ処理を行います。必要以上に多くの行をフェッチするのは避けてください。フェッチされる行が多すぎると、問合せに時間がかかるだけでなく、アプリケーションの処理時間が長くなり、クライアントに返されるデータの量も増えるためです。問合せAPIには、ユーザーに返される該当行の数および開始行を制御するページング・パラメータが用意されています。
たとえば、次のようなqueryTasks
メソッドがあるとします。
List tasks = querySvc.queryTasks(ctx, queryColumns, null, ITaskQueryService.AssignmentFilter.MY, null, pred, null, startRow, endRow);
startRow
パラメータおよびendRow
パラメータを、返される一致レコードの数を制限するような値に設定することを検討してください。
queryTaskサービスを使用する際は、リスト内のタスクごとに取得するオプション情報の量を減らすことを検討してください。そうすることで、追加のSQL問合せやJavaロジックがパフォーマンスに与える影響を軽減できます。
たとえば、次のqueryTasks
メソッドでは、グループ・アクションの情報のみが取得されます。添付ファイルおよびペイロードの情報を直接リストに取得することもできますが、パフォーマンスに影響が出る可能性があります。
List<ITaskQueryService.OptionalInfo> optionalInfo = new ArrayList<ITaskQueryService.OptionalInfo>(); optionalInfo.add(ITaskQueryService.OptionalInfo.GROUP_ACTIONS); // optionalInfo.add(ITaskQueryService.OptionalInfo.ATTACHMENTS); // optionalInfo.add(ITaskQueryService.OptionalInfo.PAYLOAD); List tasks = querySvc.queryTasks(ctx, queryColumns, optionalInfo, ITaskQueryService.AssignmentFilter.MY, null, pred, null, startRow, endRow);
まれに、ペイロード全体が必要になることもありますが、その場合はペイロード情報をリクエストできます。通常は、タスク・リストを表示するためにペイロード・フィールドの一部が必要になるだけです。たとえば、発注関連のタスクで、発注額の列を表示する必要があるとします。ペイロードを追加情報としてフェッチしてから、xpath式を使用して金額を取得し、リストに表示するかわりに、金額の列をペイロードからフレックスフィールドにマップすることを検討してください。そうすれば、SQL問合せの中でフレックスフィールドを直接取得でき、処理時間が大幅に短縮されます。
同様に、添付ファイルの名前がリストに表示され、ドキュメント自体は外部リポジトリに格納されるようなケースでは、ペイロード内の添付ファイル名を取得してフレックスフィールドにマップすることを検討してください。そうすることで、処理時間が最適化されます。リスト情報を構成する際には、該当するフレックスフィールドをフェッチすれば、添付ファイルへのリンクを構成できます。
queryTask
サービスを使用する際は、問合せ列の数を減らして、SQLの実行時間を短縮することを検討してください。また、一般的な列を使用するよう努めてください。一般的な列は索引が作成される可能性が高く、SQLの実行時間の短縮につながるためです。
たとえば、次のqueryTasks
メソッドでは、TASKNUMBER
列およびTITLE
列のみが返されます。
List queryColumns = new ArrayList(); queryColumns.add("TASKNUMBER"); queryColumns.add("TITLE"); ... List tasks = querySvc.queryTasks(ctx, null, ITaskQueryService.AssignmentFilter.MY, null, pred, null, startRow, endRow);
タスク情報を要約したチャートや統計を表示することが必要になる場合があります。問合せAPIを使用してすべてのタスクをフェッチし、クライアント・レイヤーで統計を計算するかわりに、新しい集計APIを使用して、データベース・レベルで統計を計算することを検討してください。
たとえば次のコールは、APIを使用して、ユーザーに割り当てられたタスクの状態を基に要約された統計を取得する方法を示しています。
List taskCounts = querySvc.queryAggregatedTasks(ctx, Column.getColumn(WFTaskConstants.STATE_COLUMN), ITaskQueryService.AssignmentFilter.MY, keyWordFilter, filterPredicate, false, false);
特定の条件に一致するタスクの数をカウントするだけでよい場合があります。queryTasks
APIメソッドをコールして返されたリストのサイズを調べるかわりに、countTasks
APIメソッドをコールすれば、条件に一致するタスクの数のみが返されます。タスク数が返される場合のパフォーマンスへの影響は、タスク・オブジェクトのリストが返される場合よりはるかに小さくなります。
たとえば次のコールは、APIを使用して、ユーザーに割り当てられたタスクの総数を取得する方法を示しています。
int numberOfTasks = querySvc.countTasks(ctx, ITaskQueryService.AssignmentFilter.MY, keyWordFilter, filterPredicate);
ワークフロー・スキーマ表WFTASKには、フレックスフィールド属性列がいくつか含まれています。これらを使用すると、ワークフロー・スキーマにタスク・ペイロード値を格納できます。列の数が多く、列の使用はオプションであるため、インストール済のスキーマにはこれらの列の索引は含まれていません。特定のマップ済フレックスフィールド列が問合せの述語で頻繁に使用されるようなユースケースでは、これらの列に索引を作成するとパフォーマンスが向上します。
たとえば、TEXTATTRIBUTE1列に索引を作成するには、次のSQLコマンドを実行します。
create index WFTASKTEXTATTRIBUTE1_I on WFTASK(TEXTATTRIBUTE1);
注意: 必要になる索引そのものは、使用するフレックスフィールド属性列、および実行する問合せの性質によって異なります。索引を作成したら、WFTASK表の統計を再計算して、フラッシュする必要があります。 |
特定の問合せ条件に一致するタスクが存在するかどうかを確認することが必要になる場合があります。countTasks
メソッドをコールして、返された数がゼロかどうかを確認するかわりに、doesTaskExistを使用することを検討してください。doesTaskExist
メソッドは、指定された条件に一致する行が存在するかどうかを確認するだけの、最適化された問合せを実行します。このメソッドを使用すれば、countTasks
をコールする場合より優れた結果が得られる可能性があります。
たとえば次のコールは、APIメソッドを使用して、ユーザーがタスク・インスタンスを所有しているかどうかを特定する方法を示しています。
boolean userOwnsTask = querySvc.doesTaskExist(ctx, ITaskQueryService.AssignmentFilter.OWNER,null,null);
この項では、複雑なパフォーマンスの問題に対応するための様々な方法について説明します。
負荷の高い状況でのシステムのスケーラビリティは、サーバーのパフォーマンスによって事実上決まります。第17.3.1項「クライアント側のレスポンス時間の最小化」では、適切な量の情報をフェッチすること、および問合せに伴うパフォーマンスへの影響を軽減することによって、クライアント側のレスポンス時間を最小化する手法をいくつか取り上げています。これらの手法には、データベースおよびサービス・ロジックがサーバー側のパフォーマンスに与える影響を軽減し、サーバーのパフォーマンスを改善する効果もあります。その他、次のような構成変更を行うとサーバーのパフォーマンスが向上します。
システムのデータベース・スケーラビリティは、システム内のデータ量によって大きく変わります。ビジネス・プロセスおよびワークフローは本来一時的なものであるため、処理が終われば、頻繁に問い合せられることはありません。完了したインスタンスがシステムに多数存在すると、システムの処理速度が低下する原因となります。アーカイブ手法を使用して、完了したインスタンスを別のシステムへ定期的に移動し、そこで履歴データの問合せに役立てることを検討してください。アーカイブを行う際には、孤立したタスク・インスタンスが発生しないよう注意する必要があります。
ワークフロー・コールバック機能を使用すると、タスクの割当てや完了といった重要なワークフロー・イベントの後、外部システムに対して問合せや更新を行うことができます。この機能は非常に便利ですが、パフォーマンスに影響を与えないよう正しく実装する必要があります。
パフォーマンスの重要性が高い場合は、各ワークフロー・イベントの後ではなく、タスクの完了後に外部システムを更新するための十分なリソースがあることを確認してください。たとえば、コールバックを使用するかわりに、タスクの完了後にサービスを1回呼び出します。コールバックが避けられない場合は、BPELコールバックではなくJavaコールバックを使用することを検討してください。Javaコールバックでは、コールバック・メソッドが同じスレッド内で実行されるため、BPELコールバックで発生するようなパフォーマンスへの影響は生じません。これに対し、BPELコールバックは、BPELエンジンへメッセージを送信する際に、パフォーマンスに影響を与える可能性があります。そのため、メッセージが正しいプロセス・インスタンスへ配信されるように、メッセージの関連付けが必要になります。ワークフロー・サービスは、サービスの呼出し後にBPELエンジンによってコールする必要があります。
通知は、実行すべきタスクがあることをユーザーに知らせるのに便利です。ほとんどの承認が電子メール経由で行われる環境では、アクション可能な通知が特に有効です。この場合、ワークリストの使用状況の点ではそれほど負荷がかかっていないとも言えます。ただし、ほとんどのユーザーがワークリストを通じてやり取りし、通知には二次的な意味しかないという場合は、通知を慎重に使用する必要があります。ワークフロー・イベントごとに通知を送信するかわりに、タスクが割り当てられたことをユーザーに知らせる目的に絞って、通知を最小限に抑えることを検討してください。また、タスクの内容も通知に含めて送信すると、パフォーマンスに影響が出る可能性があります。影響を最小限に抑えるには、通知のセキュリティを確保し、タスクの内容そのものではなく、タスクへのリンクのみを通知に含めて送信することを検討してください。
ワークフロー・インスタンスおよび状態情報はすべて、デハイドレーション・データベースに格納されます。ワークフロー・サービスはステートレスです。つまり、ノードのクラスタ上で複数のワークフロー・サービスを同時に使用できます。パフォーマンスの重要性が高く、スケーラビリティに優れたシステムが必要な場合は、クラスタ環境を使用してワークフローをサポートすることが可能です。クラスタ・アーキテクチャの詳細は、第33.2項「Oracle Fusion Middlewareでのクラスタの使用」を参照してください。
ワークフローの完了に要する時間は、ワークフローに指定されたルーティング・タイプによって異なります。ワークフロー機能には、ワークフローの完了に要する時間を短縮するための手段が用意されています。この項では、そうした手段の一部を説明します。
タスクが特定のユーザーの下で止まってしまうことのないよう、エスカレーション・ルールを指定できます。たとえば、タスクが処理されずに一定の時間が経過した場合は、そのタスクをマネージャへ進めることができます。別のルーティング・ロジックに基づいて他のユーザーへタスクをエスカレートする必要がある場合は、カスタム・エスカレーション・ルールを組み込むことも可能です。適切なエスカレーション・ルールを指定することで、ワークフローの完了に要する時間を短縮できます。
タスクを他のユーザーやグループの他のメンバーに手動で再割当てするかわりに、ユーザー・ルールおよびグループ・ルールを使用して自動再割当てを実行できます。こうすると、ワークフローにタイミングよくユーザーの注意を向けることができます。たとえば、特定のタイプのワークフローや特定のフィルタ条件に一致するワークフローを、指定した期間内に別のユーザーに自動的に再割当てするようなユーザー・ルールを設定します。同様に、グループ・ルールを使用すれば、異なるルーティング条件(ラウンド・ロビンや最も生産性の高い箇所など)に基づいて、ワークフローをグループのメンバーに自動的に再割当てすることができます。このように、ルールを使用することでワークフローの待ち時間が大幅に短縮され、ワークフロー完了の迅速化につながります。
ユーザーの受信ボックスには、様々な期日が設定された様々なタイプのタスクが格納されます。ユーザーは、手動でタスクを選別したり並べ替えたりして、次に処理するタスクを決める必要があります。タスクが期日や優先度に基づいてフィルタ処理されるようなタスク・ビューを作成すれば、作業の優先順位付けが自動的に行われるため、処理するタスクを決めるのに無駄な時間を費やさずに済み、タスクの完了に専念できるようになります。これも、ワークフロー完了の迅速化につながります。
ワークフロー・サービスでは、SQL問合せを構成する際、アイデンティティ・プロバイダの情報を使用して、ユーザーのロールやグループのメンバーシップを基にそのユーザーに該当するタスクを特定します。アイデンティティ・プロバイダに対しては、ロール情報を調べてユーザーがタスク詳細をフェッチする際の権限を特定したり、ユーザーがタスクに対して実行できるアクションを特定する目的でも、問合せが行われます。アイデンティティ・プロバイダへのリクエストを迅速化するには、いくつかの方法があります。
アイデンティティ構成ファイル内の検索ベースをできるだけ細かくノードに設定します。理想的なのは、ワークフロー関連のグループを単一ノードに集めて、検索および参照のためのトラバースを最小限に抑えることです。これは常に可能であるとはかぎりません。たとえば、既存のグループを使用して、他のノードのグループにメンバーシップを付与する必要が生じる場合もあります。フィルタを指定して検索対象のノードを絞り込むことが可能であれば、アイデンティティ構成ファイルにフィルタを指定してください。
アイデンティティ・プロバイダの重要な属性(dnやcnなど)のすべてに索引を作成します。そうすることで、検索や参照の際に、ツリー全体ではなくノードのサブセットのみがトラバースされるようになります。
キャッシュをサポートするアイデンティティ・プロバイダを使用します。LDAPプロバイダの中にはキャッシュをサポートしないものもありますが、Oracle Internet Directoryはキャッシュをサポートしているため、参照および検索の問合せが高速化されます。
Human Workflowスキーマでは、すべての表の最も重要な列にいくつかの索引があらかじめ定義されています。ユーザーのタスク・リストをフェッチするため、リクエストのタイプに応じて異なるSQL問合せが生成されます。データベース・オプティマイザは、様々な計画(全表スキャン、索引による表アクセスなど)のコストを評価して、よりコストの低い計画を決定します。オプティマイザが正しく機能するよう、索引統計を常に最新の状態に維持してください。データベースの使用方法を問わず、最大限のパフォーマンスを得るには、データベース統計を定期的に更新し、その他のチューニング可能なパラメータ(メモリー、表領域、パーティションなど)を効果的に使用することが重要です。
データベースのチューニングの詳細は、第2.6項「データベース・パラメータのチューニング」を参照してください。