マイクロサービスアーキテクチャ@アーキテクチャ¶
はじめに¶
本サイトにつきまして、以下をご認識のほど宜しくお願いいたします。
01. アーキテクチャ概要¶
アーキテクチャの歴史¶
年代 | アーキテクチャ | 説明 | 補足 |
---|---|---|---|
1999 | モノリシックアーキテクチャ | 1999年台、バックエンドのアーキテクチャとしてモノリシックアーキテクチャが台頭していた。しかし、モノリシックアーキテクチャは無秩序でつぎはぎだらけのアプリケーションになることが論文 (『大きな泥だんご』) で指摘された。 | ・https://en.wikipedia.org/wiki/Big_ball_of_mud |
2000 〜 2004 | サービス指向アーキテクチャ | 1999後半〜2000前半に、Thomas Erlらがアプリケーションを機能の粒度で分割するアーキテクチャを提唱した。ただ『機能』という粒度が抽象的で、概念としては提唱されていても、実装方法の確立にまでは至らなかった。 | ・https://en.wikipedia.org/wiki/Service-oriented_architecture ・https://www.serviceorientation.org/p0.html ・https://www.amazon.com/dp/0470141115 |
2014 | マイクロサービスアーキテクチャ | 2014年にThoughtWorks社は、サービス指向アーキテクチャとドメイン駆動設計を統合し、アプリケーションを独立したマイクロサービスの集まりに分割するアーキテクチャを提唱した。サービス指向アーキテクチャにドメイン駆動設計の高凝集/低結合の考え方を取り入れることで、実装可能な理論に昇華させた。 | ・https://martinfowler.com/articles/microservices.html ・https://atmarkit.itmedia.co.jp/ait/articles/2110/22/news006.html |
2017 | ミニマイクロサービスアーキテクチャ | マイクロサービスアーキテクチャのマイクロサービス自体を独立したモノリスなアプリケーションと捉えると、その分だけ開発チーム (マネージャーとエンジニア) が必要になってしまう。2017年にCloud Elements社は、これに対処するためにミニマイクロサービスアーキテクチャを提唱した。このアーキテクチャでは、マイクロサービスアーキテクチャとモノリスアーキテクチャの間をとった粒度で、アプリケーションを複数のマイクロサービスに分割する。この粒度を、マイクロサービスに対抗して『ミニマイクロサービス』または『MASA』とよぶ。 | ・https://blog.cloud-elements.com/pragmatic-microservices-architecture ・https://atmarkit.itmedia.co.jp/ait/articles/2110/22/news006.html |
2018 | モジュラーモノリスアーキテクチャ | ミニマイクロサービスアーキテクチャではマイクロサービスの粒度が大きくなったものの、複数のマイクロサービスが必要になることは変わらず、その分だけ開発チームが必要になる問題は解決されなかった。そこで、Root Insurance社はモジュラーモノリスを提唱した。モジュラモノリスでは、マイクロサービスアーキテクチャとモノリスアーキテクチャの間をとった粒度で、アプリケーションを細かいモジュールに分割する。最初、モジュラーモノリスとして設計し、マイクロサービスアーキテクチャに移行していくという選択肢もある。 | ・https://medium.com/@dan_manges/the-modular-monolith-rails-architecture-fb1023826fc4 ・https://creators-note.chatwork.com/entry/2020/12/02/090000 ・https://eh-career.com/engineerhub/entry/2022/07/25/093000 |
各アーキテクチャの粒度の比較¶
モジュールの大きさ | 粒度名 | 説明 |
---|---|---|
一番大きい | モノリシック | アプリケーションのモジュールが分割されておらず、アプリケーションをデプロイの単位とする。 |
モジュラー | アプリケーションがモジュールに分割されており、アプリケーションをデプロイの単位とする。モジュール間のデータのやり取りに通信を使用するか否かや、モジュール間でDBを共有するか否かの選択によって、作成パターンがいくつかある。 ・https://scrapbox.io/tsuwatch/%E3%83%A2%E3%83%8E%E3%83%AA%E3%82%B9%E3%81%A8%E3%83%9E%E3%82%A4%E3%82%AF%E3%83%AD%E3%82%B5%E3%83%BC%E3%83%93%E3%82%B9%E3%81%AE%E3%81%82%E3%81%84%E3%81%A0 |
|
ミニマイクロサービス | アプリケーションがサブドメイン (または境界づけられたコンテキスト) を単位としたマイクロサービスに分割されており、アプリケーションを構成するマイクロサービスのある程度のまとまりをデプロイの単位とする。また、DBを各マイクロサービスで共有する。 | |
一番小さい | マイクロ | アプリケーションがサブドメイン (または境界づけられたコンテキスト) を単位としたマイクロサービスまたはルートエンティティに分割されており、アプリケーションを構成するマイクロサービスそれぞれをデプロイの単位とする。また、DBを各マイクロサービスで共有せずに、マイクロサービスごとに配置する。 |
プレゼンテーションドメイン分離¶
モノリシックの段階では、フロントエンドとバックエンドが1つのアプリケーションで密結合になっている。
フロントエンドとバックエンドを分離した段階では、フロントエンドとバックエンドが異なるアプリケーションとして分離される。
マイクロサービスでの段階では、さらにバックエンドが複数のアプリケーションとAPIアグリゲーション層に分離される。
関連パターン¶
▼ 関連パターンとは¶
マイクロサービスアーキテクチャでは固有の問題が起こる。
これを解決するための関連パターンがたくさんある。
*実装例*
microservices.io
サイトで紹介しきれていない実装方法は、softwarepatternslexicon
サイトで確認できる。
▼ マイクロサービスアーキテクチャとクラウドネイティブ¶
優れたクラウドネイティブアプリケーションを作成するには、マイクロサービスアーキテクチャとクラウドネイティブ技術が必要である。
マイクロサービスアーキテクチャの関連パターンは、クラウドネイティブ技術で代替できる。
マイクロサービスの関連パターン | クラウドネイティブ技術 |
---|---|
Externalized configuration | Kubernetes ConfigMap、Kubernetes Secret |
サービスディスカバリー | Kubernetes Service |
負荷分散 | Kubernetes Service |
API Gateway | Kubernetes Ingress |
集中ロギング | Fluentd |
集中メトリクス | Prometheus、Grafana |
分散トレース | OpenTelemetry、Grafana Tempo |
回復力 | Kubernetes Probe、Istio |
自己回復 | Kubernetes Deployment |
... | ... |
01-02. マイクロサービスアーキテクチャ¶
特徴¶
▼ ビジネスのスケーリングに強い¶
ビジネスがスケーリングする時、マイクロサービスの新規実装または削除を行えば良いため、ドメイン層の激しい変化に強い。
▼ コンウェイの法則が働く¶
マイクロサービスアーキテクチャにより、組織構造が小さなチームの集まりに変化することを期待できる。
▼ 高頻度でリリース可能¶
各マイクロサービスを独立してデプロイできるため、高頻度でリリースできる。
▼ 障害の影響が部分的¶
いずれかのマイクロサービスに障害が発生したとして、サーキットブレイカーを使用することにより、ダウンストリーム側マイクロサービスへの障害の波及を食い止められる。
そのため、障害の影響が部分的となり、アプリケーション全体が落ちてしまうことがない。
▼ 複数の開発言語を使用可能¶
マイクロサービス間で、共通のデータ記述言語を使用してデータ通信を行えば、各マイクロサービスの開発言語が異なっていても問題ない。
アーキテクチャ例¶
▼ Eコマース (Googleのサンプル)¶
src
ディレクトリに各マイクロサービスのディレクトリを配置する。
- カート
- 商品検索とインデックス
- 通貨の変換
- クレジットカード
- 送料と発送
- 注文確認メール
- 注文フロー
- レコメンド
- 広告
- 合成監視
▼ Eコマース (メルカリのサンプル)¶
services
ディレクトリに各マイクロサービスのディレクトリを配置する。
- 認証
- カタログ
- 顧客
- 商品
▼ Eコマース (Datadogのサンプル)¶
- 広告
- 割引
▼ Eコマース (Amazon)¶
▼ SNS (Twitter)¶
▼ 地図 (Google Map)¶
フレームワーク¶
マイクロサービスアーキテクチャのフレームワークとして、Dapr、Axon、Eventuate、MicroProfile LRAなどがある。
02. ドメイン層¶
マイクロサービス¶
▼ マイクロサービスとは¶
マイクロサービスアーキテクチャにおける分散システム状のバックエンドのコンポーネントのこと。
特定のマイクロサービスが他のマイクロサービスに侵食され、マイクロサービスの凝集度が低くならないようにするために、ACL:Anti Corruption Layer (腐食防止レイヤー) を設ける必要がある。
腐食防止レイヤーは、異なるコンテキストから受信したデータを、そのマイクロサービスのコンテキストにあったデータ形式に変換する責務を持つ。
CQRSでは、これはプロセスマネージャパターンとして知られている。
一方でSagaパターンとも呼ばれるが、分散トランザクションでも同じ用語があるため、混乱を避けるためにプロセスマネージャパターンとする。
▼ 各マイクロサービスのアーキテクチャ¶
各マイクロサービスのアーキテクチャは自由である。
この時、ドメイン駆動設計のアーキテクチャを基に実装できる。
*例*
ECサイトがあり、これの商品販売ドメインを販売サブドメインと配送サブドメインに分割できるとする。
この時、それぞれのサブドメインの問題を解決する販売コンテキストと配送コンテキストをマイクロサービスの粒度となり、オニオンアーキテクチャのアプリケーション間で同期通信/非同期通信を実行する。
分割パターン¶
▼ サブドメイン単位/境界づけられたコンテキスト単位¶
サブドメインまたは境界づけられたコンテキストを単位として、マイクロサービスを分割とする。
現状のモノリスの分割段階 | 境界づけられたコンテキスト | サブドメイン | 機能単位 |
---|---|---|---|
すでにサブドメインに分割されている | 不可 | 不可 | 記入中... |
すでに複数のサブドメインを含む境界づけられたコンテキストに分割されている | 不可 | 可 | 記入中... |
すでに単一のサブドメインを含む境界づけられたコンテキストに分割されている | 可 | 可 | 記入中... |
解決領域となる境界づけられたコンテキストがサブドメインの中に1
個しか含まれていない場合は、境界づけられたコンテキストでマイクロサービスを分割することになる。
図にて、境界づけられたコンテキスト間で、『利用者』という名詞に対する定義づけ/意味合いが異なっていることに留意する。
ドメイン駆動設計では境界づけられたコンテキストが1
個のアプリケーションに相当するため、境界づけられたコンテキストで分割した場合、マイクロサービスアーキテクチャは複数のアプリケーションから構成されるアーキテクチャと捉えられる。
加えて小さな粒度に分割する方法として、ルートエンティティを粒度ともできる。
- https://docs.microsoft.com/ja-jp/dotnet/architecture/microservices/architect-microservice-container-applications/identify-microservice-domain-model-boundaries
- https://microservices.io/patterns/decomposition/decompose-by-subdomain.html
- https://www.amazon.co.jp/dp/4873119316/
- https://booth.pm/ja/items/1835632
▼ ルートエンティティ単位 (エンティティサービス)¶
『エンティティサービス』ともいう。
ドメイン層のルートエンティティを単位として、マイクロサービスを分割する。
この場合、境界づけられたコンテキストよりもマイクロサービスの粒度が小さい。
そのため、複数のマイクロサービスで1つの境界づけられたコンテキストを構成することになり、異なるマイクロサービスが同じ種類のデータを持つオブジェクトを処理する。
ドメイン層にはマイクロサービス (例:〇〇ドメインサービス) があり、ドメイン層以外のレイヤー (インターフェース層、ユースケース層、リポジトリ層) はマイクロサービスではない。
DBレコードの書き込み/読み出しのトランザクションをルートエンティティ単位で実行するため、マイクロサービスの単位がわかりやすい。
一方で、データに着目したステートソーシングパターンのルートエンティティを使用することはアンチパターンである。
最良な解決策として、振舞に着目したイベントソーシングを使用する必要がある。
また、各マイクロサービスを名詞ではなく動詞 (例:〇〇管理サービス、〇〇中継サービス、〇〇通知サービス、〇〇集計サービス) で命名すると良い。
その他、各マイクロサービスでDBを完全に独立させることや、SAGAパターンを使用すること、がある。
分割アンチパターン¶
▼ 分散モノリス¶
複数のマイクロサービスをセットでデプロイしなければならず、マイクロサービス間のデプロイが独立していないような分割パターン。
例えば、マイクロサービス間で重複するロギングライブラリをマイクロサービスとして分離した結果、複数のマイクロサービスがこのロギングマイクロサービスに依存してしまうような場合がある。
分散モノリスにならないように、マイクロサービス間で使用するライブラリが重複することを許容する必要がある。
03. リポジトリ層¶
分割パターン¶
▼ ドメイン層と同じマイクロサービス¶
ドメイン層と同じマイクロサービス内で実行する。
最も一般的な分割パターンである。
▼ ドメイン層とは異なるマイクロサービス + 占有リポジトリ単位 (ルートエンティティ単位)¶
ドメイン層とは異なるマイクロサービス内で実行する。
また、占有リポジトリを単位として、マイクロサービスを分割する。
ドメイン駆動設計では、DBレコードの書き込み/読み出しのトランザクションをルートエンティティ単位で実行する。
そのため、リポジトリは実際にはルートエンティティに対応しており、ルートエンティティ単位で分割すると言い換えても良い。
▼ ドメイン層とは異なるマイクロサービス + 共有リポジトリ単位 (ルートエンティティ単位)¶
ドメイン層とは異なるマイクロサービス内で実行する。
また、共有リポジトリを単位として、マイクロサービスを分割する。
ただ、境界づけられたコンテキストは他のコンテキストとは異なるルートエンティティを持つため、リポジトリも完全に独立しているはずである。
そのため、異なる境界づけられたコンテキストのマイクロサービスが、同じリポジトリを共有することは起こらないはずである。
逆に言うと、複数のマイクロサービスがリポジトリを共有している場合、それらのマイクロサービスは同じコンテキストに属しており、分割する必要がないということになる。
これらのことから、この分割パターンはあまり良くない (出典は俺) 。
04. APIアグリゲーション層¶
APIアグリゲーション層とは¶
全てのAPIまたは複数のAPIのセットとして機能する。
04-02. API Gateway¶
API Gatewayとは¶
クリーンアーキテクチャでいうインフラストラクチャ層とインターフェース層のような機能を担う。
主要な機能として、受信した通信を適切なマイクロサービスのAPIにルーティング
- ルーティング
- 認証
- トレースIDの付与
- キャッシュの作成
- リクエストのレートリミット
- 通信の暗号化
- ...
なお、API Gatewayをサービスメッシュに参加させることで、これらの機能の一部 (認証、トレースIDの付与、通信の暗号化、リクエスト制限) をサイドカーに委譲できる。
分割パターン¶
▼ API Gatewayの分割パターンとは¶
API Gatewayの責務をどのように分割するかに応じて、分割パターンがある。
▼ Central Aggregating Gateway¶
マイクロサービスにリクエストを送信するアプリケーションの種類に関係なく、API Gatewayを1
個だけ作成する。
▼ BFF:Backends For Frontends¶
マイクロサービスにリクエストを送信するクライアントアプリケーションの種類 (Webアプリケーション、モバイルアプリケーション、他社向けアプリケーションなど) を単位として、API Gateway (Web API Gateway、Mobile API Gateway、他社向けAPI Gatewayなど) を作成する。
ただし、ドメインによっては同じクライアントアプリケーションの種類であっても、API Gatewayを分割することもある。
例えば、送金ドメインであれば、クライアントアプリケーションには銀行ダイレクトアプリや銀行系決済サービスアプリがあり、これらが同じモバイルアプリケーションであっても、API Gatewayを分割する。
なお、BFFはRESTful-APIであってもGraphQL-APIであっても、どちらでも問題ない。
▼ Federated Gateway¶
BFFではアプリケーションの種類ごとにAPI Gatewayを作成したが、Federated Gatewayでは各API Gatewayのエンドポイントを統合する。
API形式パターン¶
▼ API GatewayのAPI形式パターンとは¶
API GatewayのAPI形式に応じて、分割パターンがある。
▼ RESTful-API¶
記入中...
▼ GraphQL-API¶
記入中...
▼ RPC-API¶
記入中...
責務パターン¶
▼ Gateway Offloadingパターン¶
API Gatewayは、マイクロサービス間で共通する課題 (認証、ロギング、SSL証明書など) を処理する責務を持ちます。
▼ Gatewayルーティングパターン¶
API Gatewayは、複数のマイクロサービスにリクエストをルーティングする責務を持ちます。
▼ Gatewayアグリゲーターパターン¶
API GatewayにAPI Compositionを適用した方法である。
実装パターン¶
▼ 自前で実装する場合¶
API Gatewayを自前 (例:フルスクラッチ、GraphQLを使用したフルスクラッチなど) で実装する。
Kubernetes内で管理できるメリットがある。
GraphQLでAPI Gatewayを実装する場合は、特に注意が必要である。
フロントエンドとAPI Gatewayの両方でGraphQL特有の実装が必要になるので、フロントエンドとAPI Gatewayの開発が分業にしくくなってしまう。
ただ、フロントエンドとAPI Gatewayの開発チームの両方がGraphQLの知識を持ってれば、これは起こらない。
- https://techblog.zozo.com/entry/zozotown-phased-istio-service-meshing-strategy
- https://qiita.com/takurUN/items/aace0e60744d0ec92cf6#2-4-api%E3%82%B2%E3%83%BC%E3%83%88%E3%82%A6%E3%82%A7%E3%82%A4%E3%82%92kong%E3%81%A7%E6%A7%8B%E7%AF%89%E3%81%97%E3%81%9F%E7%90%86%E7%94%B1%E3%82%B3%E3%82%B9%E3%83%88%E6%9C%80%E9%81%A9
▼ OSSを使用する場合¶
API GatewayのOSS (Kong、Tyk、Apigee、Kuma、Nginx、Envoy、Apache APISIXなど) を使用する。
Kubernetes内で管理できるメリットがある。
- https://www.moesif.com/blog/technical/api-gateways/How-to-Choose-The-Right-API-Gateway-For-Your-Platform-Comparison-Of-Kong-Tyk-Apigee-And-Alternatives/
- https://qiita.com/takurUN/items/aace0e60744d0ec92cf6#2-4-api%E3%82%B2%E3%83%BC%E3%83%88%E3%82%A6%E3%82%A7%E3%82%A4%E3%82%92kong%E3%81%A7%E6%A7%8B%E7%AF%89%E3%81%97%E3%81%9F%E7%90%86%E7%94%B1%E3%82%B3%E3%82%B9%E3%83%88%E6%9C%80%E9%81%A9
▼ クラウドプロバイダーのマネージドサービスを使用する場合¶
クラウドプロバイダー (例:AWS、Google Cloud) が提供するAPI Gateway (例:AWS API Gateway、Google API Gateway) を使用する。
クラウドプロバイダーの対応状況によっては、Kubernetes内で管理できない可能性がある。
その場合、フロントエンドアプリケーションがAPI Gatewayに通信できるように、フロントエンドアプリケーションとバックエンドアプリケーションを異なるKubernetesで動かす必要がある。
- https://aws.amazon.com/jp/blogs/news/api-gateway-as-an-ingress-controller-for-eks/
- https://qiita.com/takurUN/items/aace0e60744d0ec92cf6#2-4-api%E3%82%B2%E3%83%BC%E3%83%88%E3%82%A6%E3%82%A7%E3%82%A4%E3%82%92kong%E3%81%A7%E6%A7%8B%E7%AF%89%E3%81%97%E3%81%9F%E7%90%86%E7%94%B1%E3%82%B3%E3%82%B9%E3%83%88%E6%9C%80%E9%81%A9