[アップデート] AWS Step Functions の再試行オプションで最大遅延時間とジッターが使えるようになりました

2023.09.10

いわさです。

先日、AWS Step Functions のエラーハンドリングが強化されたというアナウンスがありました。

Step Functions のドキュメントも更新されており、確認したところ再試行オプションとして新しく 2 つのオプションが追加されています。
本日は情報を整理し、実際にリトライの挙動を観察してみましたので紹介します。

AWS Step Functions の再試行処理

Step Functions ではタスクなどで「エラー処理」を設定することが可能で、様々なリトライ戦略を簡単に導入することが出来ます。
今回のアップデートでは従来のオプションに加えて次の「最大遅延」と「ジッターを追加」が追加されています。

Step Functins のリトライは AWS ではおなじみの Exponential Backoff 方式でリトライされます。
インターバルとバックオフレートが既存の設定で存在していますがこちらの設定にしたがってリトライを繰り返すごとにインターバル時間が増えていくものです。

最大遅延時間を設定することで、指数関数的に増えて続けるインターバル時間の上限を設定することが出来ます。
ジッターを設定することでインターバル時間にランダム性を持たせることが出来ます。特にこのジッターを勝手に実装してくれるのは中々嬉しいのではないでしょうか。

同時アクセス数の増加が原因でエラーが発生した場合に、同じ再試行ルールでリトライしてしまうとリトライ時にまたアクセスが集中してしまう可能性があります。
リトライ時間にランダム性を追加することでリトライのタイミングを分散させる戦略がジッターです。

なお、AWS SDK にも再試行処理が実装されていますが、AWS SDK では実は既にジッターが実装されていたりします。

やってみる

では再試行が発生するステートマシンを作成して実験して観察してみましょう。
次のように適当なエラーをスローする Lambda 関数を作成しました。

export const handler = async (event) => {

  throw new Error('hogehoge');

  const response = {
    statusCode: 200,
    body: JSON.stringify('Hello from Lambda!'),
  };
  return response;
};

そして、上記 Lambda 関数を Invoke するだけのステートマシンを作成しました。

追加オプションなし

まずは従来どおり追加オプションなしでまず試してみましょう。
インターバルに 2 秒、最大試行回数は 3 回、バックオフレートは 2.0 です。

これによって、最初のリトライは 2 秒後、次のリトライはそこから 4 秒後、3 回目のリトライはそこからさらに 8 秒後に実施され、それで最大試行回数に到達して終了するはずです。

実行してみました。

お、期待どおりじゃないですか。良いですね。

最大遅延

30 秒の最大遅延オプションを追加してみました。設定可能な最大値は 31,622,401 秒です。

ここで気になるのは 「30 秒の上限を超えるとどうなる?リトライしなくなるのか?」 という点です。
そこで、最大試行回数は多めにして、中断されるのか継続されるのか判断出来るようにしてみました。

実行結果は次のようになりました。

インターバル 16 秒のリトライ時の次からは毎回 30 秒間隔でリトライされるようになってますね。

最大遅延時間の上限到達が理由で中断されることはないということがわかりました。
なので、この場合は 100 回までリトライされそうですね。最大試行回数の代わりとして使うものではなく組み合わせて使うものだろうか。

Express ワークフローの場合はステートマシンの実行時間をかなり気にするところなので、ある程度再試行時間の上限を決めちゃいたいシーンは多そうです。

ちなみにこの値を指定しない場合、Step Functions は再試行間の待機時間を制限しません。
ドキュメントによると最大試行回数の上限が 99,999,999 回なので、その上限までバックオフレートに従って増え続けます。

ジッター

続いてジッターも確認してみましょう。
こちらはチェックを ON にするだけです。

公式ドキュメントによると、再試行ごとにランダム化されますが、0 秒から 再試行ごとの通常の再試行時間が上限となるようです。
例えば上記設定であれば、初回は 0 ~ 2 秒、次は 0 ~ 4 秒、その次は 0 ~ 8 秒の間でランダムに再試行されます。

では試してみましょう。

おお、期待どおりかなり分散されてますね。

コード

今回はマネジメントコンソールで試してみましたが、ASL 定義上だと次のようになっています。

{
  "Comment": "A description of my state machine",
  "StartAt": "Lambda Invoke",
  "States": {
    "Lambda Invoke": {
      "Type": "Task",
      "Resource": "arn:aws:states:::lambda:invoke",
      "OutputPath": "$.Payload",
      "Parameters": {
        "Payload.$": "$",
        "FunctionName": "arn:aws:lambda:ap-northeast-1:123456789012:function:hoge0910lambda:$LATEST"
      },
      "Retry": [
        {
          "ErrorEquals": [
            "States.ALL"
          ],
          "IntervalSeconds": 2,
          "MaxAttempts": 10,
          "JitterStrategy": "FULL",
          "BackoffRate": 2,
          "MaxDelaySeconds": 30
        }
      ],
      "End": true
    }
  }
}

さいごに

本日は AWS Step Functions の再試行オプションで最大遅延時間とジッターが使えるようになっていたので試してみました。

ちなみに、AWS Summit Tokyo 2023 でマイクロサービスのエラー処理に関するセッションがあったのですが、その際にもこのあたりの必要性には触れられていてとても参考になったのを覚えてます。残念ながら動画もう非公開のようですが。

Step Functions でステートマシンを構築する際に「なんだこの見慣れない設定は」という方の参考になればと思って書いてましたが、普通によく使いそうじゃないですかねこのオプション。