イベント駆動アーキテクチャ
イベント駆動アーキテクチャ(EDA:Event Driven Architecture)とは、イベントを待機し、起こったイベントに応じて処理を行うプログラムスタイルです。SaaSOvationでは、ユーザーに待ちが発生したり、タイムアウトが発生したりするような、長いタスクへの対策としてイベント駆動アーキテクチャを導入しました。ヘキサゴナルアーキテクチャの場合、複数ドメイン間で連携を行うような分散処理に適しています。
システムが複数存在する場合、イベントを使うことで複数のシステム間の結合を切り離すことができます。例えば、あるシステムの変更をドメインイベントとして、他システムのイベントサブスクライバに連携することができます。
電話番号一覧から条件一致する件数を探すサンプル
IDDD本では、イベント駆動に関するアーキテクチャーについて「パイプ&フィルター」「長期プロセス(サーガ)」「イベントソーシング」の3つを紹介しています。まずは「パイプ&フィルター」と「長期プロセス(サーガ)」について紹介します。
サンプルとして、電話番号の一覧が書かれたテキストファイルから、フリーダイヤルの件数を出力する処理をイベント駆動のイメージで考えてみましょう。UNIXコマンドでは「$cat 電話番号.txt | grep 0120- | uc -l」で実現されます。下図では、この処理を「パイプ&フィルター」方式で表現しています。また、電話番号リスト全体の件数算出を並行して行う例を「長期プロセス(サーガ)」方式にて表現しています。
パイプ&フィルターによるパイプライン
イベント駆動のシンプルな形が「パイプ&フィルター」といわれるスタイルとなります。上図では、電話番号が記載されたリストがイベントとして渡り、それぞれの処理でフィルターしたり件数を数えたりしていることがわかると思います。
「パイプ」は土管の流れで、次に渡す「イベント」を表しています。「フィルター」は受信したイベントに応じて単一のタスクを実行するコンポーネントです。このパイプとフィルターを組み合わせることでパイプラインを構築します。
複数の処理を1つのプログラムで書いてしまうと再利用やチューニングが困難ですが、パイプ&フィルター方式では、コンポーネント単位で再利用したり、ボトルネック部分のリソースを増強したりできるメリットがあります。
長期プロセス(サーガ)による並列パイプライン
パイプ&フィルターでは、ひとつのパイプラインを対象としていましたが、処理速度の向上のため、複数パイプラインを並列実行したい場合があります。このようなケースでは「長期プロセス(サーガ)」方式を用いることで、並列にパイプラインを制御できます。
長期プロセスは、柔軟性が高く並列実行もできるアーキテクチャーのため、他システムやレガシーシステムとの統合といった高度な連携時に採用可能です。ただし、長期プロセス方式では、各パイプラインの状態制御に注意を払う必要があります。例えば、インフラやアプリケーションの障害からの復旧、能動的/受動的タイムアウトの管理、重複イベントのメッセージ管理といった制御が必要になります。正常なユースケースだけではなく、失敗を想定したワークフローも組み込む必要があるため、難易度は高くなります。
イベントを記録して再現できるイベントソーシング
SaaSOvationチームは、政府からの監査対応のためにイベントソーシングを導入しました。このような履歴管理のような要件には「イベントソーシング(Event Sourcing)」というパターンを使用できます。これは、GitやSubversionといったピンポイントで過去の状態に復元できるリビジョン管理ツールの概念に似ています。
イベントソーシングの流れは、上図の通り、発生したすべてのイベントを「イベントストア」に格納する点が特徴です。記録されたイベントを最初から順番に再生することでオブジェクトの状態を復元できるため、監査やバグ調査において力を発揮します。またイベントストアを使って、データパッチを追加することも可能です。状態が変化した理由や経緯が記録されるというメリットはありますが、モデリングや実装において少なからず影響を与えるため、ビジネス的なメリットが必要な場合に採用を検討してみると良いでしょう。なお、IDDD本の付録Aでは、CQRSとイベントソーシングと組み合わせた実装例を紹介しています。
データファブリック(グリッドベース分散キャッシュ)
最後に、イベント駆動アーキテクチャの基盤例として、データファブリック(グリッドベース分散キャッシュ)について紹介します。これは一般的な技術というよりは、Pivotal社のGemFireやOracle社のCoherenceといった特定の製品で提供されている概念となります。この仕組みには次のような特徴があります。
- ドメインオブジェクトを永続化してキャッシュに保存
- マルチレプリケーションにより性能面での管理が容易
- イベント駆動における送信保証のサポート
- キャッシュ変更時のプッシュ通知(ビューの即時変更)
- 長期プロセスのような分散並行処理の管理
実装時にこれらの要件が必要になった場合は、この機能についても調査してみると良いでしょう。
最後に
以上、本稿ではDDDと関連あるアーキテクチャについて紹介してきました。DDDではアーキテクチャの制約はありませんが、多くの選択肢があることが理解できたと思います。本稿で紹介したパターンについては、参考資料やクラウドデザインパターンといった書籍にも目を通してみると理解が深まるのではないでしょうか。次の第5回ではDDDの「エンティティ」について紹介します。