Lambda の同時起動を S3 に置いたロックファイルで制御する
2018-12-07CloudWatch スケージュールで定期的に Lambda を実行する場合、稀に同時実行されてしまう場合があるようです。
それを防ぐために、S3 にロックファイルを作成することで制御してみようと思います。
同時実行数での制御
Lambda には 同時実行数 という設定項目があり、同時実行の予約数を制限することができます。
じゃあ、この値を 1
にすればそれで解決するのでは? と思ったんですが、どうやら 1
に設定した場合でも、関数の実行方法やユースケースによっては同時実行されてしまうケースがあるようです。
参考
S3 にロックファイルを設置して制御する
Lambda の同時実行を防止する方法としては、次のような方法が見つけられます。
- DB に実行状態を保持する
- 実行中であることがわかるファイルを設置する
今回は後者の方法で同時実行を制御してみます。
S3 バケットの作成
ロックファイルを設置するバケットを作成します。今回は lambda-test
というバケットとします。
関数の準備
ランタイムは Python 3.6 とします。
必要な処理としては、ロックファイルの 作成、削除、存在有無を確認 の3 種類です。次のように実装します。
import boto3
BACKET = 'lambda-test'
LOCK_FILE = 'running_lock'
def create_lock_file():
print('create lock file.')
s3 = boto3.resource('s3')
s3obj = s3.Object(BACKET, LOCK_FILE)
s3obj.put(Body='running...')
def delete_lock_file():
print('delete lock file.')
s3 = boto3.resource('s3')
s3obj = s3.Object(BACKET, LOCK_FILE)
s3obj.delete()
def is_running():
s3 = boto3.resource('s3')
try:
s3.ObjectSummary(bucket_name=BACKET, key=LOCK_FILE).load()
except Exception as e:
return False
return True
def lambda_handler(event, context):
if is_running() is True:
print('Process is running.')
else:
create_lock_file()
# do something ...
delete_lock_file()
今回、S3 のバケット内に対象のオブジェクトが存在するかどうかを ObjectSummary()
でチェックしていますが、他にもチェック方法はたくさんあるようです。
とりあえずこれで同時実行は防げそうです。
comments powered by Disqus