並列実行ブランチでAWSステップ関数を実行しています。
各ブランチは個別に成功しますが、全体的な機能は次のエラーで失敗します。
States.DataLimitExceeded-状態/タスクがサービスの最大文字数を超えるサイズの結果を返しました。
次に、AWSからこの問題を説明し、回避策を提案する記事を見つけました。
https://docs.aws.Amazon.com/step-functions/latest/dg/connect-lambda.html
その記事は言う:
Lambda呼び出しAPIは、デフォルトで応答にログを含めます。ワークフローで複数のLambdaを呼び出すと、States.DataLimitExceededエラーが発生する可能性があります。これを回避するには、Lambda関数を呼び出すときにパラメーターとして「LogType」=「None」を含めます。
私の質問は、どこに正確に置くのですか?ステートマシン定義のさまざまな場所に配置しようとしましたが、次のエラーが発生します。
フィールド「LogType」はステップ関数ではサポートされていません
そのエラーはサポート記事に反しているようですので、おそらく私はそれを間違っています!
アドバイスをいただければ幸いです。
乾杯
UPDATE 1:明確にするために、これは26の並列分岐を持つ並列関数です。以下の例のように、各ブランチには小さな出力があります。このデータの最大の項目はLogResultです。これは(base64でデコードされた場合)課金情報のみです。この情報に26を掛けるとエラーが発生したと思うので、このLogResultをオフにしたいだけです!!!
{
"ExecutedVersion": "$LATEST",
"LogResult": "U1RBUlQgUmVxdWVzdElkOiBlODJjZTRkOS0zMjk2LTRlNDctYjcyZC1iYmEwMzI1YmM3MGUgVmVyc2lvbjogJExBVEVTVApFTkQgUmVxdWVzdElkOiBlODJjZTRkOS0zMjk2LTRlNDctYjcyZC1iYmEwMzI1YmM3MGUKUkVQT1JUIFJlcXVlc3RJZDogZTgyY2U0ZDktMzI5Ni00ZTQ3LWI3MmQtYmJhMDMyNWJjNzBlCUR1cmF0aW9uOiA3NzI5Ljc2IG1zCUJpbGxlZCBEdXJhdGlvbjogNzgwMCBtcwlNZW1vcnkgU2l6ZTogMTAyNCBNQglNYXggTWVtb3J5IFVzZWQ6IDEwNCBNQglJbml0IER1cmF0aW9uOiAxMTY0Ljc3IG1zCQo=",
"Payload": {
"statusCode": 200,
"body": {
"signs": 63,
"nil": ""
}
},
"SdkHttpMetadata": {
"HttpHeaders": {
"Connection": "keep-alive",
"Content-Length": "53",
"Content-Type": "application/json",
"Date": "Thu, 21 Nov 2019 04:00:42 GMT",
"X-Amz-Executed-Version": "$LATEST",
"X-Amz-Log-Result": "U1RBUlQgUmVxdWVzdElkOiBlODJjZTRkOS0zMjk2LTRlNDctYjcyZC1iYmEwMzI1YmM3MGUgVmVyc2lvbjogJExBVEVTVApFTkQgUmVxdWVzdElkOiBlODJjZTRkOS0zMjk2LTRlNDctYjcyZC1iYmEwMzI1YmM3MGUKUkVQT1JUIFJlcXVlc3RJZDogZTgyY2U0ZDktMzI5Ni00ZTQ3LWI3MmQtYmJhMDMyNWJjNzBlCUR1cmF0aW9uOiA3NzI5Ljc2IG1zCUJpbGxlZCBEdXJhdGlvbjogNzgwMCBtcwlNZW1vcnkgU2l6ZTogMTAyNCBNQglNYXggTWVtb3J5IFVzZWQ6IDEwNCBNQglJbml0IER1cmF0aW9uOiAxMTY0Ljc3IG1zCQo=",
"x-amzn-Remapped-Content-Length": "0",
"x-amzn-RequestId": "e82ce4d9-3296-4e47-b72d-bba0325bc70e",
"X-Amzn-Trace-Id": "root=1-5dd60be1-47c4669ce54d5208b92b52a4;sampled=0"
},
"HttpStatusCode": 200
},
"SdkResponseMetadata": {
"RequestId": "e82ce4d9-3296-4e47-b72d-bba0325bc70e"
},
"StatusCode": 200
}
同じ問題で行き詰まりました。ステップ関数は、2つの状態間で受け渡しできるデータに32,768文字の制限を課します。
https://docs.aws.Amazon.com/step-functions/latest/dg/limits.html
多分あなたは問題を考えて別の方法で分解する必要がありますか?それが私がしたことです。ログ応答を削除するとある程度の弾力性が得られますが、ソリューションは特定の制限後に拡張されません。
結果をS3バケットに格納し、ステートマシンにパスを結果ファイルへのパス(およびデータの簡単な要約またはPASS/FAILなどのステータス)を返すようにして、Step Functionsで大きなデータを処理します。
DBを使用したほうが快適であれば、同じことを行うこともできます。
この方法では、結果の現在の形式を変更する必要はありません。大量のデータの代わりに参照を渡すだけで、必要な限り保持されます。
Lambdasの先頭は次のようになり、入力がファイルからのものかプレーンデータからのものかがわかります。
bucket_name = util.env('BUCKET_NAME')
if 'result_path' in input_data.keys():
# Results are in a file that is referenced.
try:
result_path = input_data['result_path']
result_data = util.get_file_content(result_path, bucket_name)
except Exception as e:
report.append(f'Failed to parse JSON from {result_path}: {e}')
else:
# Results are just raw data, not a reference.
result_data = input_data
次に、Lambdaの最後に結果をアップロードし、そのファイルへの道順を返します。
import boto3
def upload_results_to_s3(bucket_name, filename, result_data_to_upload):
try:
s3 = boto3.resource('s3')
results_prefix = 'Path/In/S3/'
results_suffix = '_Results.json'
result_file_path = '' + results_prefix + filename + results_suffix
s3.Object(bucket_name, result_file_path).put(
Body=(bytes(json.dumps(result_data_to_upload, indent=2).encode('UTF-8')))
)
return result_file_path
result_path = upload_results_to_s3(bucket_name, filename, result_data_to_upload)
result_obj = {
"result_path": result_path,
"bucket_name": bucket_name
}
return result_obj
次に、ファイルから入力を取得するために、次のLambdaには最初のコードスニペットが含まれます。
ステップ関数ノードは次のようになり、結果はpython上記のコードではresult_objになります。
"YOUR STATE":
{
"Comment": "Call Lambda that puts results in file",
"Type": "Task",
"Resource": "arn:aws:lambda:YOUR LAMBDA ARN",
"InputPath": "$.next_function_input",
"ResultPath": "$.next_function_input",
"Next": "YOUR-NEXT-STATE"
}
一週間前に問題がありました。私が解決した方法は以下のようなものです:
結果のどの部分を次のステップに送信するかを定義できます。
そのためにはあなたが使用する必要があります
"出力パス": "$ .part2"、
あなたのjson入力には
"part1":{"portion1":{"procedure": "Delete_X"
}、 "portion2":{"手順": "Load_X"}}、
"part2":{"portion1":{"procedure": "Delete_Y"
}、 "portion2":{"手順": "Load_Y"}}
Part1が処理されたら、part1が出力とそれに関連するresultpathで送信されないようにします。次のステップに必要なパート2だけが次のステップに送られます。これで: "OutputPath": "$ .part2"、
それが役立つかどうか教えてください
あなたができることは、あなたのjsonに "emptyOutputPath": ""を追加することです、
"emptyOutputPath": "",
"part1": { "portion1": { "procedure": "Delete_X"
}, "portion2":{ "procedure": "Load_X" } },
"part2": { "portion1": { "procedure": "Delete_Y"
}, "portion2":{ "procedure": "Load_Y" } }
これにより、空の "OutputPath": "$。emptyOutputPath"を実行でき、ResultPathがクリアされます。
それが役に立てば幸い
この問題をフォローアップしてループを閉じます。
基本的には、代わりにAQSメッセージキューを使用する代わりに、並列ラムダの使用をあきらめました