/ #API Gateway #cdk 

【API Gateway】タイムアウトのステータスコード

もくじ

API Gateway の timeout のステータスコードを確認してみました。

なぜ。。。?

最近 API Gateway のバイナリメディア周りで躓きました(汗)

で、「私、API Gateway を雰囲気で使っているなー」と気がつきまして、これを気に色々動作確認とかやってみようと思いました。

今回はそのシリーズ ① です(笑)

(本当はバイナリメディアに1回目から切り込みたいのですが、今はそれをブログにできるほどノウハウがないので記事書きながら学ぶ!)

ではでは、、

今回は何がしたいの?

Lambda と連携した API Gateway にタイムアウトを発生させて、その時のステータスコードを確認します。

まず、↑の場合ですが、タイムアウトが2パターンあります。

lambda がタイムアウトしたパターンAPI Gateway がタイムアウトしたパターンです。

ちなみに API Gateway のステータスコード自体はここ ↓ に書いてあるのですが、確信をもつにはやっぱり叩いてみるしかないですね!

https://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/supported-gateway-response-types.html

前提

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を返す。

今回のリポジトリはこちら

https://github.com/sisi100/cdk_api_gateway_study

Author

Sisii

インフラが好きなエンジニアぶってるなにか