API Gatewayを使用したバッチリクエスト処理
April 27, 2023
バッチリクエスト処理は、APIのパフォーマンスを向上させるためにWeb開発で使用される強力な技術です。これにより、開発者は複数のAPIリクエストを単一のHTTPリクエスト/レスポンスサイクルにまとめることができます。言い換えると、クライアントからの単一のAPIリクエストを、バックエンドサーバーへの複数のAPIリクエストに変換し、レスポンスを集約してクライアントに返すことができます。これにより、クライアントとサーバー間のラウンドトリップ回数を大幅に削減できます。
この記事では、Apache APISIXでバッチリクエスト処理を実装する方法を探り、その利点を活かせるユースケースをいくつか見ていきます。
これは、マイクロサービスアーキテクチャで広く適用されているAPI Compositionパターンに似ています。
なぜバッチリクエスト処理を使うのか?
クライアントがサーバーに複数のAPIリクエストを送信する場合、各リクエストには個別のHTTPリクエスト/レスポンスサイクルが必要です。これにより、レイテンシが増加し、パフォーマンスが低下し、サーバーの負荷が増加する可能性があります。複数のリクエストを単一のバッチリクエストにまとめることで、HTTPリクエスト/レスポンスサイクルの数を減らし、パフォーマンスを向上させ、レイテンシを削減できます。
バッチリクエスト処理は、以下のようなシナリオで特に有用です:
- データベースから複数のレコードを取得する場合
- データベース内の複数のレコードを更新する場合
- タスクを完了するために複数のAPIリクエストを実行する場合
バッチリクエスト処理の実世界の例
例1:
ユーザーのフィードを表示するソーシャルメディアアプリケーションがあるとします。このフィードには、ユーザーの友達やフォローしているページからの投稿が含まれます。このフィードを表示するためには、以下のような複数のAPIリクエストを実行する必要があります:
- ユーザーの友達とフォローしているページのリストを取得する。
- 各友達やページについて、最近の投稿を取得する。
従来のアプローチでは、これらのAPIリクエストを個別に実行します。まず、ユーザーの友達のリストを取得し、次に各友達の最近の投稿を取得します。これにより、特にユーザーが多くの友達を持ち、多くのページをフォローしている場合、レイテンシが増加する可能性があります。
例2:
別の例として、ユーザーが閲覧する製品のリストを表示するモバイルアプリケーションがあるとします。このリストを表示するためには、リモートサーバーから製品データを取得するために複数のAPIリクエストを実行する必要があります:
- 製品IDのリストを取得する。
- 各製品IDについて、製品の詳細(名前、説明、画像など)を取得する。
例3:
カンファレンス管理のWebアプリケーションを想像してください。システム内に複数のスピーカーがおり、単一のWebページにスピーカーのセッションと関連するトピックを表示したいとします。バックエンドのConference APIサービスには、この情報を公開するための2つの異なるエンドポイント/speaker/{speakerId}/sessions
と/speaker/{speakerId}/topics
があります。単一のスピーカーに属するセッションとトピックを表示するために、フロントエンドアプリから2つのリクエストを送信することは理想的ではありません。代わりに、次のセクションで説明するように、API Gatewayを使用してこれらのリクエストを単一のHTTPリクエストにまとめることができます。
Apache APISIX API Gatewayを使用したバッチリクエスト処理
APISIXでバッチリクエスト処理を実装するには、batch-requestsプラグインを使用できます。このプラグインを使用すると、単一のHTTP POST
リクエストのペイロードに複数のAPIリクエストを定義できます。各リクエストには、独自のHTTPメソッド、URLパス、ヘッダーセット、ペイロードを指定できます。例3(Conference APIリクエスト)のcurlリクエストコマンドを以下に示します:
curl -i http://{API_GATEWAY_HOST_ADDRESS}/speaker -X POST -d \
'{
"pipeline": [
{
"method": "GET",
"path": "/speaker/1/topics"
},
{
"method": "GET",
"path": "/speaker/1/sessions"
}
]
}'
APISIXがバッチリクエストを受信すると、batch-requestsプラグインがペイロードを解析し、バッチ内の各リクエストを並列に実行します。プラグインはまた、各リクエストからのレスポンスを集約し、単一のHTTPレスポンスとしてクライアントに返します。次のデモセクションで、この手順を段階的に学びましょう。
バッチリクエストプラグインのデモ
batch-requestsプラグインを使用する前に、Apache APISIXをインストールする必要があります。
前提条件
- Dockerを使用して、コンテナ化されたetcdとAPISIXをインストールします。
- curlを使用して、APISIX Admin APIにリクエストを送信します。Postmanなどの簡単なツールを使用してAPIとやり取りすることもできます。
APISIXは以下のクイックスタートスクリプトで簡単にインストールして起動できます:
curl -sL <https://run.api7.ai/apisix/quickstart> | sh
バックエンドサービス(アップストリーム)の設定
リクエストをルーティングするConference APIのバックエンドサービスを設定する必要があります。これは、Apache APISIXのAdmin APIを通じてアップストリームサーバーを追加することで行えます。
curl http://127.0.0.1:9180/apisix/admin/upstreams/1 -X PUT -d '
{
"name": "Conferences API upstream",
"desc": "Register Conferences API as the upstream",
"type": "roundrobin",
"scheme": "https",
"nodes": {
"conferenceapi.azurewebsites.net:443": 1
}
}'
バッチ処理APIのルートを作成
/speaker
へのリクエストをインターセプトし、[public-api](https://apisix.apache.org/docs/apisix/plugins/public-api/)
プラグインを使用してバッチ処理のためのパブリック仮想エンドポイントを公開する新しいルートを作成する必要があります。
curl http://127.0.0.1:9180/apisix/admin/routes/a -X PUT -d '
{
"uri": "/speaker",
"plugins": {
"public-api": {
"uri": "/apisix/batch-requests"
}
}
}'
スピーカーのトピックとセッションエンドポイントのルートを作成
次に、スピーカーのトピックとセッションエンドポイント(/speaker/*/topics
と/speaker/*/topics
パスにマッチ)のための別のルートを作成します。これにより、API Gatewayがバッチリクエストから抽出した個別のリクエストが、対応するConference APIエンドポイントに転送され、既存のアップストリームサービスを参照します。
curl http://127.0.0.1:9180/apisix/admin/routes/b -X PUT -d '
{
"methods": ["GET"],
"uris": ["/speaker/*/topics","/speaker/*/sessions"],
"plugins": {
"proxy-rewrite":{
"host":"conferenceapi.azurewebsites.net"
}
},
"upstream_id":"1"
}'
ここで、別のproxy-rewriteプラグインを使用し、Conference APIのホストアドレスを暗黙的に指定していることに気づくかもしれません。そうしないと、API GatewayがDNS変換を行い、Conference APIにIPアドレスでリクエストを送信する可能性があります。
バッチリクエスト処理のテスト
以下は、APISIXでbatch-requestsプラグインを使用する例です:
curl -i http://127.0.0.1:9080/speaker -X POST -d \
'{
"pipeline": [
{
"method": "GET",
"path": "/speaker/1/topics"
},
{
"method": "GET",
"path": "/speaker/1/sessions"
}
]
}'
この例では、/speaker
エンドポイントに対してルートが定義されており、batch-requestsプラグインを介してバッチリクエスト処理をサポートしています。プラグインは、トピックとセッションを取得するためにIDでスピーカーレコードを取得する2つのリクエストのセットで構成されています。このコマンドを実行すると、API Gatewayからマージされたレスポンスが返されます:
[
{
"body":"{\r\n \"collection\": {\r\n \"version\": \"1.0\",\r\n \"links\": [],\r\n \"items\": [\r\n {\r\n \"href\": \"https://conferenceapi.azurewebsites.net/topic/8\",\r\n \"data\": [\r\n {\r\n \"name\": \"Title\",\r\n \"value\": \"Microsoft\"\r\n }\r\n ],\r\n \"links\": [\r\n {\r\n \"rel\": \"http://tavis.net/rels/sessions\",\r\n \"href\": \"https://conferenceapi.azurewebsites.net/topic/8/sessions\"\r\n }\r\n ]\r\n },\r\n {\r\n \"href\": \"https://conferenceapi.azurewebsites.net/topic/10\",\r\n \"data\": [\r\n {\r\n \"name\": \"Title\",\r\n \"value\": \"Mobile\"\r\n }\r\n ],\r\n \"links\": [\r\n {\r\n \"rel\": \"http://tavis.net/rels/sessions\",\r\n \"href\": \"https://conferenceapi.azurewebsites.net/topic/10/sessions\"\r\n }\r\n ]\r\n }\r\n ],\r\n \"queries\": [],\r\n \"template\": {\r\n \"data\": []\r\n }\r\n }\r\n}",
"status":200,
"headers":{
"Expires":"-1",
"Connection":"keep-alive",
"Pragma":"no-cache",
"Content-Length":"953",
"Server":"APISIX/3.2.0",
"Content-Type":"application/vnd.collection+json",
"X-AspNet-Version":"4.0.30319",
"Cache-Control":"no-cache",
"X-Powered-By":"ASP.NET"
},
"reason":"OK"
},
{
"body":"{\r\n \"collection\": {\r\n \"version\": \"1.0\",\r\n \"links\": [],\r\n \"items\": [\r\n {\r\n \"href\": \"https://conferenceapi.azurewebsites.net/session/206\",\r\n \"data\": [\r\n {\r\n \"name\": \"Title\",\r\n \"value\": \"\\r\\n\\t\\t\\tjQuery Mobile and ASP.NET MVC\\r\\n\\t\\t\"\r\n },\r\n {\r\n \"name\": \"Timeslot\",\r\n \"value\": \"05 December 2013 09:00 - 10:00\"\r\n },\r\n {\r\n \"name\": \"Speaker\",\r\n \"value\": \"Scott Allen\"\r\n }\r\n ],\r\n \"links\": [\r\n {\r\n \"rel\": \"http://tavis.net/rels/speaker\",\r\n \"href\": \"https://conferenceapi.azurewebsites.net/speaker/16\"\r\n },\r\n {\r\n \"rel\": \"http://tavis.net/rels/topics\",\r\n \"href\": \"https://conferenceapi.azurewebsites.net/session/206/topics\"\r\n }\r\n ]\r\n }\r\n ],\r\n \"queries\": [],\r\n \"template\": {\r\n \"data\": []\r\n }\r\n }\r\n}",
"status":200,
"headers":{
"Expires":"-1",
"Connection":"keep-alive",
"Pragma":"no-cache",
"Content-Length":"961",
"Server":"APISIX/3.2.0",
"Content-Type":"application/vnd.collection+json",
"X-AspNet-Version":"4.0.30319",
"Cache-Control":"no-cache",
"X-Powered-By":"ASP.NET"
},
"reason":"OK"
}
]
バッチリクエストの最大サイズはAPI Gatewayによって制限されています。現在の制限とリクエストタイムアウトの設定については、API Gatewayのドキュメントを確認してください。
まとめ
- API Gatewayを使用したバッチリクエスト処理は、APIのパフォーマンスを向上させるための有用な技術です。
- Apache APISIXは、開発者が簡単にバッチリクエスト処理を実装できる**
batch-requests
**プラグインを提供しています。
次のステップ
API Gatewayを使用すると、レスポンスデータに何らかのカスタム集約を提供することも可能です。serverless-functionプラグインを使用して、バックエンドサービスからのレスポンスをカスタムコードで実行し、マージしてAPIコンシューマーに異なる構造で返すことができます。