マイクロサービスにおける結合の設計
マイクロサービスアーキテクチャの目的は、結合をゼロにすることではありません(つか、それは不可能です)。
目的は、最も問題のある種類の結合を、より管理しやすく、有益な種類の結合へと「交換」することです。
1. 解消したい「密結合」
時間的な結合
同期通信では、相手のサービスが応答するまで、呼び出し元は処理をブロックされます。
相手が停止していれば、自分も停止します。(エピックサーガとかはこれです)
その結果、
応答性は、非常に悪い状態となります。
これは、障害が連鎖しやすい、非常に脆い結合です。
非同期通信は、この時間的な結合を解消してくれます。
実装の結合
あるサービスが、他のサービスのデータベース構造や内部ロジックを知っている状態です。
これは、相手の内部変更が、直接自分に影響する最悪の結合です。
カプセル化が完全に崩壊しています。
これによる、意図しないデータ不整合リスクなどにも繋がります。
DBの所有権の割り当てを正しくできていないと、こういうことが起きやすい。
2. 意図的に選択する「疎結合」
スキーマによる疎結合
JSONスキーマやgRPCは、この種類の結合を作り出します。
これは、「私たちは、この『言語仕様書』(スキーマ)に従って対話しましょう」という、
サービス間の明確で、公式な「契約」 です。
【契約による設計】の考え方と思想は一緒です。
そして、データメッシュでもこの考えが非常に重要になってきます。
この契約(スキーマ)はたしかに一種の結合ですが、時間的・実装的な結合に比べて、遥かに優れています。
徐々に変わるコントラクト
アーキテクチャが同期から非同期へと進化するのに伴い、サービス間の契約(コントラクト)の「性質」そのものも、段階的に変化していきます。
もちろん、チーム間の連携が取れないといった制約によって、
コントラクトを固定にしないといけない場合も現実的にはありますが、
そうすると、組織は硬直化します。
①. 同期通信時代のコントラクト
「命令」と「即時応答」の契約
性質
この段階での契約は、主にRPCの考え方に基づいています。
定義するもの
同期通信のAPI契約は、「契約による設計」の持つ
「事前条件(リクエストの仕様)」と「事後条件(レスポンスの仕様)」
という考え方を、ネットワーク越しに適用したものです。
それぞれ両者には以下のような責任があります。
①. 呼び出し側(クライアント)の責任:
呼び出される側に対して「何をしてほしいか(命令)」
「このような形式の正しいデータを渡します」という約束事。(事前条件)
②. 呼び出される側(サーバー/メソッド)の責任:
「どういう結果を即座に返すか(応答)」
「正しいデータが渡されれば、このような形式の結果を返すか、あるいはこういう状態になっていることを保証します」という約束事。(事後条件)
この「契約」を事前に定義することで、コンポーネントは互いの内部実装を知ることなく、信頼性の高い連携が可能になります。
アナロジーで考えると
電話での会話です。
「Aという書類を送ってください」とお願いし、「承知しました。今送ります」という返事をその場で待つ関係です。契約は、この一連の「お願いと返事」の仕方を定義します。
②. 非同期通信時代のコントラクト
「事実」と「自律的な反応」の契約
性質
この段階での契約は、イベント通知 の考え方に基づいています。
定義するもの
イベントソーシングを必須にした方が良いです。
送信側が、「どのような事実(イベント)が発生したか」
その事実に、どのようなデータが含まれているか
同期と違って、リクエストの形式を意識しなくて済みます。
アナロジーで考えると
ラジオのニュース放送です。放送局(送信側)は、
「本日、〇〇でイベントが発生しました」という事実を報じるだけです。
誰がそのニュースを聞いて、その後どう判断し、どう行動するか(受信側の反応)については関知しません。
契約では、この「ニュースのフォーマット」を定義します。
イベント駆動アーキテクチャ
上記で触れた非同期通信で使われる「事実の契約」は、イベント駆動アーキテクチャ(EDA)を成立させるための要素であり、両者は切っても切れない関係にあります。
EDAとは、システムのコンポーネントが互いに直接命令する(電話をかける)のではなく、
「こういう事実が起きました(イベント)」という出来事を通知し合い、
それを受け取った各コンポーネントが自律的に判断して次の行動を起こすという、
サービス間の論理的な結合度を極限まで下げ、自律的で拡張性の高いシステムを実現する
ための設計思想です。
このイベントの構造と意味を定義するのが「事実の契約」(コントラクト) です。
この契約があることで、イベントという情報が、システム間で信頼性を持ってやり取りされます。
ニュース速報のアナロジー
この関係は、ニュース速報に例えることができます。
①. イベントの発生と契約
現場の記者(例:注文サービス)が、「首相が辞任を表明」という重大な事実を目撃します。記者は、その情報を「いつ、どこで、誰が、何をしたか」という**決まったフォーマット(=契約)**に従って、速報として通信社に送ります。
②. イベントの発行
通信社(例:メッセージブローカー)は、その速報をニュース配信網に流します。通信社は、どのテレビ局や新聞社がそのニュースをどう使うかには関知しません。ただ「事実」を配信するだけです。
③. イベントの消費と自律的な反応
各テレビ局や新聞社(例:配送サービス、通知サービス)は、ニュース速報を購読しています。「首相辞任」という速報(イベント)を受け取ると、
・A局は「特別番組を編成する」という判断をします。
・B新聞社は「号外を印刷する」という判断をします。
関係性のまとめ
このように、「事実の契約」は、サービス間の関係を直接的な指示命令から、事実の共有と自律的な反応へと変えることで、イベント駆動による疎結合なアーキテクチャを実現するのです。
また、言うまでもないですが、イベント駆動アーキテクチャをするには、
モデリング手法として、イベントストーミングを実践できないといけないです。
結論
同期から非同期への移行は、サービス間の関係性を「指示を待つ、密な主従関係」から、
「不変な起きた事実を共有し、各自が自律的に判断する、疎な関係」へと変化させます。
この関係性の変化に伴い、コントラクトもまた動的に以下のように変わります。
「命令と応答(振る舞い)」を定義 ⇒ 「事実(データ)」を定義
と、その性質を変化させていくのです。
同期的な「命令の契約」
注文サービスが配送サービスに対し、「この注文を配送せよ」と直接命令し、完了を待ちます。両者は強く結合しています。
イベント駆動の「事実の契約」
注文サービスは、「注文が確定した」という事実(イベント)を通知するだけです。
配送サービスは、その事実を自主的に受け取り、「ならば、配送プロセスを開始しよう」と自律的に判断します。