COM+ CRM の運用プロセス
通常の操作では、サーバー アプリケーション プロセスで実行されているアプリケーション コンポーネントは、CRM ワーカーを作成することによって COM+ CRM を使用します。 CRM ワーカーは、実行するように設計されたタスクに固有の COM インターフェイスを実装します。 CRM ワーカーがアプリケーション コンポーネントのトランザクションを継承するには、アプリケーション コンポーネントがトランザクションで実行されている必要があります。 CRM ワーカーには常にトランザクションが必要です。
COM+ CRM にアクセスするために、CRM ワーカーは最初に ICrmLogControl インターフェイスを取得します。これにより、CRM ワーカーは永続ログにレコードを書き込むことができます。 CRM ワーカーは、CRM クラーク コンポーネントを作成することによって、このインターフェイスを取得します。
次に、CRM ワーカーは、使用する CRM コンペンセータの名前を CRM クラークに伝える必要があります。 これを行うには、ICrmLogControl::RegisterCompensator メソッドを呼び出します。 このメソッドが呼び出されると、トランザクションの完了時に CRM インフラストラクチャによって CRM コンペンセータが作成されます。
CRM ワーカーは、CRM コンペンセータを登録した後、ICrmLogControl を使用して CRM ログにレコードを書き込むことができます。 CRM ワーカーは、先に書き込みを行う必要があります。つまり、アクションの完了直後にクラッシュが発生した場合に、アクションを実際に実行する前に、アクションを説明するレコードをログに書き込む必要があります。 これらの先書きログ レコードがないと、アクションを修正する方法はありません。
また、先に書き込むことは、復旧時にログ レコードを受け取るコンポーネントである CRM コンペンセータが、ログ レコードが書き込まれたがアクションが実際には発生しなかった場合に対処する必要があることを意味します。 CRM コンペンセータによるアクションは、べき等である必要があります。つまり、2 回以上実行できる必要がありますが、同じ結果が得られなければなりません。 たとえば、口座残高を $100 の値に設定することは、べき等アクションですが、口座残高に $100 を追加することは、べき等ではありません。
ICrmLogControl インターフェイスには、ログ レコードを書き込むための次の 2 つのメソッドが用意されています。
- WriteLogRecordVariants は、Variants のコレクションとして構築された構造化されたログ レコードを書き込む場合に使用されます。 これは主に、Microsoft Visual Basic で CRM を開発するときに使用するものです。
- WriteLogRecord は、非構造化ログ レコードをバイトの BLOB として書き込む場合に使用されます。 これは主に、Microsoft Visual C++ で CRM を開発するときに使用するものです。 C のレコード構造は、多くの場合、メモリに散在する可能性のあるヘッダーとフィールドのセットで構成されるため、WriteLogRecord メソッドは、データのコピーを減らす収集機能を実装します。
Note
ログ レコード内のデータ構造内のユーザー ポインター型は使用しないでください。 CRM コンペンセータは、ログ レコードを書き込んだ CRM ワーカーとは異なるプロセスで実行されるため、ポインターが復旧フェーズ中に有効ではなくなりました。 ログ レコードにポインター型を含めると、回復中にアプリケーションがクラッシュしたり、破損したりする可能性があります。
どちらの書き込み方法も、ログ レコードをディスクに書き込みますが、レコードの持続性を保証するものではありません。 ディスクに強制する前に遅延書き込みを蓄積できるようにすることでパフォーマンスを向上させることができますが、代わりに ICrmLogControl::ForceLog メソッドを使用して、CRM によって実行されるすべての書き込みがディスク上で永続的であることを保証できます。これは障害復旧に重要なことです。
CRM ワーカーがアクションを実行し、ログへのレコードの書き込みと強制が完了したら、ICrmLogControl を解放する必要があります。 トランザクションが完了すると (通常、SetComplete または SetAbort を呼び出すアプリケーション コンポーネントが原因で)、CRM インフラストラクチャによって CRM コンペンセータ コンポーネントが作成されます。このコンポーネントは、ICrmCompensator インターフェイスまたは ICrmCompensatorVariants インターフェイスを実装します。 これらのインターフェイスは、非構造化 (Visual C++) または構造化 (Visual Basic) レコードをトランザクション結果通知と共に CRM コンペンセータに渡すために使用されます。
CRM コンペンセータは、最初にトランザクション完了の準備フェーズを通知され、準備要求に対して「はい」または「いいえ」を投票できます。 CRM コンペンセータが「いいえ」に投票した場合、それ以上中止通知は受け取りません。 準備要求に「はい」を投票すると、コミット通知または中止通知を受け取ります。 クライアントの中止の場合、準備通知は受信されません。中止通知のみを受け取ります。 CRM コンペンセータは、これらのすべてのケースを処理するように準備する必要があります。また、CRM ワーカーによってログ レコードが正常に書き込まれなかった場合も処理する必要があります。 CRM コンペンセータでは、同じ CRM コンペンセータ インスタンスがフェーズ 1 (準備) とフェーズ 2 (コミットまたは中止) の通知の両方を受信することを想定しないでください。これらは復旧によって中断される可能性があります。
通常、CRM コンペンセータは中止通知を使用して、CRM ワーカーによって実行されたアクションを元に戻します。 CRM ワーカーは、アクションを取り消す必要がある場合に備えて、何らかの状態を残す可能性があります。 その状態はログ レコードに完全に含まれている可能性があり、含まれていない場合、トランザクションがコミットされた場合は、CRM コンペンセータはその状態をクリーンアップする必要があります。 CRM コンペンセータがコミット通知を受信するのは、このためです。 CRM コンペンセータは、DTC トランザクションでは実行されません。
CRM コンペンセータは、ICrmLogControl を使用することで、必要に応じて、作成されると受信する新しいレコードをログに記録できます。 CRM ワーカーと CRM コンペンセータはどちらも、書き込んだ最後のログ レコードを記憶しないこともできます。これは、不要な回復を回避するために必要な場合があります。
関連トピック