Step Functions × DynamoDBで実現する動的API連携ワークフロー
この記事は クラウドワークス グループ Advent Calendar 2024 シリーズ2の6日目の記事です。
はじめに
こんにちは!
株式会社ソニックムーブでバックエンドエンジニア兼マネージャーをしています、小西です。最近マネージャーになったばかりで、まだまだ勉強中ですが、毎日楽しくやっています!
今回の記事では、案件で外部システムとの連携要件があり、条件に応じて異なるAPIエンドポイントに接続する必要があった課題を解決するために、AWS Step FunctionsとDynamoDBを組み合わせて、柔軟なAPI呼び出しワークフローを構築した事例をご紹介します。
本記事では、Step Functionsの「Call third-party API」機能を活用し、DynamoDBを用いて動的にAPIエンドポイントを管理する仕組みをご紹介します。
この構成を使用することで、従来必要だった外部APIリクエスト用のLambdaを削減できるだけでなく、エンドポイント情報をDynamoDBで一元管理することで、スケーラブルかつ効率的なワークフローを実現しました。
構成概要
ワークフローの流れは以下の通りです:
- DynamoDBから
endpointId
をキーとしてエンドポイント情報を取得。 - エンドポイント情報があればサードパーティAPIを呼び出す。
- なければそのまま終了。
SAMでの構築
以下はSAMテンプレートの例です。記事として載せるために一部簡易的な値を使用しています。
Transform: AWS::Serverless-2016-10-31
Resources:
MyStateMachine:
Type: AWS::Serverless::StateMachine
Properties:
Name: MyStateMachine
Type: STANDARD
Definition:
StartAt: GetItemFromDynamoDB
States:
GetItemFromDynamoDB:
Type: Task
Resource: arn:aws:states:::dynamodb:getItem
Parameters:
TableName: !Ref DynamoDBTable
Key:
endpointId:
S.$: $.endpointId
ResultPath: $.dynamodbResult
Next: CheckIfItemExists
CheckIfItemExists:
Type: Choice
Choices:
- Variable: $.dynamodbResult.Item
IsPresent: true
Next: CallExternalApi
Default: SuccessState
CallExternalApi:
Type: Task
Resource: arn:aws:states:::http:invoke
Parameters:
ApiEndpoint.$: $.dynamodbResult.Item.endpoint.S
Method: POST
Headers:
Content-Type: application/json
x-api-key.$: $.dynamodbResult.Item.apiKey.S
RequestBody.$: $.body
Authentication:
ConnectionArn: ConnectionArn
Retry:
- ErrorEquals: ["States.Http.StatusCode.429"]
BackoffRate: 2.0
MaxAttempts: 3
Next: SuccessState
SuccessState:
Type: Succeed
DynamoDBTable:
Type: AWS::DynamoDB::Table
Properties:
TableName: EndpointTable
AttributeDefinitions:
- AttributeName: endpointId
AttributeType: S
KeySchema:
- AttributeName: endpointId
KeyType: HASH
BillingMode: PAY_PER_REQUEST
各セクションの説明
GetItemFromDynamoDB
このステートでは、DynamoDBのテーブルから特定のエンドポイント情報を取得します。
- 入力: ワークフローの実行時に渡される
endpointId
。 - 処理内容:
- DynamoDBの
GetItem
操作を利用して、endpointId
をキーにテーブルから該当データを検索します。 - 結果は
dynamodbResult
に格納されます。
- DynamoDBの
CheckIfItemExists
DynamoDBから取得したデータの有無を確認する条件分岐ステートです。
- 処理内容:
- DynamoDBのレスポンスを検査し、
Item
が存在するかを確認します。 -
Item
が存在する場合は次のCallExternalApi
ステートに進みます。 - 存在しない場合は、そのままワークフローを終了(
SuccessState
)します。
- DynamoDBのレスポンスを検査し、
CallExternalApi
外部のサードパーティAPIを呼び出すステートです。
- 入力: DynamoDBから取得したエンドポイント情報とリクエストボディ。
- 処理内容:
- エンドポイントURL(
endpoint.S
)とAPIキー(apiKey.S
)を動的に設定。 - リクエストヘッダーやボディを構築し、APIを呼び出します。
- 状態管理として、リトライロジックを導入。
- 429エラーが発生した場合、指数バックオフを使用したリトライを設定。(もちろん他のステータスもあるといいです)
- リトライごとに間隔が指数関数的に増加(例: 2秒 -> 4秒 -> 8秒)。
- 最大3回のリトライでで失敗時にはワークフローを終了。
- 429エラーが発生した場合、指数バックオフを使用したリトライを設定。(もちろん他のステータスもあるといいです)
- エンドポイントURL(
- メリット:
- 外部APIを直接呼び出すLambdaを作成する必要がなく、コスト削減とメンテナンス性の向上が実現。
このようにして、DynamoDBとStep Functionsを組み合わせることで、効率的で柔軟なAPI呼び出しが可能になります。
DynamoDBへのデータ準備
以下は、DynamoDBに保存するデータの例です。このデータは、endpointId
に基づいて特定のAPIエンドポイントとその認証情報を保存するものです。
AWS CLIでのコマンド
aws dynamodb put-item \
--table-name EndpointTable \
--item '{
"endpointId": {"S": "12345"},
"endpoint": {"S": "https://api.example.com/endpoint"},
"apiKey": {"S": "your-api-key"}
}'
DynamoDBテーブルに保存されるデータの例
{
"endpointId": {
"S": "12345"
},
"endpoint": {
"S": "https://api.example.com/endpoint"
},
"apiKey": {
"S": "your-api-key"
}
}
実行時の入力例
以下は、Step Functionsを実行する際に渡す入力の例です。
{
"endpointId": "12345",
"body": {
"exampleKey": "exampleValue"
}
}
これで、DynamoDBからエンドポイント情報を取得し、APIを呼び出すワークフローが実行されます。
まとめ
DynamoDBとStep Functionsを組み合わせると、柔軟で効率的なワークフローが簡単に作れます。
ぜひ試してみてください!
Discussion