マイクロサービスを支えるフレームワークを考える

# はじめに
これまでマイクロサービスに関して、[マイクロサービスが開発・運用コスト削減におよぼす効果](https://qiita.com/takahashisansan/items/7470a14e45aee2b6739f)を皮切りに何回かに分けて考えてきました。
マイクロサービスに限らず何かを実現するに際して、全てを一から作り上げるのも大変なので、既にオープンソースソフトウェアとして提供されているものがあれば、出来るだけ取り込んで作り上げるのが効率的になると考えます。
このため、今回は現在提供されているマイクロサービスの実現を支えるためのフレームワークを複数選び出し、機能面、基盤面の観点で比較してみました。

# 何をもって比較するか？
各フレームワークを比較するにあたり、機能面とデータベースという二つの側面から以下の項目を抽出しています。
機能面については、マイクロサービスに関する本の中でよく見られるキーワードを中心にしました。
具体的には以下としました。

| No. | 大分類 | 中分類 | 小分類 |
| :------: | :------: | :------: | :------: |
| 1 | コンポーネント間通信 |  |  |
| 1-1 | | 同期通信 | | |
| 1-1-1 | | | REST |
| 1-1-2 | | | RPC(gRPC含む) |
| 1-2 | | 非同期通信 | |
| 2 | データの一貫性 | | |
| 2-1 | | ACID | |
| 2-2 | | 結果整合性 | |
| 3 | 使用可能なデータベース | | |
| 3-1 | | Oracle | | 
| 3-2 | | MySQL | |
| 3-3 | | PostgresSQL | |
| 3-4 | | MongoDB | |
| 3-5 | | Redis | |
| 4 | 使用可能な言語 | | |
| 4-1 | | Java | |

## コンポーネント間通信
マイクロサービスのシステムでは、機能ごとにマイクロサービスとして分かれた形になっていて、そのマイクロサービス間の通信(以降はコンポーネント間通信と呼びます)が非常に重要になってきます。
そこで、このコンポーネント間通信が同期通信であるのか非同期通信であるのかで分類し、さらに同期通信を実現するための手段としてのRESTなのかRPC(gRPCを含むとしました。)ということで分類して、それぞれのフレームワークのサポートがどうなっているのかを見てみたいと思います。

## データの一貫性
マイクロサービスのシステムでは、データベースを個々のマイクロサービスごとに持たせるようにしたものが多いと思います。
この場合、異なるマイクロサービス配下にあるデータベースの更新をしようとすると、マイクロサービス間でなんらかの通信が発生します。この通信による遅延等によってデータの一貫性を保つのが非常に難しくなることが容易に想像されます。
このためデータの一貫性をどのようにして保つようにしているのかで、手段はおいておいて一つはACID(Atomicity(不可分性), Consistency(一貫性), Isolation(独立性), Durability(永続性))という考え方もう一つは結果整合性(Eventual Consistency)という考え方を実現出来るのかどうかという点で見てみたいと思います。

## 使用可能なデータベース
使用可能なデータベースとしては、一般的によく使われていると思われるOracle, MySQL, PostgresSQL, MongoDB, Redisといったものを考えました。

# どんなマイクロサービス用のフレームワークを考えるか？
以下の5つのフレームワークを調べる対象としました。

* Eventuate
* Axon Framework
* Spring Boot + Spring Cloud
* Lagom
* KumuluzEE microservice framework

## Eventuate
マイクロサービスに関心を持っている方であれば、読んだことがあるかもしれませんが「Microservices Patterns」という本の著者でコンサルタントでもあるChris Richardsonが起業した[Eventuate](https://eventuate.io/)がオープンソースソフトウェアとして提供しているものです。
Eventuateが提供しているプラトフォームには以下の特徴があります。

* [Saga](https://microservices.io/patterns/data/saga.html)を使ってデータの一貫性を実現することが出来ます。
* [CQRS(Command Query Responsibility Segregation)](https://microservices.io/patterns/data/cqrs.html)を使うことで複数サービスに跨ったデータベースに効率的にアクセスすることが出来ます。
* [Transactional Outbox](https://microservices.io/patterns/data/transactional-outbox.html)や[Event Sourcing](https://microservices.io/patterns/data/event-sourcing.html)を使ってメッセージやイベントのやり取りを行うことが出来ます。

CQRSやEvent Sourcingは、他のプラットフォームでもよく見かけますので、Sagaを使ってデータの一貫性を実現するというのが、このプラットフォームの一番の特徴ではないかと思います。
Eventuateを使ったSagaの実現は、下図のようになります。
ここでは、お客様から商品の注文があった時に、支払いをクレジットで行う場合を想定しています。お客様から注文があれば、まずここではOrder Serviceが注文を受け付けます。注文が入ったから商品は確保しておくのですが、Customer Serviceにおいてクレジットの情報紹介を行って支払い可能であるのかどうか分かるまでは決済を保留にしておかなければいけません。支払い可能であることが分かって初めて決済完了となりますが、支払い不可能となれば決済はリジェクトされ、確保しておいた商品を開放する必要があります。このように判定結果によって、過去のトランザクションに遡ってどのようにするのか制御して、データの一貫性を保証するのがSagaになります。

![Eventuateを使ったSagaの実現](https://chrisrichardson.net/i/sagas/CreateOrderSagaOrchestrationDesign.png)

この図から分かるように、全てがEventuateのフレームワーク(図の紫の箱の部分)で隠蔽されるわけではなく、自分たちのアプリケーションで作りこまなければいけない部分もそれなりにあります。そのためにはSagaとはどういったものなのかを理解しておく必要があるということに注意しておく必要があります。
図は[Chris RichardsonのBlog](https://chrisrichardson.net/post/sagas/2019/12/12/developing-sagas-part-4.html)から引用しています。

## Axon Framework
こちらは[AxonIQ](https://axoniq.io/)がオープンソースソフトウェアとして提供しているものです。
AxonIQが提供しているものは以下を備えた強力なプラットフォームであるとのことです。

* DDD(Domain Driven Design)
* Event Sourcing
* CQRS(Command Query Responsibility Segregation)
* Microservices

## Spring Boot + Spring Cloud
こちらは[Spring](https://spring.io/)がオープンソースソフトウェアとして提供しているものです。
構成は下図のようになります。

![Spring BootとSpring Cloudを使った構成図](https://spring.io/images/diagram-microservices-88e01c7d34c688cb49556435c130d352.svg)

図は[SpringのMicroservice](https://spring.io/microservices)から引用しています。

## Lagom
こちらは[Lightbend社](https://www.lightbend.com/)がオープンソースソフトウェアとして提供しているものです。

## KumuluzEE microservice framework
こちらは[KumuluzEE社](https://ee.kumuluz.com/)がオープンソースソフトウェアとして提供しているものです。

# それぞれ比較してみると
それぞれのプラットフォームで比較をしてみると、以下のようになりました。

| No. | 大分類 | 中分類 | 小分類 | Eventuate | Axon Framework |  Spring Boot + Spring Cloud | Lagom | KumuluzEE microservice framework |
| :------: | :------: | :------: | :------: | :-----: | :-----: | :-----: | :-----: | :-----: |
| 1 | コンポーネント間通信 |  |  | △ | 〇 | △ | 〇 | 〇 |
| 1-1 | | 同期通信 | | △ | 〇 | △ | 〇 | 〇 |
| 1-1-1 | | | REST | 〇 | 〇 | 〇 | 〇 | 〇 |
| 1-1-2 | | | RPC(gRPC含む) | × | 〇 | × | 〇 | 〇 |
| 1-2 | | 非同期通信 | | 〇 | 〇 | 〇 | 〇 | 〇 |
| 2 | データの一貫性 | | | 〇 | 〇 | 〇 | △ | × |
| 2-1 | | ACID | | 〇 | 〇 | 〇 | × | × |
| 2-2 | | 結果整合性 | | 〇 | 〇 | 〇 | 〇 | × |
| 3 | 使用可能なデータベース | | | △ | △ | △ | △ | 〇 |
| 3-1 | | Oracle | |  × | × | × | 〇 | 〇 |
| 3-2 | | MySQL | | 〇 | 〇 | 〇 | 〇 | 〇 |
| 3-3 | | PostgresSQL | | × | 〇 | × | 〇 | 〇 |
| 3-4 | | MongoDB | | × | 〇 | 〇 | × | 〇 |
| 3-5 | | Redis | | × | × | 〇 | × | 〇 |
| 4 | 使用可能な言語 | | | 〇 | 〇 | 〇 | 〇 | 〇 |
| 4-1 | | Java | | 〇 | 〇 | 〇 | 〇 | 〇 |

※ ある項目において単一の項目しかないものについては、その項目をサポートしていれば〇、サポートしていなければ×としています。
※ ある項目において複数項目のあるものについては(例えば3項については3-1, 3-2, 3-2, 3-3, 3-4, 3-5と複数項目ある) 、すべての項目をサポートしている場合には○、一部項目をサポートしている場合には△、一つもサポートしていなければ×としています。

# さいごに
マイクロサービスを実現するためにオープンソースソフトウェアとして提供されている複数のプラットフォームについて比較してみました。
ただ、どのような場合でもこれがベストというものがあるわけではありません。自分が実現しようとしているシステムに合わせて最適なものを選択することになるのだとは思います。例えば、データの一貫性にしても自分たちがどこまでのものを求めるのかを明らかにした上で、性能が見合っているのかどうかを見ていく必要があります。
そして適用するオープンソースソフトウェアを選んだ上で、自分たちとしては他社と差別化を図りたいところ、より性能向上を図りたいところに注力していくのがよいのではないかと思います。

なお、本記事はグループで検討したものを記載しています。

# 参考文献・参考記事
* [Chris Richardsonによる"Microservice Architecture"](https://microservices.io/index.html)
* [Eventuate](https://eventuate.io/)
* [Eventuate Tram Github リポジトリ](https://github.com/eventuate-tram/eventuate-tram-core)
* [Eventuate Tram Sagas Github リポジトリ](https://github.com/eventuate-tram/eventuate-tram-sagas)
* [Chris RichardsonのBlog](https://chrisrichardson.net/post/sagas/2019/12/12/developing-sagas-part-4.html)
* [AxonIQ](https://axoniq.io/)
* [Axon Framework Github リポジトリ](https://github.com/AxonFramework)
* [Spring](https://spring.io/)
* [Spring Boot Github リポジトリ](https://github.com/spring-projects/spring-boot)
* [Spring Cloud リポジトリ](https://github.com/spring-cloud)
* [Lightbend社](https://www.lightbend.com/)
* [Lagom Github リポジトリ](https://github.com/lagom/lagom)
* [KumuluzEE社](https://ee.kumuluz.com/)
* [KumuluzEE microservice framework Github リポジトリ](https://github.com/kumuluz/kumuluzee)