AWSのLambdaを1分よりも短い間隔で呼ぶ
目的
ユニークビジョン株式会社 Advent Calendar 2024のシリーズ2、12/5の記事です。
AWSのLambdaをバッチとして使いたいです。Eventbrige Schedulerでは最小1分単位で呼び出すことが可能ですが、30秒ごととか10秒ごとで設定できません。
ここではStep Functionを使ってこれを実現します。
説明
AWS Lambda
定期処理をするLambdaです。Rubyで書いています。
呼び出される度にカウントアップして返します。
require 'json'
def batch
# 定期的に実行した処理
end
def lambda_handler(event:, context:)
count = event['count'] || 0
batch()
{ count: count + 1 }
end
Step Function
以下のようにStepFunctionを組みます。
StepFunctionでは1分以内で回したい数だけ呼び出します。
例えば20秒なら2回呼び出してそれぞれ20秒待つ。
例えば10秒なら5回呼び出してそれぞれ10秒待つ。
詳細は以下のようになります。ここでは20秒に1回呼ばれる想定をしています。
{
"QueryLanguage": "JSONata",
"Comment": "A description of my state machine",
"StartAt": "Lambda Invoke",
"States": {
"Lambda Invoke": {
"Type": "Task",
"Resource": "arn:aws:states:::lambda:invoke",
"Output": "{% $states.result.Payload %}",
"Arguments": {
"FunctionName": "arn:aws:lambda:us-east-1:xxxxxxxxxx:function:target_function:$LATEST",
"Payload": "{% $states.input %}"
},
"Retry": [
{
"ErrorEquals": [
"Lambda.ServiceException",
"Lambda.AWSLambdaException",
"Lambda.SdkClientException",
"Lambda.TooManyRequestsException"
],
"IntervalSeconds": 1,
"MaxAttempts": 3,
"BackoffRate": 2,
"JitterStrategy": "FULL"
}
],
"Next": "Choice"
},
"Choice": {
"Type": "Choice",
"Choices": [
{
"Next": "成功",
"Condition": "{% $states.input.count >= 2 %}"
}
],
"Default": "Wait"
},
"成功": {
"Type": "Succeed"
},
"Wait": {
"Type": "Wait",
"Seconds": 20,
"Next": "Lambda Invoke"
}
}
}
Eventbridge Scheduler
1分ごとに呼び出すcron式は以下の通りです。これ以上短くすることができません。
上記のStepFunctionを呼び出すように設定しておきます。
分 | 時間 | 日 | 月 | 曜日 | 年 |
---|---|---|---|---|---|
*/1 | * | * | * | * | ? |
まとめ
Step Functionを利用することで1分よりも短いLambdaの呼び出しが可能になりました。
これをAWS Lambdaだけで実現しようとするとプログラム内でsleepすることになりコストが高くなります。StepFunctionは状態遷移で課金されますが20秒設定で8回動きます。
また月4000回の無料枠があり、それ以上はUSD 0.025/1,000 回の状態遷移で課金されます。
計算結果は以下の通りです。
(8 * 60 * 24 * 30 - 4000) / 1000 / 40 = 8.54
Lambdaの料金も含めてもおそらく10$もいかないと思います。
これがLambdaで起動し続けるとClaudeに聞いたら15分動かし続けると0.2$とのことで
0.2 * 4 * 24 * 30 = 576
10秒ごとでも15$だったのでだいぶお安いです。
Discussion