API Gatewayのタイムアウトに対処する

2024/11/20に公開

やりたかったこと

  • APIGatewayとLambdaを用いてエンドポイントを叩いた際にLambda関数を実行し画像処理を行い,レスポンスを返したかった
  • しかし、Lambdaのタイムアウト設定が3s~900s(15m)で設定できるのに対してAPIGatewayのタイムアウトは最大で29sまでしか設定できない。
  • 画像のサイズが大きくなってくるとAPIGatewayがタイムアウトしてしまうという問題に直面していた。
  • そこでStep Functionsを組み合わせることで先にレスポンスを返し、裏ではLambdaが処理を実行し続けるような非同期の形にする方針をとった。

https://dev.classmethod.jp/articles/apigateway-stepfunctions-asynchronous/

構築方法は以下を参考にして実装しました
https://qiita.com/handy-dd18/items/a4740e4c68d749922d24

API Gatewayのテストメソッドを使用して、実行テストを行いました。
以下のパラメータを指定します。

{
  "stateMachineArn": "arn:aws:states:us-west-2:123456789:stateMachine:test”,
  "input": "{ \”name\”: \"$input.params(‘name’)\”, \"body\": $util.escapeJavaScript($input.body) }"
}

また、Goで実装したため、関数ハンドラは以下を参考にして実装しました。

https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/golang-handler.html

package main

import (
	"context"
	"fmt"
	"github.com/aws/aws-lambda-go/lambda"
)

type MyEvent struct {
	Name string `json:"name"`
}

func HandleRequest(ctx context.Context, event *MyEvent) (*string, error) {
	if event == nil {
		return nil, fmt.Errorf("received nil event")
	}
	message := fmt.Sprintf("Hello %s!", event.Name)
	return &message, nil
}

func main() {
	lambda.Start(HandleRequest)
}

このように実装し、APIGatewayでテストをすると、Step Functionsが動くことが確認できると思います。
Lambda関数が実行され、成功すると、レスポンスが返ってくるのが確認できると思います。

しかし、この後にも問題が発生しました。Step Functionsのデータサイズ上限は256KBなので、大きな画像データを返すことができなかったのです。

https://qiita.com/yuken/items/dd9ec4d0a47ad643a096

The state/task 'lambda' returned a result with a size exceeding the maximum number of bytes service limit.


どのように対処したかというと、s3にデータを格納し、そのurlを返す、という実装に変更しました。Go側でAWSSDK経由でs3にアップロード、取得を行い、そのurlを返すことで画像を返すことに成功しました。

https://qiita.com/Takayuki_Nakano/items/f7997b5533d5e98b5b6c

Discussion