マイクロサービスをどう切り出すか ~マイクロサービスの凝集性・疎結合性を保つベストプラクティスと最適手法

マイクロサービス・アーキテクチャで
避けて通れない「切り出し」の話題

マイクロサービス・アーキテクチャに関わる話題は、以下の2つに大別される。

・「モノリス」と呼ばれる大きなシステムから、どのような指針に基づき、マイクロサービス(注1)を切り出すか。

・切り出されたマイクロサービスを組み合わせ、どのようにシステムとして機能させるか。

注1:本稿ではマイクロサービスを「十分に絞り込まれた責務が割り当てられた、凝集性・疎結合性に優れるWebサービス」と定義する

このうち前者は、「なぜ、システムにマイクロサービス・アーキテクチャを適用するのか」という「Why」の話題として捉えられる。

それに対して後者は、「粒度が細かいマイクロサービスを組み合わせてシステムを構成することで生じる課題に、どのように対処すべきか」という「How」の話題と考えられる。

そうした意味では、システムからのマイクロサービスの切り出しとは、マイクロサービス・アーキテクチャを採用する動機、課題解決、成果の追求と表裏一体の関係にあると言える。

つまり「モノリス」と呼ばれる大きなシステムを漫然と分割して、小さなサービスをたくさん作り出したとしても、そうした分割に適切な動機が伴わない限りは、システムのマイクロサービス化に伴うメリットは保証されない。

そして逆に捉えれば、マイクロサービス・アーキテクチャ採用による課題解決、もしくは成果追求のビジョンが伴わなければ、マイクロサービスを切り出す際の判断には裏付けを欠く。

そのため、適切なビジョンに基づくマイクロサービスの切り出しは、マイクロサービス・アーキテクチャの取り組みの初期段階(たとえばマイクロサービス・アーキテクチャ採用のための基礎検討や提案活動)において、非常に重要度が高くなる。

どのようなビジョンとともに
マイクロサービス・アーキテクチャを採用するか

前述のとおり、マイクロサービスの切り出し方に裏付けを持たせるには、マイクロサービス・アーキテクチャの採用を通じて課題を解決する、もしくは成果を追求するためのビジョンが欠かせない(図表1)。

図表1 マイクロサービス・アーキテクチャを活用するための代表的なビジョン

図表1に示されるビジョンのうち、どれを重視するかによって、マイクロサービスを切り出す際の具体的な最適解(たとえば切り出すべきマイクロサービスの最適な粒度など)が異なる。

そのためマイクロサービスを切り出す際は、図表1に示されるビジョン(もしくは複数ビジョンの組み合わせ)のなかでどれを重視するかを踏まえたうえで、サービス切り出しの結果が、掲げたビジョンに適合するかを意識的に確認しなければならない。

とは言え、どのようなビジョンを重視するとしても、サービスの切り出しには普遍的に働く指針も存在する。これを避けては通れない。そうした指針としてとくに重要なのが、「凝集性」および「疎結合性」という、ソフトウェア工学で常に重視されてきた2つのシステム特性である。

マイクロサービス・アーキテクチャから見た凝集性と疎結合性

凝集性および疎結合性という概念は、マイクロサービス・アーキテクチャという観点では以下のように要約される。

凝集性
あるマイクロサービスが単一の責務を持つこと。加えて、ある責務が複数のマイクロサービスにわたって割り当てられないこと。

疎結合性
あるマイクロサービスでの仕様の変更が、他のマイクロサービスに影響を及ぼさないこと。

例えて言うなら、凝集性とは、顔を拭くためのフェイスタオルと、床をぬぐうための雑巾とを1枚の布で兼用させないことに似ている。

無論、1枚の布を複数の用途に兼用すれば、全体として必要な布の枚数を抑えられるメリットはあるだろう。しかし、より用途に適した布を調達する、もしくは、より用途に適するように布の品質を改善するという観点からすれば、用途に特化した布をそれぞれ用意することが望ましい。

つまり布に求められる要件として、フェイスタオル用途ならば肌触り、雑巾用途ならば耐久性があり、それらの要件は往々にして相反しがちである。

同じことがマイクロサービスの場合にも当てはまる。あるマイクロサービスに複数の責務を課すと、それぞれの責務から相反する要件が提示されるため、それらの要件を実現するサービスの開発や改善にハードルが生じがちである。

一方、疎結合性という概念は、「扉と錠とを別々の部品として扱う」ことに例えられる。扉と錠とが一体化していると、錠を交換したい場合、たとえば鍵をなくした場合などに、錠の交換に付随する形で扉の交換も必要になる。

同様に、あるマイクロサービスを交換する、もしくはその仕様を変更した場合、その仕様変更の影響がシステムを構成する他のマイクロサービスに波及すると、システムを構成する「部品」としてのマイクロサービスの独立性が失われれる。

図表1に示すようなマイクロサービス・アーキテクチャを活用するためのビジョンが、個々のマイクロサービスの独立性を暗黙の前提にしていることを考えると、マイクロサービスでの疎結合性の欠如はマイクロサービスの活用に多大な悪影響を及ぼす。

このようにマイクロサービス・アーキテクチャの活用では、それぞれのマイクロサービスの凝集性や疎結合性が重要である。そしてアーキテクチャ検討の巧拙が、そうした凝集性や疎結合性を保てるか否かを大きく左右する。そこがマイクロサービス・アーキテクチャに取り組むうえでの1つの大きな勘所となる。

凝集性と疎結合性が保たれたマイクロサービスの理想像

凝集性と疎結合性を確保する観点から、マイクロサービスが目指すべき状態を図表2にまとめる。

図表2 凝集性と疎結合性を確保する観点からマイクロサービスが目指すべき状態

ただしマイクロサービスの目指すべき姿が明確に示されたにせよ、そうした姿に至るまでの「道のり」が明確であるかどうかは、また別問題である。

無論、マイクロサービスの切り出しに関わるアーキテクチャ検討の成果を、その理想形と照らし合わせて反復的にチェックすることで、アーキテクチャは少しずつ改善していける。

しかしアーキテクチャ検討の手戻りを抑えるため、理想像に至るまでの「より効率的な道のり」を求めるニーズも当然ながら存在する。システム開発の現場では、そうした「より効率的な道のり」を示すベストプラクティスが模索されてきた。

そのベストプラクティスには、以下の2つが挙げられる。

・マイクロサービスの構造を業務構造と関連付ける
・マイクロサービスの構造をシステム階層構造と関連付ける

この2つのベストプラクティスについて、以下に説明していこう。

ベストプラクティス1
マイクロサービスの構造を業務構造と関連付ける

マイクロサービスの構造を業務構造と関連付けることによって凝集性・疎結合性を確保することは、「ドメイン駆動設計」と呼ばれるシステム設計手法の流れに属している。

このベストプラクティスの趣旨は、以下の2つに要約される。

・マイクロサービスの切り出しに業務構造を反映させることで、個々のマイクロサービスの業務上の責務、およびそれらの責務が反映された形での個々のマイクロサービスに対するシステム要求の出所(例:アクター、ステークホルダー)が明らかとなる。つまり、マイクロサービスが備えるべき仕様を見極めることがより容易となる。

・システムが置かれた環境の変化(例:アプリケーションの利用者が用いる端末の流行)と比較して、業務構造はより安定的であることが期待される。そのため、マイクロサービスの切り出しに業務構造を反映させることで、マイクロサービスの責務および提供するインターフェースの仕様がより安定する。

これらを踏まえたうえで求められるのが、マイクロサービスの切り出しに業務構造を反映させるための手法である。そうした手法については、さまざまな識者が多種多様なアイデアを提供している。それは大局的には、図表3に示す3つの手法のいずれか(もしくは組み合わせ)に帰着する。

図表3 マイクロサービスの切り出しに業務構造を反映させる3つの手法

手法①「業務に基づく切り出し」

これら3つの手法のうち、手法①の「業務に基づく切り出し」では、業務そのものを基準としてサービスを切り出していく(図表4)。

図表4 業務そのものを基準としたサービスの切り出し

手法①の特徴として、業務の一覧をマイクロサービスの一覧として扱う単純明快さが挙げられる。

そのためこの手法に適した状況としては、業務像やシステム像が明確でない基礎検討段階などで、マイクロサービスの中核とすべき業務上の責務に大まかなアタリを付けるような場合が挙げられる。

その一方、この手法は業務とマイクロサービスを単純に対応付けているだけなので、マイクロサービスの一覧と対応付けるべき業務の一覧それ自体の品質に問題がある場合(たとえば計上されるべき業務が抜け落ちていたり、粒度が大きな、より細かく分割すべき業務が混在しているような場合)には、業務分析上の品質の限界が、マイクロサービスを切り出した結果の妥当性を損なうことになる。

手法②「業務文脈の境界に基づく切り出し」

手法①のこうした欠点を補うのが、手法②の「業務文脈の境界に基づく切り出し」である。

ここではまず業務上の文脈の範囲、つまりある業務用語に対応する語彙が一意となる範囲(ドメイン駆動設計で言う「Bounded Context」に相当する)を見極めたうえで、その文脈の範囲を基準としてマイクロサービスを切り出す。

たとえば図表5のように、「顧客」という業務用語があったとして、その用語が示す語彙は業務上の文脈に応じた形でのバリエーションを持ち得る。

図表5 「顧客」という業務用語から派生し得る4つの文脈

こうした業務用語の語彙のバリエーションをヒントに、業務上の文脈、およびそうした業務上の文脈に属する関心事を具体化することで、マイクロサービスに課すべき責務をより絞り込むことが可能となる。

ここで図表5にある4つの文脈を単一のマイクロサービスに割り当てるのも、それはそれでシステム設計上の1つの選択肢ではある。

しかしそうした場合には、複数の文脈を単一のサービスに割り当てることによるマイクロサービスでの責務の発散、つまり凝集性の欠如が懸念される。

そのため、手法②に準じる形で、図表5の文脈1~4のそれぞれに専用のマイクロサービスを設けることで、凝集性の欠如に繋がる肥大化を抑止する。

手法②の特徴としては、あるマイクロサービスに過大な責務を割り当てることを避けられる点が挙げられる。

そのため手法②は、手法①で生じ得る、マイクロサービス切り出し作業での網羅性や粒度の観点での品質問題に対する解決策となる。

ただし業務上の文脈を見極めるには、業務用語に伴う語彙の微妙なニュアンスを扱える程度にまで業務への理解を深める必要がある。その労力の大きさが、手法②の典型的な弱点となる。

手法③「業務データ構造に基づく切り出し」

手法③の「業務データ構造に基づく切り出し」では、互いに整合させるべき業務データの塊(データセット)を単位として、サービスを切り出す(このような業務データの塊は「エンティティ」、もしくはドメイン駆動設計で言う「集約」に相当する)。

互いに整合させるべき業務データの塊に対しては、「ビジネスルールに則った形でのデータセット内での整合確保」という非常に明瞭、かつ強い責務が生じる。

そのため、仮にそうした非常に強い責務(≒凝集性が高い責務)を複数のマイクロサービスに割り当ててしまうと、それらのマイクロサービスは互いに密結合することになる。

そうした発想に基づき、「マイクロサービスを必要以上に細かく砕くような事態」を避けることが、手法③の趣旨となる。

結局のところ、手法③とは、データ構造に包含される業務構造を、マイクロサービスの切り出し結果に反映する手法であると捉えられる。

そうした意味では、この手法の成否は、マイクロサービス切り出しのためのインプット情報として用いるデータ構造(≒データモデル)の品質に強く依存する。

そのため、一定以上の品質を備える業務データモデルがすでに存在するような場合は除き、手法③には、業務データ構造の分析に伴う作業上のオーバーヘッドが伴うことに留意しなければならない。

3つの手法を的確に使い分ける

このように、業務構造をマイクロサービスの切り出しに反映するための3つの手法には、それぞれ固有の利点・欠点、そして効果的な「使いどころ」がある。

そのため各手法の特徴を踏まえたうえで、適切に使い分けるのが望ましい。各手法の使い分けの一例としては、以下のようなステップを踏んだマイクロサービス切り出し検討が挙げられる。

ステップ1
まず大まかな業務分析の結果として得られた業務構造を反映する形で、手法①を用いたマイクロサービスの大雑把な切り出しを行う。

ステップ2
手法①の結果として得られたマイクロサービスの粒度、および網羅性観点での妥当性を高めるために、手法②を用いて、マイクロサービスの切り出し結果が業務文脈の構造に沿っているかを確認する。確認した結果、マイクロサービスの肥大化が認められた場合は、その分割を検討する。

ステップ3
手法③を用いて、切り出されたマイクロサービスの粒度が「互いに整合させるべき業務データの塊」を下回っていないことを確認する。確認した結果、マイクロサービスが必要以上に細分化していると認められた場合は、それらのマイクロサービスの統合も選択肢にしつつ、業務データ構造とマイクロサービス構造の整合確保を図る。

ベストプラクティス2
マイクロサービスの構造をシステム階層構造と関連付ける

2つ目のベストプラクティスは、「マイクロサービスの構造をシステム階層構造と関連付けることによる凝集性・疎結合性の確保」である。この趣旨は、以下の2つに要約される。

・マイクロサービスの切り出しにシステム階層構造を反映させることで、個々のマイクロサービが果たすべき責務がシステム階層観点で明確となる。その結果として、マイクロサービスが備えるべき責務を見極めることがより容易となる。

・組織のエンタープライズアーキテクチャとしてのシステム階層構造は、相応に安定的であることが期待される。またシステム階層構造を設けることで、システムのコアとなる責務が、システムの置かれた環境の変化(例:アプリケーションの利用者が用いる端末の流行)から保護される。そのため、マイクロサービスの切り出しにシステム階層構造を反映させることで、マイクロサービスの責務、および提供するインターフェースの仕様がより安定的となる。

このためのアーキテクチャパターンの類型が、システムのコアとなる責務をシステムが置かれた環境の変化から保護することを主眼とした、同心円状のシステム階層構造である。

この同心円状のシステム構造に属する具体的なアーキテクチャパターンの代表例には、クリーン・アーキテクチャ図表6)、オニオン・アーキテクチャヘクサゴナル・アーキテクチャなどが挙げられる。

図表6 クリーン・アーキテクチャの概念

たとえば図表6のクリーン・アーキテクチャで言うと、階層構造の中核側に位置するエンティティやユースケースといったシステム要素を、デバイス、DB、外部インターフェース、ユーザーインターフェース、Webといった、仕様変更のための要求頻度が高くなりがちなシステム要素と分離することで、中核に位置するシステム要素の責務をより安定的に保つことを意図している。

そして前述した趣旨に基づく形で、マイクロサービスの構造をシステム階層構造と関連付ける場合、その関連付けの方向性は図表7のように2つに大別される。

図表7 マイクロサービスの構造をシステム階層構造と関連付けるための2つの方向性

このうち1つ目の方向性は、個々のマイクロサービス単位で同心円状の階層構造を適用することで、マイクロサービスの中核に位置する責務を保護するという考え方である。

たとえばこれには、マイクロサービスのコア側からデータベースを呼び出すためのインターフェースを抽象化することで、マイクロサービスが用いるデータベース・ミドルウェアを事後に容易に差し替えられるような設計上のアイデアや工夫が当てはまる。

2つ目の方向性は、マイクロサービスを用いる側のシステム自体が、エンタープライズレベルで階層化されていると想定したうえで、エンタープライズレベルでの大局的なシステム階層での個々のマイクロサービスの位置づけを明確にするという発想である。

これら2つの方向性のうち、本稿で取り上げる「サービスの切り出し」に対応するのは、後者である。

たとえば図表8にあるように、エンタープライズレベルでのシステム階層構造が適用されたシステム環境では、システム階層が果たすべき責務を反映したマイクロサービスの類型をシステムの各階層にそれぞれ設けることで、それらの類型が反映されたマイクロサービスの凝集性をより高められる。

図表8 エンタープライズレベルでのシステム階層構造を反映したマイクロサービス類型化のイメージ

またこうしたシステム階層自体が、システム階層間での疎結合性の向上を狙いに設けられている。

これにより、マイクロサービスの切り出しに向けて、エンタープライズレベルでのシステム階層構造を反映することにより、あるシステム階層に属するマイクロサービスと、他のシステム階層に属するマイクロサービスの間の疎結合性を実現することになる。


著者
泉谷 恭明氏

日本アイ・ビー・エム システムズ・エンジニアリング株式会社
クラウド・プラットフォーム部
アドバイザリーITアーキテクト

2003年に日本IBMシステムズ・エンジニアリング株式会社に入社。以来、分散系システム基盤の設計・デリバリーに従事する。近年はシステム・アーキテクトとして、クラウドを中心とした先進技術領域で、お客様による新たな技術への取り組みを幅広くサポートする活動を行っている。

 

[i Magazine・IS magazine]

More Posts