LoginSignup
0
0

More than 1 year has passed since last update.

AWS Step Functions のステート定義におけるリトライの書き方

Last updated at Posted at 2021-10-08

指数バックオフアルゴリズム  

SFN(Step Functions) は指数バックオフによるリトライが行われます。
(エクスポネンシャルバックオフ)

SFNにおける式はこんな感じ
リトライ時間 = IntervalSeconds * BackoffRate ^ (Attempts-1)

簡単に言うと、回数を追うごとに待ち時間が長くなっていくようなリトライアルゴリズムです。

いきなりこんな式を見てもピンと来ないので、エラー時に成功するまでn回リトライするようなケースを考えてみます。

よくあるリトライ

  • リトライ間隔 = 2秒 (固定)
  • リトライ回数 = n回

nomal_retry.png

リトライ間隔は常に一定で、n回リトライを行います。

指数バックオフによるリトライ

  • リトライ間隔 = 2秒 (初回のみ)
  • リトライ回数 = n回
  • バックオフレート = 3秒

exp_retry.png

こちらは通常のリトライとは異なり、リトライ回数が増えるごとに、リトライ間隔が増えていきます。

リトライ間隔の計算

  • リトライ間隔 = 2秒 (初回のみ)
  • リトライ回数 = 10回
  • バックオフレート = 3秒

リトライ間隔を計算するワンライナーのPython スクリプト
(python環境があるコンソールに貼り付ければ動きます)

python -c "for s in (lambda i,m,b: (i*b**(n-1) for n in range(1, m+1)))(2,10,3): print(s)"

2 ・・・ 2 * 3^(1-1) = 2 * 3^0 = 2 * 1
6 ・・・ 2 * 3^(2-1) = 2 * 3^1 = 2 * 3
18 ・・・2 * 3^(3-1) = 2 * 3^2 = 2 * 9
54 ・・・2 * 3^(4-1) = 2 * 3^3 = 2 * 27
162 ・・・ 以下省略
486
1458
4374
13122
39366

総リトライ時間[s]

  • リトライ間隔 = 2秒 (初回のみ)
  • リトライ回数 = 10回
  • バックオフレート = 3秒
python -c "print(sum((lambda i,m,b: (i*b**(n-1) for n in range(1, m+1)))(2,10,3)),'[s]')"

59048 [s]

総リトライ時間[h]

  • リトライ間隔 = 2秒 (初回のみ)
  • リトライ回数 = 10回
  • バックオフレート = 3秒
python -c "print(sum((lambda i,m,b: (i*b**(n-1) for n in range(1, m+1)))(2,10,3))/3600,'[h]')"

16.40222222222222 [h]

SFN での書き方

使用するステートマシン

特定のEC2インスタンスを起動するステートマシン
example_sfn

定義(JSON)

{
  "Comment": "Start the EC2 instance.",
  "StartAt": "StartInstances",
  "States": {
    "StartInstance": {
      "Type": "Task",
      "Resource": "arn:aws:states:::aws-sdk:ec2:startInstances",
      "Parameters": {
        "InstanceIds": [
          "i-1234567890abcdef0"
        ]
      },
      "Retry": [
        {
          "ErrorEquals": [
            "States.ALL"
          ],
          "IntervalSeconds": 2,
          "MaxAttempts": 10,
          "BackoffRate": 3
        }
      ],
      "End": true
    }
  }
}

定義(YAML)

※Serverless Framework などでデプロイする時

--- 
Comment: "Start the EC2 instance."
StartAt: "StartInstances"
States: 
  StartInstance: 
    Type: "Task"
    Resource: "arn:aws:states:::aws-sdk:ec2:startInstances"
    Parameters: 
      InstanceIds: 
        - "i-1234567890abcdef0"
    Retry: 
      - ErrorEquals: 
          - "States.ALL"
        IntervalSeconds: "2"
        MaxAttempts: "10"
        BackoffRate: "3"
    End: "true"

ErrorEquals

このエラーに合致したものが、リトライの対象となります。

以下のようなものがデフォルトで用意されているっぽいですね
* States.Runtime
* States.Timeout
* etc...

Lambda なんかだと・・・

ErrorEquals によるエラー判定 (独自実装の例外)

例えばPythonランタイムのLambdaで例外クラスAccountAlreadyExistsException をraise する

class AccountAlreadyExistsException(Exception): pass

def create_account(event, context):
  raise AccountAlreadyExistsException("Account is in use!")

ステートマシンでAccountAlreadyExistsExceptionをキャッチしたい場合、以下のように書く

"ErrorEquals": ["AccountAlreadyExistsException"]

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0