MuleRuntimeにおけるAPIデザインパターン ~ CQRSとEvent Sourcing~
MuleSoftでAPIデザインを行う際にいくつかのAPIデザインパターンを利用することが多いですが、その中にCQRSとEvent Sourcingというパターンがあります。
これらは特にMuleSoftに特化したものではなく一般的なデザインパターンなのですが、MuleSoftでAPIを設計する上でも有効となる場面が多い概念なので簡単にご紹介します。
CQRS(Command Query Responsibility Segregation)とは?
CQRSはCommand Query Responsibility Segregation (コマンドクエリ責務分離)の略で、簡単に言えば問い合わせ(Query)とデータ操作(Command)は別のオペレーションものと考えるべきだというデザインパターンです。
あるビジネスドメインに対するAPIを考える時、そのAPIにおいて書き込み/読み込みの速度を重要視するのか、トランザクションやデータ整合性を重要視するのか、読み込みの細かな権限をコントロールするのかはビジネスドメインによって異なります。そして書き込み時(整合性・トランザクション・バージョン管理など)と、書き込み時(検索の効率性、スケーラビリティ、セキュリティ)では担当すべき主に責務も異なるため、概念として分けて考えたほうがシンプルかつ柔軟性に優れた構成を取ることができます。
例えば、読み込みのスピードを最大化するためは、書き込まれたデータを直接読み込ませるのではなく、Denormalize(非正規化)したデータストアをクエリさせるケースなどが考えられます。
このようなAPIを検討しなければならない場合には、読み込みのパフォーマンスやスケーラビリティ、柔軟性に優れるCQRSパターンが役に立ちます。
CQRSパターンでは、以下の様に動作します
- APIは、作成、更新、または削除コマンドを受け取ります。
- 検証および更新ロジックが実行され、書込データストアへの書込が行われます。
- 書込データストアは、変更を読取データストアに伝達します。 このステップにはクエリのパフォーマンスを向上させるための非正規化などが含まれます。
- クエリはAPIによって受信されます。
- クエリロジックはデータベースから読み取り、応答を作成します。
多くのシステムでは、読み取りの負荷が書き込みよりもかなり大きい傾向があります。 読み取り側と書き込み側をbounded contextによって別々のモデルに分離することで、それぞれ個別にスケーリング戦略を取ることができます。
この様にCommandとQuery & Responseを分けて考えた事によって設計の幅が広がりますが、単一の責任でコンポーネントを作成するよりも複雑な点は注意が必要です。
Event Sourcingとは?
Event Sourcingとは、通常のデータストアではデータ現在の状態を記録しますが、データの更新されるとなるイベントを積み上げていくデザインパターンの事を指します。
イベントソーシングの良い所は状態の履歴であるイベントが残っていることにより、現在を含めたある特定時点の状態を再現できる点にあります。例えば、あるデータストアが3日前にどのような状態だったかを再現したい場合には、3日前までのイベントを再試行すれば完全に過去のある時点のリソースの状態を再現できます。
過去のある時点のリソースの状態が再現できるということは、複数のタイムライン(昨日と2週間前とか)の比較を可能にするといった拡張を施したり、誤ったイベントの受信によって問題の起きたAPIリソースの状態を修復することも可能です。
注意点として、イベントソーシングを利用すれば一般的には作成と更新のパフォーマンスを向上させられますが、集約された状態(現在の状態)をイベントから構築するには時間がかかってしまいます。
対策としては定期的な状態のスナップショットを作成し、その時点からイベントを再生することで必要な時間を短縮できます。
CQRSとEvent Sourcingの併用
このCQRSとEvent Sourcingは非常に相性が良く、組み合わせて利用することによりいくつかの課題に対して有効なソリューションとなりえます。例えば更新処理が高速かつ堅牢、クエリにスケーラビリティとパフォーマンスが求められるケースでは以下のような構成が考えられます。
CQRSにおけるCommand(書き込み)部分の実装にEvent Sourcingを適用する事で、状態の履歴であるイベントを持ちつつ高速な更新処理を可能にします。書込データストアと読取データストアの間にはPub/Subサービスを入れることにより、イベントをデータウェアハウスへ投入したり、別のサービスでイベントを購読することでイベント・ドリブンなサービスの追加も可能となります。
Query(読み込み)部分の実装には非正規化されたデータベースを用意し、Queryロジックはこのデータベースに対して行わせる事によって、パフォーマンスとスケーラビリティの確保が行えます。
またAPIデザインにおいてCQRSとEvent Sourcingが相性の良い点として、APIコンシューマに対しては内部の複雑なデザインパターンを公開したり意識させたりする必要はなく、APIのシェイプ自体はシンプルに保つことが可能な点があげられます。
ただし、注意点として、この仕組ではデータを更新した瞬間にそのデータがQueryできるかの保証が無いため、そういった処理が要件にある場合には更に工夫が必要な点は注意が必要です。
全てにおいて万能なパターンというのは存在しませんが、CQRSとEvent Sourcingの組み合わせは、API設計をするにあたり常に頭の中に置いておくに値する有効なパターンだと思います。