

翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。

# Step Functions のベストプラクティス
<a name="sfn-best-practices"></a>

**ステートの管理とデータの変換**  
[変数を使用したステート間のデータ受け渡し](workflow-variables.md)と [JSONata を使用したデータ変換](transforming-data.md)について説明します。

以下のトピックは、Step Functions ワークフローの管理と最適化に役立つベストプラクティスです。

**Topics**
+ [Express ワークフローを使用したコストの最適化](#cost-opt-exp-workflows)
+ [Step Functions でのステートマシンとアクティビティのタグ付け](#concepts-tagging)
+ [タイムアウトを使用して Step Functions ワークフローの実行のスタックを回避する](#sfn-stuck-execution)
+ [Step Functions で大きなペイロードを渡す代わりに Amazon S3 の ARN を使用する](#avoid-exec-failures)
+ [Step Functions で履歴クォータに到達しないように新しい実行を開始する](#bp-history-limit)
+ [Lambda サービスの一時的な例外の処理](#bp-lambda-serviceexception)
+ [アクティビティタスクのポーリング時のレイテンシーを回避する](#bp-activity-pollers)
+ [CloudWatch Logs リソースポリシーのサイズ制限の回避](#bp-cwl)

## Express ワークフローを使用したコストの最適化
<a name="cost-opt-exp-workflows"></a>

Step Functions は、ステートマシンの構築に使用するワークフロータイプに基づいて、標準ワークフローと Express ワークフローの価格を決定します。サーバーレスワークフローのコストを最適化するには、以下の推奨事項のどちらかまたは両方に従ってください。

Standard または Express ワークフロータイプの選択が請求にどのように影響するかについては、「[AWS Step Functions の料金](https://aws.amazon.com/step-functions/pricing/)」を参照してください。

### Standard ワークフローでの Express ワークフローのネスト
<a name="cost-opt-exp-wflow-nesting"></a>

Step Functions は一定の期間とステップ数のあるワークフローを実行します。ワークフローによっては、短時間待機した後に実行を完了する場合があります。また、長時間実行されるワークフローとイベントレートの高いワークフローの両方を組み合わせなければならない場合があります。Step Functions を使用すると、小さくて単純な複数のワークフローから大規模で複雑なワークフローを構築できます。

例えば、注文処理ワークフローを構築する場合、同一ではないすべてのアクションを標準ワークフローに含めることができます。これには、人が操作する注文の承認や支払いの処理などのアクションが含まれる場合があります。その後、支払い通知の送信や商品在庫の更新など、一連の独立したアクションを Express ワークフローにまとめることができます。この Express ワークフローは標準ワークフロー内にネストできます。この例で、標準ワークフローは*親ステートマシン*と呼ばれます。ネストされた Express ワークフローは*子ステートマシン*と呼ばれます。

### Standard ワークフローから Express ワークフローへの移行
<a name="cost-opt-exp-wflow-conversion"></a>

次の要件を満たしている場合は、Standard ワークフローから Express ワークフローへの移行を検討する必要があります。
+ ワークフローは 5 分以内に実行を完了する必要があります。
+ ワークフローが *at-least-once* 実行モデルに準拠している (各ステップの 1 回以上の実行が許可される) 必要があります。
+ ワークフローは `.waitForTaskToken` または `.sync` サービス統合パターンを使用**しません**。

**重要**  
Express ワークフローは Amazon CloudWatch Logs を使用して実行履歴を記録します。CloudWatch Logs を使用すると、追加のコストが発生します。

**コンソールを使用して Standard ワークフローを Express ワークフローに移行するには**

1. [Step Functions コンソール](https://console.aws.amazon.com/states/home?region=us-east-1#/)を開きます。

1. **[ステートマシン]** ページで、標準タイプのステートマシンを選択して開きます。
**ヒント**  
**[すべてのタイプ]** ドロップダウンリストから **[標準]** を選択すると、ステートマシンのリストがフィルタリングされ、標準ワークフローのみが表示されます。

1. **[新規にコピー]** を選択します。

   [デザインモード](workflow-studio.md#wfs-interface-design-mode) で Workflow Studio が開き、選択したステートマシンのワークフローが表示されます。

1. (オプション) ワークフローのデザインを更新します。

1. ステートマシンの名前を指定します。これを行うには、**MyStateMachine** のデフォルトステートマシン名の横にある編集アイコンを選択します。次に、**[ステートマシンの設定]** の **[ステートマシン名]** ボックスに名前を指定します。

1. (オプション) **[ステートマシンの設定]** で、ステートマシンのタイプや実行ロールなど、他のワークフロー設定を指定します。

   **[タイプ]** では必ず **[Express]** を選択してください。**[ステートマシンの設定]** のその他のデフォルト設定をすべてそのまま使用します。
**注記**  
以前に [AWS CDK](https://docs.aws.amazon.com/cdk/api/latest/docs/aws-stepfunctions-readme.html)または で定義した標準ワークフローを移行する場合はAWS SAM、 の値`Type`と`Resource`名前を変更する必要があります。

1. **[ロールの作成を確認]** ダイアログボックスで、**[確認]** を選択して続行します。

   **[ロールの設定を表示]** を選択して **[ステートマシンの設定]** に戻ることもできます。
**注記**  
Step Functions が作成した IAM ロールを削除すると、Step Functions を後で再作成することはできません。同様に、ロールを変更すると (例えば、IAM ポリシーのプリンシパルから Step Functions を削除するなど)、後で Step Functions でそれを元の設定に復元することはできません。

ワークフローのコスト最適化を管理する際のベストプラクティスとガイドラインの詳細については、[「費用対効果の高いAWS Step Functionsワークフローの構築](https://aws.amazon.com/blogs/compute/building-cost-effective-aws-step-functions-workflows/)」を参照してください。

## Step Functions でのステートマシンとアクティビティのタグ付け
<a name="concepts-tagging"></a>

AWS Step Functionsは、ステートマシン (Standard と Express の両方) とアクティビティのタグ付けをサポートしています。タグは、リソースを追跡および管理し、AWS Identity and Access Management(IAM) ポリシーのセキュリティを向上させるのに役立ちます。Step Functions リソースにタグを付けたら、 で管理できますAWS Resource Groups。方法については、「[AWS Resource Groups ユーザーガイド](https://docs.aws.amazon.com/ARG/latest/userguide/)」を参照してください。

次の例のように、タグベースの認可の場合、ステートマシンの実行リソースはステートマシンに関連付けられたタグを継承します。

```
arn:partition:states:region:account-id:execution:<StateMachineName>:<ExecutionId>
```

実行リソース ARN を指定する [DescribeExecution](https://docs.aws.amazon.com/step-functions/latest/apireference/API_DescribeExecution.html) またはその他の API を呼び出すとき、Step Functions はタグベースの認可を実行しながら、ステートマシンに関連付けられたタグを使用してリクエストを許可または拒否します。これにより、ステートマシンレベルの実行へのアクセスを許可または拒否できます。

リソースのタグ付けに関連する制限を確認するには、[タグ付けに関連する制限](service-quotas.md#sfn-limits-tagging) を参照してください。

### コスト割り当てのタグ付け
<a name="tagging-cost"></a>

コスト配分タグを使用してステートマシンの目的を特定し、その組織をAWS請求に反映できます。サインアップして、タグキーと値を含めるためのAWSアカウント請求書を取得します。レポートの設定についての詳細は、「*AWS Billing ユーザーガイド*」の「[Setting Up a Monthly Cost Allocation Report](https://docs.aws.amazon.com/awsaccountbilling/latest/aboutv2/configurecostallocreport.html#allocation-report)」を参照してください。

例えば、次のようにコストセンターと Step Functions リソースの目的を表すタグを追加できます。

[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ja_jp/step-functions/latest/dg/sfn-best-practices.html)

### セキュリティのためのタグ付け
<a name="tagging-security"></a>

IAM は、タグに基づくリソースへのアクセスの制御をサポートしています。タグに基づいてアクセスを制御するには、IAM ポリシーの条件要素でリソースタグに関する情報を提供します。

例えば、キー `environment` および値 `production` のタグを含むすべての Step Functions リソースへのアクセスを制限できます。

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Deny",
            "Action": [
                "states:TagResource",
                "states:DeleteActivity",
                "states:DeleteStateMachine",
                "states:StopExecution"
            ],
            "Resource": "*",
            "Condition": {
                "StringEquals": {"aws:ResourceTag/environment": "production"}
            }
        }
    ]
}
```

詳細については、IAM ユーザーガイドの [[Controlling Access Using Tags]](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_tags.html) (タグを使用したアクセス制御) を参照してください。

### Step Functions コンソールでのタグの管理
<a name="tagging-console"></a>

Step Functions コンソールでステートマシンのタグを表示および管理できます。ステートマシンの **[Details]** (詳細) ページから、**[Tags]** (タグ) を選択します。

### Step Functions API アクションを使用したタグの管理
<a name="tagging-api"></a>

Step Functions API を使用してタグを管理するには、次の API アクションを使用します。
+ [https://docs.aws.amazon.com/step-functions/latest/apireference/API_ListTagsForResource.html](https://docs.aws.amazon.com/step-functions/latest/apireference/API_ListTagsForResource.html)
+ [https://docs.aws.amazon.com/step-functions/latest/apireference/API_TagResource.html](https://docs.aws.amazon.com/step-functions/latest/apireference/API_TagResource.html)
+ [https://docs.aws.amazon.com/step-functions/latest/apireference/API_UntagResource.html](https://docs.aws.amazon.com/step-functions/latest/apireference/API_UntagResource.html)

## タイムアウトを使用して Step Functions ワークフローの実行のスタックを回避する
<a name="sfn-stuck-execution"></a>

デフォルトでは、Amazon States Language はステートマシンの定義にタイムアウトを指定しません。明示的なタイムアウトが設定されていないと、Step Functions は多くの場合、アクティビティのワーカーからのレスポンスでしか、タスクが完了したことを知ることができません。エラーが発生した場合、`TimeoutSeconds` フィールドに `Activity` 状態または `Task` 状態が指定されていないと、実行は、返されることのないレスポンスを待ち続けるため、スタックします。

この状況を回避するには、ステートマシンで `Task` を作成するときに、適切なタイムアウトを指定します。例えば、次のようになります。

```
"ActivityState": {
  "Type": "Task",
  "Resource": "arn:aws:states:region:account-id:activity:HelloWorld",
  "TimeoutSeconds": 300,
  "Next": "NextState"
}
```

[タスクトークン (.waitForTaskToken) でコールバック](connect-to-resource.md#connect-wait-token)を使用する場合は、ハートビートを使用して `Task` 状態定義に `HeartbeatSeconds` フィールドを追加することを推奨します。`HeartbeatSeconds` をタスクのタイムアウトよりも短く設定できるので、ワークフローがハートビートエラーで失敗した場合、タスクが完了するまでに時間がかかったのではなく、タスクの失敗が原因であることがわかります。

```
{
  "StartAt": "Push to SQS",
  "States": {
    "Push to SQS": {
      "Type": "Task",
      "Resource": "arn:aws:states:::sqs:sendMessage.waitForTaskToken",
      "HeartbeatSeconds": 600,
      "Parameters": {
        "MessageBody": { "myTaskToken.$": "$$.Task.Token" },
        "QueueUrl": "https://sqs.us-east-1.amazonaws.com/account-id/push-based-queue"
      },
      "ResultPath": "$.SQS",
      "End": true
    }
  }
}
```

詳細については、Amazon States Language ドキュメントの [Task ワークフロー状態](state-task.md) を参照してください。

**注記**  
Amazon States Language の定義の `TimeoutSeconds` フィールドを使用してステートマシンのタイムアウトを設定できます。詳細については、「[Step Functions ワークフローの Amazon States Language でのステートマシン構造](statemachine-structure.md)」を参照してください。

## Step Functions で大きなペイロードを渡す代わりに Amazon S3 の ARN を使用する
<a name="avoid-exec-failures"></a>

状態間でデータの大きいペイロードを渡す実行を終了できます。ステートの間で渡すデータが 256 KiB を超える場合、Amazon Simple Storage Service (Amazon S3) を使用してデータを保存し、バケット名とキーバリューを取得するため、`Payload` パラメータでバケットの Amazon リソースネーム (ARN) を解析します。または、実行時に小さいペイロードを渡すように実装を調整します。

次の例では、ステートマシンは Amazon S3 バケット内の JSON ファイルを処理する AWS Lambda関数に入力を渡します。このステートマシンを実行すると、Lambda 関数は JSON ファイルの内容を読み取り、ファイルの内容を出力として返します。

**Lambda 関数を作成する**  
`pass-large-payload` という名前の次の Lambda 関数は、特定の Amazon S3 バケットに保存されている JSON ファイルの内容を読み取ります。

**注記**  
この Lambda 関数を作成したら、必ず、その IAM ロールに Amazon S3 バケットから読み取るための適切なアクセス許可を付与してください。例えば、Lambda 関数のロールに **AmazonS3ReadOnlyAccess** のアクセス許可をアタッチします。

```
import json
import boto3
import io
import os

s3 = boto3.client('s3')

def lambda_handler(event, context):
    event = event['Input']
    final_json = str()
    
    s3 = boto3.resource('s3')
    bucket = event['bucket'].split(':')[-1]
    filename = event['key']
    directory = "/tmp/{}".format(filename)
    
    s3.Bucket(bucket).download_file(filename, directory)
    
    with open(directory, "r") as jsonfile:
    
        final_json = json.load(jsonfile)
    
    os.popen("rm -rf /tmp")
    
    return final_json
```

**ステートマシンを作成する**  
次のステートマシンは、以前に作成した Lambda 関数を呼び出します。

```
{  
   "StartAt":"Invoke Lambda function",
   "States":{  
      "Invoke Lambda function":{  
         "Type":"Task",
         "Resource":"arn:aws:states:::lambda:invoke",
         "Parameters":{  
            "FunctionName":"arn:aws:lambda:us-east-2:123456789012:function:pass-large-payload",
            "Payload":{  
               "Input.$":"$"
            }
         },
         "OutputPath": "$.Payload",
         "End":true
      }
   }
}
```

大量のデータを入力で渡すのではなく、そのデータを Amazon S3 バケットに保存し、`Payload` パラメータでバケットの Amazon リソースネーム (ARN) を解析して、バケット名とキーバリューを取得します。Lambda 関数はその ARN を使用してデータに直接、アクセスできます。次に示しているステートマシン実行の入力例では、データが `amzn-s3-demo-large-payload-json` という名前の Amazon S3 バケット内の `data.json` に保存されています。

```
{
  "key": "data.json",
  "bucket": "arn:aws:s3:::amzn-s3-demo-large-payload-json"
}
```

## Step Functions で履歴クォータに到達しないように新しい実行を開始する
<a name="bp-history-limit"></a>

AWS Step Functionsの実行イベント履歴には 25,000 エントリのハードクォータがあります。実行イベントが 24,999 件に達すると、次のイベントが発生するまで待機します。
+ イベント番号 25,000 が `ExecutionSucceeded` の場合、実行は正常に終了します。
+ イベント番号 25,000 が `ExecutionSucceeded` 以外の場合、`ExecutionFailed` イベントはログに記録され、履歴の上限に達したためステートマシンの実行は失敗します。

長時間の実行でこのクォータに達しないようにするには、次のいずれかの方法を試行できます。
+ [マップステートを分散モードで使用します](state-map-distributed.md)。このモードでは、`Map` 状態は各反復を子ワークフロー実行として実行します。これにより、最大 10,000 件という高い並列性を持つの並列子ワークフロー実行が可能になります。それぞれの子ワークフローの実行には、親ワークフローとは別の実行履歴があります。
+ 進行中の実行の `Task` 状態から、新しいステートマシンを直接実行します。このようなネストされたワークフロー実行を開始するには、親ステートマシンで必要なパラメータとともに、Step Functions の `[StartExecution](https://docs.aws.amazon.com/step-functions/latest/apireference/API_StartExecution.html)` API アクションを使用します。ネストされたワークフローの使用についての詳細は、「[Step Functions で Task 状態からワークフロー実行を開始する](concepts-nested-workflows.md)」または「[Step Functions API アクションを使用して新しい実行を継続する](tutorial-continue-new.md)」のチュートリアルを参照してください。
**ヒント**  
ネストされたワークフローの例をデプロイするには、*「 AWS Step Functionsワークショップ*」の[「コストの最適化](https://catalog.workshops.aws/stepfunctions/nested-workflow)」を参照してください。
+ ステートマシンの新しい実行を開始して進行中の作業を複数のワークフロー実行に分割できる AWS Lambda関数を使用するパターンを実装します。詳細については、[Step Functions で Lambda 関数を使用して新しい実行を継続する](tutorial-use-lambda-cont-exec.md) のチュートリアルを参照してください。

## Lambda サービスの一時的な例外の処理
<a name="bp-lambda-serviceexception"></a>

AWS Lambdaでは、一時的なサービスエラーが発生することがあります。この場合、Lambda を呼び出すと、`ClientExecutionTimeoutException`、`ServiceException`、`AWSLambdaException`、または `SdkClientException` などの 500 エラーが生じます。ベストプラクティスとしては、Lambda 関数を呼び出す `Retry`、あるいはエラーを `Catch` するために、ステートマシンでのこのような例外を事前に処理します。

Lambda エラーは、`Lambda.ErrorName` として報告されます。Lambda サービス例外エラーを再試行するには、次の `Retry` コードを使用します。

```
"Retry": [ {
   "ErrorEquals": [ "Lambda.ClientExecutionTimeoutException", "Lambda.ServiceException", "Lambda.AWSLambdaException", "Lambda.SdkClientException"],
   "IntervalSeconds": 2,
   "MaxAttempts": 6,
   "BackoffRate": 2
} ]
```

**注記**  
Lambda ランタイムの未処理のエラーは、以前は `Lambda.Unknown` としてのみ報告されていました。新しいランタイムでは、タイムアウトはエラー出力で `Sandbox.Timedout` として報告されます。  
Lambda が最大呼び出し回数を超えると、報告されるエラーは `Lambda.TooManyRequestsException` となります。  
`Lambda.Unknown`、`Sandbox.Timedout`、`States.TaskFailed` で照合して、考えられるエラーを処理します。`States.ALL` も使用できますが、単独で、かつリストの最後に記述する必要があります。  
Lambda `Handled` と `Unhandled` エラーの詳細については、[AWS Lambda デベロッパーガイド](https://docs.aws.amazon.com/lambda/latest/dg/API_Invoke.html#API_Invoke_ResponseSyntax)の `FunctionError` を参照してください。

詳細については次を参照してください:
+ [エラー後の再試行](concepts-error-handling.md#error-handling-retrying-after-an-error)
+ [Step Functions ステートマシンでのエラー条件の処理](tutorial-handling-error-conditions.md)
+ [Lambda 呼び出しエラー](https://docs.aws.amazon.com/lambda/latest/dg/API_Invoke.html#API_Invoke_Errors)

## アクティビティタスクのポーリング時のレイテンシーを回避する
<a name="bp-activity-pollers"></a>

`[GetActivityTask](https://docs.aws.amazon.com/step-functions/latest/apireference/API_GetActivityTask.html)` API は、[https://docs.aws.amazon.com/step-functions/latest/apireference/API_GetActivityTask.html#StepFunctions-GetActivityTask-response-taskToken](https://docs.aws.amazon.com/step-functions/latest/apireference/API_GetActivityTask.html#StepFunctions-GetActivityTask-response-taskToken) を *1 回のみ*提供するように設計されています。アクティビティワーカーと通信している間に `taskToken` がドロップされた場合、`GetActivityTask` がタイムアウトするまで、レスポンスの待機のため複数の `GetActivityTask` リクエストが 60 秒ブロックされます。

レスポンス待ちのポーリングが少数しかない場合、ブロックされたリクエストの後ろにすべてのリクエストが追加され、停止する可能性があります。ただし、各アクティビティ Amazon リソースネーム (ARN) に多数の未処理のポーリングがあり、リクエストの一部が待機中のままになる場合、`taskToken` を取得して処理の実行を開始するリクエストがさらにたくさんあります。

本番稼働用システムでは、それぞれのアクティビティ ARN の各時点で少なくとも 100 のオープンポーリングを推奨します。1 つのポーリングがブロックされ、それらのポーリングの一部がその後ろに並んでいる場合、`GetActivityTask` のリクエストがブロックされている間に処理を実行するための `taskToken` を受け取るさらに多くのリクエストがあります。

タスクのポーリング時に、これらのレイテンシーの問題を回避する方法。
+ アクティビティワーカーの実装の作業とは別のスレッドとしてポーラーを実装します。
+ 各時点でのアクティビティ ARN あたり、少なくとも 100 のオープンポーリングが必要です。
**注記**  
ARN あたり 100 のオープンポーリングにスケーリングすると、コストが高くなる可能性があります。例えば、ARN あたり 100 の Lambda 関数でポーリングする場合、1 つの Lambda 関数で 100 のポーリングスレッドを実行するよりも 100 倍コストが高くなります。レイテンシーを短縮*しながら*コストを最小限に抑えるには、非同期 I/O を使用する言語により、ワーカーごとに複数のポーリングスレッドを実装します。ポーラースレッドとワークスレッドが異なるアクティビティワーカーの例については、[例: Ruby のアクティビティワーカー](concepts-activities.md#example-ruby-activity-worker) を参照してください 

アクティビティおよびアクティビティワーカーの詳細については、[Step Functions のアクティビティについて](concepts-activities.md) を参照してください

## CloudWatch Logs リソースポリシーのサイズ制限の回避
<a name="bp-cwl"></a>

ログでステートマシンを作成する場合、または既存のステートマシンのログ記録を有効にするよう更新する場合、Step Functions は、指定したロググループで CloudWatch Logs リソースポリシーを更新する必要があります。CloudWatch Logs リソースポリシーは 5,120 文字に制限されています。

CloudWatch Logs でポリシーがサイズ制限に近づいていることが検出されると、CloudWatch Logs は `/aws/vendedlogs/` でスタートするロググループのログ記録を自動的に有効にします。

CloudWatch Logs リソースポリシーのサイズ制限に達しないようにするには、CloudWatch Logs ロググループ名の先頭に `/aws/vendedlogs/` というプレフィックスを付けます。Step Function コンソールでロググループを作成すると、推奨されるロググループ名には既に `/aws/vendedlogs/states` のプレフィックスが付いています。

また、CloudWatch Logs には、リージョンごと、アカウントごとに 10 のリソースポリシーのクォータもあります。アカウントのリージョンに既に 10 個の CloudWatch Logs リソースポリシーがあるステートマシンでログ記録を有効にしようとすると、ステートマシンは作成または更新されません。ログ記録に関するクォータの詳細については、「[CloudWatch Logs のクォータ](https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/cloudwatch_limits_cwl.html)」を参照してください。

CloudWatch Logs へのログの送信に問題がある場合は、「[Troubleshooting state machine logging to CloudWatch Logs](cw-logs.md#troubleshooting-logging-to-cloudwatch)」を参照してください。