この記事では、さまざまな種類のメッセージと、メッセージング インフラストラクチャに参加するエンティティについて説明します。 この記事では、各メッセージの種類の要件に基づいて、Azure メッセージング サービスを推奨しています。 オプションには、Azure Service Bus メッセージング、Azure Event Grid、Azure Event Hubs などがあります。 製品の比較については、「 メッセージング サービスの比較」を参照してください。
アーキテクチャ レベルでは、メッセージはエンティティ (プロデューサー) によって作成されたデータグラムであり、他のエンティティ (コンシューマー) がそれに応じて認識して行動できるように、情報を配布します。 プロデューサーとコンシューマーは、中間エンティティ (メッセージ ブローカー) を介して直接または必要に応じて通信できます。 この記事では、メッセージ ブローカーを使用した非同期メッセージングについて説明します。
メッセージを 2 つの主要なカテゴリに分類できます。 プロデューサーがコンシューマーからのアクションを予期している場合、そのメッセージは コマンドです。 アクションが発生したことをメッセージがコンシューマーに通知した場合、メッセージは イベントになります。
コマンド
プロデューサーは、コンシューマーがビジネス トランザクションのスコープ内で操作を実行することを意図してコマンドを送信します。
コマンドは価値の高いメッセージであり、少なくとも 1 回は配信する必要があります。 コマンドが失われると、ビジネス トランザクション全体が失敗する可能性があります。 また、1 つのコマンドを複数回処理しないでください。 これを行うと、誤ったトランザクションが発生する可能性があります。 顧客が重複した注文を受け取ったり、2 回請求されたりすることがあります。
コマンドは、多くの場合、マルチステップビジネストランザクションのワークフローを管理するために使用されます。 ビジネス ロジックによっては、プロデューサーはコンシューマーがメッセージを確認し、操作の結果を報告することを期待する場合があります。 その結果に基づいて、プロデューサーは適切なアクション のコースを選択する場合があります。
イベント
イベントは、プロデューサーがファクトを発表するために生成するメッセージの一種です。
プロデューサー (このコンテキストでは 発行元 と呼ばれます) は、イベントによって何らかのアクションが発生することを期待しません。
関心のあるコンシューマーは、サブスクライブし、イベントをリッスンし、消費シナリオに応じてアクションを実行できます。 イベントには、複数のサブスクライバーを含めたり、サブスクライバーをまったく含めなかったりする場合があります。 2 つの異なるサブスクライバーは、異なるアクションを持つイベントに反応でき、互いに認識することはできません。
プロデューサーとコンシューマーは疎結合され、独立して管理されます。 プロデューサーは、コンシューマーがプロデューサーにイベントを受信確認することを想定していません。 イベントに関心がなくなったコンシューマーはサブスクライブを解除できます。これにより、プロデューサーやシステムの全体的な機能に影響を与えることなく、パイプラインからコンシューマーが削除されます。
イベントには次の 2 つのカテゴリがあります。
プロデューサーは、個別の事実を発表するイベントを発生させます。 一般的なユース ケースはイベント通知です。 たとえば、Azure Resource Manager は、リソースの作成、変更、または削除時にイベントを発生させます。 これらのイベントのサブスクライバーは、アラート 電子メールを送信するロジック アプリである可能性があります。
プロデューサーは、一定期間にわたって、シーケンスまたはイベントのストリームで関連するイベントを発生させます。 通常、ストリームは統計評価のために使用されます。 評価は、テンポラル ウィンドウ内で、またはイベントの到着時に行うことができます。 テレメトリは一般的なユース ケースです (たとえば、システムの正常性と負荷の監視)。 もう 1 つのケースは、IoT デバイスからのイベント ストリーミングです。
イベント メッセージングを実装するための一般的なパターンは、 パブリッシャーとサブスクライバーの パターンです。
メッセージ ブローカーの役割と利点
中間メッセージ ブローカーは、プロデューサーからコンシューマーにメッセージを移動する機能を提供し、より多くの利点を提供できます。
分離
メッセージ ブローカーは、メッセージを生成して使用するロジック内のコンシューマーからプロデューサーをそれぞれ切り離します。 複雑なワークフローでは、ブローカーはビジネス操作の分離を促し、ワークフローの調整に役立ちます。
たとえば、1 つのビジネス トランザクションには、ビジネス ロジック シーケンスで実行される個別の操作が必要です。 プロデューサーは、コンシューマーに操作の開始を通知するコマンドを発行します。 コンシューマーは、プロデューサーの応答を並べるため予約された別のキュー内のメッセージを確認します。 応答を受信した後にのみ、プロデューサーは新しいメッセージを送信して、シーケンス内の次の操作を開始します。 別のコンシューマーがそのメッセージを処理し、完了メッセージを応答キューに送信します。 メッセージングを使用することで、サービスはトランザクションのワークフローを調整します。
メッセージ ブローカーは、一時的な切り離しを提供します。 プロデューサーとコンシューマーは同時に実行する必要はありません。 プロデューサーは、コンシューマーの可用性に関係なく、メッセージ ブローカーにメッセージを送信できます。 逆に、コンシューマーはプロデューサーの可用性によって制限されません。
たとえば、Web アプリのユーザー インターフェイスはメッセージを生成し、メッセージ ブローカーとしてキューを使用します。 コンシューマーの準備ができたら、キューからメッセージを取得し、処理を実行できます。 一時的な切り離しは、ユーザー インターフェイスの応答性を維持するのに役立ちます。 メッセージが非同期的に処理されている間はブロックされません。
特定の操作の完了には時間がかかる場合があります。 コマンドを発行した後、プロデューサーはコンシューマーが完了するまで待機する必要はありません。 メッセージ ブローカーは、メッセージの非同期処理に役立ちます。
負荷分散
プロデューサーは、多くのコンシューマーが処理する多数のメッセージを投稿できます。 メッセージ ブローカーを使用して、サーバー間で処理を分散し、スループットを向上させます。 コンシューマーは、さまざまなサーバーで実行して負荷を分散できます。 コンシューマーを動的に追加して、必要に応じてシステムをスケールアウトしたり、それ以外の場合は削除したりできます。
競合コンシューマー パターンでは、複数のメッセージを同時に処理してスループットを最適化し、スケーラビリティと可用性を向上させ、ワークロードのバランスを取る方法について説明します。
負荷平準化
プロデューサーまたはプロデューサーのグループによって生成されるメッセージの量は可変にすることができます。 場合によっては、大量のメッセージが急増する可能性があります。 この作業を処理するためにコンシューマーを追加する代わりに、メッセージ ブローカーはバッファーとして機能でき、コンシューマーはシステムに負荷をかけずに、自分のペースで徐々にメッセージをドレインします。
キュー ベースの負荷平準化パターンでは、詳細が提供されます。
信頼性の高いメッセージング
メッセージ ブローカーは、プロデューサーとコンシューマーの間の通信に失敗した場合でも、メッセージが失われないようにするのに役立ちます。 プロデューサーはメッセージ ブローカーにメッセージを投稿でき、コンシューマーは通信が再確立されたときにメッセージを取得できます。 プロデューサーは、メッセージ ブローカーとの接続を失わない限りブロックされません。
回復性のあるメッセージング
メッセージ ブローカーは、システム内のコンシューマーに回復性を追加できます。 メッセージの処理中にコンシューマーが失敗した場合、コンシューマーの別のインスタンスがそのメッセージを処理できます。 メッセージがブローカーに保持されるため、再処理が可能です。
メッセージ ブローカーのテクノロジの選択
Azure には、さまざまな機能を備えた複数のメッセージ ブローカー サービスが用意されています。 サービスを選択する前に、メッセージの意図と要件を決定します。
Azure Service Bus Messaging
Azure Service Bus メッセージング キューは、プロデューサーからコンシューマーにコマンドを転送するのに適しています。 いくつかの考慮事項を次に示します。
プル モデル
Service Bus キューのコンシューマーは常に Service Bus をポーリングして、新しいメッセージが使用可能かどうかを確認します。 Service Bus のクライアント SDK と Azure Functions トリガー は、そのモデルを抽象化します。 新しいメッセージが使用可能になると、コンシューマーのコールバックが呼び出され、メッセージがコンシューマーに送信されます。
保証された配信
Service Bus を使用すると、コンシューマーはキューをピークし、他のコンシューマーからのメッセージをロックできます。
メッセージの処理状態を報告するのはコンシューマーの責任です。 コンシューマーがメッセージを使用済みとしてマークした場合にのみ、Service Bus はキューからメッセージを削除します。 エラー、タイムアウト、またはクラッシュが発生した場合、Service Bus はメッセージのロックを解除して、他のコンシューマーがメッセージを取得できるようにします。 この方法では、転送中にメッセージが失われることはありません。
プロデューサーが誤って同じメッセージを 2 回送信する可能性があります。 たとえば、プロデューサー インスタンスは、メッセージの送信後に失敗します。 別のプロデューサーが元のインスタンスを置き換え、メッセージをもう一度送信します。 Azure Service Bus キューには、重複するメッセージを検出して削除する 組み込みのデデュピング機能 が用意されています。 メッセージが 2 回配信される可能性はまだあります。 たとえば、処理中にコンシューマーが失敗した場合、メッセージはキューに返され、同じコンシューマーまたは別のコンシューマーによって取得されます。 処理が繰り返されてもシステムの状態が変更されないように、コンシューマーのメッセージ処理ロジックはべき等である必要があります。
メッセージの順序付け
コンシューマーが送信された順序でメッセージを取得する場合、Service Bus キューでは、セッションを使用して先入れ先出し (FIFO) の順序付けされた配信が保証されます。 セッションには、1 つ以上のメッセージを含めることができます。 メッセージは SessionId プロパティと関連付けられます。 セッションの一部であるメッセージは期限切れになりません。 セッションをコンシューマーにロックして、メッセージが別のコンシューマーによって処理されないようにすることができます。
詳細については、「メッセージ セッション」を参照してください。
メッセージの永続化
Service Bus キューでは、一時的な切り離しがサポートされます。 コンシューマーが使用できない場合やメッセージを処理できない場合でも、キューに残ります。
チェックポイントの実行時間の長いトランザクション
ビジネス トランザクションは長時間実行できます。 トランザクション内の各操作には、複数のメッセージを含めることができます。 チェックポイント処理を使用してワークフローを調整し、トランザクションが失敗した場合の回復性を提供します。
Service Bus キューを使用すると、 セッション状態機能を使用してチェックポイントを設定できます。 状態情報は、セッションに属するメッセージのキュー (SetState) に増分的に記録されます。 たとえば、コンシューマーは、毎回状態 (GetState) を確認することで進行状況を追跡できます。 コンシューマーが失敗した場合、別のコンシューマーは状態情報を使用して、セッションを再開する最後の既知のチェックポイントを決定できます。
配信不能キュー (DLQ)
Service Bus キューには、配信または処理できなかったメッセージを保持するための 配信不能キュー (DLQ) と呼ばれる既定のサブキューがあります。 Service Bus またはコンシューマーのメッセージ処理ロジックは、DLQ にメッセージを追加できます。 DLQ は、メッセージがキューから取得されるまで保持します。
メッセージが DLQ に入る場合の例を次に示します。
有害メッセージは、形式が正しくないか、予期しない情報が含まれているために処理できないメッセージです。 Service Bus キューでは、キューの MaxDeliveryCount プロパティを設定することで有害メッセージを検出できます。 同じメッセージが受信された回数がそのプロパティ値を超えた場合、Service Bus はメッセージを DLQ に移動します。
メッセージが期間内に処理されないと、メッセージが関連しなくなる可能性があります。 Service Bus キューを使用すると、プロデューサーは time-to-live 属性を持つメッセージを投稿できます。 メッセージを受信する前にこの期間が経過すると、メッセージは DLQ に配置されます。
DLQ 内のメッセージを調べて、エラーの理由を判別します。
ハイブリッド ソリューション
Service Bus は、オンプレミスのシステムとクラウド ソリューションをブリッジします。 オンプレミス システムは、多くの場合、ファイアウォールの制限のために到達するのが困難です。 プロデューサーとコンシューマー (オンプレミスまたはクラウドのいずれか) の両方で、Service Bus キュー エンドポイントをメッセージのピックアップとドロップオフの場所として使用できます。
メッセージング ブリッジ パターンは、これらのシナリオを処理するもう 1 つの方法です。
トピックとサブスクリプション
Service Bus は、Service Bus のトピックとサブスクリプションを通じて Publisher-Subscriber パターンをサポートします。
この機能は、プロデューサーが複数のコンシューマーにメッセージをブロードキャストする方法を提供します。 トピックがメッセージを受信すると、サブスクライブされているすべてのコンシューマーに転送されます。 必要に応じて、サブスクリプションにフィルター条件を設定して、コンシューマーがメッセージのサブセットを取得できるようにします。 各コンシューマーは、キューと同様の方法でサブスクリプションからメッセージを取得します。
詳細については、 Azure Service Bus のトピックを参照してください。
Azure Event Grid
個別 のイベントには Azure Event Grid をお勧めします。 Event Grid は、Publisher-Subscriber パターンに従います。 イベント ソースがイベントをトリガーすると、 Event Grid トピックに発行されます。 これらのイベントのコンシューマーは、イベントを処理するイベントの種類とイベント ハンドラーを指定して、Event Grid サブスクリプションを作成します。 サブスクライバーが存在しない場合、イベントは破棄されます。 各イベントには複数のサブスクリプションを含めることができます。
プッシュ モデル
Event Grid は、プッシュ モデルのサブスクライバーにメッセージを伝達します。 Webhook を使用する Event Grid サブスクリプションがあるとします。 新しいイベントが到着すると、Event Grid は Webhook エンドポイントにイベントを投稿します。
Azure との統合
Azure リソースに関する通知を取得する場合は、Event Grid を選択します。 多くの Azure サービスは、Event Grid トピックが組み込まれている イベント ソース として機能します。 Event Grid では、 イベント ハンドラーとして構成できるさまざまな Azure サービスもサポートされています。 これらのトピックをサブスクライブして、好みのイベント ハンドラーにイベントをルーティングするのは簡単です。 たとえば、Event Grid を使用して、BLOB ストレージが作成または削除されたときに Azure 関数を呼び出すことができます。
カスタム トピック
アプリケーションまたは Event Grid と統合されていない Azure サービスからイベントを送信する場合は、カスタム Event Grid トピックを作成します。
たとえば、ビジネス トランザクション全体の進行状況を確認するには、参加しているサービスが個々の業務を処理するときにイベントを発生させる必要があります。 Web アプリには、これらのイベントが表示されます。 このタスクを実行する 1 つの方法は、カスタム トピックを作成し、HTTP WebHook 経由で登録された Web アプリでサブスクリプションを追加することです。 ビジネス サービスがカスタム トピックにイベントを送信すると、Event Grid によって Web アプリにプッシュされます。
フィルター処理されたイベント
サブスクリプションでフィルターを指定して、イベントのサブセットのみを特定のイベント ハンドラーにルーティングするように Event Grid に指示できます。 サブスクリプション スキーマでフィルターを指定します。 フィルターに一致する値を持つトピックに送信されるすべてのイベントは、そのサブスクリプションに自動的に転送されます。
たとえば、さまざまな形式のコンテンツが Blob Storage にアップロードされます。 ファイルが追加されるたびに、イベントが発生し、Event Grid に発行されます。 イベント サブスクリプションには、イベント ハンドラーがサムネイルを生成できるように、画像のイベントのみを送信するフィルターがある場合があります。
フィルター処理の詳細については、「 Event Grid のイベントのフィルター処理」を参照してください。
高スループット
Event Grid では、リージョンあたり 1 秒あたり 10,000,000 イベントをルーティングできます。 毎月の最初の 100,000 操作は無料です。 コストに関する考慮事項については、「Event Grid のコストはどのくらいですか?」を参照してください。
回復性のある配信
イベントの正常な配信はコマンドほど重要ではありませんが、イベントの種類によっては何らかの保証が必要になる場合があります。 Event Grid には、再試行ポリシー、有効期限、配信不能など、有効にしてカスタマイズできる機能が用意されています。 詳細については、Event Grid のメッセージの配信と再試行に関する記事を参照してください。
Event Grid の再試行プロセスは回復性に役立ちますが、フェールセーフではありません。 再試行プロセスでは、エンドポイントが長時間応答しない場合、Event Grid によってメッセージが複数回配信されたり、スキップされたり、再試行が遅れたりすることがあります。 詳細については、「 再試行スケジュール」を参照してください。
配信不能を有効にすると、配信不能イベントを BLOB ストレージ アカウントに保持できます。 BLOB ストレージ エンドポイントへのメッセージの配信に遅延があり、そのエンドポイントが応答しない場合、Event Grid はイベントを破棄します。 詳細については、「 配信不能の場所と再試行ポリシーを設定する」を参照してください。
Azure Event Hubs
イベント ストリームを使用する場合は、 Azure Event Hubs が推奨されるメッセージ ブローカーです。 基本的には、待機時間が短い大量のデータを受信できる大きなバッファーです。 受信したデータは、同時操作によってすばやく読み取ることができます。 受信したデータは、任意のリアルタイム分析プロバイダーを使用して変換できます。 Event Hubs には、ストレージ アカウントにイベントを格納する機能も用意されています。
高速インジェスト
Event Hubs では、1 秒あたり何百万ものイベントを取り込めます。 イベントはストリームにのみ追加され、時間順に並べ替えられます。
プル モデル
Event Grid と同様に、Event Hubs には Publisher-Subscriber 機能も用意されています。 Event Grid と Event Hubs の主な違いは、サブスクライバーがイベント データを使用できるようにする方法です。 Event Grid は取り込まれたデータをサブスクライバーにプッシュしますが、Event Hubs はプル モデルでデータを使用できるようにします。 イベントが受信されると、Event Hubs によってストリームに追加されます。 サブスクライバーはカーソルを管理し、ストリーム内で前後に移動したり、時間オフセットを選択したり、そのペースでシーケンスを再生することができます。
ストリーム プロセッサは、変換と統計分析のために Event Hubs からデータをプルするサブスクライバーです。 時間の経過に伴う集計や異常検出などの複雑な処理には 、Azure Stream Analytics と Apache Spark を使用します。
パーティションごとに各イベントを処理する場合は、 イベント プロセッサ ホストを使用するか、 Azure Logic Apps などの組み込みコネクタを使用して変換ロジックを提供することで、データをプルできます。 もう 1 つのオプションは、 Azure Functions を使用することです。
パーティショニング
パーティションは、イベント ストリームの一部です。 イベントはパーティション キーを使用して分割されます。 たとえば、複数の IoT デバイスがデバイス データをイベント ハブに送信します。 パーティション キーはデバイス識別子です。 イベントが取り込まれると、Event Hubs によって別のパーティションに移動されます。 各パーティション内では、すべてのイベントが時間順に並べ替えられます。
コンシューマーは、イベント データを処理するコードのインスタンスです。 Event Hubs は、パーティション分割されたコンシューマー パターンに従います。 各コンシューマーは、特定のパーティションのみを読み取ります。 複数のパーティションを使用すると、ストリームを複数のコンシューマーが同時に読み取ることができるため、処理が高速になります。
同じコンシューマーのインスタンスは、1 つのコンシューマー グループを構成します。 複数のコンシューマー グループは、異なる意図で同じストリームを読み取ることができます。 イベント ストリームに温度センサーからのデータがあるとします。 1 つのコンシューマー グループでストリームを読み取り、温度の急上昇などの異常を検出できます。 もう 1 つは、同じストリームを読み取って、テンポラル ウィンドウ内のローリング平均温度を計算できます。
Event Hubs では、複数のコンシューマー グループを許可することで、Publisher-Subscriber パターンがサポートされます。 各コンシューマー グループはサブスクライバーです。
Event Hubs のパーティション分割の詳細については、「 パーティション」を参照してください。
Event Hubs Capture
キャプチャ機能を使用すると、イベント ストリームを Azure Blob Storage または Data Lake Storage に格納できます。 ストレージ アカウントが使用できない場合でも、Capture はデータを一定期間保持し、使用可能な後にストレージに書き込むため、この方法でイベントを格納することは信頼性が高いです。
ストレージ サービスでは、イベントを分析するための追加機能を提供することもできます。 たとえば、BLOB ストレージ アカウントのアクセス層を利用することで、頻繁にアクセスする必要があるデータのイベントをホット層に格納できます。 視覚化にはそのデータを使用できます。 または、アーカイブ層にデータを格納し、監査目的でデータを取得することもできます。
キャプチャは、Event Hubs によって取り込まれた すべての イベントを格納し、バッチ処理に役立ちます。 MapReduce 関数を使用して、データに関するレポートを生成できます。 キャプチャされたデータは、真実のソースとしても機能します。 データの集計中に特定の事実が見逃された場合は、キャプチャされたデータを参照できます。
この機能の詳細については、 Azure Blob Storage または Azure Data Lake Storage の Azure Event Hubs を使用したイベントのキャプチャに関するページを参照してください。
Apache Kafka クライアントのサポート
Event Hubs は、 Apache Kafka クライアントのエンドポイントを提供します。 既存のクライアントは、エンドポイントをポイントするように構成を更新し、Event Hubs へのイベントの送信を開始できます。 コードを変更する必要はありません。
詳細については、Apache Kafka 用の Event Hubs に関するページを参照してください。
クロスオーバーシナリオ
場合によっては、2 つのメッセージング サービスを組み合わせることが有利です。
サービスを組み合わせると、メッセージング システムの効率が向上する可能性があります。 たとえば、ビジネス トランザクションでは、Azure Service Bus キューを使用してメッセージを処理します。 ほとんどの場合アイドル状態でメッセージを受信するキューは、コンシューマーが常に新しいメッセージのキューをポーリングしているため、非効率的です。 イベント ハンドラーとして Azure 関数を使用して Event Grid サブスクリプションを設定できます。 キューがメッセージを受信し、リッスンしているコンシューマーが存在しないたびに、Event Grid によって通知が送信され、キューがドレインされる Azure 関数が呼び出されます。
Service Bus を Event Grid に接続する方法の詳細については、 Azure Service Bus と Event Grid の統合の概要に関するページを参照してください。
メッセージ キューとイベント参照アーキテクチャを使用したエンタープライズ統合は、Service Bus と Event Grid の統合の実装を示しています。
もう 1 つの例を次に示します。Event Grid は一連のイベントを受け取ります。一部のイベントではワークフローが必要ですが、他のイベントは通知用です。 メッセージ メタデータは、イベントの種類を示します。 区別する 1 つの方法は、イベント サブスクリプションのフィルター機能を使用してメタデータを確認することです。 ワークフローが必要な場合、Event Grid によって Azure Service Bus キューに送信されます。 そのキューの受信側は、必要なアクションを実行できます。 通知イベントは、アラート 電子メールを送信するために Logic Apps に送信されます。
関連するパターン
非同期メッセージングを実装するときは、次のパターンを考慮してください。
- 競合コンシューマー パターン。 キューからメッセージを読み取るために、複数のコンシューマーが競合する必要がある場合があります。 このパターンでは、複数のメッセージを同時に処理してスループットを最適化し、スケーラビリティと可用性を向上させ、ワークロードのバランスを取る方法について説明します。
- 優先順位キュー パターン。 ビジネス ロジックで一部のメッセージを他のメッセージよりも先に処理する必要がある場合、このパターンでは、優先順位の高いプロデューサーによって投稿されたメッセージを、優先順位の低いメッセージよりもコンシューマーが受信して処理する方法を示します。
- キュー ベースの負荷平準化パターン。 このパターンでは、メッセージ ブローカーを使用してプロデューサーとコンシューマーの間のバッファーとして機能し、両方のエンティティに対する断続的な負荷の可用性と応答性への影響を最小限に抑えます。
- 再試行パターン。 プロデューサーまたはコンシューマーがキューに接続できない可能性がありますが、このエラーの原因は一時的ですぐに成功する可能性があります。 このパターンでは、この状況を処理して、アプリケーションに回復性を追加する方法について説明します。
- Scheduler Agent Supervisor パターン。 メッセージングは、多くの場合、ワークフロー実装の一部として使用されます。 このパターンは、メッセージングが分散された一連のサービスおよびその他のリモート リソース全体で一連のアクションを調整し、システムが失敗したアクションを回復して再試行できるようにする方法を示しています。
- 振り付けパターン。 このパターンは、サービスがメッセージングを使用してビジネス トランザクションのワークフローを制御する方法を示しています。
- Claim-Check パターン。 このパターンは、大きなメッセージを要求チェックとペイロードに分割する方法を示しています。