Contents
参考書籍
サム・ニューマン著,島田浩二訳 (2003) 『モノリスからマイクロサービスへ』,株式会社オライリー・ジャパン.
マイクロサービスアーキテクチャとは何か
マイクロサービス:「ビジネスドメインに基づいてモデル化された、独立してデプロイ可能なサービス(1頁)」
マイクロサービスアーキテクチャ:上記のマイクロサービス同士がネットワークを介して連携することにより形成されるシステムアーキテクチャ
マイクロサービスアーキテクチャの必要条件:「独立デプロイ可能性」すなわち「あるマイクロサービスに対する変更を、他のサービスに影響を与えることなく本番環境へデプロイできる(2頁)」こと
独立デプロイ可能性を実現するために必要なこと:サービス間に安定な「契約(=エンドポイントやメッセージの形式などのインターフェースに関する取り決め)」が存在すること」。事実上、サービスごとに①UI②アプリケーションロジック③データベース④インターフェースがカプセル化されることとなる。
マイクロサービスアーキテクチャ開発の面倒な点:サービスを跨いだ変更を加える場合、①関連するサービス全てに変更を加える必要がある②関連サービスの変更のデプロイを全てオーケストレーションする必要がある
マイクロサービスアーキテクチャのメリット:インターフェースに関する取り決めさえしてしまえば、各サービスごとの開発を独立して行うことができる。これにより、①他サービス②他サービスの開発メンバ③プログラミング言語④データベース⑤開発スタイルのいずれについてもいわば疎結合なシステム構成および開発の分業体制を実現することができる。
マイクロサービスアーキテクチャのデメリット:事あるごとに通信が必要となるため、レイテンシーによる問題が常に付きまとう。
モノリスのメリット:①レイテンシーの問題が発生しない。②監視・トラブルシューティング・エンドツーエンドテストなどの工数が大幅に削減される。③コードの再利用が容易である。
伝統的な三層アーキテクチャとマイクロサービスアーキテクチャの比較
結合と凝縮
結合(Coupling):任意のものの変更の別のものの変更への依存度
凝縮(Cohension):関連するコードのグループ化の度合い
「構造は、凝縮度が高く、結合度が低い場合に安定する(16頁)」
- 任意のサービスやシステムやコードを変更した際に、その他のサービスやシステムやコードについても大量の変更を行わなければならないシステムはよろしくない(密結合)
- 特定機能の改修のためにコードに改修を加える際、(当該ロジックに)関連するコードが様々なシステムやクラスに散逸しているのはよろしくない(低凝縮)
蜜結合の例とその解消パターン
過去の注文データに基づいたレコメンド機能を開発する場合、レコメンドサービスは注文サービスに依存する(ドメイン結合)。
この際、レコメンドサービスが注文サービスのDBに直接アクセスするような設計にした場合、注文DBの変更は必然的にレコメンドサービスの変更を発生させる(実装結合)。
上記の回避策としては以下が考えられる。
- 注文履歴取得用のAPIを作成し、レコメンドサービスが当該のAPI経由で過去の注文データを取得するようにする(推奨)
- 注文履歴をデータベース形式でデータセットとして公開する(非推奨)
また、あるECサイトにおいて「チェックアウト時にカート内の商品全てに関して倉庫在庫を確認する」という”同期”処理を実装したいとする。
この場合、チェックアウトサービスが(在庫確認アクションサービスを読み出し、)カートサービスを読み出し、在庫サービスを呼び出すという処理となり、この同期処理において各サービスは依存しあうこととなる(一時的結合)。
上記の回避策としては以下が考えられる。
- カート内の商品の情報をキャッシュすることで、カートサービスに対するチェックアウトサービスの一時的結合を回避する。
- メッセージブローカーのような非同期トランスポートを利用することで、メッセージ送信を非同期処理に変更する。
その他、単一のプロセスが複数のモジュールにより構成されているケースなどで、もし特定モジュールのコードの変更のデプロイが関連するモジュールやモノリス全体のデプロイを要する場合、デプロイ時結合があると言われる。
サービス間連携における結合回避の設計
注文情報を倉庫に渡して在庫引当処理や発送処理準備を行わせたい場合
最悪の設計
- 注文処理サービス(チェックアウトサービス)が倉庫に対して注文詳細データを送信する
- 在庫が顧客サービスを呼び出して、顧客情報(発送先情報)を取得する
betterな設計
- 注文処理サービス(チェックアウトサービス)が倉庫に対して配送指示データ(=注文詳細データから不要な情報を省いたもの)を送信する
- 在庫が顧客サービスを呼び出して、顧客情報(発送先情報)を取得する
よりbetterな設計
- 注文処理サービス(チェックアウトサービス)が倉庫に対して配送先情報付きの配送指示データ(=注文詳細データから不要な情報を省いたうえで配送先情報を追加したもの)を送信する
優れた設計(Streaming APIによるイベント駆動型システム連携)
- 注文処理サービス(チェックアウトサービス)が注文済イベントを発行する
- 注文済みイベントが発生したら倉庫サービスが反応する
既存システムのマイクロサービスアーキテクチャへの移行時に検討すべきこと
モノリスをモジュラーモノリスに再編することを検討する。具体的には、ロジックをビジネスドメインの境界線に沿ってモジュール単位に分割し、モジュール間でリンクさせる構成への変更を検討する。モジュラーモノリスはマイクロサービスアーキテクチャと同様のメリットを有するうえに、API連携に纏わりつくレイテンシーの問題や連携処理・連携失敗時の処理といったデメリットを回避することができる。
多くの場合において、モジュラーモノリスはマイクロサービスアーキテクチャよりも優れている。
移行パターン
■ストラングラーアプリケーション
概要:既存モノリスの特定の機能をマイクロサービスに移行した上で、呼び出し先を旧機能から新サービスにリダイレクトさせる。
利点:①既存システムの変更が一切不要②(問題発生時に)元機能を再利用できる
■UI合成
概要:ページ内の表示モジュールで表示されるコンテンツの取得元を既存サービスから新モジュールサービスに変更
利点:①既存システムの変更が一切不要②(旧表示モジュールは旧モジュールからコンテンツを取得する状態を維持するなど)段階的な移行が容易
■抽象化によるブランチ
概要:既存機能から抽象を作成したうえで、既存機能にその抽象を実装させ、既存機能を直接呼び出していたその他の機能(モジュール)の呼び出し先を既存機能から抽象に変更する。その上で、外部の新しいサービスを呼び出す機能をモノリスのなかで作成し、必要なタイミングで抽象の実装をそちらに切り替える。
利点:ストラングラーアプリケーションでは対応できない、モノリスの奥深くにある機能についても対応可能。
■同時実行
概要:旧モノリスと新マイクロサービスを同時実行&両者の結果を比較したうえで、片方を正しい情報と判定する
利点:金融機関のシステムなど、非機能への要件が高いサービスで、このような手法を一時的に取ることでレスポンスまでの時間やタイムアウトなどの数を測定することが可能。
■デコレーティングコラボレーター
概要:プロキシを用いて既存モノリスからのレスポンスを取得or変更データキャプチャを用いて既存モノリスのイベントを感知したうえで、それをトリガして別サービスを呼び出す。
利点:基礎となる機能に一切の変更を加えることなく、新しい機能を追加することができる。