マイクロサービスアーキテクチャ
マイクロサービスとは
- システムを機能ごとに別プロセスとして独立させたもの
- マイクロサービス同士はネットワーク経由で通信し、データをやりとりする(REST APIやgRPCなど)
- 各マイクロサービスは独立したDBを持ち、別のサービスからのアクセスを禁止する
- 各マイクロサービスは独立して稼働する為、個別にデプロイ/リリースが可能
比較対象としてのモノリス
- 一つのコンポーネントが全機能を提供する
- 普通に作るとこうなる
モノリスの課題
- 開発者の数が増えるとデプロイやリリースの調整コストが過大になる
- ひとつの言語/技術に限定されがち
- コードが密結合化しやすく、保守性が低下しがち
- アプリケーションが単一プロセスなので(マイクロサービスと比べた時)単一障害点になる
- 時間の経過と共にコードやDBの規模が膨らむと人間の認知限界を超えてしまい、保守不可能になる
マイクロサービスのメリット
デプロイ/リリースの観点
- モノリスアーキテクチャの場合、開発者や開発チームが同じシステムを更新し続けることになるとデプロイやリリースの調整に時間がかかるようになる
- このコミュニケーションコストは本質的には何も産んでいないので無駄である
- それぞれのチームが調整コスト無しで自由にリリースできた方がよい
- その為に機能をサービスに分割し、それぞれを独立させることでリリースサイクルを早くしていく
- ことがマイクロサービスを導入する狙い
DBの観点
- DBの共有を避けたい
- ひとつのDBを複数のサブシステムで共有する場合、DBの管理コストが著しく増大する
- データの追加や更新に対する影響度の検討がとても難しくなる
マイクロサービスのデメリット
- サービス毎にDBを分割するのでJOINができなくなる(=参照整合性が保証できない)
- 結果整合性で我慢せざるを得ない
- ネットワークを経由することでのレイテンシが増大する
- 監視やリトライ制御など運用コストの増大が避けられない
- エンジニアに求められるスキルが増加する
- 対応できる人材の幅が少なくなる
- マイクロサービスは何の手当もないとマスタデータと整合性が取れなくなる
- APIでデータの実在性チェックを行う場合はレイテンシが大きくなるのでパフォーマンスに影響する
- 確認用のマスタデータをデータ連携する場合、常にETLが発生するので監視や運用のコストが重くなる
マイクロサービスとデータ同期
- マイクロサービスは(基本的に)DBも独立させるので、データの存在チェックにコストがかかる
- モノリスならクエリ発行時にJOINすればマスタデータとの突き合わせは容易
- 毎回トランザクション前に別のマイクロサービスに問い合わせてデータが存在するかチェックする必要がある
- あるいは、必要最小限のデータ(IDと表示名など)を定期的にデータ連携して自分のDBに持つなど
- いずれにしても何らかの部分でコストが掛かることになる
- システムの独立性とのトレードオフになる
データ同期の方法
共有DB
- DB(とテーブル)をマイクロサービス間で共有する
- シンプルで簡単だが、複数のマイクロサービスがひとつのDBに依存することになるので、マイクロサービスの独立性が失われる
- 共有DBに依存するマイクロサービスが増えるとDBの変更やマイグレーションに調整が必要になり、結局モノリスと同じことになる
API呼び出し
- DBは共有せず、APIで必要なデータを取得する
- 基本はこれを選択するらしい
- REST APIやgRPC、GraphQLが有力候補か
データレプリケーション
- 参照元になるサービスから必要なデータをレプリケートする(マイクロサービス間でデータ連携)
- データコピーを伴う分、同期には若干の遅延が発生することに注意が必要
- レプリケーションの死活監視や失敗時のリカバリ、リトライについての検討が必須
静的データとして埋め込み
- 数が少なく、変更されることがほぼ無いのであれば定数としてアプリに埋め込んでしまう
- 都道府県リストや郵便番号、祝日情報などは動的に取得するよりコードに埋め込んでしまう方が楽だったりする
- データ更新時は再度コードを変更する
マイクロサービスを導入するべきか
- マイクロサービスは設計/実装の検討事項がモノリスに比べて膨れ上がるので実装コストが膨らむ
- マイクロサービスを適切に設計/実装するにはモノリスに比べて高度なスキルや経験値が要求される
- 現状、マイクロサービスを適切に運用しようと思うとほぼkubernetesやSassの導入が必須になるので開発者の学習コストも大きい
- 小規模/機能数が少ないシステムなら導入するべきではない
- 大規模かつ複数のチームによって開発が同時並行的に行われるのであれば導入を検討する余地がある
- デプロイ/リリースの調整コストが無視できないレベルになってから検討しても遅くない
- むしろマイクロサービス自体がアンチパターン的な側面もある(早まった一般化)
モノリスはアンチパターンか?
- モノリスはアンチパターンではない
- 大抵の場合、モノリスは有効な選択肢である
- マイクロサービスが常に最善の選択というわけでもない
モノリスのメリット
- 構成が単純である
- 単純であることからくる堅牢性、デプロイの容易さ、理解しやすさ、トランザクション制御の容易さはマイクロサービスに対する明確な優位性
マイクロサービスのアンチパターン
アンチパターン1「データを先に移行するな」
アンチパターン2「レポート作成機能がサービスを跨っている」
アンチパターン3「コントラクトのバージョン管理をしていない」
アンチパターン4「マイクロサービスの粒度が細かすぎる」
参考資料
- A pattern language for microservices
- マイクロサービス化デザインパターン - #AWSDevDay Tokyo 2018
- マイクロサービスアーキテクチャとそれを支える技術 | さくらのナレッジ
- サービス分割とデータ統合アーキテクチャに関する考察 - Qiita
- マイクロサービス分割におけるモデリングの観点 - Qiita
- モノリシックからマイクロサービスへ。あるいは、サービスベースアーキテクチャを考える。 | アスクル株式会社
- マイクロサービスアーキテクチャ本の感想(5章) - もりはやメモφ(・ω・ )
- マイクロサービスのデータに関する考慮事項 - Azure Architecture Center | Microsoft Docs
- 勉強会レポート|巨大モノリシックシステムのマイクロサービス化はどうやって実現するのか | レバテックラボ(レバテックLAB)
- モノリスのマイクロサービスへのリファクタリング | Cloud アーキテクチャ センター | Google Cloud
- マイクロサービスとは? 使われている技術やメリット・デメリットを解説 - お役立ち情報詳細 | メルカート
- マイクロサービスのための正しいデータベースの選択 | IBM ソリューション ブログ
- クックパッドにおける最近のMicroservices事例 - クックパッド開発者ブログ
- Microservices on “Rails” - Wantedly のマイクロサービス事例 - Speaker Deck
- 技術的負債と向き合うためのマイクロサービスアーキテクチャーとは? BtoB SaaSのアカウントデータに関する取り組みを紹介 (1/2):CodeZine(コードジン)