AWS Lambdaウォームスタートではグローバル変数が共有される

AWS-Lambdaウォームスタートでは-グローバル領域の-命令が実行されないアイキャッチ

AWS LambdaでAPIを作成したときのことです。ハンドラー外で実装したグローバル変数初期化が実行されずにハマったことがあるので注意喚起を込めて記事にします。

目次

先に結論 Lambdaのグローバル変数は呼び出し間で共有される

  • Lambda関数のグローバル領域(ハンドラー外)に動的な処理は書かない方が良い
  • グローバル領域(ハンドラー外)に何か書くときは以下の点を意識する
    • コールドスタート時はグローバル領域(ハンドラー外)の処理が実行される
    • ウォームスタート時はグローバル領域(ハンドラー外)の処理が実行されない

図にするとこんな感じです。

lambdaのウォームスタートとコールドスタートの挙動の違い

発生した事象 呼出しごとにグローバル変数の初期化が実行されない

以下、もちろんハンドラー関数はlambda_handlerです。

import datetime
dt_now = datetime.datetime.now()


def lambda_handler(event, context):
    return {"dt_now":str(dt_now)}

何回も実行してもdt_nowが更新されませんでした。

ウォームスタート時、Lambda関数を何回実行してもグローバル変数でセットしている現在時刻が更新されない

原因 Lambdaはウォームスタート時にグローバル変数は呼び出し間で共有される仕様である

ウォームスタート時はpyファイル冒頭の処理(グローバル変数初期化)は実行されないようでした。ハンドラー関数からの実行です。

一方でコールドスタート時はpyファイル冒頭のグローバル変数の初期化から実行されるようでした。

lambdaのウォームスタートとコールドスタートの挙動の違い

AWS公式ブログをあさっていたら当事象に対する見解が記載されていました。

当事象は呼び出し間でのグローバル変数のリークと呼ばれるようです。

グローバル変数は、呼び出しごとのコンテキスト固有の情報の格納先としては避けるべきです。1回の呼び出しの間だけ使用され、次の呼び出しでリセットされるグローバル変数を持つ関数の場合は、ハンドラのローカルな変数スコープを使用してください。これにより、呼び出し間でのグローバル変数のリークを防ぐだけでなく、静的初期化のパフォーマンスも向上します。

https://aws.amazon.com/jp/blogs/news/operating-lambda-performance-optimization-part-2/

教訓と対策

AWSブログに記載されている通り、

グローバル変数は、呼び出しごとのコンテキスト固有の情報の格納先としては避けるべき

です。

それによりグローバル変数リークによるバグの抑制に加え、初期化(コールドスタート)のパフォーマンス向上につながるようです。

ランキング

ランキングに参加しています。クリックして応援いただけると嬉しいです。
にほんブログ村 IT技術ブログ クラウドコンピューティングへ
にほんブログ村
AWSランキング
AWSランキング

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
目次