イベント駆動アーキテクチャの可能性

### はじめに
**イベント駆動アーキテクチャ**(Event-Driven-Architecture)とは何か？
AWSの公式サイトには以下のような記述がありました。
>**イベントをトリガー**として使い、分離されたサービス間の通信を行うもので、マイクロサービスによって構築されたモダンアプリケーションでよく見られるものです。
> https://aws.amazon.com/jp/event-driven-architecture/

また、オライリーの『ソフトウェアアーキテクチャの基礎』においては以下の表現がされてます。
>非同期的にイベントを受診をして処理する、分離されたイベント処理コンポーネントで構成される。
https://www.oreilly.co.jp/books/9784873119823/

つまり、どちらにも共通して言える表現として、『***非同期なイベント**が分離されたサービス間の連携において中心となっているアーキテクチャ*』という表現ができるかと思います。さらに、アーキテクチャ特性の観点で補足をすると、高度に**スケーラブル**で、かつ、**高パフォーマンス**であり、さらに高い**レジリエンス**(耐障害性)そして、高い**モジュール性**などの特徴ながあると一般的に言われております。ただし、以下で説明がある二つのトポロジー間においては一部トレードオフがあります。

### 重要なコンポーネントの概念
1. イベント コンシューマー:
特定のイベントを購読(受信)することで、特定のアクション(データベースの更新、メールの送信、新しいイベントの発行など)を発火します。AWSにおいては『Lambda, SNS, SQS, Step Functions』などが相当します。文脈にもよりますが、ビジネスロジックも含まれた『イベントプロセッサー』もこれに含んで説明される場合があります。

2. イベント プロデューサー :
とある状態変化が発生した場合、イベントを発生させる部分です。これは、ユーザーが特定のアクションを実行したときや、定期的に発生するタスクが完了したときなど、様々な状況で発生します。生成されたイベントは、『イベントルーター』などを通じて適切なコンシューマーに送信されます。例えば『AWS DynamoDB Streams』がこの役割として用いられて、テーブル操作をリアルタイムで検知して、特定のLambdaを発火させる手法があります。

3. イベント ルーター (イベント チャネル, ブローカー) :
プロデューサーが発生させたイベントの情報を適切なコンシューマーへとルーティングする役割を果たします。例えば『AWS EventBridge』が挙げられ、イベントのフィルタリングや、異常検知のアラートなどのカスタムルール設定、イベントに含まれるペイロードの変換などができます。

### イベント駆動アーキテクチャのトポロジー
それでは、それぞれのコンポーネントが具体的にどのように連携して、結果的に上記のアーキテクチャ特性を生み出しているのかを見ていきます。ただし、『ブローカー・メディエーター』二つの設計パターンが存在し、それぞれ特性や目的が異なりますので、分けて説明したいと思います。
(※以下、オライリー社の『ソフトウェアアーキテクチャからの基礎』から引用しております。)
#### 1. ブローカートポロジー
![ ブローカートポロジー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2730785/e7678869-90eb-7ed9-747e-d97532549b35.png)
ブローカートポロジーは、上図のように単一のイベントプロセッサー(イベントを実行するコンポーネントの集合)に渡されて、その後処理イベントというどんなイベントを起きたのかを残りのワークフローへ**数珠繋ぎ**で伝達されそれぞれでイベントが発火されます。この時、基本イベントの伝達にはキューをイベントチャネル上で使用するので、結果、非同期的な処理となります。なので例えば、最初のユーザーのイベントを一部受信、処理できた時点でフロントに処理を返すことで、レスポンス速度を向上させることができます。

注意点として、**イベント処理をなるべく全て後続に伝える方がいよい**というプラクティスがあります。たしかに無駄な情報を伝達させることにはなるのですが、これは追加機能をイベントプロセッサに入れやすくして拡張性を高めるためであります。例えば、ユーザー登録の一連の処理をEDAで開発するケースで、アカウント登録後の非同期的なメール送信の処理に対して、送信されたメールの解析という要件が発生したとします。この時必要な情報がイベント処理によって事前に伝達されていることで、既存のイベントプロセッサに変更を入れたり、新しいインフラサービスを入れたりする機能拡張の工数を減らすことができます。

#### ブローカートポロジーのトレードオフ
イベントを処理するサービスは互いに独立したサービスであり、それぞれ個別でスケールさせたり、それぞれのサービスを冗長化させることでレジリエンスを担保することができます。さらに後述の**メディエータートポロジー**と比較して、イベント毎にワークフローを制御する**メディエーター**(仲介者)が存在しないため、その分、素早い応答速度を実現します。

一方、デメリットとして、障害発生時に全体を監視、制御するメディエーターが存在しないことで、イベントの情報がワークフローの途中で失われ、データの不整合が発生するリスクがあります。さらに、トランザクションが複数のサービスにまたがる場合、途中のサービスで障害が発生した時にそこまでの処理をロールバックしたり、再開したりすることが難しく、結果的に**回復性**が弱まる可能性があります。
そして、個々のサービスがそれぞれ連携し合っていることで依存関係が複雑化して、**エラー処理やテスト**が難しくなる傾向もあります。
|メリット|デメリット|
|:--|:--|
|プロセッサーが疎結合|ワークフロー制御|
|高いスケーラビリティ|エラー処理|
|高パフォーマンス|再起動能力|
|レジリエンス|データ不整合|

#### 2.  メディエータートポロジー
![イベント駆動アーキテクチャ (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2730785/9f240dc7-3bee-523e-6b07-5cf2cd469193.png)
メディエータートポロジーは、上記のブローカートポロジーの欠点を解消する設計パターンと言えるでしょう。大きな違いとして、**複数のプロセッサーを管理・制御するメディエーター**がシステムの中心となっております。具体的には、中央集権的なエラーハンドリングや、データの一貫性の担保、通信プロトコルの変換などの役割があります。これにより、各プロセッサーがメディエーターとのみ基本依存するので、モック化できたりテストが導入しやすい傾向にもあります。


一方、システム全体がメディエーターに依存してしまうことで、メディエーター自体に障害が発生した場合のリスクや、サービスを個別にスケーリングできないこと、また機能拡張をするときにメディエーターにも変更を入れることで影響範囲が大きくなることなどのデメリットがあります。

|メリット|デメリット|
|:--|:--|
|ワークフロー制御|プロセッサーが密結合|
|回復性|スケーラビリティの低下|
|再起動能力|耐障害性の低下|
|データ整合性|ワークフローの複雑化|


### まとめ
以上、イベント駆動アーキテクチャに関する記事でした。
ただし、文脈に応じて個々のキーワードの表現が異なる場合がありますので、その点ご容赦ください。また、そのように言葉の定義が一部曖昧であるがために、今回はなるべく、著名な、本の内容や企業サイトの内容参照するように心がけました。
イベント駆動アーキテクチャに可能性を感じるきっかけになりましたら、ぜひいいねいただけると幸いでございます。


### 参照元

https://cloud.google.com/eventarc/docs/event-driven-architectures?hl=ja

https://aws.amazon.com/jp/what-is/eda/

https://www.alexdebrie.com/posts/event-driven-vs-event-based/

https://developers.cyberagent.co.jp/blog/archives/40441/

https://www.oreilly.co.jp/books/9784873119823/