モノリスとマイクロサービスのあいだ
マイクロサービス化する?
主な利点として(Sam Newmanのマイクロサービスアーキテクチャより
技術的異質性
回復性
スケーリング
デプロイの容易性
組織面の一致
チームの大きさ、生産性の最適化
合成可能性
機能の再利用
交換可能にするための最適化
置き換え、書き換え
などがあるが、マイクロサービス化したからといってこれらの利点が享受できるわけではなく、分散システムに関する複雑さを解決し、利点を引き出すようにしなければならない
これを踏まえて、マイクロサービス化するしないのメリットデメリットの比較は多くの変数があり判断に難しい
マイクロサービス化にあたっての検討項目の洗い出しとマイクロサービス未満の解決策の模索したい
マイクロサービス化の検討項目については、各組織やチーム状況によって様々だと思うが、
システムの複雑性の解消
コードベースの複雑化
理解容易性が高い
変更容易性が高い
メンテナビリティが悪い
デプロイ独立性
マイクロサービスに分割させてスッキリさせたい、もしくは作り直したいとか。しかし分散システムにする必要が本当にあるのか
複雑性とは少し話が変わるが、システムに蓄積した様々なデータを利活用して多数のアプリケーションを展開していきたいということになるとそれぞれマイクロサービス化していく意味がありそうだが、コストに見合うのか
技術的な制約
DB選択
言語選択
このシステムで扱うデータはRDBMSでは良くないとか、この言語でないと難しいとかそういった部分はシステムとして切り出さざるを得ないことが多い。技術的な制約は判断しやすいかもしれない
組織、チームの問題
チーム規模
自律性
単体のチームとして自律性を持たせたい。本当にその自律性は必要なのか?そのシステムだけで継続的に開発が存在するのか?などのリソース効率や他チームとのコミュニケーションコストからのアジリティ低下、サイロ化などを考慮しないといけない
マイクロサービス化するにしても、複数のシステムをみんなで開発していくことが十分可能であれば、1つのシステムに1つのチームを割り当てなければならないということはない。その場合、そのシステムへの責任感が薄れ、メンテがおろそかになったり、ドメイン知識の偏りによる問題があり、レビュワーが集中したり、誰がどの機能に詳しいのかわかりづらく相談とかが面倒だったり、知識不足から変な設計をしてしまったりとかには十分注意する必要がある
事業の問題
将来的にサービスをスケールさせていくのに、蓄積したデータを他アプリケーションから利活用するため。あるシステムを基盤的に使用する見込みがすでにある場合とか
分散システムの難しさ
さてではマイクロサービス化しようとなっても実現するにあたって技術的に大変なことが多い
トランザクションとデータの一貫性
トランザクション境界を単位にアプリケーションを分割するやり方はある。しかしトランザクション境界で分割できているのはその時その瞬間だけで将来的に本当にトランザクション境界をまたがないことは実現できるのだろうか?技術的制約でアプリケーションの発展をさまたげないだろうか?
分割すればするほど、データの整合性やリアルタイム性は落ちていく
データの一貫性を担保するには
後でリトライ
操作全体の中止
分散トランザクション
などやり方があるが、
これらの解決策はすべて複雑です。おわかりのように、分散トランザクションは正しく実行するのが困難で、実際にはスケーリングを妨げることもあります。最終的には補正リトライロジックで収束するシステムは検証が難しく、データの非一貫性を修正するために他の補正動作が必要な場合があります。
(中略)
とあり、なかなかに避けるべき道のよう
その他もろもろ
これらを解決してもなおマイクロサービスを採用するかはまた考慮が必要となる。そこでマイクロサービスの一歩手前の選択肢としてのモジュラーモノリスを考えたい
モジュラーモノリス
モノリスアプリケーション内で何らかの単位でモジュール化して独立性を高めるアーキテクチャ
マイクロサービスだと各システムが独立し、それぞれAPIなどによってやりとりされるが、モジュラーモノリスでは、同一コードベース内でモジュールとして分割し、モジュール間でやりとりを行う
もちろん様々な状況にはよるのだが、モジュラーモノリスという選択肢がありえるならモジュラーモノリスにするのは妥当な選択肢のように思う
優れたシステムは疎結合、高凝集であることで、もしマイクロサービス化するにしても、いきなりマイクロサービス化するのではなく、まずモジュラーモノリスに移行してから段階的にマイクロサービス化するという選択肢が経験的にも有効
新規システムはよりモノリシックになるようにしてください。サービス境界を間違えるとコストがかかるので、新しいドメインに着手する際は事態が安定するまで待つのが賢明です(Sam Newman, マイクロサービスアーキテクチャ)
DBとモジュール間のやり取りを中心にモジュラーモノリスのパターンをいろいろ考えてみる
A1パターン
1つのDBを共有し、お互い公開IFを介してモジュール間のやり取りをする
https://gyazo.com/dcfbe06d9cba3e3837deb6706cfd0826
DBが1つでネットワークを介さないのでマイクロサービスのデメリットを最小限にし、トランザクションや外部キー制約などDBによるメリットも受けられ、分散システムによる辛さがない
Shopifyはこのカタチを取っており
デプロイ単位数を増やさずにモジュール性を高め、モノリスとマイクロサービスの両方の利点それほど多くの欠点なしに得ることができるソリューションとして採用されている
ただモジュール間の依存が大変でそのままでは採用しづらく、ShopifyではWedgeという社内ツールを使用して依存関係を管理している
将来的にマイクロサービス化するということはあまり考えていない印象がある
A2パターン
1つのDBを共有し、お互いネットワークを介してモジュール間のやり取りをする
https://gyazo.com/ef1b45a56a88c82ba2c0cb2a30ef86d2
モノリスではあるが、やり取りがネットワーク越しなので分散システムとなりマイクロサービスのデメリットが発生する。A1パターンにおけるモジュール間の依存関係管理も難しくなる。マイクロサービス化していくとなった場合に考えられるかも知れないが、前段にゲートウェイを配置し、そこで依存関係の管理をするのが筋か
A3パターン
1つのDBを共有し、前段にゲートウェイを配置してやり取りをする
https://gyazo.com/8dbc519b92858446a55b92eef3140f3f
後ろのサービスはモジュラーモノリスだが、A2パターンにおけるモジュール間のやりとりを避け、ゲートウェイで制御するやり方
将来的にマイクロサービス化することは決まっているが、立ち上げ時期からマイクロサービスでスタートするのはモジュール分割が難しかったり、アジリティの問題などで、モノリスファーストで進めたい場合に考えられる
DBの分割も見据える必要があるので、外部キー制約などはつけられない
トランザクションが必要になったら、モジュール間でやり取りをするという逃げ道もありえる
B1パターン
モジュールごとにDBが存在し、お互い公開IFを介してモジュール間のやり取りをする
https://gyazo.com/6852696868c3945bc0e2769533d17688
A1パターンからDBを分けたいパターン。モジュールによって使用したいDBが異なる場合は、このようなカタチも取れるのかもしれない。もしくはマイクロサービス化していきたいという段階だろうか
DBとしては別になってしまうので、分散システムとしての複雑さはないが、データの一貫性については配慮が必要となる
B2パターン
モジュールごとにDBが存在し、お互いネットワークを介してモジュール間のやり取りをする
https://gyazo.com/d0cc74151e67f82e50ae1ca5bc08fe81
これはほぼマイクロサービス。この段階があるかわからないが一応
B3パターン
モジュールごとにDBが存在し、前段にゲートウェイを配置してやり取りをする
https://gyazo.com/877be45d97d1a80ab648b6bed42bd8fe
A3パターンのDBが分割されているバージョン。特性の違うDBを使用したければありえる
and more
リンク集