メッセージのシーケンス処理とタイムスタンプ
シーケンス処理とタイムスタンプは、受信または参照するメッセージの SequenceNumber
および EnqueuedTimeUtc
プロパティを通じて Service Bus のすべてのエンティティとサーフェスで常に有効になる 2 つの機能です。
メッセージの絶対的な順序が重要なケースや、コンシューマーが信頼できるメッセージの一意識別子を必要とするケースでは、ブローカーは、キューまたはトピックを基準とした、ギャップのない増分するシーケンス番号をメッセージに付けます。 パーティション分割されたエンティティの場合、シーケンス番号はパーティションを基準として発行されます。
Sequence number
SequenceNumber
の値は、メッセージがブローカーによって受け入れられ格納されるときに、そのメッセージに割り当てられる 64 ビットの一意の整数であり、その内部識別子として機能します。 パーティション分割されたエンティティの場合、最上位の 16 ビットはパーティション識別子を表します。 64 ビットまたは 48 ビット (パーティション識別子の場合の 16 ビットを除く) の範囲が使い果たされると、シーケンス番号は 0 にロール オーバーされます。
シーケンス番号はクライアントではなく中立的な中央機関によって割り当てられるため、一意識別子として信頼できます。 また、この番号は真の到着順序を表しており、順序の基準としてはタイムスタンプよりも正確です。なぜなら、タイムスタンプは極端に高いメッセージ送信率での十分な分解能がなく、ブローカーの所有権がノード間で移動する状況では (最小限ではありますが) 時間のずれが生じる可能性があるからです。
絶対的な到着順序は、たとえば限定数の商品を先着順で提供するビジネス シナリオ (コンサート チケットの販売など) で最後の商品を提供する際に重要となります。
タイムスタンプ
タイムスタンプ機能は中立的で信頼できる機関として機能し、EnqueuedTimeUtc
プロパティで示される、メッセージが到着した UTC 時刻を正確にキャプチャします。 この値は、ビジネス シナリオが期限に依存する場合 (たとえば、作業項目が特定の日付の午前 0 時より前に送信されたが、キューのバックログでかなり遅れて処理される場合など) に役立ちます。
注意
シーケンス番号自体はメッセージのキュー順序と抽出順序を保証しますが、セッションを必要とする処理順序は保証しません。
たとえば、キューに 5 つのメッセージがあり、2 つのコンシューマーがあるとします。 コンシューマー 1 がメッセージ 1 を取得します。 コンシューマー 2 がメッセージ 2 を取得します。 コンシューマー 2 はメッセージ 2 の処理を終了し、メッセージ 3 を取得しますが、コンシューマー 1 はまだメッセージ 1 の処理を終了していません。 コンシューマー 2 がメッセージ 3 の処理を終了しますが、コンシューマー 1 はまだメッセージ 1 の処理を終了していません。 最後に、コンシューマー 1 がメッセージ 1 の処理を完了します。 この場合、メッセージの処理は、メッセージ 2、メッセージ 3、メッセージ 1 の順に行われます。 メッセージ 1、2、3 を順番に処理する必要がある場合は、セッションを使用する必要があります。
メッセージを順番に取得するだけでよい場合は、セッションを使用する必要はありません。 メッセージを順番に処理する必要がある場合は、セッションを使用します。 同類のメッセージには同じセッション ID を設定する必要があります。たとえば、あるセットのメッセージ 1、4、8 と、別のセットの 2、3、6 のようになります。
詳細については、Service Bus のメッセージ セッションに関する記事を参照してください。
スケジュール設定されたメッセージ
メッセージを、遅延処理されるようにキューまたはトピックに送信できます。たとえば、特定の時刻にシステムによって処理可能になるようにジョブをスケジュール設定できます。 この機能により、分散された時間ベースのスケジューラが実現します。
スケジュール設定されたメッセージは、定義されたエンキュー時刻まではキューで具体化されません。 その時刻より前であれば、スケジュール設定されたメッセージをキャンセルできます。 キャンセルすると、メッセージが削除されます。
任意のクライアントを使用してメッセージをスケジュールするには、次の 2 つの方法があります。
- 通常の送信 API を使用しますが、送信する前にメッセージの
ScheduledEnqueueTimeUtc
プロパティを設定します。 - スケジュール メッセージ API を使用して、通常のメッセージとスケジュールされた時刻の両方を渡します。 API により、スケジュールされたメッセージの
SequenceNumber
が返されます。必要な場合はこれを後で使用して、スケジュールされたメッセージをキャンセルできます。
スケジュール設定されたメッセージとそのシーケンス番号を、メッセージのブラウズを使用して調べることもできます。
スケジュールされたメッセージの SequenceNumber
は、メッセージがスケジュールされた状態にある間のみ有効です。 メッセージがアクティブ状態に移行すると、そのメッセージは、たった今エンキューされたようにキューに追加され、これには新しい SequenceNumber
の割り当てが含まれます。
この機能は個別のメッセージにアンカーされており、メッセージは 1 回しかエンキューできないため、Service Bus はメッセージの繰り返しスケジュールをサポートしていません。
Note
- メッセージのエンキュー時間は、メッセージが同時に送信されることを意味するものではありません。 エンキューされますが、実際の送信時間はキューのワークロードとその状態によって異なります。
- パフォーマンス上の考慮事項により、スケジュールされたメッセージのアクティブ化と取り消しは、相互ロックのない独立した操作です。 アクティブ化中のメッセージが同時に取り消された場合、アクティブ化プロセスは取り消されず、メッセージは引き続きアクティブ化されます。 さらに、スケジュールされたメッセージの数が負になる可能性があります。 この競合状態を最小限に抑えるには、アクティブ化と取り消しの操作を連続してスケジュールしないようにすることをお勧めします。
ワークフローでのスケジュールされたメッセージの使用
一般的には、明示的な時間の構成要素を持つ、実行時間のより長いビジネス ワークフローが表示されます。これは、2 要素認証の 5 分間のタイムアウト、メール アドレスを確認するユーザーの 1 時間のタイムアウト、銀行や保険などの分野での複数の日、週、または月にわたる時間の構成要素などです。
これらのワークフローは、多くの場合、何らかのメッセージの処理によって開始され、その後、何らかの状態が保存され、後でプロセスを続行するようにメッセージがスケジュールされます。 NServiceBus や MassTransit などのフレームワークを使用すると、これらすべての要素を簡単に統合できます。
関連するコンテンツ
Service Bus メッセージングの詳細については、次のトピックをご覧ください。