SOA ベスト・プラクティス: BPEL Cookbook

BPEL の本番環境の管理
Stany Blanvalet

Oracle BPEL Process ManagerのAPIとデハイドレーション・ストアを使って、BPELの本番環境で共通の管理タスクを自動化する方法を学習します。

BPEL Cookbookの全記事

この記事に必要なダウンロード
Oracle BPEL Process Manager

2006 年1月公開

現行のITの機能や運用のメンテナンス/管理のために、 IT予算の約70%を費やしている組織もあります。しかし皮肉なことに、Webサービスのパフォーマンスと可用性の管理は、サービス指向アーキテクチャ (SOA)を実装しているほとんどの企業で優先度が高くありません。そのため、組織がSOAインフラストラクチャを構築するためにWebサービスと BPELを導入するにつれて、アプリケーションの管理コストを削減するための新しい戦略の設計がより急務となります。

この目標は、複数のビジネス・プロセスが本番環境に配置さ れていることが多いBPEL実装では、特に重要となります。本番環境にデプロイされるプロセスが多くなればなるほど、効率的な管理がますます重要となりま す。正常終了したか異常終了したかに関係なく、実行が完了したすべてのBPELプロセスは、プロセス・フローの各ステップで交換されたすべてのXMLメッ セージとともに、データベースに格納されます。ご推察の通り、このプロセスはデータベースのサイズを急激に拡大させ、パフォーマンス上のボトルネックを引 き起こします。

このため、BPELの本番環境では、次のことを実行できる 機能が重要となります。

  • 本番システムの安定性に影響を与えることなく、完了 したBPELプロセスに関する情報をアーカイブする
  • 正常に配信され解決されたすべてのXMLメッセージ を、データベースから削除する
  • 失効したインスタンスを削除する
  • 失敗したプロセスを再実行する

BPEL Cookbookの今回の記事では、Oracle BPEL Process ManagerのAPIとデハイドレーション・ストアを使ったこれらの機能の実現や、BPELプロセスの完了したインスタンス情報のアーカイブ/削除の戦 略について説明します。また、PL/SQLやEJBを使って、古いインスタンスを削除したり、XMLメッセージの呼び出しとコールバックを完了したりする 方法についても説明します。最後に、BPELテスト・ユーティリティを介して、失敗したプロセス・インスタンスを再実行する方法について説明します。

Oracle BPEL Process ManagerのAPIとデハイドレーション・ストア

Oracle BPEL Process Managerコンソールは、BPELサーバーにデプロイされたプロセスの管理やデバッグのための、使いやすいWebベースのインタフェースを提供してい ます。しかし、本番環境では、管理者は管理タスクを強力に制御する必要があります。BPELデハイドレーション・ストア・データベースに対する PL/SQL問合せやBPEL APIの実行を介して、これらの管理タスクのほとんどを自動化することができます。ただし、作業項目を作成する前に、デハイドレーション・ストアと BPEL Process Manager APIの基礎となる概念を理解しておく必要があります。

デハイドレーション・ストア・データベースは、(特に非同 期BPELプロセスの)プロセス・ステータスを格納するために使われます。ここでは、いくつかの比較的重要な表の概要を説明します。

内 容

CUBE_INSTANCE

インスタンス・メタデータ情報(作成日時、現 行の状態、プロセスID)

CUBE_SCOPE

インスタンスのスコープ・データ

AUDIT_TRAIL

インスタンスの監査証跡情報。この情報は、 BPELコンソールで表示できます。

AUDIT_DETAILS

プロセス・インスタンスに関する(サイズの大 きな)監査情報の詳細

DLV_MESSAGE

コールバック・メッセージ・メタデータ

DLV_MESSAGE_BIN

コールバック・メッセージのペイロード

INVOKE_MESSAGE

呼び出しメッセージ・メタデータ

INVOKE_MESSAGE_BIN

呼び出しメッセージのペイロード

DLV_SUBSCRIPTION

インスタンスの配信サブスクリプション

TASK

インスタンスに作成されたタスク(タイトル、 割当て先、ステータス、有効期限など)


表1: BPELデハイドレーション・ストアの主な表

データベース・スキーマは、$ORABPEL$ /integration/orabpel/system/database/scriptsディレクトリにあるDDLスクリプト domain_oracle.ddlで確認できます。このスキーマを正しく理解すれば、管理者はBPELコンソールを飛び越えて、デハイドレーション・ス トアに対する直接的なSQL問合せを書くことができます。

管理者は、SQLの利用に加えて、Oracle BPEL Process Manager APIを利用することもできます。さまざまな状態のインスタンスの検索、アーカイブ、削除、異なるドメインにわたるコールバック/呼び出しメッセージの削 除、特定のドメイン/プロセス/インスタンスのステータスの問合せを実行するための包括的な一連のクラスが、このAPIにはあります(API に関するドキュメントは、$ORABPEL$/integration/orabpel/docs/apidocs/index.htmlにあります)。 下の表に、関連するクラス/インタフェースと対応するメソッドの要約を示しています。

ク ラス/インタフェース

メ ソッド

WhereConditionHelperク ラス

各インスタンスを検索するwhere句 を構成するwhereInstancesClosed()whereInstancesStale()whereInstancesOpen()な どのメソッドを提供します。

IBPELDomainHandleインタ フェース

これによって、開発者は実行中のBPELプロ セス・ドメインで操作を実行できます。archiveAllInstances()deleteAllInstances()deleteInstancesByProcessId()deployProcess()undeployPorcess()deleteAllHandledCallback()deleteAllHandledInvoke()な どのメソッドを提供します。

IinstanceHandleインタフェー ス

これによって、ユーザーはアクティブ・インス タンスで操作を実行できます。isStale()getState()getModifyDate()delete()な どのメソッドを提供します。

Locatorクラス

これによって、ユーザーはプロセス・ドメイン でデプロイされインスタンス化されたプロセス、インスタンス、アクティビティを検索できます。listInstances()listActivities()な どのメソッドを提供し、パラメータとしてwhere句を取ることができます。


表2: 管理タスクを実行するための主なクラス

次に、いくつかの最も重要な管理タスクを実行する方法につ いて学習します。

完了したイン スタンスのアーカイブ

前述のとおり、正常に実行されたすべてのプロセス・インス タンスは、デハイドレーション・ストアに格納されます。現行リリースでは、BPELインスタンスは、インスタンス完了後にcube_instance、 cube_scopeという2つの表に保存されます。cube_instance表には、ドメイン、作成日時、状態(完了、実行中、失効、取消)、優先順 位、タイトルといったインスタンス・ヘッダー情報が格納されます。cube_scope表には、インスタンスの状態(変数値など)が格納されます。デフォ ルトでは、どちらの表も完了したインスタンスを格納するために使われます。

下図に示したとおり、BPELコンソールでデータベースか らインスタンス情報を消去することができます。


図1: 完了したインスタンスの削除

本番環境では、インスタンス情報を削除する前にその情報を アーカイブする必要があります。そして、それを数百ものインスタンスに対して実行する必要があります。幸運にも、PL/SQLやEJBを使ってこれを実現 できます(情報をBPEL データベースから消去する前に、その情報を別の場所に移動しなければならない点に注意しましょう)。いくつかの例を見てみましょう。

EJB を使ったアーカイブ。この例では、次のインタフェースとメソッドを使います。

com.oracle.bpel.client パッケージ

IBPELDomainHandleイ ンタフェース

メソッドの要約

int

archiveInstances(WhereCondition wc, boolean deleteInstances)

wc によって指定された検索条件に従って返されたすべてのインスタンスをアーカイブします。)

archiveInstancesメソッドは、完了したす べてのインスタンスをアーカイブし削除します。このメソッドは、完了したインスタンスがアーカイブされるまでの日数を示すkeepdaysパ ラメータを受け入れます。

public static int archiveInstances(Locator locator, String processId, int keepdays)
throws ORABPELAccessException {
try {
WhereCondition wc = WhereConditionHelper.whereInstancesClosed();
WhereCondition tmpWhere = new WhereCondition();
NonSyncStringBuffer buf = new NonSyncStringBuffer();
if (!"*".equals(processId)) {
buf.setLength(0);
tmpWhere.setClause(buf.append(" AND ").append(
SQLDefs.AL_ci_process_id).append(" = ? ").toString());
tmpWhere.setString(1, processId);
wc.append(tmpWhere);
}
Calendar cal = Calendar.getInstance();
cal.add(Calendar.DATE, -keepdays);
buf.setLength(0);
tmpWhere.setClause(buf.append(" AND ").append(
SQLDefs.AL_ci_modify_date).append(" <= ? ").toString());
tmpWhere.setTimestamp(1, cal.getTime());
wc.append(tmpWhere);
IBPELDomainHandle domain = locator.lookupDomain();
return domain.archiveInstances(wc, true);
} catch (ServerException se) {
throw new ORABPELAccessException(se.getMessage());
}
}

PL/SQL を使ったアーカイブ。管理者は、PL/SQLを使ってこの目的を達成することもできます。データベースからレコードを削除する前に、DBA は要件に応じてレコードを異なるデータベース/表に移動することができます。次に例を示します。


問合せ:
	SELECT CIKEY FROM CUBE_INSTANCE, DOMAIN
	WHERE BPELMNG.CUBE_INSTANCE.DOMAIN_REF = BPELMNG.DOMAIN.DOMAIN_REF
	AND BPELMNG.DOMAIN.DOMAIN_ID = 'XXX'		- XXXはドメイン名
	AND STATE = 5 					- '5'は「完了」
	AND MODIFY_DATE < SYSDATE-X			- Xは日数(前述のkeepdaysに相当)
	AND PROCESS_ID = 'XXX';				- XXXはプロセス名
	
アクション:
	各CIKEYに対して、COLLAXA.delete_ci(CIKEY)を呼び出します

                                          

次のセクションでは、コールバック・メッセージと呼び出し メッセージを削除する方法を学習します。

コールバッ ク・メッセージと呼び出しメッセージの削除

インスタンスがパートナからのメッセージを待機する状態(receiveonMessageな ど)になると、その特定の受信アクティビティのためのサブスクリプションが発行されます。配信メッセージを受信すると、配信レイヤーはそのメッセージを対 象のサブスクリプションとの相関を試みます。 正常にサブスクライブされたメッセージは、引き続きデータベース内に保持されます。これらのメッセージは、(前のセクションではインスタンスのアーカイブ のために実行した)collaxa.delete_ci(CIKEY)ストアド・プロシージャを介して削除されます。

すべてのコールバック/起動XMLメッセージに対しても、 同じことが当てはまります。このようなメッセージはすべて、正常に解決され配信された場合でも、データベースに保持されたままです。

次のメソッドを使用して、コールバック、呼び出し、サブス クリプションを削除できます。

com.oracle.bpel.client パッケージ

IBPELDomainHandleイ ンタフェース

メソッドの要約

int

deleteAllHandledCallback()

(このドメインに配信され、正常に解決され配 信されたすべてのコールバック・メッセージを削除します。)

int

DeleteAllHandledInvoke()

(このドメインに配信され、正常に解決され配 信されたすべての起動メッセージを削除します。)

int

DeleteAllHandledSubscription()

(正常に解決され処理された、つまりそのサブ スクライバにメッセージが配信された、このドメイン内のすべてのメッセージ・サブスクライバを削除します。)

次のストアド・プロシージャに示したとおり、PL/SQL を使っても同じことを実行できます。DBAはこのスクリプトを出発点として使用し、特定のアーカイブのニーズ(削除、別のデータベースへの移動、ビジネス 条件に基づいて選択するためのwhere句の変更など)に合わせてこのスクリプトを変更することをお勧めします。


/**
* 特定のドメインの呼び出しメッセージを削除するプロシージャ。
* 呼び出しメッセージは、invoke_message表とinvoke_message_bin
* 表に格納されています。このプロシージャは、invoke_message表
* からすべての呼び出しメッセージを選択します。配信され解決
* された各メッセージを、invoke_message表とinvoke_message_bin
* 表から削除します。
*/	
procedure delete_invoke( p_domain_ref in integer ) 
as
	cursor c_invoke_message is
	select message_guid
	from invoke_message
	where ( state = 2 or state = 3 )
		and domain_ref = p_domain_ref
	for update;
begin
	for r_invoke_message in c_invoke_message loop
		delete from invoke_message_bin
		where message_guid = r_invoke_message.message_guid;
		delete from invoke_message
		where current of c_invoke_message;
	end loop;
	commit; 
end delete_invoke;

/**
* 特定のドメインのコールバック・メッセージを削除するプロシージャ。
* コールバック・メッセージは、dlv_message表とdlv_message_bin表に
* 格納されています。このプロシージャは、dlv_message表からすべての
* 呼び出しメッセージを選択します。配信され解決された各メッセージを、
* dlv_message表とdlv_message_bin表から削除します。
*/	
procedure delete_callback( p_domain_ref in integer ) 
as
	cursor c_dlv_message is
	select message_guid
	from dlv_message
	where ( state = 2 or state = 3 )
		and domain_ref = p_domain_ref
	for update;
begin
	for r_dlv_message in c_dlv_message loop
		delete from dlv_message_bin
		where message_guid = r_dlv_message.message_guid;
        	delete from dlv_message 
        	where current of c_dlv_message;
	end loop;
	commit; 
end delete_callback;

                                          

次に、失効したインスタンスを削除する方法の概要を説明し ます。

失効したイン スタンスの削除

下図に示したように、BPELコンソールを使って、失効し たすべてのインスタンスを識別し、それらを削除することができます。


図2: BPELコンソールでの失効したインスタンスの削除

残念なことに、失効したインスタンスは特定のドメインに対 してしか検索できません。しかし、本番環境では、異なるドメインにまたがって複数のプロセスがデプロイされている可能性があるため、結果として管理負荷が 膨大になります。 その上、失効したすべてのインスタンスを1度に消去することは、不可能です。

別のアプローチとして、次のSQL問合せを使って、失効し た各インスタンスごとに一意のキューブ・インスタンス・キー(cikey)を検索できます。

SELECT CUBE_INSTANCE.cikey, CUBE_INSTANCE.root_id, 
CUBE_INSTANCE.process_id, CUBE_INSTANCE.domain_ref
FROM CUBE_INSTANCE
WHERE STATE = 9

失効した各インスタンスのcikeyを識別したら、その キーを使って、SQL問合せで検索した各キューブ・インスタンスごとにdelete_ci(CIKEY)を呼び出すことで、 CUBE_INSTANCE表と(そのキューブ・インスタンスを参照する)他の表から失効したインスタンスを削除できます。delete_ci(CIKEY) は、キューブ・インスタンスをパラメータとして取るストアド・プロシージャで、キューブ・インスタンスと(そのキューブ・インスタンスを参照する)他の BPEL表のすべての行を削除します。

このアプローチの1つの利点は、(where条件で domain句を削除すれば)複数のドメインにまたがって失効したインスタンスを削除できることです。もう1つの利点は、失効したインスタンスを一括消去 できることです。これら2つの利点から、PL/SQLは本番環境を管理する上での強力な候補となります。

次のサンプル・コードは、EJBでこれらのメソッドを使っ て、どのように失効したインスタンスをリストし削除するかを示しています。

WhereCondition where = WhereConditionHelper.whereInstancesStale();
IInstanceHandle[] instances = getLocator(domainId, domainPassword).listInstances(where);
for(int i=0; i<instances.length; i++){
instances[i].delete();
}

最初の2行は、ドメインごとに失効したすべてのインスタン スに対応するIInstanceHandle Beanの配列を返します。それから、IInstanceHandle.delete()を 使ってこれらすべてのインスタンスを削除しています。このコードは、すべてのドメインをカバーするように拡張するのは簡単です。

古いインスタンスのアーカイブと、失効したインスタンスや 処理済みのXMLメッセージの削除は、表のサイズを小さくする上で役立ちます。ただし、表をtruncateするかリビルドしないかぎり、行を削除するだ けでは空き領域は表領域に返されません。

次のコマンドを使うと、空き領域を取り戻すことができます。デハイドレーション・ストアの他の表に対しても同様のコマンドを実行できます。
alter table cube_scope enable row movement;
alter table cube_scope shrink space compact;
alter table cube_scope shrink space;
alter table cube_scope disable row movement;

さらに、将来的な拡大を防ぐために、DBAは PCTFREE、PCTUSED、PCTVERSIONパラメータを操作できます。

最後に、実行時に失敗したインスタンスを処理する方法につ いて説明します。

失敗したイン スタンスの再実行

BPELプロセスは、さまざまな理由で失敗することがあり ます。いくつか例を挙げると、不正な入力、不適切なプロセス設計、利用できない外部アプリケーションなどです。どの場合にも、プロセスは実行を正常に完了 せず、「フォルト」状態で終了します。不適切な設計が原因でプロセスが失敗した場合は、プロセス設計を変更し、BPELプロセスを再デプロイする必要があ ります。

しかし、不正な入力や外部の問題(ネットワーク障害、利用 できない外部アプリケーション)が原因でプロセスが失敗した場合には、入力を修正したり外部の問題を解消したりしてからプロセスを再実行したいと考えるで しょう。元のリクエストが適切に処理されるように、以前の入力を使ってプロセスを再実行できるのが理想的です。

(10.1.3以降で提供される)BPELテストを使っ て、この目的を達成できます。BPELテストは、ユニット・テストや統合テスト向けに、BPELプロセスのテスト・ケースの作成と実行のために設計された 重要なユーティリティです。BPELテストは、パートナ呼び出しをシミュレートしたり、アサーションを実行したりできます。また、各種テスト結果に関する 情報を提供できます (詳細については、こ こで公開されているBPELテストのオンライン・セミナーをご覧ください)。

BPELテストのもっとも重要な側面は、自動テスト生成と 呼ばれる、監査証跡からテスト・ケースを作成する機能です。たとえば、外部アプリケーションがダウンしていたために、プロセス・インスタンスが実行中に失 敗した場合を考えてみましょう。この場合、外部アプリケーションがオンラインに戻ったときに、まったく同じシナリオでプロセスを再実行できるのが理想的で す。ただし、このアプローチには若干の問題があります。外部の依存性を再構成する必要があるからです。外部の依存性は、プロセスの所有者によって制御され ている場合もあれば、制御されていない場合もあります。

代わりに、BPELテストを使って、失敗したインスタンス の監査証跡から基本的なテスト・ケースを生成できます。生成されたテスト・ケースには、失敗したインスタンスが保持していたとおりに正確にパートナをエ ミュレートするコマンドが含まれています。不正なデータが失敗の原因の場合には、テスト・ケースを正しいデータに変更できます。利用できない外部アプリ ケーションが原因でインスタンスが失敗した場合には、アプリケーションが稼動状態に戻ったときに、テスト・ケースを実行するだけで済みます。

まとめ

お分かりのとおり、Oracle BPEL Process ManagerのAPI、EJB、PL/SQLをBPELデハイドレーション・ストアに対して使って、BPELの本番環境の管理を部分的に自動化すること が可能です。より多くのBPELプロセスをデプロイすればするほど、日々のタスクを自動化し、本番環境の潜在的な問題を事前に解決するユーティリティのリ ポジトリの設計が急務となります。


Stany Blanvalet Stany Blanvaletは、BPELと J2EEのコンサルタントです。Stanyは、以前はJava EEのアーキテクトとして、ミッション・クリティカルなBPELの本番システムであるBelgacom社のBPELベースのDSLプロビジョニング・アプ リケーションの導入と管理に携わっていました。Stanyは、Oracle BPEL Process Manager対応のオープンソースJMXモニタリング・ツールを開発するjaisy -OrabpelInterfaceプロジェクトにも大きく貢献しています。