皆さんはグローバル変数って使ったことはありますか?
どのメソッドからも参照することができて非常に便利なのですが、多用しすぎるとコードが読み辛くなったり、デメリットも様々です。
そんなグローバル変数ですが、
AWSLambdaで使用する場合は必ず知っておく必要がある仕様があります。
その落とし穴について記していきます。
目次
● Lambda関数の作成
● グローバル変数を含んだコードに編集
● Lambdaのコールド/ホットスタート
● 初回実行時はバグに気付きにくい
Lambda関数の作成
最初にLambda関数を作成しましょう。
イメージ図はLambda関数をPython3.12で作成した直後です。
この状態で動作させると、「Hello from Lambda!」とレスポンスが返ってきます。
グローバル変数を含んだコードに編集
初期状態では「Hello from Lambda!」という文字列がレスポンスされるプログラムとなっていますが、
「マッシュルームさん」「こんにちは!」という文字列が配列でレスポンスされるコードに変更します。
helloArray = [] # グローバル変数定義
def lambda_handler(event, context):
# グローバル変数に挨拶をセット
helloArray.append("マッシュルームさん")
helloArray.append("こんにちは!")
return {
'statusCode': 200,
'body': helloArray
}
実行します。
正しく動作しました。
もう一回挨拶がほしくなったので、再度実行します。
いっぱい返ってきました。
ちょっと目の錯覚かもしれないので、もう一度
もっといっぱい返ってきました。
Lambdaのコールド/ホットスタート
なぜ実行するたびに挨拶が増えるのか。
それはLambdaのコールドスタート/ホットスタートが関係しています。
▼コールドスタート
空いているサーバにLambda関数を割り当て、そのサーバ上で処理を実行する
▼ホットスタート
既にLambda関数が割り当てられているサーバ上で処理を実行する
Lmabdaは初回起動時は必ずコールドスタートで実行されます。
二回目以降はホットスタートで実行されます。
ただし、しばらくLambdaが実行されていない時間が続くとサーバのインスタンスが破棄され、次回実行時は再びコールドスタートとなります。
「二回目以降はホットスタートで実行される」
すなわち、直前に実行したリソースが初期化されずにそのまま使い回されるということです。
(AWSLambda 公式FAQ)
https://aws.amazon.com/jp/lambda/faqs/
Q: AWS Lambda は関数インスタンスを再利用しますか?
パフォーマンス向上のため、AWS Lambda は新しく関数のインスタンスを作成するのではなく、関数のインスタンスを保持してその後のリクエストに対応することがあります。Lambda で関数インスタンスを再利用する方法の詳細については、「ドキュメント」を参照してください。ただし、常にインスタンスを再利用するわけではありません。
常にインスタンスを再利用するわけではありませんと書かれていますが、感覚上99.9%の確率で再利用されます。
初回実行時はバグに気付きにくい
この問題を気付きにくくさせている最大の要因は、
コールドスタート時は期待通りに動作してしまうという点でしょう。
一度だけ動作を確認し、「ちゃんと動いているな!」と納得してしまうと、落とし穴にハマってしまいます。
グローバル変数は必ず初期化してから使用しましょう。
helloArray = [] # グローバル変数定義
def lambda_handler(event, context):
# グローバル変数初期化helloArray = []
# グローバル変数に挨拶をセット
helloArray.append("マッシュルームさん")
helloArray.append("こんにちは!")
return {
'statusCode': 200,
'body': helloArray
}
本番環境では目の錯覚や笑い話では済みませんので!