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

なぜマイクロサービスアーキテクチャなのか?

再利用か分離か

まず、コンポーネントの再利用性と分離は共存できない

再利用を前提としてシステムを組む場合、アーキテクトはその再利用性を実現するために、

クラスの継承が発生する。

しかし、クラスAからクラスBへの継承には当然結合が発生する。

なぜならクラスBはクラスAの存在を前提としてプログラムが組んであるからだ。

このような依存関係のことを結合と呼ぶ。

再利用のメリットとデメリット

これまで多くの技術者は限られたリソースを有効活用するためにシステムの再利用性を重要視してきた。

しかし、システムの再利用性を重視するということは同時に結合を多く生み出してしまう。

結合を多く生み出すことは、システムの一部分の変更を、予測できない怖い変化へと置き換わってしまう

たとえば、クラスAからクラスBへ継承を行う場合、クラスAの変更はクラスBにも影響してしまう。

この継承が一世代のみであれば問題ないが、開発者の見えないところでクラスCが存在し、クラスBを継承していた場合、クラスCは予想外の変更を受けることになる。

分離のメリット

クラスAとクラスBの間に継承関係が存在しない場合、再利用によるデメリットは発生しなくなる。

クラスAの変更はクラスBに届かないからだ。(当然クラスCも変化は起きない)

このように、コンポーネントコンポーネントの分離には、システムの変更をよりポジティブなものにできる。

同様のことはクラスレベルだけでなく、サーバーレベルでも発生する。

強制的に分離する手段

マイクロサービスアーキテクチャの先駆者のアーキテクチャは、次のようにしてマイクロサービスが始まったと告白している。

あるスタートアップの開発チームは変化が早い領域で問題を抱えており、ほかの開発チームに結合点を作成してほしくなかった。

そこでそのアーキテクトは、各チームをドメインベースで分割されている状態に加えて、技術的スキルでも分割するようにしたのだ。つまりチームAがJavaを使用しているのであれば、ほかのチームはJavaではなく.NETフレームワークを使うようにした。

Javaと.NETフレームワークを使用している環境であれば、誤ってクラスを共有することもないからだ。

このコンセプトはほとんどの企業で進めている技術の統一化と真逆の方向性のはずだ。

しかしこのことが、逆に企業の競争力を強化することになった。

  • 機械学習を進めたい領域であれば迷わずPythonを使用できるし、

  • PostgressよりもMySQLの方が得意であれば迷わずそれを使用できるからだ。

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

以下はマイクロサービスの基本的なトポロジーである

マイクロサービスは分散アーキテクチャを形成し、各サービスは独自のプロセスで実行されます。

「各サービスのプロセス」とは元々は物理コンピューターを意味していましたが、すぐに仮想マシンとコンテナーに進化しました。

マイクロサービスのコアな価値観は疎な結合による高度な分離です。

各サービスでは、会社がやりたい事業をそのままシステム化しています。

例えば、ECサイトをマイクロサービス化する場合、注文受付サービス、在庫管理サービス、物量管理サービスの3つがマイクロサービスとしてひとつの仕事と責任をこなします。

そして、注文受付サービスの変更は在庫管理サービスに影響しないようにするのです。

そのような高度な分離による変更可能性こそがマイクロサービスアーキテクチャの真価です。

マイクロサービスのコアな価値観は疎な結合です。

そして疎な結合を求めるため、再利用性をあきらめています。

マイクロサービスアーキテクチャの構成要素

マイクロサービスアーキテクチャの構成要素は非常にシンプルです。

  • サービスの受付となるAPIレイヤー(NginxやApacheを使って実装されることもあります)

  • 各サービス

この二つです。

また、各サービスはそのサービスが成り立つために必要なすべてを持ちます。

例えば

などなどです。

そのサービスが必要なものはすべて自前で用意するのです。

この性質上、各サービスにて重複するビジネスロジック(会計期の計算ロジックや会社で設定する日付)が重複してもそれをよしとします。

マイクロサービスアーキテクチャサイドカーパターン

マイクロサービスアーキテクチャが高度な分離を目指すとしても、どうしてもサービス同士で結合したいパターンもあります。

例えば、運用Tが各サービスを監視する必要があった場合、各サービスに散らばったログ機能、モニタリング機能をどのように集計すればよいのでしょうか。

この場合は、マイクロサービスアーキテクチャサイドカーパターンが回答としてあり得ます。

サイドカーパターンでは各サービスの内部に運用で必要な機能を共通のコンポーネントとして保有するという実装を行います。

このサイドカー自体は共有インフラストラクチャーチームがソースの管理を行い、更新があればgit等で変更をpushし、各チームがpullすることで実装まで完了します。

マイクロサービスアーキテクチャのフロントエンドの実装

マイクロサービスアーキテクチャは分離を推奨していますが、それはフロントエンドも含みます。

以前はWebアプリケーションがそのような分離されたUIを提供すること自体が不可能でした。

現在ではReactのようなコンポーネントベースのWebフレームワークが登場してきたため、マイクロフロントエンドとよばれるフロントエンドの実装方法が取られます。

マイクロフロントエンドは次のように、各サービスがフロントエンドの一部分であるコンポーネントを持ち、フロントエンドがそれを組み合わせて実装する形式のことです。

各サービスは自サービス用のユーザーインターフェースを提供し、フロントエンドはそれぞれのあサービスから提供されたUIコンポーネントを組み合わせて利用します。

開発者にはReactのようなWebフレームワークを使う選択肢から、(icestack)https://micro-frontends.ice.work/と呼ばれるマイクロフロント専用のフレームワークを使う手段もあります。

マイクロサービスアーキテクチャの連携方式

マイクロサービスアーキテクチャでは、プロトコルを意識した異種間相互運用性を利用する。

この言葉を丁寧に説明すると次の意味になる

  • プロトコルを意識した

    マイクロサービスは通常、運用面での結合を避けるため、中央の統合ハブを持たず、すべてのシステムはP2P方式で通信を行う。

    このP2P方式では、ほかのサービスが自分のサービスを呼び出す方法を知っておく必要がある。その意味で、サービスを呼び出すための規約(プロトコル)を意識した通信方式である必要がある。

    これにはREST APIやメッセージキューなどが使用される。

  • 異種間

    マイクロサービスは分散型であるため、各サービスは異なる技術スタックで書かれる。

    異なる言語やフレームワークを使用するということだ。

    マイクロサービスは、言語によらない通信方式である必要がある。

  • 相互運用性

    マイクロサービスは一方的な通信ではなく、双方向の通信である。

つまり、通信方式を意識し、異なる言語でもサポートされる手段であり、双方向の伝達が可能である。という意味だ。

サービス間のオーケストレーション

サービス間で通信のタイミングを合わせる必要があるケースがある。

例えば、ECサイトの注文では「注文確定サービス」「在庫確認サービス」「支払いサービス」の3つのサービスの協調が必要となる。

ここで問題となるのは誰がこの「協調(オーケストレーション)」を行うべきなのか。

「注文確定サービス」が行うべきと判断した場合は、次のようなリクエストフローになる。

最初に呼び出されたサービスがほかのサービスを横断的に調整する必要があるため、

ドメインの責任に加えて、メディエーターとしても機能する。

このパターンはフロントコントローラーパターンと呼ばれる。

サービスが二つの責任を追うため、サービスの複雑さが増すのがこのパターンの欠点だ。

サービス間ごとの協調を行うためのもう一つのパターンが、メディエーターパターン

この例では、サービス間のリクエストを調整することに責任を負わせるサービスを設置している。

これにより、サービス間には結合が生じるものの、アーキテクトは調整を単一のサービスに集中させ、ほかのサービスに影響を与えないようにできる。

各サービスの粒度について

多くの開発者は「マイクロサービス」という言葉を説明で反買う戒律ととらえてしまい、細かすぎるサービスを作ってしまうことがある。

これは、有益な作業を行うためにサービス間の通信リンクを構築しなければならなくなり、サービスを小さくしすぎてしまうが故の弊害である。

したがってアーキテクトはマイクロサービス全体が実装するサービスの粒度を適切にとらえなければならない。

サービスの粒度を適切にとらえるヒントは次の3つがある。

  • 各サービスの目的は

    各マイクロサービスは機能的にきわめてまとまっている状態であり、アプリケーションを代表する一つの機能を提供するのが望ましい。

  • トランザクション

    SQLがサービスをまたいだJOINを必要とする場合、そのサービスは小さく分離しすぎた可能性が高い。二つのサービスを一つにまとめ、代表する一つの機能としてまとめることはできるだろうか?

  • コレオグラフィ

    ドメイン単位にサービスを分離したはずなのに、そのサービスが機能するのに必要な通信が大量に発生する場合、そのサービスは小さく分離しすぎた可能性が高い。

データの分離

サービスの粒度を見るときに、アーキテクトが考慮しなければならないのはデータだ。

ほかのアーキテクチャとの違い

ほかのアーキテクチャスタイル(サービスベースアーキテクチャ等)は単一のデータベースを使用して、永続性を確保している。

しかし、マイクロサービスアーキテクチャは共有スキーマ等による結合を避けようとする。

また、ほかのアーキテクチャスタイルでは単一のデータベースを持つことでシステム内の値を一つの信頼できる情報源として確保できた。

アーキテクチャ全体にデータを分散させるマイクロサービスでは、その選択肢はない。

分散されたデータへの対応方法

この分散された情報源に対応するには次の2通りの選択肢がある。

  • ある事実に対する信頼できる勇逸の情報源としてドメインを一つ特定し、そのサービスと連携させる。

  • データベースのレプリケーションやキャッシュを使用して情報を分散させる

マイクロサービスのデータ分離のメリット

たしかにこのようなデータ分離をうまく決断するのは難しいが、これはチームによい機会をもたらす。

その機会とは、チームが自由にデータベースを選べるという点だ。

各サービスは、価格やストレージの種類など、様々な要因に基づいて最適なツールを選択できるようになるからだ。

備考

title:マイクロサービスアーキテクチャのメリットとデメリット

description:マイクロサービスは分散アーキテクチャを形成し、各サービスは独自のプロセスで実行されます。これは元々は物理コンピューターを意味していましたが、すぐに仮想マシンとコンテナーに進化しました。

img:https://github.com/minegishirei/store/blob/main/0/inhouse_se/2008microservice_arch/microservice_arch.png?raw=true

category_script:page_name.startswith("2")

page:https://minegishirei.hatenablog.com/entry/2023/01/29/151901