はじめに
TIG DXユニット真野です。2022/04/06にGAになったと発表された、Lambda Function URLsは、AWS Lambdaに直接HTTPSエンドポイントを追加できるというもので、API Gateway(やALB)無しでWeb APIやサイトを構築できると話題になりました。
私も業務でAPI Gateway + Lambdaの組み合わせで稼働している事例があります。非常に安定稼働していますが、この組み合わせだとタイムアウトがAPI GatewayのLambda統合となるため上限が29秒1です。Lambda Function URLs だとAPI Gatewayを経由しない分、Lambda側の15分2になることが嬉しいなと思いました。Web APIでそんなに長時間動かすことって無いだろうと思いますよね。私もそう思っていましたが、Excelファイルアップロードによるバッチ登録や、Excel帳票ダウンロード機能の登場を予見できず目論見は崩れました。
さて、ドキュメントにはLambda Function URLsで個別のタイムアウト制約があるという記載がないため、制約は通常のLambdaと同様に15分が上限であることは自明な気がしますが、せっかくなので検証します。また、GoでJSONを返すWeb APIを構築するときにどういった使い方になるかコードベースで試します。
タイムアウトについて
Lambdaについては「関数URLを有効化」し、cURLやブラウザなどで簡易的に疎通したかったので認証タイプは「NONE」を選択します。関数名は「my-function-url-lambda」とします。
Lambda設定は、ランタイムを「Go 1.x」、ハンドラは適当に「lambda」にしています。Lambdaリソースのタイムアウトは「15分0秒」(最長)にします。
AWS LambdaをGoで動かすためには、ドキュメントにもあるように github.com/aws/aws-lambda-go/lambda
パッケージを利用します。本来は不要ですが、動いているか心配になったので、tickerで1分ごとに標準出力しています。
package main |
デプロイは次のようなMakefileを作って行います(どのようなやり方でも良いと思います)
deploy: |
アクセスするURLは、関数URLという部分に表示されるので、ブラウザでクリックしてLambdaを実行します。
15分待つと Internal Server Error
がブラウザで表示されます。CloudWatch Logsで確認すると、以下のように約900秒(15分)起動したことが分かります。おお..!! 29秒の呪縛から開放されている!!
2022-05-05T00:34:58.224+09:00 START RequestId: 5203b933-276b-4abc-b1cb-8a92ffbfec06 Version: $LATEST |
これで、Lambda Function URLsは実行時間の面でかなり有用だと感じます。
WAFの制御
API Gatewayのようなリッチな制御は行えなくても、セキュリティ要件でWAF設置が必須な場合があります。Lambda Function URLsは2022.5.5時点ではAWS WAFの設定は不可のようです。AWS WAFの設定画面をみても、現状はAPI Gateway, ALB, AppSyncの3つに限られています。
そのためブラウザアクセスを許容したいけど、検証用のエンドポイントは送信元IPを絞りたいとかも現状はできないです。スロットリング、カスタムドメイン名などとともに、これらの要件が必要な場合はAPI Gatewayを利用しましょうということです(InboundのSecurity Groupが設定できれば最高なんですが..)
httpハンドラー対応
AWS Lambdaですが、aws-sdk for Goのお作法にそのまま従うとGoのhttpハンドラーと微妙に使い勝手が異なります。このギャップを吸収するために用いるのが github.com/awslabs/aws-lambda-go-api-proxy
で、API Gatewayリクエストをnet/httpのhandlerの形式に変換してくれ、アプリコードとしてはnet/http、Gin、Echoの形式で実装すれば良くなります。
Lambda Function URLsでも使えるかなと試しました。
package main |
動かしてみます。
$ curl https://ma5pnqdphjf6tvd5xxxxxxxxxxxxxxxx.lambda-url.ap-northeast-1.on.aws/ |
そのまま、、、動きましたね。 API Gateway用のアダプターだと思いましたが、Lambda Function URLsでも動きます。
というのも、ドキュメントを見ると、Lambda Function URLsのリクエスト形式は API Gatewayペイロードフォーマットv2.0と同じ だからです。
The request and response event formats follow the same schema as the Amazon API Gateway payload format version 2.0.
https://docs.aws.amazon.com/lambda/latest/dg/urls-invocation.html#urls-payloads
そのため、現在API Gateway + Lambda構成で開発しているアプリも、アプリコードとしてはそのまま Lambda Function URLsに移植できますし、同様に awslabs/aws-lambda-go-api-proxy
を使っている場合もです。 awslabs/aws-lambda-go-api-proxy
を使っていれば、ECSでもAPI Gateway Lambdaでも Lambda Function URLs でもコアなアプリコードは同じにできるので、非常に安心ですね(ECSはproxyなしで生のHTTPサーバを実行するイメージです)
2022.10.6 追記
AWS lambda’s function URL without API Gateway in Go - Stack Over Flow にあるように、aws-sdk-for-go における apigateway-requestとlambda-function-urlsの構造体が異なるようで、上記の例だとリクエストパラメータはうまく渡るものの、URLのマッピングがすべて /
になってしまうというフィードバックが社内のチームから報告を受けました。そのままadaptorをつかうのではなく、 events.LambdaFunctionURLRequest
に載せ替える一手間がひつようかもしれません。
まとめ
- Lambda Function URLsのタイムアウトは最長15分になり、API Gatewayを経由するときより伸びた
- AWS WAFはつけられないので、ブラウザ経由のアクセス制御は個別に実施する必要がある
- リクエストはAPI Gatewayペイロードフォーマットと同じなので、エコシステムをそのまま流用できる
- 1.2022.4.30時点でAPI Gatewayの統合のタイムアウトは最大29秒で上限緩和不可。 https://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/limits.html ↩
- 2.2022.4.30時点でLambda関数タイムアウトは最大15分で上限緩和不可。https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/gettingstarted-limits.html ↩