Kinesis DataStreamをトリガーに起動するLambdaは、「1秒毎に起動するとは限らない」という話
はじめに
サーバーレス開発部の藤井元貴です。
AWS公式の形で考えるサーバーレス設計は良いものですね。
このうち、Lambdaの同時実行数を制御したい等の理由で、Kinesis DataStream
を使う事は多々あります。
Kinesis DataStreamの設定にシャード数があり、「Lambdaの同時実行数の上限」はこのシャード数と一致します。
そして、Lambdaは1秒毎にシャードを監視しており、Kinesis DataStreamにデータがあれば起動して処理します。
このとき、下記が気になったので試してみました。
- Lambdaの実行時間が1秒より短いとき、Lambdaが終了したらすぐ起動するの? それとも1秒待つの?
- Lambdaの実行時間が1秒より長いとき、Lambdaの終了を待たず1秒後に起動するの? それともLambdaの終了まで待つの?
以下、やってみた
おすすめの方
- AWS SAMを使いたい
- AWS SAMでKinesis DataStreamを定義したい
- Kinesis DataStreamにAWS CLIでデータを送りたい
- Kinesis DataStreamとLambdaについて、Lambdaの起動タイミングが知りたい
環境
項目 | バージョン |
---|---|
macOS | Mojave 10.14.4 |
AWS CLI | aws-cli/1.16.89 Python/3.6.1 Darwin/17.7.0 botocore/1.12.79 |
AWS SAM CLI | 0.10.0 |
Python | 3.6 |
作成する
プロジェクトフォルダの作成
sam init --runtime python3.6 --name TryKinesisLambda
Lambda関数とtemplateファイル
app.pyとtemplate.yamlは下記です。
実験内容によって、Lambdaのtime.sleep()
の秒数を変更します。
requirements.txt
は空っぽにします。
S3バケットの作成
コード等を格納するためのS3バケットを作成します。作成済みの場合は飛ばします。
aws s3 mb s3://cm-fujii.genki-sam-test-bucket
build
下記でビルドします。
sam build
package
コード一式をS3バケットにアップロードします。
sam package \ --output-template-file packaged.yaml \ --s3-bucket cm-fujii.genki-sam-test-bucket
deploy
デプロイします。
sam deploy \ --template-file packaged.yaml \ --stack-name TryKinesisLambda \ --capabilities CAPABILITY_IAM
動作確認
Kinesis DataStreamにデータを送信する準備
Kinesis DataStreamに送信するデータを作成します。
$ touch test-data.json
中身は下記です。全部で14個のデータを送信します。
{ "Records": [ { "Data": "aaa", "PartitionKey": "pk-1" }, { "Data": "bbb", "PartitionKey": "pk-2" }, { "Data": "ccc", "PartitionKey": "pk-1" }, { "Data": "ddd", "PartitionKey": "pk-2" }, { "Data": "eee", "PartitionKey": "pk-1" }, { "Data": "fff", "PartitionKey": "pk-2" }, { "Data": "ggg", "PartitionKey": "pk-1" }, { "Data": "hhh", "PartitionKey": "pk-2" }, { "Data": "iii", "PartitionKey": "pk-1" }, { "Data": "jjj", "PartitionKey": "pk-2" }, { "Data": "kkk", "PartitionKey": "pk-1" }, { "Data": "lll", "PartitionKey": "pk-2" }, { "Data": "mmm", "PartitionKey": "pk-1" }, { "Data": "nnn", "PartitionKey": "pk-2" } ], "StreamName": "test-stream" }
実際にデータを送信する場合は、下記コマンドを実行します。
aws kinesis put-records --cli-input-json file://test-data.json
データ数は14個のため、Lambdaは5回起動するはずです。
Lambda実行時間:50ミリ秒のとき
Lambda | time | Duration |
---|---|---|
1回目 | 2019-05-22T08:09:40.763796 | 50.67 ms |
2回目 | 2019-05-22T08:09:40.853314 | 50.70 ms |
3回目 | 2019-05-22T08:09:40.929184 | 50.61 ms |
4回目 | 2019-05-22T08:09:41.004926 | 50.72 ms |
5回目 | 2019-05-22T08:09:41.083495 | 50.74 ms |
- Kinesis DataStreamにあるデータが無くなるまで、Lambdaは起動し続ける
Lambda実行時間:5秒のとき
Lambda | time | Duration |
---|---|---|
1回目 | 2019-05-22T08:25:09.246640 | 5005.61 ms |
2回目 | 2019-05-22T08:25:14.279199 | 5005.60 ms |
3回目 | 2019-05-22T08:25:19.309775 | 5004.83 ms |
4回目 | 2019-05-22T08:25:24.337513 | 5005.57 ms |
5回目 | 2019-05-22T08:25:29.367969 | 5005.57 ms |
- Lambdaは5秒毎に起動する
実験終了
Kinesis DataStreamをそのままにしておくと随時課金されるため、作成したStackを削除します。
aws cloudformation delete-stack --stack-name TryKinesisLambda
まとめ
下記動作と理解しました。(間違ってたら教えてください!)
- Lambda関数が起動していないとき、Kinesis DataStreamに対して「データある?」と聞く
- Kinesis DataStreamにデータがある場合は、Lambda関数は起動する
- Kinesis DataStreamにデータがない場合は、何もしない(1秒後にまた聞く)
- Lambda関数が終了したあと、
- Kinesis DataStreamにデータがまだあるとき、Lambda関数は続けて起動する
- Kinesis DataStreamにデータがないとき、Lambda関数は起動しない
ざっくり図にすると下記ですね。
- AWS公式ドキュメントをよく見ると、「なるほど」といった感想です。
Lambda は、レコードの Kinesis ストリームにある各シャードを 1 秒あたり 1 回の基本レートでポーリングします。利用可能なレコードが増えると、Lambda は設定されている最大バッチサイズより小さいバッチを受け取るまでバッチの処理を維持します。
冒頭の振り返り
- Lambdaの実行時間が1秒より短いとき、Lambdaが終了したらすぐ起動するの? それとも1秒待つの?
- → Lambdaが終了したらすぐ起動する
- Lambdaの実行時間が1秒より長いとき、Lambdaの終了を待たず1秒後に起動するの? それともLambdaの終了まで待つの?
- → Lambdaの終了まで待つ
スッキリしました。