ワークフロー サービス

Windows Server AppFabric によるスケーラブルで実行時間の長いワークフロー

Rafael Godinho

コード サンプルのダウンロード

ビジネス プロセスは、さまざまなアプリケーション シナリオに対応することが求められます。ヒューマン ワークフロー、サービスを通じて公開されるビジネス ロジック、プレゼンテーション層の調整、アプリケーションの統合などが考えられます。

こうしたシナリオはそれぞれ異なりますが、成功を収めたビジネス プロセスにはいくつか共通点があります。こうしたビジネス プロセスは、構築、使用、および修正が容易である必要があります。変化するビジネス ニーズを満たすことができるよう、スケーラブルであることも必要です。また、多くの場合、状態、準拠性、およびデバッグに関するなんらかのログ記録が必要となります。

ワークフローは、アプリケーションの形にまとめられたビジネス プロセスの良い例です。ワークフローには、前述の要素すべて (人のビジネス ニーズ、ビジネス ロジック、人とアプリケーションの間の調整、データの入力と状態の取得を容易に行えること) が盛り込まれています。これは、アプリケーションにとっても、コードにとっても、かなり多くの作業です。

さいわい、Microsoft .NET Framework と Windows Server AppFabric では、追跡可能で実行時間の長いワークフロー サービスを作成、配置、および構成するために必要なツールが提供されます。皆さんはおそらく、.NET Framework については既によくご存じでしょう。Windows Server AppFabric は、Windows Server 用の拡張機能の集まりで、これには、Windows Communication Foundation (WCF) および Windows Workflow Foundation (WF) をベースとしたサービス用のキャッシュ サービスとホスティング サービスが含まれます。

今月は、WCF、WF、および Windows Server AppFabric を使用して単純かつスケーラブルなワークフロー サービスを構築するプロセスについて、順を追って説明します。

ワークフロー サービスを作成する

ワークフロー サービスを作成するには、WCF と WF という 2 つのテクノロジを組み合わせる必要があります。この統合は開発者にとってシームレスで、ワークフロー内の WCF メッセージを受信するための特別なメッセージング アクティビティを使用して行います。ワークフローは、こうしたメッセージ用の WCF エンドポイントを公開する、ワークフロー固有の WCF ServiceHost (WorkflowServiceHost) でホストされます。メッセージング アクティビティ グループの中で、Receive アクティビティと ReceiveAndSendReply テンプレートの 2 つを情報の受信に使用することができます。これにより、ワークフローでは外部クライアントから Web サービス呼び出しとしてメッセージを受け取ることができます。

Receive アクティビティは、ワークフローが処理する情報の受信に使用します。このアクティビティでは、組み込みデータ型、アプリケーション定義のクラス、XML にシリアル化可能な型など、ほぼどのような種類のデータでも受信できます。図 1 は、ワークフロー デザイナー上の Receive アクティビティの例を示しています。

image: A Receive Activity on the Workflow Designer

図 1 ワークフロー デザイナー上の Receive アクティビティ

この種のアクティビティには多くのプロパティがありますが、中でも覚えておくことが非常に重要なのは次の 4 つです。

  • CanCreateInstance は、ワークフロー ランタイムが受信メッセージを処理するために新しいワークフロー インスタンスを作成する必要があるか、関連付けの手法を使用して既存のワークフロー インスタンスを再利用するかを特定するために使用します。関連付けについては、後で詳しく説明します。ワークフローの最初の Receive アクティビティでは、おそらくこのプロパティを true に設定することになるでしょう。
  • OperationName は、この Receive アクティビティが実装するサービス操作の名前を指定します。
  • Content は、サービスが受信するデータを示します。これは、WCF サービスの操作コントラクト パラメーターとよく似ています。
  • ServiceContractName は、生成された Web サービス記述言語 (WSDL) 内でサービス操作をグループ化するサービス コントラクトの作成に使用します。

Receive アクティビティは、単独で使用した場合、一方向のメッセージ交換パターンを実装します。このパターンは、クライアントから情報を受信するのに使用しますが、クライアントに応答は送信されません。この種のアクティビティは、SendReply アクティビティと関連付けることで、要求 - 応答パターンの実装に使用することもできます。

要求 - 応答パターンの実装に役立つように、WF は、Visual Studio ツールボックスに ReceiveAndSendReply というオプションを追加しています。これをワークフロー デザイナーにドロップすると、Sequence アクティビティ内に、構成済みの Receive アクティビティと SendReplyToReceive アクティビティのペアが自動的に作成されます (図 2 参照)。

image: ReceiveAndSendReply on the Workflow Designer

図 2 ワークフロー デザイナー上の ReceiveAndSendReply

ReceiveAndSendReply テンプレートの考え方は、Receive アクションと SendReplyToReceive アクションの間でなんらかの処理を行うというものです。ただし、Receive と SendReplyToReceive のペアの間で永続化は許可されていないことにご注意ください。非永続化ゾーンが作成され、このゾーンは両方のアクティビティが完了するまで存続します。つまり、ホストがアイドル状態になったワークフローを永続化するように構成されていたとしても、ワークフロー インスタンスがアイドル状態になった場合、そのワークフロー インスタンスは永続化されません。アクティビティが非永続化ゾーンでワークフロー インスタンスを明示的に永続化しようとした場合、致命的な例外がスローされ、ワークフローは中止され、呼び出し元に例外が返されます。

呼び出しを関連付ける

ビジネス プロセスは複数の外部呼出しを受信することもあります。その場合、最初の呼び出しで新しいワークフロー インスタンスが作成され、そのアクティビティが実行され、ワークフローは後続の呼び出しを待機してアイドル状態になります。その後の呼び出しが行われると、ワークフロー インスタンスはアイドル状態ではなくなり、引き続き実行されます。

このように、ワークフロー ランタイムが処理を継続するには、後の呼び出しで受信する情報を使用して、以前に作成されたワークフロー インスタンスを区別する方法が必要です。このような方法がなければ、ワークフロー ランタイムはどのようなインスタンスでも呼び出すことができてしまい、プロセス全体の整合性が危険にさらされてしまいます。この方法は関連付けと呼ばれ、後続の呼び出しを、その呼び出しに対応する保留中のワークフローと関連付けます。

関連付けは、特定のメッセージ内の特定のデータを識別するために XPath クエリとして表現され、InitializeCorrelation アクティビティを使用するか、いくつかのアクティビティ (Receive、SendReply、Send、ReceiveReply など) のプロパティである CorrelationInitializers に値を追加することで、初期化することができます。

この初期化処理は、コードで行うことも、Visual Studio 2010 のワークフロー デザイナーを使用して行うこともできます。Visual Studio には、XPath クエリの作成に役立つウィザードがあるため、そちらの方が、ほとんどの開発者にとって、より簡単な (そしておそらく、より好ましい) 方法です。

関連付けを使用する可能性があるシナリオの 1 つに、経費報告書ワークフローがあります。まず、従業員が経費報告書データを提出します。後で、管理者はその報告書を確認し、経費を承認または拒否することができます (図 3 参照)。

image: Expense Report Sample Scenario

図 3 経費報告書のサンプル シナリオ

このシナリオでは、ワークフローが従業員のクライアント アプリケーションに応答を返すときに関連付けが作成されます。関連付けを作成するには、経費報告書 ID (これはおそらく既に一意の ID でしょう) のような、なんらかのコンテキスト識別情報が必要です。その後、ワークフロー インスタンスは、管理者が経費報告書を承認または拒否するのを待機してアイドル状態になります。管理者のクライアント アプリケーションから承認呼び出しが行われると、ワークフロー ランタイムは、受信した経費報告書 ID を以前に作成したワークフロー インスタンスと関連付けて処理を継続します。

Visual Studio 2010 で関連付けを作成するには、まず、ワークフロー デザイナーで、関連付けを初期化するアクティビティを選択します。今回の例では、これは経費報告書 ID をクライアントに返すアクティビティです。SendReply アクティビティのプロパティ ウィンドウで CorrelationInitializers プロパティを設定します。これを行うには、省略記号ボタンをクリックします。[関連付け初期化子の追加] ダイアログ ボックスが表示されます (図 4 参照)。ここで関連付けを構成できます。

image: Setting the XPath Query Correlation

図 4 XPath クエリの関連付けを設定

関連付けハンドル、関連付けの種類、および XPath クエリという 3 つの項目を設定する必要があります。関連付けハンドルは、ワークフロー ランタイムが関連付けデータの格納に使用する変数で、Visual Studio が自動作成します。

次に、関連付けの種類を設定します。.NET Framework にはいくつかの種類の関連付けがありますが、今回は、クライアントと交換する情報の一部を照会する必要があるため (つまり、コンテンツ ベースの関連付けなので) クエリ関連付け初期化子を使用するのが最適な選択肢です。これを行ったら、今度は、XPath クエリを経費報告書 ID に設定します。矢印をクリックすると、メッセージの内容がチェックされ、一覧が表示されるため、適切な情報を選択します。

経費が承認された後でワークフローを継続するには、対応する Receive アクティビテが関連付けを使用する必要があります。これを行うには、CorrelatesOn プロパティを設定します。プロパティ ウィンドウで、このプロパティの近くの省略記号ボタンをクリックして、[CorrelatesOn の定義] ダイアログ ボックスを開きます (図 5 参照)。このダイアログで、CorrelatesWith プロパティを、SendReplyToReceive アクティビティの関連付けを初期化するのに使用するのと同じハンドルに設定する必要があります。また、XPath クエリ プロパティを、経費報告書承認メッセージで受信するのと同じキーおよび経費報告書 ID に設定する必要があります。

image: CorrelatesOn Definition

図 5 CorrelatesOn の定義

WF には、基本アクティビティ ライブラリ (BAL) という汎用アクティビティのセットが用意されており、その一部をここで情報の送受信に使用しました。BAL のアクティビティは便利ですが、よりビジネス ルールに関連したアクティビティが必要な場合もあります。これまでに説明してきたシナリオを踏まえると、経費報告書の提出と承認には、経費報告書の作成 (Create)、承認 (Approve)、および拒否 (Deny) という 3 つのアクティビティが必要です。この 3 つのアクティビティはどれもよく似ているため、CreateExpenseReportActivity のコードだけご紹介します。

public sealed class CreateExpenseReportActivity 
  : CodeActivity<int> {
  public InArgument<decimal> Amount { get; set; }
  public InArgument<string> Description { get; set; }
  protected override int Execute(CodeActivityContext context) {
    Data.ExpenseReportManager expenseReportManager = 
      new Data.ExpenseReportManager();
    return expenseReportManager.CreateExpenseReport(
      Amount.Get(context), Description.Get(context));
  }
}

このアクティビティは、経費の額と説明 (どちらも InArgument として宣言しています) を受け取ります。厄介な処理のほとんどは Execute メソッドで行います。このメソッドでは、データベース アクセスを処理し経費報告書情報を保存するために、Entity Framework を使用するクラスにアクセスし、また、Entity Framework は経費報告書 ID を返します。今回は CLR コードを実行する必要があるだけで、WF ランタイムとやり取りする必要はないため、アクティビティを作成する最も簡単な方法は CodeActivity から継承することです。完全なワークフローを図 6 に示します。

image: Complete Expense Report Workflow

図 6 完全な経費報告書ワークフロー

ワークフロー サービスをホストする

ワークフロー サービスを作成したら、それをどこで実行するかを決める必要があります。従来の選択肢は、独自のホスティング環境、IIS、または Windows プロセス アクティブ化サービス (WAS) で実行するというものでした。ですが、Windows Server AppFabric (WCF または WF を使用して作成されたサービスのホスティング、管理、セキュリティ保護、およびスケール変更のための、Windows Server 2008 R2 のアプリケーション サーバーの役割に対する拡張機能) を利用するという選択肢もあります。開発やテストのために、Windows Vista または Windows 7 を実行している PC で Windows Server AppFabric を使用することもできます。

IIS と WAS もサービスのホスティングをサポートしてはいますが、Windows Server AppFabric は、WCF と WF の機能 (永続化や IIS マネージャーによる追跡など) が統合された、より便利で管理しやすい環境を提供します。

簡略化されたワークフロー永続化

コンピューターがすべてのビジネス プロセスを処理するために使用できるリソースは依然として限られているため、コンピューティング リソースをアイドル状態のワークフローに無駄に費やすわけにはいきません。実行時間の長いプロセスについては、初めから終わりまでの合計時間を制御できない可能性があります。実行には、数分、数時間、数日、またはそれよりさらに長くかかる可能性があります。また、プロセスが外部エンティティ (他のシステムやエンド ユーザーなど) に依存する場合は、応答を待機してアイドル状態になっている時間がほとんどという可能性もあります。

WF では、ワークフロー インスタンス状態の永続的なキャプチャ (プロセスやコンピューターの情報に依存しない) をインスタンス ストアに格納することができる永続化フレームワークが提供されます。WF 4 には、追加設定なしで使用できる SQL Server インスタンス ストアが既定で用意されています。ただし、WF は拡張性が非常に高いため、必要であれば、ワークフロー インスタンス状態を永続化する独自のインスタンス ストアを作成することも可能です。ワークフロー インスタンスは、アイドル状態に永続化すると、メモリと CPU のリソースを確保するためにアンロードできます。また、最終的には、このインスタンスをサーバー ファーム内のあるノードから別のノードに移動することができます。

Windows Server AppFabric では、WF の永続化機能との統合を簡単に設定および管理することができます。このプロセス全体がワークフロー ランタイムに影響を与えることはなく、永続化タスクを AppFabric に委任するため、既定の WF 永続化フレームワークが拡張されます。

永続化を構成する最初の手順は、Windows Server AppFabric 構成ウィザードまたは Windows PowerShell コマンドレットを使用して SQL Server データベースを設定することです。ウィザードは、永続化データベースが存在しなければ作成することができます。また、単に AppFabric スキーマを作成することもできます。データベースの作成が済んだら、他の手順はすべて IIS マネージャーで実行することができます。

IIS マネージャーで、構成するノード (サーバー、Web サイト、またはアプリケーション) を右クリックし、[WCF サービスと WF サービスの管理] をポイントし、[構成] をクリックして [アプリケーションの WCF と WF の構成] ダイアログを開いたら、[ワークフロー永続化] をクリックします (図 7 参照)。ワークフロー永続化を有効または無効にするオプションがあることがわかります。

image: Configuring Workflow Persistence

図 7 ワークフロー永続化を構成

ワークフローがアイドル状態になったときにワークフロー ランタイムがワークフロー インスタンスをメモリからアンロードしてデータベースに永続化するのにかかる時間を設定するオプションもあります。既定値は 60 秒です。値をゼロに設定すると、ワークフロー インスタンスはすぐに永続化されます。これは、ロード バランサーによるスケールアウトにとって特に重要です。

ワークフローの追跡

外部のユーザーやアプリケーションとやり取りするプロセスで問題が発生することがあります。実行時間の長いプロセスが独立しているため、こうしたシナリオで問題がさらに悪化する場合があります。問題が発生すると、開発者は通常、何が起こったのか、問題の再現方法、および (最も重要なことですが) 問題を解決しシステムを動作させ続ける方法を突き止めるために、大量のログを分析する必要があります。WF を使用する場合、この種のログ記録が既にフレームワークに組み込まれています。

WF には、アイドル状態のインスタンスを永続化するための拡張可能なフレームワークがあるのと同様に、ワークフローの実行を可視化するための拡張可能なフレームワークもあります。このフレームワークは追跡と呼ばれます。追跡では、ワークフローが透過的にインストルメント化され、ワークフローの実行中に主要なイベントが記録されます。Windows Server AppFabric では、この拡張性を使用して、組み込みの WF 追跡機能を強化し、SQL Server データベースの実行イベントを記録します。

Windows Server AppFabric の追跡の構成は、永続化の構成と似ており、Windows Server AppFabric 構成ウィザードまたは Windows PowerShell コマンドレットを通じてアクセスできます。前述の [アプリケーションの WCF と WF の構成] ダイアログで、[監視] をクリックします。追跡を有効または無効にしたり、追跡レベルを選択したりできます (図 8 参照)。

image: Enabling Tracking on Windows Server AppFabric

図 8 Windows Server AppFabric での追跡を有効化

Windows Server AppFabric の追跡を構成する際は、次の 5 つの監視レベルを選択できます。

  • "オフ" には、監視を無効にするのと同じ効果があり、追跡オーバーヘッドを最小限に抑える必要があるシナリオに最適です。
  • "エラーのみ" では、エラーや警告などの重大なイベントのみが記録されます。このモードは、最小限のエラーのみをログ記録する必要がある高パフォーマンス シナリオに最適です。
  • "正常性の監視" は既定の監視レベルです。このレベルには、"エラーのみ" レベルで記録されるすべてのデータに加えて、追加の処理データが含まれます。
  • "エンドツーエンド監視" には、"正常性の監視" レベルで記録されるすべてのデータに加えて、メッセージ フロー全体を再構築するための追加の情報が含まれます。このレベルは、あるサービスが別のサービスを呼び出すシナリオで使用されます。
  • "トラブルシューティング" は、名前からわかるように、最も詳細なレベルで、アプリケーションが正常でない状態にあり修正する必要があるシナリオで役に立ちます。

ワークフロー サービスのスケールを変更する

Windows Server AppFabric は、Windows Server のアプリケーション サーバーの役割を拡張するものなので、前身である Windows Server からスケーラビリティの高いインフラストラクチャを継承しており、ネットワーク ロード バランサー (NLB) 背後のサーバー ファームで実行することができます。また、ここまで説明したとおり、Windows Server AppFabric では必要に応じてワークフロー インスタンスを永続化および追跡することができます。したがって、Windows Server AppFabric は、実行時間の長いワークフロー プロセスをホストしクライアントからの多数の要求をサポートするための優れた選択肢となります。

スケーラブルな環境におけるワークフロー サービスの例については、図 9 を参照してください。この例では 2 つの Windows Server AppFabric インスタンスがあり、どちらも同じワークフロー定義のコピーを実行しています。NLB は、利用可能な AppFabric インスタンスに要求をルーティングします。

image: Workflows in a Scalable Environment

図 9 スケーラブルな環境におけるワークフロー

経費報告書シナリオでは、クライアントが経費報告書を作成するために最初にサービスにアクセスしたときに、バランサーが、利用可能な Windows Server AppFabric インスタンスに要求をリダイレクトします。リダイレクト先の Windows Server AppFabric インスタンスでは、経費データをデータベースに保存し、生成された ID をクライアントに返し、(ワークフローはワークフロー ランタイムからの経費の承認を待機してアイドル状態になるため) 実行中のインスタンスをデータベースに永続化します。

その後、クライアント アプリケーションが経費報告書を承認または拒否するためにサービスにアクセスすると、NLB が、利用可能な Windows Server AppFabric インスタンス (最初のサービス呼び出しとは異なるサーバーの場合もあります) に要求をリダイレクトし、サーバーが要求の関連付けと永続化データベースからのワークフロー インスタンスの復元を行います。続いて、メモリ内のインスタンスが処理を継続し、承認をデータベースに保存し、それが済んだらクライアントに返します。

まとめ

ご覧のとおり、負荷分散環境でワークフロー サービスを関連付け、永続化、および追跡と併用すると、ワークフロー サービスをスケーラブルな方法で実行するための強力な手法となります。これらの機能を組み合わせると、実行中のサービスを積極的に処理でき、ワークフローが複数のスレッド、プロセス、さらにはコンピューターに分散されて、運用の生産性が向上する場合があります。これにより、開発者は、インフラストラクチャの複雑さを気にすることなく、1 台のコンピューターで (または大規模なサーバー ファームでも) 実行する用意が整った非常にスケーラビリティの高いソリューションを作成できるようになります。

WCF と WF によるワークフローのデザインの詳細については、MSDN マガジン 2010 年 5 月号の Leon Welicki による記事「WCF と WF 4 によるワークフローのビジュアル デザイン」(msdn.microsoft.com/magazine/ff646977) を参照してください。実行時間の長いプロセスとワークフロー永続化の詳細については、2009 年 1 月号の Michael Kennedy による記事「長時間実行処理をサポートする Web アプリケーション」(msdn.microsoft.com/magazine/dd296718) を参照してください。

Windows Server AppFabric の詳細については、Windows Server デベロッパー センター (msdn.microsoft.com/windowsserver/ee695849、英語) を参照してください。

Rafael Godinho は Microsoft Brazil の ISV デベロッパー エバンジェリストとして、担当地域のパートナーがマイクロソフト テクノロジを導入するのを支援しています。また、blogs.msdn.com/rafaelgodinho (ポルトガル語) で彼のブログをご覧いただけます。

この記事のレビューに協力してくれた技術スタッフの Dave CliffeRon Jacobs、および Leon Welicki に心より感謝いたします。