はじめに
Amazon API Gateway (REST API) には「エッジ最適化」と「リージョナル」の2つのエンドポイントタイプがあります。CDKでAPI Gatewayを構築する際、endpoint_typesを明示的に指定しないとデフォルトでエッジ最適化が選択されます。
本記事では、両者の違いと、CDKでリージョナルに切り替える際の注意点をまとめます。特に、エッジ最適化ではAPI Gatewayの統合タイムアウトを29秒以上に延長できないという制約について詳しく触れます。
API Gatewayのリージョナルとエッジ最適化の違い
エッジ最適化エンドポイント
- API Gatewayのデフォルトのエンドポイントタイプ
- 内部的にCloudFrontディストリビューションが自動で前段に配置される
- クライアントからのリクエストは最寄りのCloudFront POP(Point of Presence)を経由してAPIリージョンにルーティングされる
- グローバルに分散したクライアントからのアクセスに適している
- TLS接続の終端がエッジロケーションで行われるため、遠方のクライアントとの接続レイテンシが低減される
リージョナルエンドポイント
- CloudFrontを前段に配置せず、APIがデプロイされたリージョンで直接リクエストを処理する
- 同一リージョンまたは近隣のクライアントからのアクセスに最適
- 独自のCloudFrontディストリビューションやCDNを組み合わせたい場合に柔軟性が高い
- キャッシュ戦略やWAFの設定を自分でコントロールできる
比較表
| 項目 | エッジ最適化 | リージョナル |
|---|---|---|
| CloudFront | 自動で配置(API Gateway管理) | なし(必要なら自分で構成) |
| デフォルト | はい | いいえ |
| 統合タイムアウト上限 | 29秒(延長不可) | 延長可能(クォータ引き上げ申請) |
| 同一リージョンからのレイテンシ | エッジ経由のオーバーヘッドあり | 低い |
| グローバルアクセス | 有利 | 自前でCloudFrontを構成すれば同等 |
統合タイムアウトに関する重要な注意点
2024年6月にAWSはAPI Gatewayの統合タイムアウト上限を29秒から引き上げ可能にしました。
しかし、この引き上げはリージョナルAPIとプライベートAPIのみが対象です。
エッジ最適化APIでは、Service Quotasでクォータ引き上げリクエストが承認されても、内部のCloudFrontのオリジンリクエストタイムアウト(デフォルト30秒)が壁となり、実質的に29秒を超えるタイムアウトは機能しません。
Service Quotasコンソールにも以下のように記載されています:
This limit can only be increased for Regional and private APIs
つまり、Lambdaの処理に30秒以上かかる可能性がある場合は、リージョナルエンドポイントを選択する必要があります。
この落とし穴については、以下の記事で詳しく解説されています
CDKでリージョナルエンドポイントを指定してデプロイする
デフォルトの挙動
CDKのRestApiコンストラクトでは、endpoint_typesを省略するとデフォルトでEDGE(エッジ最適化)になります。
# endpoint_typesを指定しない場合 → エッジ最適化
api = _apigateway.RestApi(
self,
"MyAPI",
rest_api_name="MyAPI",
deploy_options=_apigateway.StageOptions(
stage_name="stage",
),
)
リージョナルを明示的に指定する
endpoint_typesパラメータにEndpointType.REGIONALを指定します。
api = _apigateway.RestApi(
self,
"MyAPI",
rest_api_name="MyAPI",
endpoint_types=[_apigateway.EndpointType.REGIONAL], # リージョナルを明示
deploy_options=_apigateway.StageOptions(
stage_name="stage",
),
)
Lambda関数のタイムアウトも合わせて調整する
API Gatewayの統合タイムアウトを延長する場合、バックエンドのLambda関数のタイムアウトも合わせて調整が必要です。
例えば、Athenaクエリの完了待機など処理時間が長くなるLambdaには、個別にタイムアウトを設定します。
def deploy_lambda_function(self, name, layers, role, extra_scripts=None, timeout_seconds=30):
"""Lambda関数デプロイメソッド
:param name: 関数名
:param layers: Lambdaレイヤー
:param extra_scripts: 追加でバンドルするスクリプトファイル名のリスト
:param timeout_seconds: タイムアウト秒数(デフォルト30秒)
"""
lambdaScript = _lambda.Function(
self,
'lambda' + name,
handler='script' + name + '.lambda_handler',
function_name='lambda' + name,
runtime=_lambda.Runtime.PYTHON_3_10,
code=_lambda.Code.from_asset(asset_path),
role=role,
timeout=Duration.seconds(timeout_seconds), # 個別に指定可能
memory_size=1024,
layers=layers,
)
return lambdaScript
# 通常のLambda(デフォルト30秒)
lambdaGetData = self.deploy_lambda_function("GetData", common_layers, self.lambda_role)
# 長時間処理が必要なLambda(300秒)
lambdaGetHistory = self.deploy_lambda_function(
"GetHistory", common_layers, self.lambda_role,
timeout_seconds=300
)
上記はLambda関数デプロイをCDKでメソッド化しています。
同じようなLambda関数を大量に生成する場合、このようにメソッド化しておくと便利です。
タイムアウトの関係は以下を満たすように設定します:
API Gateway統合タイムアウト > Lambda関数タイムアウト > アプリケーション内タイムアウト
途中でエッジ最適化からリージョナルに切り替える場合の注意
既存のAPI Gatewayをエッジ最適化からリージョナルに変更する場合、いくつかの注意点があります。
1. エンドポイントURLの変更
エンドポイントタイプを変更すると、API GatewayのDNS解決先が変わります。カスタムドメインを使用していない場合、クライアント側でURLの切り替えが必要になる可能性があります。
digコマンドで確認すると、エッジ最適化ではCloudFrontのIPアドレスが返りますが、リージョナルではリージョン内のIPアドレスが返ります。
2. カスタムドメインについて
API自体のエンドポイントタイプ(RestApiのendpoint_types)を変更しても、カスタムドメインのベースパスマッピングはデプロイステージに紐づいているため、マッピング自体は自動的に追従します。
ただし、カスタムドメイン自体にもエンドポイントタイプ(EDGE/REGIONAL)の設定があります。カスタムドメインのエンドポイントタイプも合わせて変更したい場合は、以下の対応が必要です:
- リージョナル用のACM証明書(APIと同じリージョンで発行したもの)の準備
- DNSレコードの更新(
distributionDomainNameからregionalDomainNameへの切り替え) - 旧エンドポイント設定の削除
詳細は公式ドキュメント:Migrate a custom domain name to a different API endpoint typeを参照してください。
3. CloudFrontの二重構成に注意
エッジ最適化APIの前段に独自のCloudFrontを配置していた場合、CloudFrontが二重になっている状態です。リージョナルに切り替えることで、この二重構成が解消され、キャッシュやタイムアウトの制御がシンプルになります。
CDKではデフォルトでAPI Gatewayをデプロイするとエッジ最適化になり、CloudFrontが自動で配置されてしまいます。
なので、エッジ最適化→リージョナルに変更する場合は、必要に応じて前段にCloudFrontを配置してください。
4. CDKでの変更はインプレース更新
CDKでendpoint_typesを変更してデプロイすると、CloudFormationはAPI Gatewayリソースをインプレースで更新します(API IDは変わりません)。エッジ最適化からリージョナルへの切り替えでは、内部のCloudFrontディストリビューションが外れるため、DNS解決先が変わります。DNSのTTLによっては、一部のクライアントが一時的に旧IPへ接続を試みる可能性があるため、影響の少ない時間帯でのデプロイを推奨します。
特にダウンタイムが厳しいシステムにおいては、API Gatewayエンドポイントタイプの変更は慎重に実施しましょう。
5. API Gatewayの統合タイムアウト設定
リージョナルに切り替えた後、統合タイムアウトを29秒以上に設定したい場合は、以下の手順が必要です:
- Service Quotasコンソールから「Amazon API Gateway」の統合タイムアウトのクォータ引き上げをリクエスト
- 承認後、各統合(Integration)のタイムアウト値を変更
CDKではLambdaIntegrationのタイムアウトを以下のように指定できます:
resource.add_method(
"GET",
_apigateway.LambdaIntegration(
lambda_func,
timeout=Duration.seconds(120) # 統合タイムアウトを120秒に
),
)
まとめ
- CDKで
RestApiを作成する際、endpoint_typesを省略するとエッジ最適化がデフォルトで選択される - エッジ最適化APIでは内部的にCloudFrontが配置されるため、統合タイムアウトを29秒以上に延長できない
- 30秒以上の処理時間が必要なAPIがある場合は、リージョナルエンドポイントを選択する
- 途中で切り替える場合は、エンドポイントURL変更やカスタムドメインの再設定に注意が必要
- タイムアウトは「API Gateway統合タイムアウト > Lambda関数タイムアウト > アプリ内タイムアウト」の関係を維持する
エンドポイントタイプの選択は後から変更可能ですが、影響範囲が広いため、プロジェクト初期段階でユースケースに合った選択をすることが重要です。特に日本国内のクライアントが中心であれば、リージョナルエンドポイントの方がレイテンシ・柔軟性の両面で有利なケースが多いでしょう。
