- 有志勉強会第四弾です。
- 今回は書籍マイクロサービスパターン「実践的システムデザインのためのコード解説」モノリスからマイクロサービスへを基にしたマイクロサービスについての解説です。
- マイクロサービスはあくまでアプリケーションのアーキテクチャの一形態、またはその開発手法を指します。
- なので「これが正解」ではなく「こういった形もある」と理解いただいた上で、最適なアーキテクチャの設計や検討の土台を作る事が今回の勉強会の目的です。
- モノリスとマイクロサービスについて
- マイクロサービスの概要とそのメリット・デメリット
- マイクロサービスが開発組織に与える影響
- 具体的なサービス間通信の実装
- DDD
- マイクロサービスの対比として登場するのが「モノリス」「モノリシック・アーキテクチャ」と呼ばれる言葉
- まずはモノリスについて解説
- モノリスとマイクロサービスの比較の導入として、こちらの記事が分かりやすいです。
- 英語で「一枚岩」を指す
- すべてのコードが単一のプロセスに詰め込まれている
- システム内のすべての機能を一緒にデプロイする必要がある
- コードを再利用するのが容易
- 分散システムでコードを再利用する場合は、コードをコピーするかライブラリとして切り出す必要がある
- 異なる開発者・チームが同じコードを変更する際、所有権や意思決定を巡る混乱が生じる
- マイクロサービスは2010年台前半に登場したソフトウェア開発の技法、そしてアーキテクチャ(http://2012.33degree.org/talk/show/67)
- マイクロサービスの特徴と導入におけるメリットデメリットについて今回は解説します。
- マイクロサービスはサービス志向アーキテクチャの一種
- サービスがお互いに疎結合で、API以外では通信できない
- エンドポイントを介して各サービスの機能が公開される
- 各サービスは専用のDBを持つ
- 注文サービスは注文テーブルを含む専用DB、顧客サービスは顧客テーブルを含む専用DB
- 外部アプリはAPI(ex. REST、gRPC)を介してしか該当DBの情報を取得できない
- 他のサービスと調整しなくとも、サービスのスキーマを変更できる。
- サービスは独立したリポジトリ、パイプラインを持つ
- サービスがお互いに疎結合で、API以外では通信できない
- 大規模で複雑なアプリケーションの継続的デリバリ/デプロイを可能にする
- 個々のサービスが小さく、テストが書きやすく、短時間で実行される
- 他のサービスから独立して、個別にデプロイできる
- ビジネス要件として、素早い要望への対応が可能で、信頼性の高いアプリケーションに
- 個々のサービスが小さく、簡単にメンテナンスできる
- コードを理解しやすく、IDEが遅くなることもない
- サービスをそれぞれ個別にデプロイ、スケーリングできる
- リソース要件に応じてスケール。(ハード面を考慮し)
- チームに自主性、自立性を与える
- two pizza teamを構成でき、独立して開発できるため開発速度が早い
- 障害分離に優れている
- 他のサービスに影響を与えない(一部分のダウンで済む)
- 新しいテクノロジを簡単に実験、採用できる
- テクノロジスタックに長期に縛られない
- 最初に選択したテクノロジに縛られる事がない
- サービスの適切な分割方法を見つけるのが難しい
- 分割方法を間違えると、一緒にデプロイする必要のある密結合のサービスが生まれてしまう
- 分散システムは複雑になる
- メソッドの呼び出しよりも複雑なプロセス間通信が必要
- プロセス間通信の失敗の処理などが必要
- IDEはモノシリックアプリケーションの開発を対象としている事が多い
- 高度なソフトウェア開発、デリバリースキルが必要
- 何らかの役に立つ機能を実装するスタンドアロンの個別にデプロイできるソフトウェアコンポーネントの事
- 開発者は、APIを迂回してサービス実装に直接アクセスするコードを書くことは出来ない
- サービス別のコードの重複を削減する事ができる
- ただし、変更を加えた際に依存関係のある別サービスの再ビルド、デプロイが必要となってしまう
- なので、マイクロサービスにおいては基本変更がない機能だけライブラリ化した方が良い(という主張もある)
- 「システム設計(アーキテクチャ)は、組織構造を反映させたものになる」という法則
- メルヴィン・コンウェイが提唱
- 1つの大規模なチームよりも、複数の小さなチームの方が作業速度が速くなる
- チームとチームが担当するサービスを分割し、コミュニケーションのオーバーヘッドを避ける
- コンウェイの法則と逆コンウェイの法則についてはこちらの記事が分かりやすいです。
- マイクロサービスをウォーターフォールで開発すると、開発速度の速さが打ち消されてしまう
- Scrumやカンバン等アジャイルを取り入れる必要がある
- 継続的デリバリーを取り入れる事も重要で、自動テストや自動デプロイといった自動化が必要
- ネットワークレイテンシ
- APIによる呼び出しが必要なため
- サービス間でのデータ整合性
- 複数サービスに更新を掛ける必要がある際、従来のトランザクションの管理とは別の方法が必要
- 神クラス(god class)
- アプリケーションのさまざまな側面の為に、複数の振る舞い・状態を保持している
- DDD(ドメイン駆動設計)を応用して、別々のドメインモデルを定義して取り除く
- 神クラスについてはこちらの説明が分かりやすかったです。
実際にモノリスからマイクロサービスへの移行を考えた際には、段階的なアプローチが必要です。
ビッグバンリライト(一気に書き換え)ではなく、ここではストラングラーパターンによる移行が推奨されています。
- ストラングラーアプリケーションとは
- モノリスと繋がって動作するマイクロサービスの事
- モノリスは最終的に消えるか、マイクロサービスの1つとなる
- ビッグバンリライトに比べれば、リスクを抑えつつ移行が可能
- ストラングラーを利用して、モノリスをマイクロサービスに置き換える具体的な方法
- パターン1:新機能をサービスとして実装する
- モノリスに新機能の為のコードを足さない。(モノリスを成長させない)
- まったく新しいコードベースで開発する事で、新機能の開発が加速化される
- パターン2:プレゼンテーションとバックエンドを分離する
- プレゼンテーション、ビジネスロジック、データアクセスの内、プレゼンテーション(UI)部分は分離できる
- これにより、UIチームはバックエンドに影響を及ぼすことなくデザイン変更を行える
- パターン3:モノリスから機能を抽出してサービスで置き換え、モノリスを分解する
- 1.2だけではメインの処理がモノリスである事には変わりがない
- モノリス内の処理をサービスとして切り出す
- パターン1:新機能をサービスとして実装する
- モノリスとマイクロサービスについて話してきましたが、モジュラーモノリスというアーキテクチャも存在する
- モジュラーモノリスの場合、プロセス内のコードが複数モジュールに分解されている状態
- これにより、各モジュールで独立して作業を行う事が可能
- 「モノリス」も「マイクロサービス」も「選択肢の1つ」であり、どちらが絶対に良い・悪いという話ではない点には注意が必要です。
- いずれにしても、継続的に開発速度を維持したまま開発を続けていく上で「サービスの境界」を考えてアーキテクチャを設計していく必要があると考えています。
- プログラムのライブラリ化はその第一歩として、(依存関係はあるものの)サービス境界を再定義する機会になるのでは?と考えています