先日の "JAWS-UG 千葉支部 Vol.5 ~秋のAWS Lambda & API Gateway 祭り!!~" の懇親会で飛び入りLTさせて頂いた内容です。
これまでのLambda を cron 的に使う試み
■AWS Lambdaをcronの代わりに使ってみるよ
S3のEventから起動され、S3のobjectを作成する事でループする手法
もしLambdaからS3にobjectを入れるのに失敗すると、そこでループが途切れてしまう、また頻度は最長でも1分に1回程度
■Azure Job Scheduler + AWS Lambdaで夢のサーバレス定期ジョブを実現する
自分もこの記事を見て、同じ形で長らく使っていました(無料枠でも1時間に1度なら使用できます)。
どうにかしてAWSのサービスのみで実装できないだろうか?
■ 実験1 Dead Dead Queue DeDeDeDe-Destruction パティーン
最初はSQSを2つ作って Dead Queue として指定したらお互いにメッセージを投げ合えないだろうか?と考えてみました。
→ 一度も受信されなかったメッセージは Dead Queue には入らなかった...
#LambdaでSQSを読み捨てするのもアリかと思ったけど、失敗した時に途切れるのでボツ
■ 実験2 Return to myself パティーン
Alarm を設定しているうちに、ふと SQS は SNS Topic を Subscribe できる事に気付いたので、以下の手順で定期的に SNS Alarm を鳴らす事に成功した。
- SQS のキューを作成する(その際にメッセージ保持期間を繰り返したい時間-5分とかに設定する)
- SQSにメッセージがない状態(ApproximateNumberOfMessagesVisible<=0)が一定時間(5分)続いたら、CloudWatch Alarm から SNS Topic へアラートを送る
- 上記 SNS Topic には 上記の SQS Queue を Subscribe させておく
これによって、メッセージがないというアラートがSQSメッセージとして同じキューに届き、メッセージ保持期間を過ぎたらまたアラートが飛んでメッセージが届く、というループ状態になる。
これを使用して、SNS Topic に Lambda function を指定しておくと、一定時間に1度 Lambda function が実行される状態となる。
SNS から SQS へのアラートが失敗する事はリスクとして存在するが、例えば1時間以上0が続いたらアラートが鳴るような設定を追加する事で、何か問題が発生しても1時間でリトライがかかるようになる。
ただ、SQS の ApproximateNumberOfMessagesVisible メトリックはメッセージが入れられてから数字が検知されるまでに間があるので、メッセージ保持期間は10分未満には設定しない方がよいと思われる。
まとめ
汎用のスケジューラ( REST の URL や AWS の API コールが行えるもの)があるといいのですが!