イベント ドリブン アーキテクチャは、 イベント の ストリームを生成するイベント プロデューサー、これらのイベントをリッスンする イベント コンシューマー 、およびイベント をプロデューサーからコンシューマーに転送する イベント チャネル (多くの場合、イベント ブローカーまたはインジェスト サービスとして実装) で構成されます。
Architecture
イベントはほぼリアルタイムで配信されるため、コンシューマーはイベントの発生時にすぐに応答できます。 プロデューサーはコンシューマーから切り離されます。つまり、プロデューサーは、どのコンシューマーがリッスンしているかがわからないことを意味します。 コンシューマーも互いに切り離され、すべてのコンシューマーにすべてのイベントが表示されます。
このプロセスは 、競合コンシューマー パターンとは異なります。 競合コンシューマー パターンでは、コンシューマーはキューからメッセージをプルします。 各メッセージは、エラーがないと仮定して 1 回だけ処理されます。 Azure IoT などの一部のシステムでは、イベントを大量に取り込む必要があります。
イベント ドリブン アーキテクチャでは、 パブリッシュ/サブスクライブ モデル またはイベント ストリーム モデルを使用できます。
Publish-subscribe: パブリッシュ/サブスクライブ メッセージング インフラストラクチャは、サブスクリプションを追跡します。 イベントが発行されると、各サブスクライバーにイベントが送信されます。 イベントが配信された後は再生できません。また、新しいサブスクライバーにはイベントが表示されません。 発行/サブスクライブシナリオには Azure Event Grid を使用することをお勧めします。
イベント ストリーミング: イベントはログに書き込まれます。 イベントはパーティション内で厳密に順序付けされ、永続的です。 クライアントはストリームをサブスクライブしません。 代わりに、クライアントはストリームの任意の部分から読み取ることができます。 クライアントは、ストリーム内での位置を進める役割を担います。つまり、クライアントはいつでも参加でき、イベントを再生できます。 Azure Event Hubs は、 高スループットのイベント ストリーミング用に設計されています。
コンシューマー側には、いくつかの一般的なバリエーションがあります。
単純なイベント処理: イベントによって、コンシューマー内のアクションが直ちにトリガーされます。 たとえば、Event Grid トリガーまたは Azure Service Bus トリガーで Azure Functions を使用して、メッセージが発行されたときにコードを実行できます。
基本的なイベントの相関関係: コンシューマーは、いくつかの個別のビジネス イベントを処理し、それらを識別子によって関連付け、以前のイベントからの情報を保持して、後でイベントを処理するときに使用します。 NServiceBus や MassTransit などのライブラリでは、このパターンがサポートされています。
複雑なイベント処理: コンシューマーは 、Azure Stream Analytics などのテクノロジを使用して一連のイベントを分析し、イベント データ内のパターンを識別します。 たとえば、時間枠内の埋め込みデバイスからの読み取り値を集計し、移動平均が特定のしきい値を超えた場合に通知を生成できます。
イベント ストリーム処理:Azure IoT Hub、Event Hubs、Event Hubsfor Apache Kafka などのデータ ストリーミング プラットフォームをパイプラインとして使用して、イベントを取り込み、ストリーム プロセッサにフィードします。 ストリーム プロセッサは、ストリームを処理または変換するために動作します。 アプリケーションのサブシステムごとに複数のストリーム プロセッサが存在する可能性があります。 このアプローチは、IoT ワークロードに適しています。
イベントのソースは、IoT ソリューションの物理デバイスなど、システムの外部にある可能性があります。 その場合、システムは、データ ソースに必要なボリュームとスループットでデータを取り込める必要があります。
イベント ペイロードを構造化するには、主に 2 つの方法があります。 イベント コンシューマーを制御できる場合は、各コンシューマーのペイロード構造を決定できます。 この戦略により、1 つのワークロード内で必要に応じてアプローチを混在させることができます。
ペイロードに必要なすべての属性を含めます。 この方法は、コンシューマーが外部データ ソースに対してクエリを実行することなく、使用可能なすべての情報を取得する場合に使用します。 ただし、特に更新後に、複数 のレコード システムが原因でデータ整合性の問題が発生する可能性があります。 コントラクトの管理とバージョン管理も複雑になる可能性があります。
ペイロードにキーのみを含めます。 この方法では、コンシューマーは、データ ソースから残りのデータを個別にフェッチするために必要な属性 (主キーなど) を取得します。 このメソッドでは、単一のレコード システムがあるため、データの整合性が向上します。 ただし、コンシューマーはデータ ソースに頻繁にクエリを実行する必要があるため、最初のアプローチよりもパフォーマンスが低下する可能性があります。 イベントが小さくなり、コントラクトが単純になるため、結合、帯域幅、コントラクト管理、またはバージョン管理に関する懸念が少なくなります。
上の図では、各種類のコンシューマーが 1 つのボックスとして表示されています。 コンシューマーがシステムの単一障害点にならないようにするには、コンシューマーのインスタンスが複数あるのが一般的です。 イベントのボリュームと頻度を処理するために、複数のインスタンスが必要になる場合もあります。 1 つのコンシューマーが複数のスレッドでイベントを処理できます。 このセットアップでは、イベントを順番に処理する必要がある場合、または 1 回だけセマンティクスを必要とする場合に、チャレンジを作成できます。 詳細については、「調整の 最小化」を参照してください。
多くのイベント ドリブン アーキテクチャには、次の 2 つの主要なトポロジがあります。
ブローカー トポロジ: コンポーネントは、イベントをシステム全体にブロードキャストします。 他のコンポーネントは、イベントに対して動作するか、イベントを無視します。 このトポロジは、イベント処理フローが比較的単純な場合に便利です。 中央の調整やオーケストレーションがないため、このトポロジは動的にすることができます。
このトポロジは高度に分離されており、スケーラビリティ、応答性、およびコンポーネントのフォールト トレランスを提供するのに役立ちます。 コンポーネントは、マルチステップ ビジネス トランザクションの状態を所有または認識せず、アクションは非同期的に実行されます。 その結果、分散トランザクションを再起動または再生するための組み込みのメカニズムがないため、リスクが高くなります。 このトポロジはデータの不整合の原因になる可能性があるため、エラー処理と手動介入戦略を慎重に検討する必要があります。
メディエーター トポロジ: このトポロジは、ブローカー トポロジの欠点の一部に対処します。 イベントのフローを管理および制御するイベント メディエーターがあります。 イベント メディエーターは状態を維持し、エラー処理と再起動の機能を管理します。 ブローカー トポロジとは異なり、メディエーター トポロジ内のコンポーネントは、指定されたチャネルのみに対してのみ、発生箇所をコマンドとしてブロードキャストします。 多くの場合、これらのチャネルはメッセージ キューです。 コンシューマーは、これらのコマンドを処理する必要があります。
このトポロジにより、制御が強化され、分散エラー処理が向上し、データの整合性が向上する可能性があります。 ただし、このトポロジではコンポーネント間の結合が増え、イベント メディエーターがボトルネックまたは信頼性の問題になる可能性があります。
このアーキテクチャを使用する場合
次の条件に該当する場合は、このアーキテクチャを使用する必要があります。
複数のサブシステムが同じイベントを処理する必要があります。
タイム ラグを最小限に抑えたリアルタイム処理が必要です。
パターン マッチングや時間経過に伴う集計などの複雑なイベント処理が必要です。
IoT など、大量のデータと高速のデータが必要です。
独立したスケーラビリティと信頼性の目標のために、プロデューサーとコンシューマーを分離する必要があります。
メリット
このアーキテクチャには、次の利点があります。
- プロデューサーとコンシューマーは切り離されます。
- ポイントツーポイント統合はありません。 新しいコンシューマーをシステムに簡単に追加できます。
- コンシューマーは、発生したイベントにすぐに応答できます。
- 拡張性が高く、柔軟性が高く、分散型です。
- サブシステムには、イベント ストリームの独立したビューがあります。
課題
保証された配信
一部のシステム (特に IoT シナリオ) では、イベントが配信されることを保証することが重要です。
イベントを順番に処理するか、1 回だけ処理する
回復性とスケーラビリティのために、各コンシューマーの種類は通常、複数のインスタンスで実行されます。 このプロセスは、コンシューマーの種類内でイベントを順番に処理する必要がある場合、または べき等メッセージ処理 ロジックが実装されていない場合にチャレンジを作成できます。
サービス間のメッセージ調整
ビジネス プロセスには、多くの場合、ワークロード全体で一貫した結果を実現するためにメッセージを発行してサブスクライブする複数のサービスがあります。 コレオグラフィや Saga オーケストレーションなどのワークフロー パターンを使用して、さまざまなサービス間のメッセージ フローを確実に管理できます。
エラー処理
イベント ドリブン アーキテクチャは、主に非同期通信に依存します。 非同期通信で発生する一般的な課題は、エラー処理です。 この問題に対処する 1 つの方法は、専用のエラー ハンドラー プロセッサを使用することです。
イベント コンシューマーは、エラーが発生すると、問題のあるイベントをすぐに非同期的にエラー ハンドラー プロセッサに送信し、他のイベントの処理を続行します。 エラー ハンドラー プロセッサは、問題の解決を試みます。 成功した場合、エラー ハンドラー プロセッサはイベントを元のインジェスト チャネルに再送信します。 失敗した場合、プロセッサはイベントをさらに検査するために管理者に転送できます。 エラー ハンドラー プロセッサを使用すると、再送信されたイベントは順番に処理されません。
データ損失
非同期通信で発生するもう 1 つの課題は、データ損失です。 イベントを処理して次のコンポーネントに渡す前にいずれかのコンポーネントがクラッシュした場合、イベントは破棄され、最終的な宛先に到達することはありません。 データ損失の可能性を最小限に抑えるには、転送中のイベントを保持し、次のコンポーネントがイベントの受信を確認した場合にのみ、イベントを削除またはデキューします。 これらの機能は、 クライアント受信確認モード および 最後の参加者サポートと呼ばれます。
従来の要求/応答パターンの実装
イベント プロデューサーは、注文を続行する前に顧客の適格性を取得するなど、イベント コンシューマーからの即時応答を必要とする場合があります。 イベント ドリブン アーキテクチャでは、 要求/応答メッセージングを使用して同期通信を実現できます。
このパターンは、要求キューと応答キューで実装されます。 イベント プロデューサーは、要求キューに非同期要求を送信し、そのタスクに対する他の操作を一時停止し、応答キュー内の応答を待機します。 この方法では、このパターンを効果的に同期プロセスに変換します。 その後、イベント コンシューマーは要求を処理し、応答キューを介して返信を送信します。 この方法では通常、追跡にセッション ID が使用されるため、イベント プロデューサーは、応答キュー内のどのメッセージが特定の要求に関連しているかを認識します。 元の要求では、応答キューの名前 (一時的な可能性がある)、 応答先ヘッダー、または相互に合意された別のカスタム属性を指定することもできます。
適切な数のイベントのメンテナンス
過剰な数のきめ細かいイベントを生成すると、システムが飽和し、圧倒される可能性があります。 イベントの量が多すぎると、イベントの全体的なフローを効果的に分析することが困難になります。 この問題は、変更をロールバックする必要があるときに悪化します。 逆に、イベントを過度に統合すると問題が発生する可能性があり、その結果、イベント コンシューマーからの不要な処理と応答が発生する可能性があります。
適切なバランスを実現するには、イベントの結果と、コンシューマーが応答を決定するためにイベント ペイロードを検査する必要があるかどうかを検討します。 たとえば、コンプライアンス チェック コンポーネントがある場合は、 準拠 と 非準拠の 2 種類のイベントのみを発行するだけで十分な場合があります。 この方法は、関連するコンシューマーのみが各イベントを処理し、不要な処理を防ぐのに役立ちます。
その他の考慮事項
イベントに含めるデータの量は、パフォーマンスとコストに影響を与える大きな考慮事項となる可能性があります。 処理に必要なすべての関連情報をイベントに直接配置することで、処理コードを簡略化し、余分な参照を排除できます。 少数の識別子など、最小限の情報のみをイベントに追加すると、トランスポート時間とコストが削減されます。 ただし、この方法では、必要な追加情報を取得する処理コードが必要です。 詳細については、「 食事にイベントを配置する」を参照してください。
要求は、要求処理コンポーネントにのみ表示されます。 ただし、多くの場合、イベントはワークロード内の複数のコンポーネントに表示されます。ただし、それらのコンポーネントがそれらのコンポーネントを使用しない場合や、それらを使用する意図がない場合でも、イベントは表示されます。 "侵害を想定する" 考え方で運用するには、意図しない情報の漏洩を防ぐために、イベントに含める情報に注意してください。
多くのアプリケーションでは、プライマリ アーキテクチャとしてイベント ドリブン アーキテクチャが使用されています。 このアプローチを他のアーキテクチャ スタイルと組み合わせて、ハイブリッド アーキテクチャを作成できます。 一般的な組み合わせには、 マイクロサービス と パイプとフィルターが含まれます。 イベントドリブン アーキテクチャを統合して、ボトルネックを排除し、要求量が多い場合に バックプレッシャー を提供することで、システムのパフォーマンスを向上させます。
特定のドメインは、 多くの場合、複数のイベント プロデューサー、コンシューマー、またはイベント チャネルにまたがっています。 特定のドメインに対する変更は、多くのコンポーネントに影響する可能性があります。