26 マイクロサービス・アーキテクチャ
この章では、マイクロサービス・アーキテクチャおよびマイクロサービスベースのデータベース・アプリケーションの構築に使用するメリットについて説明します。
トピック:
26.1 マイクロサービス・アーキテクチャについて
マイクロサービス・アーキテクチャは、疎結合された自律型サービスのコレクションとしてアプリケーションを開発するための手法です。アプリケーションのマイクロサービスは、契約が限定された、小さい自己完結型サービスです。たとえば、旅行代理店は、航空会社、ホテルおよびレンタカー予約をマイクロサービスとして提供するマイクロサービス・アプリケーションを実装できます。
マイクロサービス・アプリケーションの各サービスは、単一のビジネス機能を実装し、APIまたはメッセージング・システムを介して他のサービスと通信します。疎結合されたサービスとカプセル化されたデータにより、個々のコンポーネントを個別にスケーリングし、各サービス専用のチームを保持し、ビジネスの機敏性および利益を高めるためのアプリケーションを構築できます。
モノリシック・アプリケーションからマイクロサービスに切り替える理由は、次のとおりです。
-
アプリケーション・アーキテクチャが複雑化することで、アプリケーションのスケーリングおよび管理が困難になります。
-
モノリスで1つの機能を変更または追加するには、アプリケーション全体のコードを変更する必要があり、これは時間とコストがかかるプロセスになります。
-
製品がスケール・アップできるほど成熟しており、チームにはマイクロサービスを採用するために必要なツールとスキルがあります。
図26-1に、旅行代理店アプリケーションをモノリシック・アプリケーションとして、また飛行機の予約、ホテルの予約、レンタカー・サービスが含まれるマイクロサービスベースのアプリケーションとして示します。
図26-1モノリスとマイクロサービス

マイクロサービスのメリット
-
個々のアプリケーション・コンポーネントは個別にスケーリングできます。クラウドまたはハイブリッド環境内で動作するアプリケーションは、サービスの独立した開発およびデプロイメントによって簡単にスケーリングできます。
-
アプリケーションの構築、メンテナンスおよびデプロイが簡単になります。各サービスは、他のサービスに影響を与えずに個別に構築およびデプロイすることも、アプリケーション全体を再構築することもできます。
-
ソフトウェア開発がパラレル化されます。チームに別個のコードベースで作業させているため、ソフトウェアの開発とテストおよび新しいテクノロジの採用が容易になります。
-
アプリケーションは、Java、.NET、Pythonなどの複数の言語で構築できます。また、JSON、グラフ、空間など様々なデータ型を使用できます。マイクロサービスは言語に依存しないAPIを介して通信するため、各サービス・チームは独自のテクノロジ・スタックとツールを選択できます。
-
データ所有権は分散されます。各サービスには独自のデータベースがあります。あるいは、データベース・サーバーが1つ存在する場合もありますが、そのサーバー内では各サービスに独自のプライベート・スキーマとプライベート表があります。
26.2 マイクロサービス・アーキテクチャの機能
マイクロサービス・アーキテクチャには、次の機能が必要です。
疎結合されたサービス
マイクロサービス・アーキテクチャでは、アプリケーションを小さなコンポーネント・サービスに分解する必要があります。各コンポーネント・サービスは個別にデプロイできます。各自己完結型サービスはコア機能を実装し、境界付けられたコンテキストに分割されたデータとの明確に定義された境界があります。データベース・スキーマは、各サービスに必要なデータセットを識別するために再構築されます。
分散されたデータ
マイクロサービスは、サービスおよびチームの自律性を保証します。サービスが同じデータ・ソースまたはテクノロジを共有することはできません。たとえば、ユーザー登録と請求管理を、それぞれの分野に熟達し、特定の要件やスキルセットに適したテクノロジ・スタックに取り組んでいる別のチームと考えることができます。
独立したデプロイメント
独立したサービスは、コードベースの大部分に影響を与えずに、小規模で管理可能な単位で開発およびデプロイされます。
自動化されたインフラストラクチャ
マイクロサービスは、自動化されたインフラストラクチャを使用して動作し、次のものが必要になる場合があります。
-
非同期メッセージングおよびメッセージ・ブローカを使用するサービス間通信システム。
-
サービスの開発に集中でき、デプロイメントおよび依存性をシステムに処理させるコンテナ化されたシステム。
再利用可能なシステム
開発者は、別の機能またはサービスおよびチーム間で(同じ言語およびプラットフォームを使用している場合)コードを再利用したり、ライブラリ機能を再利用できます。
レジリエント・アーキテクチャ
マイクロサービスはアプリケーション全体のクラッシュに耐えることができます。これは、独立したサービスに障害が発生した場合、アプリケーションの機能の一部は失われることが予想されますが、アプリケーションの他の部分は機能し続けることができるためです。
26.3 分散システムにおける課題
データの整合性と一貫性を確保するには、トランザクションにACID (原子性、一貫性、独立性、永続性)プロパティが必要です。モノリスでは、ローカル・データベース・トランザクションが単一のデータベース・システムで機能するため、ACID性を保証するデータベース・システムがあります。トランザクションでは、すべてのステップが完了しているか、ステップが一切完了していないかのいずれかです。ステップのいずれかが失敗すると、トランザクションはロールバックされます。
マイクロサービスベースのアーキテクチャを設計する場合は、その課題を認識する必要があります。ここでは、一般的な課題をいくつか示します。
サービス分解
マイクロサービスを設計する際、モノリスまたはレガシー・アプリケーションを境界が明確に定義されている疎結合コンポーネントに分割する必要があります。コンポーネント間の依存性をチェックして、コンポーネントが十分に独立しているかどうかを確認する必要があります。
複雑さ
分散システムであるマイクロサービス・アプリケーションは、複数のシステムおよびサービスにわたるビジネス・トランザクションを保持できます。サービスレベルのトランザクション(わかりやすくするために、サービスレベルのトランザクションを「サブトランザクション」と呼びます)は、トランザクション全体を完了するために順番にまたは並行してコールされます。サービス間通信メカニズムを使用し、部分的な障害を処理するように設計された分散システムを作成する際の複雑さが増すことに対処する必要があります。
分散トランザクション
マイクロサービス・アーキテクチャでは、モノリシック・システムが自己カプセル化されたサービスに分解されます。マイクロサービスごとのデータベース手法では、トランザクションが完了していることを保証するために、トランザクションは複数のデータベースにまたがる必要があります。サブトランザクションのいずれかが失敗した場合、以前に完了した成功したトランザクションをロールバックする必要があります。トランザクションの原子性を維持するには、すべてのサービスがトランザクションの成功時にコミットするか、またはコミットしたサービスがトランザクションの失敗時にロールバックするように、サービスにはサービス間通信および調整が必要です。
トランザクションの一貫性および独立性
別の課題として、同時リクエストの処理があります。サブトランザクションは、トランザクションの結果が認識されるまでデータ・ソース(行)をロックしておくことで動作します。複数のサービス・コールが同じデータ・ソースに同時にアクセスしようとする場合、同時実行性を処理し、同時トランザクションで使用可能にする必要があるデータ量を割り出すメカニズムが必要です。複数のサービスにまたがる銀行トランザクションのような長時間実行アクション(LRA)では、トランザクション・ライフサイクルにおいて、複数のオブジェクトでデータをロックされた状態で保持できます。サービス間でデータの一貫性を維持するには、データ・ロックを使用して同時実行性の制御メカニズムを実装する必要があります。
サービス間通信
モノリスでは、アプリケーション・コンポーネントは関数のコールを使用して相互に起動します。マイクロサービスは、ネットワークを介して相互にやり取りします。複数のマイクロサービス間で変更を伝播する場合は、非同期メッセージングを使用したサービス間通信が不可欠です。
26.4 マイクロサービスのソリューション
2つのパターン(2フェーズ・コミット(2PC)とSaga)は、分散トランザクション管理での課題を緩和し、一貫性を実現しようとします。2PCは即時トランザクションに最適で、長時間実行アクション(LRA)用に分散トランザクションを実装する場合はSagaが良好に機能します。
マイクロサービス・ソリューションが必要な企業のために、Oracleはマイクロサービスの成功に不可欠な実績ある12のパターンを開発しました。これらの12のパターンの詳細は、次の項を参照してください。
26.4.1 2フェーズ・コミット・パターン
2フェーズ・コミット(2PC)は、トランザクションの結果を一方的に決定するコーディネータを持つアトミック・コミット・プロトコルです。トランザクションのすべての参加者が、コーディネータの決定に基づいてコミットまたはロールバックする必要があります。複数の表で発生するすべてのプロセス(挿入、更新、削除、すべてなど)は、同時にコミットまたはロールバックします。
2PCには、準備フェーズとコミット・フェーズの2つのフェーズがあります。準備フェーズでは、トランザクション・コーディネータが各マイクロサービスにprepareコマンドを送信します。各マイクロサービスは、トランザクションのコミットを保証できるかどうかを確認し、できる場合は、トランザクション・コーディネータに"準備済"レスポンスを送り返します。
すべてのマイクロサービスの準備ができたら、コーディネータはマイクロサービスに変更をコミットするよう指示します。マイクロサービスがprepareコマンドに応答しないか、失敗したレスポンスを送り返す場合、トランザクション・コーディネータはすべてのマイクロサービスにcancelコマンドを送信します。サブトランザクションはロールバックされ、すべての変更が取り消されます。
マイクロサービスが確実にコミットできるように、2PCは、変更されたデータに対するロックおよび準備の決定が永続ストレージにあることを保証します。このロックは、コミットまたはロールバックされるまでアクティブのままになり、他のトランザクションでこの情報を使用することはできません。これらのロックは、システムの速度を低下させるボトルネックになる可能性があります。複数のサービスを処理するアプリケーションでは、2PCは複雑さとパフォーマンスへの悪影響を引き起こす可能性があります。
2PCを使用すると、次の図26-2に示すように、飛行機、ホテルおよびタクシーのサービスを同時に予約できます。トランザクションが失敗した場合、どのサービスも予約されません。
図26-2 2フェーズ・コミット

関連項目:
2PCパターンの詳細は、2フェーズ・コミットを参照してください。
26.4.2 Saga設計パターン
Saga設計パターンは、マイクロサービスでのトランザクション管理を実現し、ビジネス・トランザクションでマイクロサービス間のデータの一貫性を維持できるようにします。Sagaは、分散トランザクションを一連の独立したローカル・トランザクション(サブトランザクション)に分割します。各サービスは独自のサブトランザクションを実行し、イベントまたはメッセージを発行します。後続のサービスは、そのイベントまたはメッセージをリスニングし、次のサブトランザクションを実行します。
トランザクションは複数のデータベース(PDB)にまたがり、各マイクロサービスでデータベースのサブトランザクションを実行できます。シーケンス内のすべてのサブトランザクションが正常に完了すると、ビジネス・トランザクションは成功します。サブトランザクションのいずれかが失敗した場合、直前のサブトランザクションの変更によって影響を受けるデータベース内の状態を"元に戻す"ために、補正トランザクションが起動されます。各サブトランザクションは、単一のデータベースでACIDプロパティを保持できます。Sagaの各サブトランザクションには、ロールバックがある場合に実行される対応する補正トランザクションがあります。
次の図26-3では、トランザクションが正常に完了したとき、およびトランザクションが失敗してロールバックを要求しているときのSagaトランザクションのシーケンスを示します。
図26-3 Sagaトランザクション

Sagaパターンの重要な側面はSagaコーディネータです。Sagaコーディネータは、他の参加者に実行内容を指示します。コーディネータはSaga参加者を起動し、すべてのレスポンスでコーディネータは次の状態に遷移します。非同期メッセージングは、Sagaのもう1つの重要な側面で、キューイング・システムを介してサービス間メッセージを送信します。
Sagaパターンを使用すると、Sagaで障害管理パターンが使用されるため、より堅牢なシステムを構築できます。すべてのアクションにロールバック用の補正アクションがあり、これにより、マイクロサービス全体で最終的なデータの一貫性と正確性が確保されます。
26.4.2.1 Sagaを使用する理由
Sagaを使用する理由は、次のとおりです。
-
様々なマイクロサービスに関連する一連の操作を自動的に実行する。
-
Sagaパターンを基にして、マイクロサービス間や異なるデータベースでのデータの一貫性を確保する。
-
ロック期間を短縮し、同時実行性を向上させるために、データ・ロックをローカル・トランザクションの期間に制限する。
-
ロック期間が長くなりパフォーマンスの制約があるため、2フェーズ・コミット(2PC)の使用を回避する。
-
マイクロサービスのシーケンスでトランザクション操作のいずれかが失敗した場合、ロールバックまたは補正する。
-
2PCをサポートしていないマイクロサービスを使用する。
Sagaを使用する方が2PCトランザクションを使用するより適切なオプションである理由
-
2PCトランザクションは、2PCトランザクションがコミットされるか取り消されるまで、ロック期間が長くなり、問合せの結果が不完全になる可能性があります。Sagaでは、データ・ロックは、(マイクロサービス・トランザクションを実装する)ローカル・トランザクションの存続期間にのみ設定され、Sagaライフサイクル全体では設定されません。ロック期間を短縮すると、Sagaトランザクションのスループットが改善し、アプリケーションのスケーラビリティが向上します。
-
Sagaは長期のトランザクションに役立ちます。長期間にわたるリソースのロックはパフォーマンスおよびスケーラビリティに影響する可能性があるため、2PCは長期トランザクションには理想的ではありません。
Oracle DatabaseでSagaを使用すると、データベースに組み込まれたロックフリー予約機能により、同時実行性が向上しボトルネックが軽減されます。
26.4.2.2 Sagaの実装方法
一般的なsagaの実装方法として、オーケストレーション・モデルとコレオグラフィ・モデルの2つがあります。
オーケストレーション
マイクロサービス間の通信はすべて、Sagaコーディネータと呼ばれる一元化されたサービスを介して行われます。コーディネータ・サービスは、リクエストの受信と、それぞれのサービスのコールを担当します。いずれかのサービスに障害が発生した場合、コーディネータ・サービスはロールバック・メソッドを実装します。オーケストレーション・モデルは、Sagaコーディネータ・サービスを必要とする複雑なワークフローに使用できます。
コレオグラフィ
コレオグラフィ・モデルでは、サービスは相互に通信し、いずれかのリクエストが失敗した場合、各サービスには、トランザクションをロールバックするための独自のフォールバック・メソッドが必要です。より単純なワークフローの場合は、コレオグラフィ・モデルを使用できます。
26.4.2.4 Sagaフロー
旅行代理店アプリケーションの例を挙げて、旅行予約のSagaフローを見てみましょう。
-
旅行代理店アプリケーション・ユーザーが、アプリケーションUIから旅行予約リクエストを送信します。このリクエストは旅行代理店サービスに送信されます。
-
旅行代理店サービスは、SagaコーディネータにSagaを開始するよう要求します。
-
コーディネータには、レスポンスにSaga識別子(Saga ID)が含まれます。
-
旅行代理店はSagaに登録します。代理店は、Saga完了(補正またはコミット)コールバックをコーディネータに送信します。Sagaの各参加者は、saga完了時に使用されるコールバックをsagaに提示する必要があります。
-
旅行代理店は、飛行機を予約するためにフライト・マイクロサービスへのリクエスト・コールにSaga IDを追加します。
-
参加者マイクロサービス(フライト)は、コーディネータに連絡して、Sagaに参加します(Sagaに登録します)。また、参加者サービスは、Saga完了(補正またはコミット)コールバックをコーディネータに送信します。
-
旅行代理店は他の参加者に対して、同じプロセス(ホテルやレンタカー・サービスなど)を繰り返します。
-
参加者マイクロサービスは、ビジネス・プロセスを実行します。
-
旅行代理店はすべての返信を受信した後、Sagaをコミットするかロールバックするかを決定してコーディネータに通知します。
-
コーディネータは、Saga参加者に適切なコールバック(補正またはコミット)をコールして、コントロールを旅行代理店に戻します。
-
旅行代理店は、Sagaの成否をコーディネータに確認し、Sagaを終了します。
26.4.3 マイクロサービスの成功のための12のパターンのBackend as a Service
マイクロサービスの成功事例を検索すると、業界ではマイクロサービスがビジネスにもたらすメリットについて意見が分かれています。
従来、モノリスは標準アーキテクチャで、アプリケーション全体が単一のドメインおよびデータ・アクセス・パターンを持ち、トランザクション境界を単一のデータベース内でローカルに保ち、アプリケーションが分散トランザクションを必要とすることはほとんどありませんでした。これにより、データ設計が簡略化されますが、スキーマ内の表へのアクセスがスパゲッティ・パターンになり、エンティティ関係の設定が非常に複雑になります。したがって、モノリスの大きな短所の1つは、変更が複雑になり、アプリケーションで新機能を開始するのに時間がかかる点です。
一方、マイクロサービス(マイクロサービス・アーキテクチャ)では、利点は機敏性であり、コンテキストをバインドして様々なマイクロサービス間の疎結合を使用することで実現します。これにより、(マイクロサービスからのデータへの)アクセス・パターンがローカルに制限され、非常にまれに、非同期でスケーラブルなSagaがサポートするマイクロサービス間のトランザクションに依存します。
ただし、マイクロサービスの利点が、(1)マイクロサービスとAPIまたはメッセージングを統合するためのインフラストラクチャの設定のオーバーヘッド、および(2)マイクロサービスの数が数百に及ぶ場合の単一マイクロサービスの変更のテストのオーバーヘッドによって活用できない場合があります。バインドされたコンテキストは、モノリスで使用される密結合から離れ、マイクロサービス間のデータ・アクセスの疎結合を強制するデータ・レイアウトを識別するために重要です。既存のモノリスからマイクロサービスを抽出することもできます。ストラングラー・パターンを使用すると、ボトムアップ・アフィニティ分析を実行して独立した関数を決定できます。しかし、このような問題により、ほとんどの企業はマイクロサービス・アーキテクチャの構築とデプロイに苦労しています。
マイクロサービスを使用する企業にとって、Oracleは豊富な経験を活用して、マイクロサービスを成功させるための次の12パターンを開発しました:
-
境界付けられたコンテキスト - 事前に設計するか、データ・リファクタリング・アドバイザを使用してモノリスをマイクロサービスに分解します
疎結合 - スキーマをマイクロサービスに分離し、信頼性の高いイベント・メッシュを使用してデータを分離します
-
トランザクション送信ボックス - 単一のローカル・トランザクションでメッセージおよびデータ操作を送信します
-
信頼性の高いイベント・メッシュ - すべてのイベントにイベント・メッシュ(スループットの高いトランザクション・メッセージングとパブリッシュ/サブスクライブ、イベント変換とイベント・ルーティング、およびKafka (必要な場合)を使用)を使用します
-
Saga - マイクロサービス間のトランザクション(データベース内のEvent MeshおよびEscrowジャーナリングのサポートを使用)です
-
マイクロサービス用のセキュリティ - APIゲートウェイからロード・バランサ、イベント・メッシュ、データベースへの各エンドポイントを保護します
-
多言語のマイクロサービス - ペイロードとしてJSONを使用する様々な言語でマイクロサービスおよびメッセージ形式をサポートします
-
マイクロサービスの統一された可観測性 - チューニングと自己修復のために、メトリック、ログ、トレースを単一のダッシュボードに表示します
-
イベント集計 - イベントは一時的であり、リアルタイム・アクションを通知/トリガーします。その後、それらはデータベースに集計されます。データベースは最終的な圧縮されたトピックです
-
CQRS - コマンド・クエリ責務分離(マイクロサービスでデータの運用コピーと分析コピーを使用可能)
-
マイクロサービス用のCI/CD - マルチテナント・データベースにより、マイクロサービス+PDBを独立してデプロイ/構築できるようになり、アプリケーション(JenkinsまたはGitHub Actionsを使用)およびスキーマ(データベース内のLiquibase、FlywayおよびEBR)にも適しています
-
マイクロサービス用のAIサンドボックス - RAGを実行するための実験的なサンドボックスと、チャットボットやその他のユース・ケースに対する企業の正確性を向上させる関連技術- 導入の準備が整います
-
BaaS (Backend as a Service) - 任意のクラウドまたはオンプレミス・デプロイメント(Spring Bootアプリケーションの場合)でのテスト/開発および本番デプロイメント(小規模、中規模)に適したサイズのマイクロサービス・インフラストラクチャ
Backend as a Self-Service (BaaS)パターンは、マイクロサービス・プラットフォームのデプロイメントを容易にして、前述のすべてのパターンを正常な開発/テストおよび本番環境に取り込みます。
次の章では、Oracle Backend for Microservices and AIプラットフォームとも呼ばれるOracle Backend as a Self-Service (OBaaS)について説明します。
Spring BootはJavaで最も一般的なマイクロサービス・フレームワークであり、OBaaSを使用すると、Java開発者はSpring Bootベースのマイクロサービスの構築、テスト、運用タスクを簡素化できます。