トレーニング
モジュール
Azure Cosmos DB for NoSQL を使用してドキュメント間のトランザクション操作を実行する - Training
1 つの論理的な作業単位で複数の項目に対して操作を実行します。
このブラウザーはサポートされなくなりました。
Microsoft Edge にアップグレードすると、最新の機能、セキュリティ更新プログラム、およびテクニカル サポートを利用できます。
受信アダプターによってメッセージング エンジンに送信されるバッチは、非同期に処理されます。 したがって、成功または失敗が通知されるように、また、必要なクリーンアップ処理が実行されるように、受信アダプターにはコールバックを受信アダプターの状態に関連付けるメカニズムが必要です。 コールバックのセマンティクスは柔軟なので、アダプターには、3 つの方法のうちの 1 つまたはそれらの方法の組み合わせを使用できます。 これらのボタンの役割は、次のとおりです。
すべてのコールバックは、 IBTBatchCallBack を実装する同じオブジェクト インスタンスで行われます。
新しいバッチの要求時にエンジンに渡される Cookie を使用して、コールバックをアダプターの状態に関連付けます。
IBTBatchCallBack を実装するバッチごとに異なるコールバック オブジェクトがあります。 各オブジェクトが、独自のプライベート状態を保持します。
バッチが処理されると、アダプターは IBTBatchCallBack.BatchComplete の実装で呼び出されます。 このバッチの全体的な状態は、最初のパラメーターである HRESULT 値によって示されます。 この値がゼロ以上の場合、エンジンにデータの所有権があり、受信アダプターがそのデータを回線から自由に削除できるという意味で、バッチは成功です。 負の状態は、バッチが失敗したことを示します。バッチ内のどの操作も成功しなかったため、アダプターはエラーの処理を担当します。
バッチが失敗した場合、アダプターはどの操作のどの項目が失敗したのかを認識する必要があります。 たとえば、アダプターがディスクから 20 個のファイルを読み取り、1 つのバッチを使用してBizTalk Serverに送信したとします。 10 番目のファイルが破損している場合、アダプターはその 1 つのファイルを中断し、残りの 19 ファイルを再送信する必要があります。 この情報は、アダプターで 2 番目と 3 番目のパラメーターopCount
(short 型と operationStatus
型の操作数) で使用できます。これは BTBatchOperationStatus[]型です。
注意
1 つのバッチ オブジェクトで 1 つのメッセージを複数回送信しないでください。 同じメッセージ オブジェクトを同じバッチで複数回送信すると、エンジンでエラーが発生します。
操作数は、バッチ内の操作の種類の数 ( BTBatchOperationStatus 配列のサイズ) を示します。 操作の状態配列内の各要素は、バッチに含まれている操作の種類に対応しています。 アダプターは、BTBatchOperationStatus 配列を使用して、エラーを示す負の HRESULT 値の BTBatchOperationStatus.MessageStatus 配列を調べることで、特定の操作で失敗した項目を特定できます。 上記のシナリオのアダプターは、19 メッセージを送信し 1 メッセージを保留する新しいバッチを作成します。
次のコードでは、アダプターが新しいバッチをトランスポート プロキシを使用してエンジンに要求し、Cookie を利用して 1 つのメッセージをエンジンに送信する方法を示しています。 メッセージング エンジンは、送信されたメッセージのバッチ全体の処理が完了すると、バッチ コールバックとして BatchComplete メソッドを呼び出します。
using Microsoft.BizTalk.TransportProxy.Interop;
using Microsoft.BizTalk.Message.Interop;
public class MyAdapter :
IBTTransport,
IBTTransportConfig,
IBTTransportControl,
IPersistPropertyBag,
IBaseComponent,
IBTBatchCallBack
{
private IBTTransportProxy _tp;
public void BatchComplete(
Int32 status,
Int16 opCount,
BTBatchOperationStatus[] operationStatus,
System.Object callbackCookie)
{
// Use cookie to correlate callback with work done,
// in this example the batch is to submit a single
// file the name of which will be in the
// callbackCookie
string fileName = (string)callbackCookie;
if ( status >= 0 )
// DeleteFile from disc
File.Delete(fileName);
else
// Rename file to fileName.bad
File.Move(fileName, fileName + ".bad");
}
private void SubmitMessage(
IBaseMessage msg,
string fileName)
{
// Note: Pass in the filename as the cookie
IBTTransportBatch batch =
_tp.GetBatch(this, (object)fileName);
// Add msg to batch for submitting
batch.SubmitMessage(msg);
// Process this batch
batch.Done(null);
}
}
BizTalk Server SDK には、ファイル、HTTP、MSMQ、トランザクション アダプターの各アダプターのサンプルが含まれています。 これらのアダプターはすべて BaseAdapter と呼ばれる共通のビルド ブロックに基づいて作成されています。 バージョン 1.0.1 の BaseAdapter には、操作の状態を解析し、新しいバッチを再作成して送信するための関連コードがすべて含まれています。
エラーを解決するタスクと、送信されたバッチの最終結果を決定するタスクは単純に見えますが、実際には、これらのタスクは次に示す異なるスレッドの情報に基づいています。
アダプターは、アダプターの BatchComplete コールバック メソッドにBizTalk Server渡された情報に基づいてエラーを処理します。 このコールバックはアダプターのスレッドで実行されます。
DTCCommitConfirm は、 IBTDTCCommitConfirm オブジェクトのメソッドです。 IBTDTCCommitConfirm オブジェクトのインスタンスは、バッチ IBTTransportBatch::D one 呼び出しによって返されます。 このインスタンスは、アダプターのコールバック スレッドとは異なる IBTTransportBatch::D one 呼び出しと同じスレッド上にあります。
アダプターが IBTTransportBatch::D one に対して行う呼び出しごとに、メッセージング エンジンは、バッチ送信の結果を報告するために、別のスレッドでコールバック メソッド BatchComplete に対応する呼び出しを行います。 BatchComplete では、バッチが成功したか失敗したかに基づいて、アダプターがトランザクションをコミットまたはロールバックする必要があります。 どちらの場合も、アダプターは DTCCommitConfirm を呼び出してトランザクションの状態を報告する必要があります。
アダプターの BatchComplete の実装では、IBTTransportBatch::D one によって返される IBTDTCCommitConfirm オブジェクトが BatchComplete の実行時に常に使用可能であると想定できるため、競合状態が発生する可能性があります。 ただし、IBTTransportBatch::D one が返される前であっても、BatchComplete は別のメッセージング エンジン スレッドで呼び出すことができます。 アダプターが BatchComplete 実装の一部として IBTDTCCommitConfirm オブジェクトにアクセスしようとすると、呼び出し元スレッドが存在しなくなったため、アクセス違反が発生する可能性があります。 この状態を回避するには、次の解決方法を使用します。
次の例では、イベントを使用してこの問題を解決します。 この例では、イベントを使用するプロパティを通じてインターフェイス ポインターにアクセスします。 get の処理は、必ず set が完了した後で行われます。
protected IBTDTCCommitConfirm CommitConfirm
{
set
{
this.commitConfirm = value;
this.commitConfirmEvent.Set();
}
get
{
this.commitConfirmEvent.WaitOne();
return this.commitConfirm;
}
}
protected IBTDTCCommitConfirm commitConfirm = null;
private ManualResetEvent commitConfirmEvent = new ManualResetEvent(false);
バッチの状態コード全体は、バッチの結果を示します。 操作の状態からは、個々のメッセージ項目の送信の状態コードが得られます。 バッチが失敗するのにはさまざまな理由があります。 セキュリティ関連のエラーが発生している可能性があります。または、エンジンのシャットダウン時にメッセージが送信された可能性があります。 (通常、エンジンがシャットダウンすると、新しい作業は受け入れられませんが、インプロセス作業を完了できます)。次の表は、バッチ状態または操作状態のいずれかで返される一般的な HRESULT 値を示しています。 また、それらの値が成功コードなのか失敗コードなのかも示します。 これらのコードの適切な処理については、「 アダプターエラーを処理する方法」で詳しく説明されています。
コード (BTTransportProxy クラスで定義) | 成功コード/失敗コード | 説明 |
---|---|---|
BTS_S_EPM_SECURITY_CHECK_FAILED | Success | セキュリティ チェックを行うようにポートが構成されたので、認証に失敗したメッセージは削除されます。 アダプターでは、この状態コードを返すバッチを保留しないようにする必要があります。 |
BTS_S_EPM_MESSAGE_SUSPENDED | Success | 1 つ以上のメッセージが保留され、エンジンにデータの所有権があることを示します。 これは、メッセージ エンジンがメッセージの送信を受け入れたという点で、成功コードです。 |
E_BTS_URL_DISALLOWED | 障害 | 無効な InboundTransportLocation を含むメッセージが送信されました。 |
次の表では、アダプターが特定のバッチに作業を追加するために使用する IBTTransportBatch オブジェクトのメンバー メソッドと操作について詳しく説明します。
メソッド名 | 演算の種類 | 説明 |
---|---|---|
SubmitMessage | 送信 | メッセージをエンジンに送信します。 |
SubmitResponseMessage | 送信 | 応答メッセージをエンジンに送信します。 これは、送信請求 - 応答の組み合わせの応答メッセージです。 |
DeleteMessage | 削除 | アダプターが非ブロッキング送信を使用して回線上で正常に送信したメッセージを削除します。 ブロック送信を使用するアダプターは、アダプターが TransmitMesssage から返された場合に、メッセージング エンジンによってアダプターの代わりに削除されるため、このメソッドを呼び出すtrue 必要はありません。 |
MoveToSuspendQ | MoveToSuspendQ | メッセージを保留キューに移動します。 |
Resubmit | Resubmit | 後でメッセージの送信を再試行するように要求します。 一般に、送信の試行が失敗した後にこのメソッドを呼び出します。 |
MoveToNextTransport | MoveToNextTransport | メッセージをバックアップ トランスポートを使用して送信することを要求します。 通常、すべての試行回数が完了した後にこのメソッドを呼び出します。 バックアップ トランスポートが存在しない場合、このメソッドは失敗します。 |
SubmitRequestMessage | SubmitRequest | 要求メッセージを送信します。 これは、要求 - 応答の組み合わせの要求メッセージです。 |
CancelRequestForResponse | CancelRequestForResponse | エンジンに、アダプターが要求 - 応答の組み合わせの応答メッセージを待機しなくなったことを通知します。 |
[クリア] | NA | バッチからすべての作業を削除します。 |
完了 | NA | メッセージのバッチをエンジンに送信して処理します。 |
バッチは、メッセージ エンジンでネイティブ コードで実装されます。 そのため、マネージド コードで記述されたアダプターは、バッチのランタイム呼び出し可能ラッパー (RCW) を、バッチの処理の終了後に解放する必要があります。 これは、 Marshal.ReleaseComObject API を使用してマネージド コードで行われます。 返される参照カウントが 0 になるまで、この API は while ループで呼び出す必要があります。
BizTalk Serverは、バッチ内でメッセージを同期的に処理します。 多数のバッチが同時に処理されることがあるので、アプリケーション ドメイン内でバッチ サイズを調整することによって、アダプターで何らかの最適化を行うことになる場合があります。 たとえば、FTP サイトですべてのファイルを処理する場合が考えられます (何らかの制限に該当するまで)。 SAP の場合は、1 つのストリームを多数のメッセージにし、後でそれらを 1 つのバッチとして送信することがあります。
アダプターが操作をBizTalk Serverに渡すために使用するバッチは、アダプターに与BizTalk Serverメッセージの一覧に正確に対応する必要はありません。 つまり、トランザクション送信を行う場合は、再送信操作 MoveToNextTransport と MoveToSuspendQ を別々のバッチに分割する必要があります。 多くのアダプターでは、その後の処理のために、複数のエンドポイントへ送信されたメッセージのバッチを別々のメッセージ一覧に振り分けます。
要するに、BizTalk Serverのメッセージ バッチ処理に関連付けられているルール (トランザクションに関連付けられているルール以外) が存在しないということです。 バッチ処理は、アダプターがメッセージをBizTalk Serverにチャンクする実装固有の方法です。
アダプターは、BizTalk ServerがBizTalk Serverへの応答のためにより大きなバッチに渡した複数の小さなバッチからのメッセージをバッチ処理できます。 この処理では、非常に小さな多数のメッセージを処理するトランザクション アダプターで大幅な最適化が行われる場合があります。 この最適化により、"メッセージごとの総トランザクション数" の比率が最小になります。
通常、BizTalk Serverでは、5 ~ 10 個のメッセージの送信側バッチが生成されます。 これらのメッセージが非常に小さい場合、アダプターは削除のトランザクション バッチを送信してBizTalk Serverに戻す前に、最大 100 件以上のメッセージをバッチ処理する可能性があります。 このような最適化を実装するのは困難です。メッセージがアダプター メモリにとどまらないようにする一方で、基準値を満たすまで無期限に待機する必要があるためです。
バッチ処理の重要性は、MQSeries などの高スループット・アダプターのBizTalk Serverのパフォーマンス数値で確認できます。 これらのアダプターでは、1 回のメッセージの送信で少なくとも 2 回、そのメッセージが受信されます。 既定では、受信アダプターは 100 個のメッセージのバッチを使用し、送信アダプターは指定された既定のBizTalk Serverバッチを使用します。
トランザクション オブジェクトを作成し、それをBizTalk Serverに渡すアダプターを作成する場合、次の処理を行うコードを記述する責任を負います。
バッチ操作の最終結果として、トランザクションのコミットまたは終了のいずれかを決定します。 これは、メッセージ キュー (MSMQ) キューへの書き込みやトランザクション データベース操作など、BizTalk Server依存しない、この 1 つのトランザクションのスコープ内の他のトランザクション ブランチによって異なります。
IBTDTCCommitConfirm.DTCCommitConfirm メソッドを呼び出して、最終的な結果をBizTalk Serverに通知します。 戻り値 true
は、トランザクションの正常なコミットを示します。を返すと false
、トランザクションの失敗とロールバックが示されます。
アダプターは、内部追跡データを維持するために、トランザクションの最終的な結果についてBizTalk Serverに通知する必要があります。 アダプターは、DTCCommitConfirm を呼び出すことによって、結果をBizTalk Serverに通知します。 アダプターがこの呼び出しを行わない場合、重大なメモリ リークが発生して、操作が正常に完了した場合にも MSDTC トランザクションがタイムアウトして失敗することがあります。
トレーニング
モジュール
Azure Cosmos DB for NoSQL を使用してドキュメント間のトランザクション操作を実行する - Training
1 つの論理的な作業単位で複数の項目に対して操作を実行します。