マイクロサービスアーキテクチャ

2024/10/01

プログラミング

マイクロサービスとは

マイクロサービスとは、システム全体をビジネスドメインに基づいてモデル化し、サービスに分割したアーキテクチャのこと。各サービスはカプセル化されていて、他のサービスに影響を与えることなくデプロイでき(独立デプロイ可能)、他のサービスとはネットワークを経由して相互にアクセスできるように設計される。

サービスが独立デプロイ可能であるためには、サービス間に明確で安定した契約(インターフェースに関する約束事)が必要になる。そのため、基本的に他のサービスとデータベースを共有することを避け、各サービスが独自のデータベースを所有して、サービス内部に隠蔽するようにする。他のサービスが保持するデータにアクセスしたい場合は、そのサービスにデータを送ってくれるように要求する。このようなサービスの内部状態の隠蔽(情報隠蔽)は、オブジェクト指向プログラミングのカプセル化に似ている。もし内部データベースを直接外部に公開してしまうと、内部データベースの構造の変更に伴ってそのデータベースを利用している側にも変更が強いられるため、もはや独立デプロイ可能ではなくなってしまう。

マイクロサービスのサービス境界を見つけるためにドメイン駆動設計の考え方が非常に役立ち、システムをビジネスドメインに基づいてモデル化することを助けてくれる。従来の3層アーキテクチャでは、ビジネス機能が3層すべてに分散していて、層をまたいで変更が必要になる可能性が高い。一方でビジネスドメインに基づいてサービスを分割すると、ビジネス機能の変更の際に、変更の範囲が1層(1つのサービス)に限定される。

Notion Image

モノリスとは

マイクロサービスはモノリスと対比して語られることが多い。モノリスとは、システムのすべての機能をまとめてデプロイする必要があるアーキテクチャのこと。デプロイ方式がシンプルで、マイクロサービスに関連する多くの落とし穴を回避できるため、モノリスは依然として有効な選択肢の一つであり、「モノリス=レガシー」というわけではない。以下に代表的なモノリスとして単一プロセスモノリス、モジュラーモノリス、分散モノリスについて紹介する。

単一プロセスのモノリス

すべてのコードが「単一プロセス」としてデプロイするシステム。小規模組織にとっては良い選択肢で、組織が大きくなるにつれてモノリスも大きくなり、モジュラーモノリスに進化することもある。

Notion Image

モジュラーモノリス

単一プロセスのモノリスの一つで、単一プロセスが別々のモジュールから構成されている。各モジュールは独立して作業できるものの、デプロイのために結合する必要がある。多くの組織にとって優れた選択肢で、モジュール境界が明確に定義されていれば、マイクロサービスの課題を回避しながら、高度な並列作業が可能になる。

Notion Image

また、データベースもモジュールに沿った境界で分割している場合もある。

Notion Image

分散モノリス

複数のサービスから構成されているものの、何らかの理由でシステム全体をまとめてデプロイしなければならなくなってしまったシステム。マイクロサービスと単一プロセスモノリスの両方の欠点を持っており、どちらの利点も持たない。情報隠蔽やビジネス機能の凝集といった概念に重点が置かれていない環境で現れ、ある変更がサービスの境界を超えて波及し、システムの他の部分を破壊する。

マイクロサービスとモノリス

マイクロサービスとモノリスの比較

マイクロサービスもモノリスもアーキテクチャの選択肢の一つであり、どちらのアーキテクチャにもメリットとデメリットがある。マイクロサービスとモノリスの主なメリットとデメリットを以下にまとめる。

マイクロサービスモノリス
メリットサービス毎にデプロイ可能なので、各サービスの開発者がお互いに邪魔することなく問題に取り組むことができ、より迅速なデバッグや新機能の提供が可能になる。サービス毎に独立しているので堅牢性高く、必要な部分のみをスケールすることができる。また、サービス毎に異なる技術や言語を選択できる。デプロイ方式がシンプルで、分散システムに関連する多くの落とし穴を回避できる。監視、トラブルシューティング、エンドツーエンドテストなどの作業が簡単。
デメリットサービスごとにコンピュータリソースが必要なため、コストが大きくなりやすい。サービス間通信はネットワークを経由するので盗聴や改ざんなどのセキュリティリスクが増加する。また、ネットワーク通信の遅延やネットワーク障害によるパケット損失などにも対処する必要がある。異なる開発者が同じコードを変更しようとしたり、異なるチームが異なるタイミングで機能を公開しようとしたり、誰が何を所有しているの決まっていなかったりといった混乱が生じる。

本当にマイクロサービスを使うべきか

マイクロサービスはアーキテクチャアプローチの一つであり、本当にマイクロサービスアーキテクチャを採用するかどうかは、マイクロサービスに固有の複雑さに対処するコストに対して十分な利益が見込まれるか、各自の状況に応じて慎重に判断する必要がある。

例えばスタートアップの場合、最初はそもそもその製品を使いたいと思う人がいるかどうかもわからず、仮にスケーラビリティの高いアーキテクチャが必要になるほど成功したとしても、開発初期とは全く違う製品になっている可能性も少なくない。このような状況下でマイクロサービスを採用すると、サービス境界を超えた変更が必要になることも多く、それに伴って大きなコストが発生する。さらに、一般にスタートアップではシステムを構築できる人数が少ないため、製品を開発する時間に対してマイクロサービスに固有の複雑さに対処する時間の割合が大きくなってしまう。そのため、アーキテクチャ上の制約となる箇所と課題を理解したうえで、最も有効な部分からマイクロサービスに移行していくようにした方がよい。

一方で100人以上の規模の企業であれば、マイクロサービスアーキテクチャがもたらしてくれる恩恵を十分に利用でき、チーム間での混乱を最小限にして、スムーズにサービスを成長させていけるかもしれない。

モノリスからマイクロサービスへの移行

目的の理解

何を達成したいのかを明確にして、マイクロサービスより簡単にその目的を実現できる代替方法があるならその方法を採用し、その目的が現在採用しているアーキテクチャでは達成できない場合のみマイクロサービスへの移行を検討するようにする。決してマイクロサービスへの移行自体が目的化してはならない。

例えばマイクロサービスを選択する理由には、チームの自律性を高める、市場投入までの時間を減らす、負荷への費用対効果が高いスケーリング、堅牢性を改善する、開発者の数を増やす、新しい技術を受け入れるなどがあるかもしれない。だがそれらには本当に、マイクロサービスに固有の複雑さに対処するコストを支払う価値があるだろうか。確かにマイクロサービスはシステムのスケールに役立つが、ロードバランサの背後に既存のモノリスをいくつかコピーして起動するだけで十分スケールさせられないだろうか。

そして、もしマイクロサービスへの移行が必須だと感じても、目的に対する進捗状況を追跡し、状況に応じて方針を変える必要があることも念頭に置いておこう。

段階的に移行する

既存のモノリスを分解すべきと判断した場合には、そのモノリスを少しずつ分解し、抽出していくのが良い。モノリスから小さな機能領域を選び、それをマイクロサービスとして一つずつ取り出していくことで、漸進的にマイクロサービスの恩恵を受けることができる。このような段階的なアプローチは、移行していく中でマイクロサービスについて学ぶことができ、随時達成したい目的に近づいているかどうか評価して、何かを間違えていることがわかってもその影響を最小限に抑えられる。サービスの境界が間違っていた場合は取り出したマイクロサービスをモノリスに戻すことになるかもしれないが、マージするマイクロサービスが一つであればダメージは少なくて済む。

どこから分割するか

マイクサービスとして取り出す機能の判断は、基本的に「抽出の容易さ」と「抽出する利点」のバランスを考えて決めることになる。最初は「抽出の容易さ」を重視して勢いをつけ、そこで学んだ教訓をもとにより複雑な抽出に取り組んでいくのがよい。

どこで止めるか

システムアーキテクチャはニーズや知識の変化に伴って進化し続けるものであり、どうしてもドメインの理解が曖昧な場所が存在する。そのため、「死にかけた技術を基盤にしている」、「引退予定のインフラに結びついている」、「高価なサードパーティシステムを破棄したいと思っている」などの理由でモノリスの消滅自体が要件になっている場合を除いて、最終的に既存のモノリスと取り出したマイクロサービスが共存することが多い。目的に対する進捗状況を追跡し、マイクロサービスへの移行をいつ止めるべきか判断することも重要になる。

うまく行っているか判定する

達成したい目的に近づいているかどうか定期的に評価して、場合によっては方針を変える必要がある。チェックポイントとして以下のことを定期的に振り返るとよい。

  • マイクロサービスへの移行で何を達成したいと期待しているのかを再確認する。ビジネスの方向性が変わって、あなたの進む方向性が意味をなさなくなってしまったのであればその時点でやめる。
  • 導入している定量的な手段を確認して、進歩しているかどうかを確認する。
  • 定性的なフィードバックを求める。みんなは物事がまだうまくいっていると思っているだろうか?
  • もし何かあるなら、今後変えていくことを決める。
  • パターンを適用する

    既存システムを段階的にマイクロサービスに移行するための多くのパターンが存在する。ここでは、代表的なパターンとしてストラングラーフィグパターンを紹介する。

    ストラングラーフィグパターンはシステムの再開発によく使われるパターンで、時間をかけて旧システムの機能を新システムの機能で置き換えていく。旧システム(モノリス)への要求をインターセプトし、その機能が新システム(マイクロサービス)で実装されている場合、その要求は新システム(マイクロサービス)に送られる。このパターンを利用すれば、旧システム(モノリス)を変更することなく新システム(マイクロサービス)に移行できる。

    Notion Image

    その他、代表的な移行パターンには以下のようなものがある。

  • ストラングラーフィグパターン
  • UI合成
  • 抽象化によるブランチ
  • 同時実行
  • デコレーティングコラボレーター
  • 変更データキャプチャ
  • 参考資料


    著者画像

    ゆうき

    2018/04からITエンジニアとして活動、2021/11から独立。主な使用言語はPython, TypeScript, SAS, etc.