【API Gateway】タイムアウトのステータスコード
API Gateway の timeout のステータスコードを確認してみました。
なぜ。。。?
最近 API Gateway のバイナリメディア周りで躓きました(汗)
で、「私、API Gateway を雰囲気で使っているなー」と気がつきまして、これを気に色々動作確認とかやってみようと思いました。
今回はそのシリーズ ① です(笑)
(本当はバイナリメディアに1回目から切り込みたいのですが、今はそれをブログにできるほどノウハウがないので記事書きながら学ぶ!)
ではでは、、
今回は何がしたいの?
Lambda と連携した API Gateway にタイムアウトを発生させて、その時のステータスコードを確認します。
まず、↑の場合ですが、タイムアウトが2パターンあります。
lambda がタイムアウトしたパターンとAPI Gateway がタイムアウトしたパターンです。
ちなみに API Gateway のステータスコード自体はここ ↓ に書いてあるのですが、確信をもつにはやっぱり叩いてみるしかないですね!
前提
CDKv2で環境作って叩こうと思います
環境用意
実際に動作確認したサンプルコードはこちら↓
https://github.com/sisi100/cdk_api_gateway_study
構成はこんな感じです。
構成の出力には https://github.com/pistazie/cdk-dia を使わせて頂いてます!感謝!
さてさて、API GatewayにタイムアウトするLambdaと長時間sleepするLambdaを設定して、それぞれにcurlコマンドで動作確認しようと!という目論見です!
で、Lambdaの中身は具体的にはこんな感じ↓
import os
from time import sleep
SLEEP_TIME = int(os.getenv("SLEEP_TIME", 0))
def handler(event, context):
sleep(SLEEP_TIME)
return {"statusCode": 200}
環境変数からsleepする時間を取得して、その時間sleepした後に200を返します。
次にインフラはこんな感じ↓
import pathlib
from aws_cdk import Duration, aws_apigateway, aws_lambda
from constructs import Construct
class TimeoutStudyApi(Construct):
def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None:
super().__init__(scope, construct_id)
api = aws_apigateway.RestApi(self, "Api")
# API Gatewayが処置待ち中にlambdaがTimeoutした場合の調査
timeout_lambda = aws_lambda.Function(
self, "TimeoutLambda", **self.__build_lambda_param(timeout=1, sleep_time=5)
) # 処理中にtimeoutするlambda
api.root.add_resource("lambda-timeout").add_method(
**self.__build_api_method_param(timeout_lambda, 10)
) # lambdaのtimeout以上待ってくれるgateway
# Lambdaの処理中にAPI Gatewayがtimeoutするときの調査
long_processing_lambda = aws_lambda.Function(
self, "LongProcessingLambda", **self.__build_lambda_param(timeout=10, sleep_time=9)
) # 9秒寝ているlambda
api.root.add_resource("gateway-timeout").add_method(
**self.__build_api_method_param(long_processing_lambda)
) # 1秒でtimeoutするgateway
def __build_api_method_param(self, _lambda, api_gateway_timeout=1):
return dict(
http_method="GET",
integration=aws_apigateway.LambdaIntegration(_lambda, timeout=Duration.seconds(api_gateway_timeout)),
)
def __build_lambda_param(self, timeout=5, sleep_time=0):
return dict(
code=aws_lambda.Code.from_asset(str(pathlib.Path(__file__).resolve().parent.joinpath("runtime"))),
runtime=aws_lambda.Runtime.PYTHON_3_9,
handler="index.handler",
timeout=Duration.seconds(timeout),
environment={"SLEEP_TIME": str(sleep_time)},
)
コメントの通りですが、
lambda-timeout
のパスにLambdaのタイムアウトが1秒!しかし5秒寝るLambdaを設定します(つまりLambdaがタイムアウトする)
gateway-timeout
のパスにはLambdaが9秒寝るけれども、API Gatewayのタイムアウトが1秒に設定します(つまりLambdaの処理中にGatewayがタイムアウトする)
そしてこんな感じでデプロイします
$ cdk deploy ApiGatewayStudyStack/TimeoutStudyApi
今回は下記のようなパスが吐き出されたので、早速curlで叩いてみましょう。
https://x64rrg23uj.execute-api.ap-northeast-1.amazonaws.com/prod/
まずはAPI Gatewayのタイムアウト!
$ curl -Gi https://x64rrg23uj.execute-api.ap-northeast-1.amazonaws.com/prod/gateway-timeout
HTTP/2 504
...
{"message": "Endpoint request timed out"}
ステータスコードは504 Gateway Timeout
でした!
次にLambdaのタイムアウト!
% curl -Gi https://x64rrg23uj.execute-api.ap-northeast-1.amazonaws.com/prod/lambda-timeout (git)-[main]:INS
HTTP/2 502
...
{"message": "Internal server error"}
ステータスコードは502 Bad Gateway
でした!
なるほど、、、Lambdaのタイムアウトは良しなに拾ってくれない。ということですね!
最後にデストロイを叩いておしまいです!
$ cdk destroy ApiGatewayStudyStack/TimeoutStudyApi
以上、最後までお読みいただきありがとうございました!
まとめ
API GatewayはLambdaのタイムアウトを拾ってくれない。
Lambdaがタイムアウトすると502 Bad Gateway
を返す。