はじめに
こんにちは。技術4課の保田(ほだ)です。こんにちは。
あれ?「こんにちは。」って二回言ってる?まるでこれは Lambda の自動リトライ機能のようですね?? というわけで本日はそういう話です。
要約
非同期呼び出しの「最大イベント経過時間」と「最大再試行回数」、片方しか変更しないときでも両方定義しないと反映されないよ
maximumEventAge: 21600 maximumRetryAttempts: 2
背景
AWS Lambda には同期実行と非同期実行があります。 非同期実行は Lambda が関数の戻り値を待たないパターンです。 例えば、 S3 にファイルが作成されたイベントを検知して Lambda が起動する、とか SNS Topic に配信されたメッセージをサブスクライブしている Lmabda が動く、みたいなパターンです。
詳細は公式ドキュメントをご参照下さい。
非同期実行の Lambda でエラーハンドリングを考えたとき、考慮すべき設定項目として「最大イベント経過時間」と「最大再試行回数」があります。(本当はデッドレターキューという、最後までうまくいかなかった場合の処理経路を定義できる機能もありますが、文脈上省かせていただきます。)
非同期実行ではキューにイベントが入ると Lambda はそのキューからイベントを取り出して関数を実行します。 このとき関数の同時実行数の制限に引っかかってしまった(スロットリングした)場合は一旦イベントをキューに戻してちゃんと実行できるようになるまで一定期間待機してくれます。 この待ち時間の上限が「最大イベント経過時間」で、デフォルトでは6時間です。
また、実行中に関数がエラーを返却したとき、 Lambda はデフォルトで2回再実行してくれます。この回数が「最大再試行回数」です。
で、この二つの設定値ですが、2019年11月の終わりごろという比較的最近になって変更できるようになっています。
AWS Lambda が非同期呼び出しの最大イベント経過時間と最大再試行回数をサポートするようになりました
私事ですがなぜかずっと昔から変更できる仕様だったと思い込んでいました。 マネジメントコンソール上ではとても簡単にそれぞれの値が変更できるようになっています。 最大イベント経過時間は 60秒から6時間 の間、最大再試行回数が 0回から2回 の間で調節できます。
さて、では皆さん大好き Serverless Framework でこれを設定してみましょう。
本題
実は 2020年8月3日にリリースされた v1.78.0 からサポートされ始めたようです。 serverless.yml を書くときによく見ることになるであろう Serverless.yml Reference には 2020年9月14日現在記載されていないので注意が必要です。
GitHub 上の ドキュメント にはちゃんと反映されていますので、こちらを参考にしましょう。
関数ごとに制御したい値のなので、各関数のセクションに以下の値をそれぞれ定義します。最大イベント経過時間 maximumEventAge
は秒数で定義され、デフォルトの6時間だと 21600 となります。数がデケェ。
maximumEventAge: 21600 maximumRetryAttempts: 2
ただし、ちょっと罠っぽい点がありまして、例えば「再実行回数だけ変更したいから maximumRetryAttempts
だけ定義しよう」(私です)と 片方だけ定義してデプロイしても、何も起きないです 。
片方だけ変更したい場合でも必ず両方明示的に書きましょう 。
オチはありません。
それだけの話ですが、新しめの機能で試してみたらうまく反映されず、「諦めるか~」となると悲しいのでブログとして共有させていただきました。
補足?
ちなみに両方を明示的に定義してデプロイしたあと片方をコメントアウトして再度デプロイした場合について考えてみます。
この場合はコメントアウトした値の方は変更されず、コメントアウトしていない方の値は変更してもちゃんと反映されます。
そしてコメントアウトしていない方の値を次に変更してもう一度デプロイすると、両方の値がデフォルト値に戻ってしまいます。
コメントアウトする / しないの変更も含めて両方の値に差分がないと値が反映されないっぽい仕様であることを考えれば納得ですが、気づかないと「???????」となってしまいそうですね。