Amazon Web Services ブログ

高速、低コストで、より良いAPIの構築 – HTTP APIが利用可能(GA)になりました

本投稿は、Senior Developer Advocate, AWS Serverless Applications のEric Johnsonの寄稿によるものです。

2015年7月、AWSはAmazon API Gatewayを発表しました。これにより、開発者はさまざまな種類のアーキテクチャのフロントに配置して安全でスケーラブルなAPIを迅速に構築できるようになりました。それ以来、API Gatewayチームは顧客向けの新しい機能とサービスを構築し続けています。

API Gateway機能追加タイムライン

図1: API Gateway機能追加タイムライン

2019年初頭、チームは現在のサービスを評価し、API Gatewayの次の姿がどうあるべきか計画を立てました。新しい言語と技術によるプロトタイプを作成し、RESTおよびWebSocket APIの構築から学んだ教訓を適用し、そして、顧客のフィードバックを入念に調べました。その結果として、Amazon API GatewayのHTTP APIが完成しました。これは、より高速で、より低コストで使い易くなるように、ゼロから構築されたサービスです。要するに、HTTP APIはAPIを構築するためのより良いソリューションを提供します。APIを構築していて、HTTP APIが要件に合っている場合は、HTTP APIから始めるのが良いでしょう。

 

より速く

ほとんどのユースケースで、HTTP APIはレイテンシを最大60%削減します。開発者は、最小限のレイテンシと最大限の機能を備えたアプリケーションの構築に苦心しており、アプリケーションプロセスに関係する各サービスがレイテンシを追加する可能性があることを理解しています。

すべてのサービスがレイテンシを追加

図2: すべてのサービスがレイテンシを追加

 

これを念頭に置いて、HTTP APIは、API Gatewayサービスのレイテンシオーバーヘッドを削減するように構築されています。リクエストとレスポンスの両方を足し合わせても、すべてのリクエストの99%(p99)でHTTP APIからの追加レイテンシが10ミリ秒未満になります。

 

より低コストで

Amazonでは、中核となるLeadership Principles の一つとして、Frugality(倹約)があります。私たちは、費用対効果の高い方法で物事を行い、その節約がお客様に還元されることを信じています。新しいテクノロジーが利用可能になり、ほぼ5年間にわたりAPI Gatewayを運用し得た専門知識により、より効率的に実行するためにHTTP APIを構築しました。

REST / HTTP APIの価格比較

図3: REST / HTTP APIの価格比較

us-east-1の価格設定を使用して説明します。図3は、1か月あたりの1億回、5億回、および10億回のリクエストのコスト比較を示しています。全体的に、HTTP APIは、API Gateway REST APIと比較して少なくとも71%低コストです。

 

よりシンプルに

HTTP APIのユーザーインターフェイスでは、API Gatewayチームが、サービス全体の利用体験をより直感的で使い易くなるようにしました。

CORS設定

図4: CORS設定

別の例は、オリジン間リソース共有(CORS)の構成です。CORSは、サーバーへのクロスドメインアクセスを制御することによりセキュリティを提供しますが、理解および構成が困難な場合があります。HTTP APIを使用すると、開発者はシンプルで理解しやすいUIを使用してCORS設定をすばやく構成できます。UI全体でこれと同じアプローチを使用しているため、強力でありながら簡単にAPIを作成できます。

 

新機能

HTTP APIベータがAWS re:Invent 2019で発表されました。JWTオーソライザー、自動デプロイステージ、ルート統合の簡素化などの強力な機能を備えています。現在、HTTP APIは一般的にご利用可能(GA)であり、開発者がAPIをより速く、より低コストで、より良く構築するのに役立つ機能が追加されています。

プライベート統合

HTTP APIにより、開発者はAmazon VPCで保護されたリソースと統合できるようになりました。Amazon Elastic Container Service(ECS)またはAmazon Elastic Kubernetes Service(EKS)を介したコンテナなどのテクノロジーを使用して開発する場合、基盤となるAmazon EC2クラスターはVPC内に存在する必要があります。Elastic Load Balancingを介してこれらのサービスを利用することは可能ですが、開発者はHTTP APIを利用することもできます。

VPCリンク設定

図5: VPCリンク設定

 

プライベート統合を作成するには、VPCリンクが必要です。VPCリンクは、Network Load BalancerNATゲートウェイに使用されるネットワーク機能仮想化プラットフォームであるAWS Hyperplane を利用します。このテクノロジーを利用すると、複数のHTTP APIがVPCへの単一のVPCリンクを使用できます。同様に、複数のREST APIが単一のREST API VPCリンクを使用できます。

プライベート統合設定

図6: プライベート統合設定

 

VPCリンクが存在すると、Network Load Balancer(NLB)Application Load Balancer(ALB)、またはリソース検出サービスであるAWS Cloud Mapを使用して、HTTP APIプライベート統合を設定できます。

 

カスタムドメインの相互互換性

Amazon API Gatewayは、REST APIとHTTP APIでカスタムドメインを共有できるようになりました。この柔軟性により、開発者はアプリケーションを構築しながらREST APIとHTTP APIを組み合わせて使用できます。

カスタムドメインの相互互換性

図7: カスタムドメインの相互互換性

以前は、一貫したドメイン名を必要とするアプリケーションを構築する場合、開発者は1種類のAPIしか使用できませんでした。アプリケーションは多くの場合、RESTでのみ利用可能な機能を必要とするため、REST APIは一般的な選択肢です。今日から、機能要件に基づいてHTTP APIとREST APIの間でこれらのルーティングができます。

リクエスト スロットリング

HTTP APIが、ステージおよびルートレベルで粒度の細かいスロットリング設定を提供するようになりました。APIのスロットリングは、見落とされがちなAPI機能ですが、APIとそのインフラストラクチャの健全性にとって重要です。デフォルトでは、API Gatewayは定常状態のリクエストレートを毎秒10,000リクエスト(rps)、リクエストバーストを5,000に制限します。これらはソフト制限であり、AWS Service Quotasで引き上げることができます。

HTTP APIには、さまざまな目的に使用できるステージの概念があります。アプリケーションは、同じAPI上でdev、beta、およびprodのステージを持つことができます。さらに、下位互換性のために、同じAPIに対して複数の商用ステージを構成できます。各ステージには、10,000 rpsのアカウントレベル設定をオーバーライドするオプションのバーストおよびレート制限設定が可能です。

ステージごとのスロットリング設定

図8: ステージごとのスロットリング設定

スロットリングは、ルートレベルでも設定できます。ルートは、パスとメソッドの組み合わせです。たとえば、ルートパス(/)にGETメソッドを組み合わせてルートを作成します。この記事の執筆時点では、AWS Command Line Interface(CLI)またはAWS SDKを使用してルートレベルのスロッリング設定をする必要があります。$defaultステージの/[ANY] のルートのスロットリングを設定するには、次のCLIコマンドを使用します。

aws apigatewayv2 update-stage \
--api-id <your API ID> \
--stage-name $default \
--route-settings '{"ANY /": {"ThrottlingBurstLimit":1000, "ThrottlingRateLimit":2000}}'

 

ステージ変数

HTTP APIは、ステージ変数の使用をサポートしていますので、動的データをバックエンド統合に渡すか、統合自体を定義することもできます。HTTP APIでステージを定義すると、バックエンド統合への新しいパスが作成されます。次の表は、ステージに対応付けられたドメインを示しています。

ステージ パス
$default www.mydomain.com
dev www.mydomain.com/dev
beta www.mydomain.com/beta

 

 

 

 

devステージのリンクにアクセスすると、devステージ変数がイベントオブジェクトのバックエンド統合に渡されます。バックエンドは、リクエストの処理時にこの情報を使用できます。シークレットを渡すためのベストプラクティスではありませんが、環境固有のエンドポイントや機能スイッチなどのシークレットではないデータを指定するのに役立ちます。

ステージ変数は、バックエンド統合を動的に定義するためにも使用されます。たとえば、統合で本番用とテスト用に1つのAWS Lambda関数を使用する場合、ステージ変数を使用して、以下に示すように適切なLambda関数に動的にルーティングできます。

統合ポイントの動的な選択

図9: 統合ポイントの動的な選択

動的統合を構築する場合、それに応じて権限を更新することも重要です。統合が単一のLambda関数を指す場合、HTTP APIは呼び出し権限を自動的に追加します。ただし、複数の関数を使用する場合は、ロールを手動で作成および管理する必要があります。これを行うには、Lambda関数オプションを呼び出すための[Grant API Gateway permission to invoke your Lambda function]をオフにし、適切な権限を持つカスタムロールを入力します。

統合カスタムロール

図10: 統合カスタムロール

Lambdaペイロードバージョン2.0

HTTP APIは、Lambda関数統合向けに最新のイベントペイロードとレスポンス形式をサポートするようになりました。バージョン2.0のペイロードは、Lambda関数に送信されるイベントオブジェクトの形式を簡素化します。バージョン1.0および2.0のLambda関数に送信されるイベントオブジェクトの比較を次に示します。

バージョン1.0

{
    "version": "1.0",
    "resource": "/Echo",
    "path": "/Echo",
    "httpMethod": "GET",
    "headers": {
        "Content-Length": "0",
        "Host": "0000000000.execute-api.us-east-1.amazonaws.com",
        "User-Agent": "TestClient",
        "X-Amzn-Trace-Id": "Root=1-5e6ab926-933e1530e55773a0709dfaa6",
        "X-Forwarded-For": "1.1.1.1",
        "X-Forwarded-Port": "443",
        "X-Forwarded-Proto": "https",
        "accept": "*/*",
        "accept-encoding": "gzip, deflate, br",
        "cache-control": "no-cache",
        "clientInformation": "private",
        "cookie": "Cookie_2=value; Cookie_3=value; Cookie_4=value"
    },
    "multiValueHeaders": {
        "Content-Length": [
            "0"
        ],
        "Host": [
            "0000000000.execute-api.us-east-1.amazonaws.com"
        ],
        "X-Amzn-Trace-Id": [
            "Root=1-5e6ab926-933e1530e55773a0709dfaa6"
        ],
        "X-Forwarded-For": [
            "1.1.1.1"
        ],
        "X-Forwarded-Port": [
            "443"
        ],
        "X-Forwarded-Proto": [
            "https"
        ],
        "accept": [
            "*/*"
        ],
        "accept-encoding": [
            "gzip, deflate, br"
        ],
        "cache-control": [
            "no-cache"
        ],
        "clientInformation": [
            "public",
            "private"
        ],
        "cookie": [
            "Cookie_2=value; Cookie_3=value; Cookie_4=value"
        ]
    },
    "queryStringParameters": {
        "getValueFor": "newClient"
    },
    "multiValueQueryStringParameters": {
        "getValueFor": [
            "newClient"
        ]
    },
    "requestContext": {
        "accountId": "0000000000",
        "apiId": "0000000000",
        "domainName": "0000000000.execute-api.us-east-1.amazonaws.com",
        "domainPrefix": "0000000000",
        "extendedRequestId": "JTHd9j2EoAMEPEA=",
        "httpMethod": "GET",
        "identity": {
            "accessKey": null,
            "accountId": null,
            "caller": null,
            "cognitoAuthenticationProvider": null,
            "cognitoAuthenticationType": null,
            "cognitoIdentityId": null,
            "cognitoIdentityPoolId": null,
            "principalOrgId": null,
            "sourceIp": "1.1.1.1",
            "user": null,
            "userAgent": "TestClient",
            "userArn": null
        },
        "path": "/Echo",
        "protocol": "HTTP/1.1",
        "requestId": "JTHd9j2EoAMEPEA=",
        "requestTime": "12/Mar/2020:22:35:18 +0000",
        "requestTimeEpoch": 1584052518094,
        "resourceId": null,
        "resourcePath": "/Echo",
        "stage": "$default"
    },
    "pathParameters": null,
    "stageVariables": null,
    "body": null,
    "isBase64Encoded": true
}

 

バージョン2.0

{
    "version": "2.0",
    "routeKey": "ANY /Echo",
    "rawPath": "/Echo",
    "rawQueryString": "getValueFor=newClient",
    "cookies": [
        "Cookie_2=value",
        "Cookie_3=value",
        "Cookie_4=value"
    ],
    "headers": {
        "accept": "*/*",
        "accept-encoding": "gzip, deflate, br",
        "cache-control": "no-cache",
        "clientinformation": "public,private",
        "content-length": "0",
        "host": "0000000000.execute-api.us-east-1.amazonaws.com",
        "user-agent": "TestClient",
        "x-amzn-trace-id": "Root=1-5e6ab967-cfe253ce6f8b90986a678c40",
        "x-forwarded-for": "1.1.1.1",
        "x-forwarded-port": "443",
        "x-forwarded-proto": "https"
    },
    "queryStringParameters": {
        "getValueFor": "newClient"
    },
    "requestContext": {
        "accountId": "0000000000",
        "apiId": "0000000000",
        "domainName": "0000000000.execute-api.us-east-1.amazonaws.com",
        "domainPrefix": "0000000000",
        "http": {
            "method": "GET",
            "path": "/Echo",
            "protocol": "HTTP/1.1",
            "sourceIp": "1.1.1.1",
            "userAgent": "TestClient"
        },
        "requestId": "JTHoQgr2oAMEPMg=",
        "routeId": "47matwk",
        "routeKey": "ANY /Echo",
        "stage": "$default",
        "time": "12/Mar/2020:22:36:23 +0000",
        "timeEpoch": 1584052583903
    },
    "isBase64Encoded": true
}

 

さらに、バージョン2.0では、Lambda関数からのレスポンスオブジェクトの形式の柔軟性が向上しています。以前は、レスポンスは下記のようなフォーマットでした:

{
    "statusCode": 200,
    "body": {
        "Name": "Eric Johnson",
        "TwitterHandle": "@edjgeek"
    },
    "Headers": {
        "Access-Control-Allow-Origin": "https://amazon.com"
    }
}

バージョン2.0を使用する場合、レスポンスはより簡単です。

{
    "Name": "Eric Johnson",
    "TwitterHandle": "@edjgeek"
}

HTTP APIは、レスポンスを受信すると、CORS設定や統合レスポンスコードなどのデータを使用して、欠落しているデータを取り込みます。

デフォルトでは、新しいLambda関数統合はバージョン2.0を使用します。Lambda関数統合の[ Advanced settings]トグルでこれを変更できます。このバージョンは、イベントペイロードとレスポンスペイロードの両方に適用されます。バージョン1.0を選択した場合、古いイベント形式がLambda関数に送信され、完全なレスポンスオブジェクトを返す必要があります。

Lambda統合のAdvanced settings

図11: Lambda統合のAdvanced settings

OpenAPI / Swaggerサポート

HTTP APIは、SwaggerまたはOpenAPI構成ファイルのインポートをサポートするようになりました。これにより、他のAPI GatewayサービスからHTTP APIへの移行が簡単になります。構成ファイルをインポートする場合、HTTP APIはサポートされているすべての機能を実装し、現在サポートされていない機能を報告します。

AWS Serverless Application Model(SAM)のサポート

この記事の執筆時点で、AWS Serverless Application Framework(SAM)は、re:Invent 2019でベータ版でリリースされたほとんどの機能をサポートしています。多くのGA機能のAWS SAMサポートは、2020年3月20日(PST)までにリリースされる予定です。

まとめ

Amazon API Gatewayは、5年間にわたり、開発者が非常にスケーラブルで耐久性のあるアプリケーションプログラミングインターフェイスを構築できるようにしてきました。アプリケーションコード内からマネージドサービスへの承認、スロットリング、データ検証などのタスクの抽象化が可能になりました。Amazon API GatewayのHTTP APIの導入により、開発者はこの強力なサービスをより速く、より低コストで、より良い方法で使用できるようになりました。

 

翻訳はServerless Specialist Solutions Architect 下川 賢介(@_kensh) が担当しました。原文はこちらです。