martinfowler .comの"How to break a Monolith into Microservices"を読んだメモ
martinfowler.comのHow to break a Monolith into Microservicesを読んだメモです.
モノリスからマイクロサービスへの移行に際して考えるべきことを理解するために記事を読みました.
自分に必要な部分について,理解したことと考えをまとめています. martinfowler.comの記事に書いてあるけどこの記事では飛ばしている部分もあります. 意訳や間違って解釈している部分もあるかもしれません.ぜひ原著も読んでください.
マイクロサービスとは
ビジネスケイパビリティをカプセル化したサービス群からなるプラットフォームのことです.
ビジネスケイパビリティとは
特定の領域において目的と責任を実現するためにビジネスが行うこと. ビジネスケイパビリティとはなんぞや,はMicroservicesの記事では明言されていなかったので,理解が曖昧でしたが,この記事で少し理解ができました.
また,以下の記事を読むとさらに理解が深まりました. ソフトウェアの構成にフォーカスすると,who(データベース,UI,etc)やhow(ユーザ情報を引き出す,ユーザから登録データを受け取る,etc)の単位ではなく,what(ユーザ認証,etc)を単位にサービス化する,という意味なのだと考えます.
cf. Business Capability Definition and Examples [Guide] | Jibility
モノリスのマイクロサービス化
条件
まず,マイクロサービス化には多くのコストとイテレーションが必要なので,モノリスの解体が正しい選択のか,解体する場合にマイクロサービスが正しいのか,をよく評価すべきです. また,以下のような運用準備が必要です.
- デプロイ環境へのオンデマンドアクセス
- 独立したサービスごとのビルド,テスト,デプロイのためのCI/CDパイプライン
- 分散アーキテクチャにおけるセキュリティ,デバッグ,モニタリング
- 変化の早いこの分野へのキャッチアップ(サービスメッシュ,コンテナオーケストレーション,GoCDのようなCDシステムなど)
以下も参考になります.
cf. MicroservicePrerequisites
cf. Microservice Trade-Offs
アプローチ
シンプルなサービスを依存方向を考慮して分離する
シンプルなエッジシステム(例えば認証サービス)から始めるのがよいです. これは,マイクロサービスを正しく運用できるかどうか検証や訓練するためです.
また,モノリスがマイクロサービスに依存するように構成するのがよいです. 逆にマイクロサービスがモノリスに依存しないように注意します. これはモノリスへの変更を最小にするためです.
続いて密結合したビジネスケイパビリティをサービス化するためには,明確なドメインコンセプトに分割する必要があります. その際,コードの依存と構造の分析を行うStructure101などのツールが有用です.
ビジネスケイパビリティごとにデータを分離する
データを分離せずにファサードやバックエンドだけ分離するのはアンチパターンです. ビジネスケイパビリティに含まれるデータはサービスとして分離します. データのマイグレーションはfour phase data migration strategyが有用です.
ビジネスに重要で高頻度で変更されるものを分離する
よく変更された・される見込みのビジネスケイパビリティを特定して分離します. この際,CodeSceneなどのソーシャルコード解析ツールが有用です.
コードを再利用するか新規作成するか考える
コードを分離するのではなくビジネスケイパビリティを分離するという考え方が肝要です. モノリスの中のコードは,往々にしてフレームワークや環境が陳腐化していたり,クリアなドメインコンセプトのない時に作られていたり,コードの複雑性が増していたりします.そのようなコードは,再利用よりrewrite/retireした方がコスト効率が高いです.
もちろん再利用が適しているケースもあります. 判断のためには,CheckStyleなどのコード解析ツールを使いコードの毒性(code toxicity)を計測すると良いです.
マクロに始め,続いてミクロに
サービスの単位が小さすぎることは,分散システムのデバッグを困難にし,トランザクション境界で壊れやすく一貫性を損ないやすくなり.運用が複雑になります. レガシーなモノリスにおいてドメイン境界を見つけるのは難しいので,まずはチームが運用できる論理的なドメインコンセプトのレベルの分離からスタートし,準備ができたら細分化を考えるのがよいです.
「独立したサービスを依存方向を考慮して分離する」の内容と矛盾するように見えますが, 例えば正規化されたデータのCRUD単位,のような小さすぎるサービスは貧血なサービス(anemic service)なので, ビジネスケイパビリティ未満のミクロなサービス化はやめましょう,という意味だと理解しています.
分離した古いコードをretireさせる
分離した古いコードをretireさせずに残すことは,エントロピーを増すだけで,アーキテクチャのゴールに近づきません. つまり,コードパスが増えることで,認知的負荷は上がりコードは理解しづらくなり,変化やテストのスピードが鈍化します. 分離した古いコードはretireさせ,アトミックなステップを歩むことで,インクリメンタルでイテレーティブでゴールにフィットしていくことができます.