ブログ | NGINX

マイクロサービスの構築: APIゲートウェイの使用

NGINX-F5 水平黒タイプ RGB の一部
クリス・リチャードソン サムネイル
クリス・リチャードソン
2015 年 6 月 15 日公開

編集者– この 7 部構成の記事シリーズはこれで完了です。

  1. マイクロサービス入門
  2. マイクロサービスの構築: API ゲートウェイの使用 (この記事)
  3. マイクロサービスの構築: マイクロサービス アーキテクチャにおけるプロセス間通信
  4. マイクロサービス アーキテクチャにおけるサービス検出
  5. マイクロサービス向けイベント駆動型データ管理
  6. マイクロサービス導入戦略の選択
  7. モノリスをマイクロサービスにリファクタリングする

また、記事の完全なセットと、NGINX Plus を使用したマイクロサービスの実装に関する情報を電子書籍「マイクロサービス」としてダウンロードすることもできます。 設計から展開まで。 また、新しいマイクロサービス ソリューション ページもご覧ください。

マイクロサービスの設計、構築、およびデプロイに関する7 部構成のシリーズの最初の記事では、マイクロサービス アーキテクチャ パターンを紹介しました。 マイクロサービスを使用する利点と欠点、そしてマイクロサービスの複雑さにもかかわらず、複雑なアプリケーションにとってマイクロサービスが理想的な選択肢となる理由について説明しました。 これはシリーズの 2 番目の記事であり、API ゲートウェイを使用したマイクロサービスの構築について説明します。

アプリケーションをマイクロサービスのセットとして構築することを選択した場合は、アプリケーションのクライアントがマイクロサービスとどのように対話するかを決定する必要があります。 モノリシック アプリケーションでは、エンドポイント (通常は複製され、負荷分散された) のセットが 1 つだけ存在します。 ただし、マイクロサービス アーキテクチャでは、各マイクロサービスは通常、きめ細かいエンドポイントのセットを公開します。 この記事では、これがクライアントとアプリケーションの通信にどのような影響を与えるかを調べ、 API ゲートウェイを使用するアプローチを提案します。

導入

ショッピング アプリケーション用のネイティブ モバイル クライアントを開発していると想像してください。 特定の製品に関する情報を表示する製品詳細ページを実装する必要がある可能性があります。

たとえば、次の図は、Amazon の Android モバイル アプリケーションで製品の詳細をスクロールしたときに表示される内容を示しています。

携帯電話の画面に表示される、Android 向け Amazon モバイル アプリのインデックス要素

スマートフォンアプリですが、商品詳細ページにはたくさんの情報が表示されます。 たとえば、このページには基本的な製品情報 (名前、説明、価格など) だけでなく、次の情報も表示されます。

  • ショッピングカート内のアイテム数
  • 注文履歴
  • 顧客レビュー
  • 在庫不足警告
  • 配送オプション
  • この製品と一緒によく購入される他の製品、この製品を購入したお客様が購入した他の製品、この製品を購入したお客様が閲覧した他の製品など、さまざまなおすすめ
  • 代替購入オプション

モノリシック アプリケーション アーキテクチャを使用する場合、モバイル クライアントは、アプリケーションに対して単一の REST 呼び出し ( GET api.company.com/productdetails/ productId ) を実行してこのデータを取得します。 ロード バランサは、リクエストを N 個の同一アプリケーション インスタンスの 1 つにルーティングします。 次に、アプリケーションはさまざまなデータベース テーブルを照会し、クライアントに応答を返します。

対照的に、マイクロサービス アーキテクチャを使用する場合、製品詳細ページに表示されるデータは複数のマイクロサービスによって所有されます。 以下に、サンプルの製品詳細ページに表示されるデータを所有する可能性のあるマイクロサービスをいくつか示します。

  • ショッピングカートサービス – ショッピングカート内のアイテム数
  • 注文サービス – 注文履歴
  • カタログサービス – 製品名、画像、価格などの基本的な製品情報
  • レビューサービス – 顧客レビュー
  • 在庫サービス – 在庫不足警告
  • 配送サービス – 配送業者の API から別途取得される配送オプション、期限、費用
  • 推奨サービス – 推奨アイテム

電子商取引アプリのモバイルクライアントには、7つのマイクロサービスのRESTful APIにアクセスする方法が必要です。

モバイル クライアントがこれらのサービスにアクセスする方法を決定する必要があります。 オプションを見てみましょう。

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

理論的には、クライアントは各マイクロサービスに直接リクエストを送信できます。 各マイクロサービスにはパブリック エンドポイント ( https:// serviceName .api.company.name ) があります。 この URL はマイクロサービスのロード バランサにマップされ、利用可能なインスタンス全体にリクエストを分散します。 製品の詳細を取得するには、モバイル クライアントは上記の各サービスにリクエストを送信します。

残念ながら、このオプションには課題と制限があります。 1 つの問題は、クライアントのニーズと各マイクロサービスによって公開されるきめ細かい API との不一致です。 この例のクライアントは 7 つの個別のリクエストを行う必要があります。 より複雑なアプリケーションでは、さらに多くのものを作成する必要があるかもしれません。 たとえば、Amazon では、製品ページのレンダリングに何百ものサービスが関与していることを説明しています。 クライアントは LAN 経由でこれほど多くのリクエストを行うことができますが、パブリック インターネット経由ではおそらく非効率すぎるでしょうし、モバイル ネットワーク経由では明らかに非実用的です。 このアプローチでは、クライアント コードもさらに複雑になります。

クライアントがマイクロサービスを直接呼び出す場合のもう 1 つの問題は、Web フレンドリーではないプロトコルが使用される可能性があることです。 あるサービスでは Thrift バイナリ RPC を使用し、別のサービスでは AMQP メッセージング プロトコルを使用する場合があります。 どちらのプロトコルも、ブラウザやファイアウォールとの相性があまり良くなく、内部で使用するのが最適です。 アプリケーションは、ファイアウォールの外部では HTTP や WebSocket などのプロトコルを使用する必要があります。

このアプローチのもう 1 つの欠点は、マイクロサービスのリファクタリングが困難になることです。 時間が経つにつれて、システムをサービスに分割する方法を変更する必要があるかもしれません。 たとえば、2 つのサービスを統合したり、1 つのサービスを 2 つ以上のサービスに分割したりすることがあります。 ただし、クライアントがサービスと直接通信する場合、この種のリファクタリングを実行するのは非常に困難になる可能性があります。

このような問題があるため、クライアントがマイクロサービスと直接通信することはほとんど意味がありません。

APIゲートウェイの使用

通常、より優れたアプローチは、 API ゲートウェイと呼ばれるものを使用することです。 API ゲートウェイは、システムへの単一のエントリ ポイントとなるサーバーです。 これは、オブジェクト指向設計のFacadeパターンに似ています。 API ゲートウェイは内部システム アーキテクチャをカプセル化し、各クライアントに合わせてカスタマイズされた API を提供します。 認証、監視、負荷分散、キャッシュ、リクエストのシェーピングと管理、静的応答の処理など、他の責任も持つ場合があります。

次の図は、API ゲートウェイがアーキテクチャに一般的にどのように適合するかを示しています。

APIゲートウェイにより、eコマースアプリのモバイルクライアントは7つのマイクロサービスのRESTful APIにアクセスできるようになります。

API ゲートウェイは、リクエストのルーティング、構成、およびプロトコル変換を担当します。 クライアントからのすべてのリクエストは、まず API ゲートウェイを通過します。 次に、リクエストを適切なマイクロサービスにルーティングします。 API ゲートウェイは、多くの場合、複数のマイクロサービスを呼び出して結果を集約することでリクエストを処理します。 HTTP や WebSocket などの Web プロトコルと、内部で使用される Web 非対応のプロトコル間の変換が可能です。

API ゲートウェイは、各クライアントにカスタム API を提供することもできます。通常、モバイル クライアント向けに粗粒度の API を公開します。 たとえば、製品の詳細のシナリオを考えてみましょう。 API ゲートウェイは、モバイル クライアントが 1 回のリクエストですべての製品詳細を取得できるようにするエンドポイント ( /productdetails?productid= xxx ) を提供できます。 API ゲートウェイは、製品情報、推奨事項、レビューなどのさまざまなサービスを呼び出し、結果を組み合わせることでリクエストを処理します。

API ゲートウェイの優れた例としては、 Netflix API ゲートウェイがあります。 Netflix ストリーミング サービスは、テレビ、セットトップ ボックス、スマートフォン、ゲーム システム、タブレットなど、数百種類のデバイスで利用できます。 当初、Netflix はストリーミング サービスに汎用的なAPI を提供しようとしました。 しかし、デバイスの種類が多様でニーズもそれぞれ異なるため、この方法はうまく機能しないことがわかりました。 現在、デバイス固有のアダプター コードを実行して、各デバイスに合わせてカスタマイズされた API を提供する API ゲートウェイを使用しています。 アダプタは通常、平均 6 ~ 7 個のバックエンド サービスを呼び出して各リクエストを処理します。 Netflix API ゲートウェイは 1 日あたり数十億件のリクエストを処理します。

APIゲートウェイの利点と欠点

ご想像のとおり、API ゲートウェイの使用には利点と欠点の両方があります。 API ゲートウェイを使用する主な利点は、アプリケーションの内部構造をカプセル化できることです。 特定のサービスを呼び出す必要はなく、クライアントはゲートウェイと通信するだけです。 API ゲートウェイは、各種類のクライアントに特定の API を提供します。これにより、クライアントとアプリケーション間の往復回数が削減されます。 また、クライアント コードも簡素化されます。

API ゲートウェイにもいくつか欠点があります。 これは、開発、展開、管理が必要な、さらに別の高可用性コンポーネントです。 API ゲートウェイが開発のボトルネックになるリスクもあります。 開発者は、各マイクロサービスのエンドポイントを公開するために API ゲートウェイを更新する必要があります。 API ゲートウェイを更新するプロセスは、できるだけ軽量にすることが重要です。 そうしないと、開発者はゲートウェイを更新するために順番待ちを強いられることになります。 ただし、これらの欠点にもかかわらず、ほとんどの実際のアプリケーションでは API ゲートウェイを使用するのが理にかなっています。

APIゲートウェイの実装

API ゲートウェイを使用する理由とトレードオフについて見てきましたので、次に考慮する必要があるさまざまな設計上の問題について見ていきましょう。

パフォーマンスとスケーラビリティ

Netflix のような規模で事業を展開し、1 日に数十億件のリクエストを処理する必要がある企業はほんの一握りです。 ただし、ほとんどのアプリケーションでは、API ゲートウェイのパフォーマンスとスケーラビリティが非常に重要です。 したがって、非同期の非ブロッキング I/O をサポートするプラットフォーム上に API ゲートウェイを構築するのが理にかなっています。 スケーラブルな API ゲートウェイを実装するために使用できるさまざまなテクノロジーがあります。 JVM では、Netty、Vertx、Spring Reactor、JBoss Undertow などの NIO ベースのフレームワークのいずれかを使用できます。 人気のある非 JVM オプションの 1 つは、Chrome の JavaScript エンジン上に構築されたプラットフォームである Node.js です。 もう 1 つのオプションは、 NGINX Plus を使用することです。 NGINX Plus は、簡単に導入、構成、プログラミングできる、成熟したスケーラブルで高性能な Web サーバーとリバース プロキシを提供します。 NGINX Plus は、認証、アクセス制御、負荷分散要求、キャッシュ応答を管理し、アプリケーション対応のヘルスチェックと監視を提供します。

リアクティブプログラミングモデルの使用

API ゲートウェイは、一部のリクエストを適切なバックエンド サービスにルーティングするだけで処理します。 複数のバックエンド サービスを呼び出し、結果を集約することで、他のリクエストを処理します。 製品詳細リクエストなどの一部のリクエストでは、バックエンド サービスへのリクエストは互いに独立しています。 応答時間を最小限に抑えるために、API ゲートウェイは独立したリクエストを同時に実行する必要があります。 ただし、リクエスト間に依存関係が存在する場合もあります。 API ゲートウェイは、リクエストをバックエンド サービスにルーティングする前に、まず認証サービスを呼び出してリクエストを検証する必要がある場合があります。 同様に、顧客のウィッシュリストにある製品に関する情報を取得するには、API ゲートウェイはまずその情報を含む顧客のプロファイルを取得し、次に各製品の情報を取得する必要があります。 API 構成のもう 1 つの興味深い例は、 Netflix Video Gridです。

従来の非同期コールバック アプローチを使用して API 構成コードを記述すると、すぐにコールバック地獄に陥ってしまいます。 コードが複雑になり、理解しにくくなり、エラーが発生しやすくなります。 はるかに優れたアプローチは、リアクティブ アプローチを使用して宣言型スタイルで API Gateway コードを記述することです。 リアクティブ抽象化の例としては、Scala のFuture 、Java 8 のCompletableFuture 、JavaScript のPromiseなどがあります。 また、もともと Microsoft によって .NET プラットフォーム用に開発されたReactive Extensions (Rx または ReactiveX とも呼ばれます) もあります。 Netflix は、API ゲートウェイで使用するために特別に JVM 用の RxJava を作成しました。 ブラウザと Node.js の両方で実行される JavaScript 用の RxJS もあります。 リアクティブ アプローチを使用すると、シンプルでありながら効率的な API ゲートウェイ コードを記述できます。

サービスの呼び出し

マイクロサービス ベースのアプリケーションは分散システムであり、プロセス間通信メカニズムを使用する必要があります。 プロセス間通信には 2 つのスタイルがあります。 1 つの選択肢は、非同期のメッセージング ベースのメカニズムを使用することです。 一部の実装では、JMS や AMQP などのメッセージ ブローカーが使用されます。 Zeromq などの他のサービスはブローカーレスであり、サービスは直接通信します。 プロセス間通信のもう 1 つのスタイルは、HTTP や Thrift などの同期メカニズムです。 システムでは通常、非同期スタイルと同期スタイルの両方が使用されます。 各スタイルの複数の実装を使用する場合もあります。 したがって、API ゲートウェイはさまざまな通信メカニズムをサポートする必要があります。

サービス検出

API ゲートウェイは、通信する各マイクロサービスの場所 (IP アドレスとポート) を認識する必要があります。 従来のアプリケーションでは、場所をハードワイヤードすることもできますが、最新のクラウドベースのマイクロサービス アプリケーションでは、これは簡単な問題ではありません。 メッセージ ブローカーなどのインフラストラクチャ サービスには通常、静的な場所があり、これは OS 環境変数を介して指定できます。 ただし、アプリケーション サービスの場所を特定するのはそれほど簡単ではありません。 アプリケーション サービスには動的に割り当てられる場所があります。 また、サービスのインスタンスのセットは、自動スケーリングやアップグレードによって動的に変更されます。 したがって、API ゲートウェイは、システム内の他のサービス クライアントと同様に、システムのサービス検出メカニズム (サーバー側検出またはクライアント側検出)を使用する必要があります。 サービスの検出については、後の記事でさらに詳しく説明します。 現時点では、システムがクライアント側検出を使用する場合、API ゲートウェイは、すべてのマイクロサービス インスタンスとその場所のデータベースであるサービス レジストリを照会できる必要があることに注意してください。

部分的な障害の処理

API ゲートウェイを実装する際に対処する必要があるもう 1 つの問題は、部分的な障害の問題です。 この問題は、あるサービスが、応答が遅いか利用できない別のサービスを呼び出すたびに、すべての分散システムで発生します。 API ゲートウェイは、ダウンストリーム サービスを待機して無期限にブロックしてはなりません。 ただし、障害の処理方法は、特定のシナリオと障害が発生しているサービスによって異なります。 たとえば、製品の詳細のシナリオで推奨サービスが応答しない場合、API ゲートウェイは、残りの製品の詳細がユーザーにとってまだ有用であるため、クライアントに返す必要があります。 推奨事項は空にすることも、たとえばハードワイヤードされたトップ 10 リストに置き換えることもできます。 ただし、製品情報サービスが応答しない場合は、API Gateway はクライアントにエラーを返す必要があります。

API ゲートウェイは、利用可能な場合はキャッシュされたデータを返すこともできます。 たとえば、商品の価格は頻繁に変更されないため、価格設定サービスが利用できない場合、API ゲートウェイはキャッシュされた価格設定データを返す可能性があります。 データは API ゲートウェイ自体によってキャッシュされるか、Redis や Memcached などの外部キャッシュに保存されます。 API ゲートウェイは、デフォルト データまたはキャッシュされたデータを返すことで、システム障害がユーザー エクスペリエンスに影響を与えないようにします。

Netflix Hystrixは、リモート サービスを呼び出すコードを作成するための非常に便利なライブラリです。 Hystrix は指定されたしきい値を超える呼び出しをタイムアウトします。 サーキットブレーカーパターンを実装し、クライアントが応答しないサービスを不必要に待機するのを防ぎます。 サービスのエラー率が指定されたしきい値を超えると、Hystrix はサーキットブレーカーをトリップし、指定された期間、すべてのリクエストが直ちに失敗します。 Hystrix を使用すると、キャッシュからの読み取りやデフォルト値の返送など、リクエストが失敗した場合のフォールバック アクションを定義できます。 JVM を使用している場合は、必ず Hystrix の使用を検討してください。 また、JVM 以外の環境で実行している場合は、同等のライブラリを使用する必要があります。

まとめ

ほとんどのマイクロサービス ベースのアプリケーションでは、システムへの単一のエントリ ポイントとして機能する API ゲートウェイを実装するのが理にかなっています。 API ゲートウェイは、リクエストのルーティング、構成、およびプロトコル変換を担当します。 アプリケーションの各クライアントにカスタム API を提供します。API ゲートウェイは、キャッシュされたデータまたはデフォルトのデータを返すことで、バックエンド サービスの障害を隠すこともできます。 シリーズの次の記事では、サービス間の通信について説明します。

編集者– この 7 部構成の記事シリーズはこれで完了です。

  1. マイクロサービス入門
  2. マイクロサービスの構築: API ゲートウェイの使用 (この記事)
  3. マイクロサービスの構築: マイクロサービス アーキテクチャにおけるプロセス間通信
  4. マイクロサービス アーキテクチャにおけるサービス検出
  5. マイクロサービス向けイベント駆動型データ管理
  6. マイクロサービス導入戦略の選択
  7. モノリスをマイクロサービスにリファクタリングする

また、記事の完全なセットと、NGINX Plus を使用したマイクロサービスの実装に関する情報を電子書籍「マイクロサービス」としてダウンロードすることもできます。 設計から展開まで

その他のユースケースの詳細については、3部構成のブログシリーズ「NGINX PlusをAPIゲートウェイとして導入する」をご覧ください。

  • パート 1 では、いくつかのユースケースの詳細な構成手順を示します。
  • パート 2 では、これらのユースケースを拡張し、運用環境でバックエンド API サービスを保護およびセキュリティ保護するために適用できるさまざまな安全対策について説明します。
  • パート 3 では、 NGINX Plus を gRPC サービスの API ゲートウェイとしてデプロイする方法について説明します。

ゲストブロガーの Chris Richardson 氏は、Amazon EC2 向けの初期の Java PaaS (Platform as a Service) であるオリジナルのCloudFoundry.comの創設者です。 彼は現在、アプリケーションの開発および展開方法の改善について組織にコンサルティングを行っています。 彼はまた、 http://microservices.ioでマイクロサービスに関するブログを定期的に書いています。


「このブログ投稿には、入手できなくなった製品やサポートされなくなった製品が参照されている場合があります。 利用可能な F5 NGINX 製品およびソリューションに関する最新情報については、 NGINX 製品ファミリーをご覧ください。 NGINX は現在 F5 の一部です。 以前の NGINX.com リンクはすべて、F5.com の同様の NGINX コンテンツにリダイレクトされます。"