API ゲートウェイ パターンと、クライアントからマイクロサービスへの直接通信との比較

ヒント

このコンテンツは eBook の「コンテナー化された .NET アプリケーションの .NET マイクロサービス アーキテクチャ」からの抜粋です。.NET Docs で閲覧できるほか、PDF として無料ダウンロードすると、オンラインで閲覧できます。

.NET Microservices Architecture for Containerized .NET Applications eBook cover thumbnail.

マイクロサービス アーキテクチャでは、各マイクロサービスによって (通常) 細かいエンドポイントのセットが公開されます。 このセクションの説明のとおり、このことがクライアントからマイクロサービスへの通信に影響する場合があります。

クライアントからマイクロサービスへの直接通信

クライアントからマイクロサービスへの直接通信アーキテクチャを使用する方法が考えられます。 この方法では、図 4-12 に示すように、クライアント アプリは一部のマイクロサービスに直接要求することができます。

Diagram showing client-to-microservice communication architecture.

図 4-12. クライアントからマイクロサービスへの直接通信アーキテクチャの使用

この方法では、各マイクロサービスにパブリック エンドポイントがあり、マイクロサービスごとに異なる TCP ポートがある場合があります。 特定のサービスの URL の例として、Azure での URL を以下に示します。

http://eshoponcontainers.westus.cloudapp.azure.com:88/

クラスターに基づく運用環境では、その URL がクラスターで使用されるロード バランサーにマップされ、その後、マイクロサービス全体に要求が分散されます。 運用環境では、マイクロサービスとインターネット間で Azure Application Gateway などのアプリケーション配信コントローラー (ADC) を使用できます。 このレイヤーは、負荷分散を実行するだけでなく、SSL 終了を提供することにより、サービスをセキュリティで保護する透過層として機能します。 このアプローチにより、CPU 負荷の高い SSL 終了と他のルーティング作業を Azure Application Gateway にオフロードすることで、ホストの負荷が改善されます。 いずれの場合も、論理アプリケーション アーキテクチャの観点からロード バランサーと ADC は透過的となります。

マイクロサービス ベースの小さなアプリケーションの場合、特にクライアント アプリが ASP.NET MVC アプリなどのサーバー側の Web アプリケーションである場合はクライアントからマイクロサービスへの直接通信アーキテクチャで十分です。 ただし、マイクロサービス ベースの大きい複雑なアプリケーションをビルドする場合 (たとえば、多数の種類のマイクロサービスを処理する場合) と、特にクライアント アプリがリモート モバイル アプリまたは SPA Web アプリケーションである場合、この方法ではいくつかの問題に直面します。

マイクロサービスに基づいて大きなアプリケーションを開発する際には、以下の点を考慮してください。

  • クライアント アプリではバックエンドへの要求数をどのように最小化し、複数のマイクロサービスへの頻繁な通信をどのように減らすことができるか

1 つの UI 画面をビルドするために複数のマイクロサービスと対話することは、インターネット上のラウンド トリップの数を増加させます。 このアプローチを使用すると、UI 側の待機時間と複雑さが増します。 理想を言えば、サーバー側で応答を効率的に集約する必要があります。 そうすれば、複数のデータ片が並列に返され、一部の UI では準備ができしだいデータを表示できるため、このアプローチでも待機時間が短くなります。

  • 承認、データ変換、動的な要求のディスパッチなど、横断的な問題をどのように処理できるか

すべてのマイクロサービスでのセキュリティと承認などのセキュリティと横断的な問題の実装には、開発作業がかなり必要になる場合があります。 考えられる 1 つの方法は、それらのサービスを Docker ホストまたは内部クラスター内に配置して外部からの直接アクセスを制限し、API ゲートウェイなどの中央の場所からそうした横断的な問題を実装することです。

  • クライアント アプリは非インターネット対応プロトコルを使用するサービスとどのように通信できるのか

サーバー側で使用されるプロトコル (AMQP やバイナリ プロトコルなど) は、クライアント アプリではサポートされません。 そのため、要求は HTTP/HTTPS などのプロトコル経由で実行し、その後、他のプロトコルに変換する必要があります。 このような状況では中間者 方法が役立つ場合があります。

  • モバイル アプリ専用のファサードはどのように形成できるのか

複数のマイクロサービスの API は、さまざまなクライアント アプリケーションのニーズに合わせて適切に設計されていない場合があります。 たとえば、モバイル アプリのニーズは、Web アプリのニーズとは異なる場合があります。 モバイル アプリでは、データ応答をより効率的にできるようにさらに最適化する必要がある場合があります。 複数のマイクロサービスからデータを集約し、単一のデータ セットを返し、場合によってはモバイル アプリには必要のない応答内のデータを排除することで、この機能を行う場合があります。 また、当然ながら、そのデータを圧縮する場合があります。 モバイル アプリとマイクロサービス間の API またはファサードはこのシナリオでも便利な場合があります。

クライアントからマイクロサービスへの直接通信の代わりに API ゲートウェイを検討する理由

マイクロサービス アーキテクチャでは、通常、クライアント アプリは複数のマイクロサービスからの機能を使用する必要があります。 その使用が直接行われる場合、クライアントは、マイクロサービス エンドポイントの呼び出しを数多く処理する必要があります。 アプリが進化して、新しいマイクロサービスが導入されたり既存のマイクロサービスが更新されるとどうなるでしょうか。 アプリに対して多数のマイクロサービスがある場合、クライアント アプリから膨大な数のエンドポイントを処理するのは大変な作業になります。 クライアント アプリはそれらの内部エンドポイントと結合されるので、将来マイクロサービスが進化するとクライアント アプリに大きな影響を及ぼす可能性があります。

したがって、マイクロサービス ベースのアプリケーションでは、中間レベルまたは間接層 (ゲートウェイ) を導入すると便利です。 API ゲートウェイを設置しないと、クライアント アプリはマイクロサービスに要求を直接送信しなければならず、それによって次のような問題が発生します。

  • 結合: API ゲートウェイ パターンがないと、クライアント アプリは内部マイクロサービスと結合されます。 クライアント アプリでは、アプリケーションのさまざまな領域がマイクロサービスにどのように分解されたかを把握する必要があります。 内部マイクロサービスを進化させてリファクタリングするときに、そのようなアクションは、クライアント アプリから内部マイクロサービスへの直接参照が原因でクライアント アプリに対する破壊的変更を生じさせるため、メンテナンスに影響が及びます。 クライアント アプリには頻繁な更新が必要なので、ソリューションの進化が困難になります。

  • 膨大な数のラウンド トリップ: クライアント アプリの 1 つのページ/画面のために、複数のサービスを何回も呼び出す必要がある場合があります。 そのアプローチの結果として、クライアントとサーバーの間で複数のネットワーク ラウンド トリップが発生し、待機時間が大幅に長くなることがあります。 中間レベルで処理される集約によって、クライアント アプリのパフォーマンスとユーザー エクスペリエンスを向上できる可能性があります。

  • セキュリティ上の問題: ゲートウェイがない場合、すべてのマイクロサービスが "外の世界" に対して公開されることになり、クライアント アプリで直接使用されない内部マイクロサービスを非表示にした場合よりも攻撃サーフェスが大きくなります。 攻撃サーフェスが小さいほど、アプリケーションの安全性は高くなります。

  • 横断的な問題: パブリックに公開される各マイクロサービスは、認可や SSL などの問題を処理する必要があります。 多くの場合、これらの問題を 1 つの層で処理することができるため、内部マイクロサービスが単純化されます。

API ゲートウェイ パターンとは

複数のクライアント アプリを持つマイクロサービス ベースの大きく複雑なアプリケーションを設計してビルドする場合、API ゲートウェイの使用を検討することをお勧めします。 このパターンは、特定のマイクロサービス グループに対して単一のエントリ ポイントを提供するサービスです。 オブジェクト指向設計のファサード パターンに似ていますが、この場合は分散システムの一部となります。 API ゲートウェイ パターンは、クライアント アプリのニーズを考えながらビルドするため、"backend for frontend" (BFF) と呼ばれることもあります。

したがって、API ゲートウェイはクライアント アプリとマイクロサービスの間に位置します。 リバース プロキシとして機能し、クライアントからサービスへと要求をルーティングします。 また、認証、SSL 終了、キャッシュといった他の横断的な機能も提供できます。

図 4-13 は、いくつかのマイクロサービスのみを含む簡略化されたマイクロサービス ベースのアーキテクチャに、カスタム API ゲートウェイを組み込む方法を示しています。

Diagram showing an API Gateway implemented as a custom service.

図 4-13. カスタム サービスとして実装された API ゲートウェイの使用

アプリは、個々のマイクロサービスに要求を転送するように構成された 1 つのエンドポイント (API ゲートウェイ) に接続します。 この例では、API ゲートウェイは、コンテナーとして実行されるカスタム ASP.NET Core WebHost サービスとして実装されます。

この図では、複数の異なるクライアント アプリに接続されている単一のカスタム API ゲートウェイ サービスを使用していることに注意してください。 クライアント アプリからの多くのさまざまな要件に基づいて API ゲートウェイ サービスが拡大し、進化するため、このことが重要なリスクになる可能性があります。 最終的に、これらのさまざまなニーズにより肥大化し、実際はモノシリック アプリケーションまたはモノシリック サービスによく似たものになる可能性があります。 そのため、API ゲートウェイを複数のサービスまたは複数のより小さい API ゲートウェイ (たとえば、クライアント アプリのフォーム ファクターの種類ごとに 1 つ) に分割することを強くお勧めします。

API ゲートウェイ パターンを実装するときには注意が必要です。 通常は、単一の API ゲートウェイでアプリケーションの内部マイクロサービスをすべて集約することはお勧めできません。 これを行うと、モノシリック アグリゲーターまたはオーケストレーターとして機能し、すべてのマイクロサービスを結合することでマイクロサービスの自律性を侵害することになります。

そのため、API ゲートウェイはビジネス境界とクライアント アプリに基づいて分離する必要があり、すべての内部マイクロサービスに対する単一のアグリゲーターとして機能しないようにする必要があります。

API ゲートウェイ層を複数の API ゲートウェイに分割するとき、ご利用のアプリケーションが複数のクライアント アプリを備えている場合は、それを複数の API ゲートウェイの種類を区別する際の第一の軸とすることで、各クライアント アプリのニーズに合わせた異なるファサードを用意できます。 このケースは "Backend for Frontend" (BFF) と呼ばれるパターンです。次の図に示すように、このパターンでは、複数の内部マイクロサービスを裏で呼び出す特定のアダプター コードを実装することにより、各 API ゲートウェイが (クライアント フォーム ファクター ベースであっても) クライアント アプリの種類ごとに調整された異なる API を提供できます。

Diagram showing multiple custom API Gateways.

図 4-13.1. 複数のカスタム API ゲートウェイの使用

図 4-13.1 は、クライアントの種類別に分離された API ゲートウェイを示します。1 つはモバイル クライアント用で、もう 1 つは Web クライアント用です。 従来の Web アプリは、Web API ゲートウェイを使用する MVC マイクロサービスに接続されます。 この例は、複数の粒度の API ゲートウェイを使用した簡素化されたアーキテクチャを示しています。 このケースでは、各 API ゲートウェイに対して指定された境界は純粋に "Backend for Frontend" (BFF) パターンに基づくものであり、したがって、各クライアント アプリで必要とされる API にのみ基づいています。 しかし、より大規模なアプリケーションではさらに、設計の第二の軸としてビジネス境界に基づく他の API ゲートウェイを作成する必要があります。

API ゲートウェイ パターンの主な機能

API ゲートウェイではさまざまな機能が提供されます。 提供される機能の幅は製品によって異なりますが、すべての API ゲートウェイにとって最も重要かつ基本的な機能は次の設計パターンです。

リバース プロキシ/ゲートウェイ ルーティング。 API ゲートウェイは、マイクロサービスのエンドポイントに要求をリダイレクト/ルーティングする (レイヤー 7 ルーティング、通常は HTTP 要求) ためのリバース プロキシを提供します。 ゲートウェイはクライアント アプリ用に 1 つのエンドポイントまたは URL を提供し、要求を内部マイクロサービスのグループに内部的にマッピングします。 このルーティング機能は、クライアント アプリをマイクロサービスから分離するのに役立つだけでなく、モノリシック API とクライアント アプリの間に API ゲートウェイを設置してモノリシック API を刷新するときにも便利です。将来多数のマイクロサービスに分割されるまでの間従来のモノリシック API を使い続けながら、新しい API を新しいマイクロサービスとして追加できます。 API ゲートウェイがあるため、クライアント アプリは、使用されている API が内部マイクロサービスとして実装されているのか、モノリシック API として実装されているのかを関知しません。さらに重要なことに、モノリシック API をマイクロサービスに進化させてリファクタリングするときに、API ゲートウェイのルーティングのおかげでクライアント アプリが URI 変更の影響を受けずに済みます。

詳細については、「ゲートウェイ ルーティング パターン」を参照してください。

要求の集約。 ゲートウェイ パターンの一部として、複数の内部マイクロサービスに対する複数のクライアント要求 (通常は HTTP 要求) を 1 つのクライアント要求に集約することができます。 このパターンは特に、クライアントのページ/画面が複数のマイクロサービスからの情報を必要とする場合に便利です。 この方法では、クライアント アプリが API ゲートウェイに 1 つの要求を送信します。API ゲートウェイは内部マイクロサービスに複数の要求をディスパッチし、結果を集約し、すべてをクライアント アプリに送り返します。 この設計パターンの主な利点と目的は、クライアント アプリとバックエンド API 間の頻繁な通信を削減することです。これは、マイクロサービスが置かれているデータセンターの外にあるリモート アプリ (モバイル アプリや、クライアントのリモート ブラウザー内の JavaScript から送信された SPA アプリからの要求など) において特に重要です。 サーバー環境で要求を実行する通常の Web アプリ (ASP.NET Core MVC Web アプリ) の場合は、リモート クライアント アプリよりも待機時間がはるかに短いため、このパターンはそれほど重要ではありません。

使用する API ゲートウェイ製品によっては、この集約を実行できる場合があります。 しかし、API ゲートウェイのスコープに基づいてマイクロサービスの集約を作成する方が柔軟性が高いため、多くの場合はコード (C# コード) で集約を定義します。

詳細については、「ゲートウェイ集約パターン」を参照してください。

横断的な問題またはゲートウェイのオフロード。 各 API ゲートウェイ製品で提供される機能に応じて、個々のマイクロサービスからゲートウェイに機能をオフロードできます。これにより、横断的な問題を 1 つの層にまとめて、各マイクロサービスの実装を単純化することができます。 このアプローチは特に、次の機能のような、内部マイクロサービスごとに正しく実装することが難しい特化した機能に役立ちます。

  • 認証と承認
  • サービス探索の統合
  • 応答キャッシュ
  • 再試行ポリシー、サーキット ブレーカー、QoS
  • レートの制限と調整
  • 負荷分散
  • ログ記録、トレース、相関関係
  • ヘッダー、クエリ文字列、クレーム変換
  • IP 許可リスト

詳細については、「ゲートウェイ オフロード パターン」を参照してください。

API ゲートウェイ機能を備えた製品の使用

API ゲートウェイ製品の実装によっては、さらに幅広い横断的な問題が処理されます。 ここでは、次の 2 つについて説明します。

Azure API Management

Azure API Management (図 4-14 を参照) では、API ゲートウェイのニーズを解決するだけでなく、API からの分析情報の収集などの機能も提供されます。 API 管理ソリューションを使用している場合、API ゲートウェイはその完全な API 管理ソリューション内の単なるコンポーネントです。

Diagram showing how to use Azure API Management as your API gateway.

図 4-14. API ゲートウェイでの Azure API Management の使用

Azure API Management では、ログ記録、セキュリティ、使用状況測定など、API ゲートウェイおよび管理の両方のニーズが解決されます。この場合、Azure API Management などの製品を使用する際に単一の API ゲートウェイを使用することはそれほど危険ではありません。この種の API ゲートウェイは "細かい" ためです。つまり、モノシリック コンポーネントに進化する可能性のあるカスタム C# コードを実装することはありません。

API ゲートウェイ製品は通常、イングレス通信のリバース プロキシに近い動作をします。ここでは内部マイクロサービスから API をフィルター処理し、さらにこの単一層で公開された API に承認を適用することもできます。

API Management システムから得られる洞察は、API の使用方法と実行方法を理解するのに役立ちます。 このアクティビティは、ほぼリアルタイムに分析レポートを表示し、ビジネスに影響する可能性のある傾向を識別できるようにすることで行われます。 さらに、オンラインとオフラインの分析のために要求と応答のアクティビティに関するログを使用できます。

Azure API Management では、キー、トークン、および IP フィルタリングを使用して API をセキュリティで保護することができます。 これらの機能では、柔軟な細かいクォータと転送率の制限を適用し、ポリシーを使用して API の形状と動作を変更し、応答キャッシュによりパフォーマンスを向上させることができます。

このガイドと参照用のサンプル アプリケーション (eShopOnContainers) では、アーキテクチャを Azure API Management などの PaaS 製品を使用しないプレーンなコンテナーに焦点を合わせるために、より単純で専用にコンテナー化されたアーキテクチャに限定しています。 しかし、Microsoft Azure にデプロイされる大規模なマイクロサービス ベースのアプリケーションでは、運用環境の API ゲートウェイのベースとして Azure API Management を検討されることをお勧めします。

Ocelot

Ocelot は、より簡単な方法としてお勧めする簡易な API ゲートウェイです。 Ocelot は、システムへの統合されたエントリ ポイントを必要とするマイクロサービス アーキテクチャ向けに特別に設計された、オープンソースの .NET Core ベースの API ゲートウェイです。 これは軽量、高速、スケーラブルで、ルーティングや認証をはじめとするさまざまな機能を提供します。

eShopOnContainers 参照アプリケーション 2.0 用に Ocelot を選択する主な理由は、Ocelot が、マイクロサービスやコンテナー (Docker ホスト、Kubernetes など) をデプロイするのと同じアプリケーション デプロイ環境にデプロイできる簡易な .NET Core API ゲートウェイであるためです。また、.NET Core をベースとしているのでクロスプラットフォームであり、Linux でも Windows でもデプロイできます。

コンテナー内で実行されるカスタム API ゲートウェイを示した前の図は、コンテナーとマイクロサービス ベースのアプリケーションで Ocelot を実行する方法も正確に示しています。

また、市場には API ゲートウェイの機能を提供する Apigee、Kong、MuleSoft、WSO2 などの製品や、サービス メッシュのイングレス コントローラー機能を提供する Linkerd や Istio などの製品が他にも数多くあります。

最初のいくつかのセクションでアーキテクチャとパターンについて説明した後、後続のセクションでは Ocelot を使用して API ゲートウェイを実装する方法について説明します。

API ゲートウェイ パターンの欠点

  • 最も重要な欠点は、API ゲートウェイを実装するときにその層を内部マイクロサービスと結合することです。 このような結合は、アプリケーションの重大な問題を発生させる可能性があります。 Azure Service Bus チームのアーキテクトである Clemens Vaster は、GOTO 2016 の "Messaging and Microservices" (メッセージングとマイクロサービス) セッションで、この潜在的な問題を "新しい ESB" と呼んでいます。

  • マイクロサービス API ゲートウェイを使用すると、単一障害点が増える可能性があります。

  • API ゲートウェイでは、追加のネットワーク呼び出しにより応答時間が増加する可能性があります。 ただし、この追加呼び出しは通常、内部マイクロサービスを直接呼び出す、やり取りが多すぎるクライアント インターフェイスの場合より影響は少なくなります。

  • 正しくスケールアウトされていない場合、API ゲートウェイがボトルネックになる可能性があります。

  • API ゲートウェイでは、カスタム ロジックとデータ集計が含まれる場合、追加の開発費と将来のメンテナンスが必要になります。 開発者は、各マイクロ サービスのエンドポイントを公開するために、API ゲートウェイを更新する必要があります。 さらに、内部マイクロサービスでの実装変更により、API ゲートウェイ レベルでのコード変更が発生する可能性があります。 ただし、API ゲートウェイがセキュリティの適用、ログ記録、バージョン管理を行うだけの場合、この追加の開発費は適用されない可能性があります。

  • API ゲートウェイが単一チームによって開発される場合、開発のボトルネックが存在する可能性があります。 この点が、さまざまなクライアントのニーズに対応する細かい API ゲートウェイをいくつか使用することをお勧めする理由です。 内部マイクロサービスに取り組むさまざまなチームによって所有されている複数の領域またはレイヤーに API ゲートウェイを内部的に分離することもできます。

その他の技術情報