1
Help us understand the problem. What are the problem?

posted at

updated at

Organization

LambdaFunctionURLsを使って30s越えのリクエストを検証する

まえがき

前回のLambda エフェメラルストレージのアップデートに引き続き、今度はAPIGateway無くてもAPI経由でLambdaが起動できるようになりました。(2022.4.5)
このアップデートによりWebhookの接続先を直接指定できたり、ExpressやFlaskなどのバックエンドframeworkをLambda上に立て、Proxyさせるなどが簡単にできるようになります。
今までもAPIGatewayのProxy機能を利用したり、ALBからLambdaを呼び出すことも可能ではありましたが、よりシンプルにできるにようになりました。

概要

既にServerlessFrameworkでも対応されているのですが、ServerlessFrameworkのブログに、それぞれの役割が載っており、とても分かりやすかったです。

AWS Lambda Function URLs with Serverless Framework 抜粋
image.png

特にMaximum HTTP response timeoutのレスポンス29秒タイムアウトの制限がなく、いとのことで調べてみようと思います。

設定

マネージメントコンソール上の「設定」から「一般設定」に「関数 URL - 新規」の項目が増えており、
こちらから作成すること可能ですが、既にServerless frameworkで対応されていましたので、こちらからデプロイしてみたいと思います。
※「LambdaFunctionsUrls」の機能を使用するにはServerless framework 3.12.0以上を使用する必要があります。

まずはserverless projectを作成します。

# serverless framework version up
$ npm install -g serverless
52 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities
$ serverless --version
Framework Core: 3.12.0
Plugin: 6.2.1
SDK: 4.3.2

$ serverless create --template aws-python3 --path LambdaFunctionUrlTest

✔ Project successfully created in "LambdaFunctionUrlTest" from "aws-python3" template (5s)
cd LambdaFunctionUrlTest

つぎにserverless.ymlを開き、urlsを追加します

serverless.yml
functions:
  hello:
    handler: handler.hello
    url: true # 追加

IAM認証を使用する場合は以下のように修正します

serverlss.yml
    url:
      authorizer: aws_iam

デフォルトではCROSが許可されていません。許可する場合は以下のように修正します

serverlss.yml
    url:
      # Configure CORS in details:
      cors:
        allowCredentials: 
        allowedHeaders: 
        allowedMethods: 
        allowedOrigins: 
        exposedResponseHeaders: 
        maxAge: ….

デプロイをします
デプロイ完了するとendpoint urlが表示されます
(外部公開されてしまうため、ダミーのURLを載せています)

$ serverless deploy

Deploying LambdaFunctionUrlsTest to stage dev (ap-northeast-1)

✔ Service deployed to stack LambdaFunctionUrlsTest-dev (49s)

endpoint: https://xxxxxxxxxxxxxxxxxxxxxxxxx.lambda-url.ap-northeast-1.on.aws/
functions:
  hello: LambdaFunctionUrlsTest-dev-hello (389 B)

マネージメントコンソールから「Lambda」 -> 「一般タブ」 -> 「関数 URL - 新規」から関数URLを確認できます。
image.png

次にAPIをcurlから実行してみます。

curl -X POST https://xxxxxxxxxxxxxxxxxxxxxxxxx.lambda-url.ap-northeast-1.on.aws/test
{
  "message": "Go Serverless v1.0! Your function executed successfully!",
  "input": {
    "version": "2.0",
    "routeKey": "$default",
    "rawPath": "/test",
    "rawQueryString": "",
    "headers": {
      "x-amzn-trace-id": "Root=1-624f6177-1a0368a27e5fa2960e347431",
      "x-forwarded-proto": "https",
      "host": "xxxxxxxxxxxxxxxxxxxxxxxxx.lambda-url.ap-northeast-1.on.aws",
      "x-forwarded-port": "443",
      "x-forwarded-for": "240d:1a:6b8:1000:f440:a4c9:405:953c",
      "accept": "*/*",
      "user-agent": "curl/7.77.0"
    },
    "requestContext": {
      "accountId": "anonymous",
      "apiId": "xxxxxxxxxxxxxxxxxxxxxxxxx",
      "domainName": "xxxxxxxxxxxxxxxxxxxxxxxxx.lambda-url.ap-northeast-1.on.aws",
      "domainPrefix": "jnizrnojzkxxevhncd3cwz5ode0leyol",
     "http": {
       "method": "POST",
       "path": "/test",
       "protocol": "HTTP/1.1",
       "sourceIp": "240d:1a:6b8:1000:f440:a4c9:405:953c",
       "userAgent": "curl/7.77.0"
    },
    "requestId": "823d3d28-62b8-4302-b2e9-5c0ef17385d7",
    "routeKey": "$default",
    "stage": "$default",
    "time": "07/Apr/2022:22:11:03 +0000",
    "timeEpoch": 1649369463756
  },
  "isBase64Encoded": false
}

リクエストのpathはlambdaのパラメータのhttp.path、methodはhttp.methodに割り当たることが確認できました。

検証

handler.pyにsleep(60)を追加し、再度APIを実行してみます。

$ curl -so /dev/nul -w "time_total: %{time_total}\n" https://xxxxxxxxxxxxxxxxxxxxxxxxx.lambda-url.ap-northeast-1.on.aws/test
time_total: 60.530532

29秒を超えてもエラーにならないことが確認できました。

一応sleep(899)に変更し15分ギリギリのリクエストも試してみます。

curl -so /dev/nul -w "time_total: %{time_total}\n" https://xxxxxxxxxxxxxxxxxxxxxxxxx.lambda-url.ap-northeast-1.on.aws/test
time_total: 1737.450523

time_totalがおかしいですが、リクエスト中放置した際にPCがスリープされた時間も含まれているようです。CloudWatch Logs上で確認します。問題なくレスポンスが返ってきています。

image.png

次にLambdaのタイムアウトを超えた場合に、どのようなエラーが返ってくるか確認します。

$ curl -so /dev/nul -w "time_total: %{time_total}\n" https://xxxxxxxxxxxxxxxxxxxxxxxxx.lambda-url.ap-northeast-1.on.aws/test
< HTTP/1.1 502 Bad Gateway
< Date: Sat, 09 Apr 2022 22:44:51 GMT
< Content-Type: application/json
< Content-Length: 21
< Connection: keep-alive
< x-amzn-RequestId: 18337225-5086-4559-ae1b-8c0eabba9b2c
< X-Amzn-Trace-Id: root=1-62520c27-0d32bdbb64658b1d19185c0b;sampled=0
< 
Internal Server Error

status codeは502 Bad Gatewayが返ってくることが確認できました。
メッセージはInternal Server Errorとなっていることに注意です。

まとめ

LambdaFunctionURLsを使うことで、29秒超えのリクエストが追加費用が必要なく簡単にできるようになりました。
いままでAPIGatewayの29秒制限によりに同期的なAPIを非同期に変更した場合など、アーキテクチャを変更せずURLsを発行して一時的に回避するなどができそうです。
次はbackend frameworkを利用してLambda Function URLsの機能を実装してみたいと思います。

Register as a new user and use Qiita more conveniently

  1. You can follow users and tags
  2. you can stock useful information
  3. You can make editorial suggestions for articles
What you can do with signing up
1
Help us understand the problem. What are the problem?