イベント ドリブン アーキテクチャのスタイル

Azure IoT
Azure Stream Analytics

イベント ドリブン アーキテクチャは、イベントのストリームを生成するイベント プロデューサーと、イベントをリッスンするイベント コンシューマーで構成されます。

Diagram of an event-driven architecture style

イベントはほぼリアルタイムで配信されるため、イベントが発生するとコンシューマーはすぐに応答できます。 プロデューサーはコンシューマーから分離されており、プロデューサーはどのコンシューマーがリッスンしているのかを認識しません。 コンシューマーも互いに分離されており、すべてのコンシューマーがすべてのイベントを見ることができます。 これは競合コンシューマー パターンとは異なり、コンシューマーがキューからメッセージを取得し、メッセージは一度だけ処理されます (エラーは想定されません)。 IoT などの一部のシステムでは、イベントを大量に取り込む必要があります。

イベント ドリブン アーキテクチャでは、パブリッシュ/サブスクライブ ("pub/sub" とも呼ばれます)モデルやイベント ストリーム モデルを使用できます。

  • パブリッシュ/サブスクライブ:メッセージング インフラストラクチャではサブスクリプションを追跡します。 イベントが発行されると、各サブスクライバーにイベントが送信されます。 イベント受信後は、イベントを再生することはできません。また、そのイベントは新しいサブスクライバーに表示されません。

  • イベント ストリーミング:イベントがログに書き込まれます。 イベントは (パーティション内で) 厳密に順序付けされ、持続します。 クライアントはストリームにサブスクライブしませんが、その代わり、ストリームのどの部分からでも読み取ることができます。 ストリーム内でクライアントの位置を進めるのは、クライアントの役割です。 つまりクライアントはいつでも参加でき、イベントを再生できます。

コンシューマー側には、いくつかの一般的なバリエーションがあります。

  • 簡単なイベント処理。 イベントがコンシューマーのアクションを即時トリガーします。 たとえば、お客様は Service Bus トリガーを備えた Azure Functions を使用でき、それにより、Service Bus トピックにメッセージが発行されるたびに関数が実行されます。

  • 基本的なイベントの相関関係。 コンシューマーは、少数の個別のビジネス イベントを処理する必要があります。通常は、何らかの識別子で関連付けられ、後でイベントを処理するときに使用するために以前のイベントの情報が保持されます。 このパターンは、NServiceBusMassTransit などのライブラリでサポートされています。

  • 複合イベント処理。 コンシューマーは一連のイベントを処理し、Azure Stream Analytics などのテクノロジを使用してイベント データのパターンを検索します。 たとえば、組み込みデバイスからの測定値を時間枠で集計し、移動平均が特定のしきい値を超えた場合に通知を生成することができます。

  • イベント ストリーム処理. Azure IoT Hub や Apache Kafka などのデータ ストリーミング プラットフォームを、イベントを取り込んでストリーム プロセッサにフィードするパイプラインとして使用します。 ストリーム プロセッサは、ストリームの処理や変換を行います。 アプリケーションの異なるサブシステムに対して、複数のストリーム プロセッサが存在する場合があります。 この手法は IoT ワークロードに適しています。

イベントのソースはシステムの外部にある場合があります。たとえば、IoT ソリューションの物理デバイスなどです。 その場合、システムはデータ ソースで必要なボリュームとスループットでデータを取り込むことができる必要があります。

上記の図では、コンシューマーが種類ごとに 1 つのボックスで表示されています。 実際には、1 つのコンシューマーに複数のインスタンスがあるのが一般的ですが、それはコンシューマーがシステムの単一障害点にならないようにするためです。 イベントのボリュームと頻度を制御するのに、複数のインスタンスが必要になることもあります。 また、1 つのコンシューマーが複数のスレッドのイベントを処理することもあります。 イベントを順番に処理しなければならない、または正確に 1 回のセマンティクスが必要な場合には、このために課題が発生することがあります。 「Minimize Coordination (調整を最小限に抑える)」をご覧ください。

このアーキテクチャを使用する状況

  • 複数のサブシステムで同じイベントを処理する必要がある。
  • 最小のタイム ラグのリアルタイム処理。
  • パターン マッチングや時間枠での集計などの複合イベント処理。
  • IoT などの高ボリューム、高ベロシティのデータ。

メリット

  • プロデューサーとコンシューマーが分離。
  • ポイント ツー ポイントの統合はなし。 システムに新しいコンシューマーを追加するのが簡単。
  • コンシューマーは、イベントが到着するとすぐに応答可能。
  • 高い拡張性と分散。
  • サブシステムにイベント ストリームの独立したビューがある。

課題

  • 保証された配信。 一部のシステムでは (特に IoT シナリオで)、イベントが配信されたことを保証することが重要です。
  • イベントを順番に、または正確に 1 回処理。 各コンシューマー タイプは通常、回復性とスケーラビリティのために複数のインスタンスで実行されます。 (コンシューマー タイプ内で) 順番にイベントを処理する必要がある場合や、べき等メッセージ処理ロジックが実装されていない場合、これにより課題が生じる可能性があります。
  • サービス間のメッセージの調整。 多くの場合、ビジネス プロセスには、ワークロード全体で一貫した結果を実現するために、複数のサービスの発行とメッセージのサブスクライブが含まれています。 コレオグラフィ パターンSaga オーケストレーションなどのワークフロー パターンは、さまざまなサービスにわたってメッセージ フローを確実に管理するために使用できます。

その他の注意点

  • イベントに含めるデータの量は、パフォーマンスとコストの両方に影響するので、慎重に検討する必要があります。 処理に必要なすべての関連情報をイベント自体に格納すると、処理コードが簡素化され、追加の検索回数を減らすことができます。 最小限の情報 (少数の識別子のみ、など) をイベントに格納すると、転送時間とコストは削減されますが、必要な追加情報を検索するには処理コードが必要になります。 これの詳細については、こちらのブログ記事を参照してください。
  • 要求は要求処理コンポーネントにのみ表示されますが、多くの場合、それらのコンポーネントがそれらのコンポーネントを使用しない、または使用する予定がない場合でも、イベントはワークロード内の複数のコンポーネントに対して表示されます。 「侵害を想定」 して運用する場合は、意図しない情報漏えいを防ぐために、イベントに含める情報に注意してください。