Kinesis Data Firehose変換処理において ServiceUnavailableException 発生
概要
- Kinesis Data Firehoseでは、Lambda 関数を呼び出して、受信した送信元データを変換後に、送信先へ配信ができます。今回、このデータ変換の処置でエラーを経験したため、備忘録としてまとめます。
前提知識
- 先ず、以前こちらの記事で紹介した様に、CloudWatch Logs を定期的にS3 へ転送する際にCloudWatch Logsのサブスクリプションフィルター、Kinesis Data Firehoseを利用します。また、Kinesis Data Firehoseでは、Lambda 関数を使用して、データを分析しやすい形式に変換してから配信することが出来ます。
- Kinesis Data Firehose データ変換は、デフォルトで最大 3 MiB まで受信データをバッファします(Min:1 MiB, Max:3 MiB)。次に、Kinesis Data Firehose は、AWS Lambda 同期呼び出しモードを使用して、バッファされた各バッチで、指定された Lambda 関数を非同期的に呼び出します。Lambdaによって変換されたデータは、Lambda から Kinesis Data Firehose に送信され、その後に指定された送信先のバッファサイズとバッファ間隔のいずれかに到達したときに、Kinesis Data Firehose から送信先に配信されます。
変換処理において ServiceUnavailableException 発生
- 今回、データ変換処理において、Lambda の PutRecordBatch リクエストで下記のエラーが発生しました。CloudWatch Logs より抜粋。
INFO Reingested 74/74 records out of 78 in to xxxxxxxxxxxxxxxxxxxx stream
INFO Some records failed while calling PutRecordBatch, retrying. Individual error codes: ServiceUnavailableException,ServiceUnavailableException,.....
INFO Some records failed while calling PutRecordBatch, retrying. Individual error codes: ServiceUnavailableException,ServiceUnavailableException,.....
.....
INFO Reingested all 74 records out of 78 in to xxxxxxxxxxxxxxxxxxxx stream
原因調査
ドキュメント調査
- 以下のドキュメントに記載の通り、PutRecordBatchリクエストの失敗によってServiceUnavailableException が発生することが分かりました。また、ServiceUnavailableException が繰り返し発生する原因は、Kinesis Data Firehoseのスループット上限を超過した可能性があるとのことです。以下、引用です。
If PutRecordBatch throws
ServiceUnavailableException
, back off and retry. If the exception persists, it is possible that the throughput limits have been exceeded for the delivery stream.
- Kinesis Data Firehoseのクォータは、以下のドキュメントに記載があります。以下、引用です。
[Direct PUT] がデータソースとして設定されている場合、各 Kinesis Data Firehose 配信ストリームは PutRecord リクエストおよび PutRecordBatch リクエストに対して次の結合クォータを提供します。
- 米国東部 (バージニア北部)、米国西部 (オレゴン)、欧州 (アイルランド) の場合: 50 万レコード/秒、2,000 リクエスト/秒、5 MiB/秒になります。
- 米国東部 (オハイオ)、米国西部 (北カリフォルニア)、AWS GovCloud (米国東部)、AWS GovCloud (米国西部)、アジアパシフィック (香港)、アジアパシフィック (ムンバイ)、アジアパシフィック (ソウル)、アジアパシフィック (シンガポール)、アジアパシフィック (シドニー)、アジアパシフィック (東京)、カナダ (中部)、欧州 (フランクフルト)、欧州 (ロンドン)、欧州 (パリ)、欧州 (ストックホルム)、中東 (バーレーン)、南米 (サンパウロ)、アフリカ (ケープタウン)、および欧州 (ミラノ) の場合: 10万レコード/秒、1,000 リクエスト/秒、1 MiB/秒になります。
- PutRecordBatch オペレーションは、コールごとに最大 500 レコードまたは 4 MiB のどちらか小さい方を受け取ることができます。このクォータは変更できません。
Kinesis Data Firehose の設定値
- 変換処理の設定は、バッファサイズ 3MiB です。また、タイムアウトを 15 min としておりました。
結果
推定原因
- 先ず、今回エラーが発生した環境は、CloudWatch Logsロググループのサブスクリプションフィルタに特にフィルターのパターンを設定せず、すべてのログをS3 へ転送しておりました。
- 前述のドキュメントの調査より、今回発生したエラーは、PutRecordBatchリクエストの失敗によって発生しています。Kinesis Data Firehoseでは、受信データをバッファしてLambda に渡します。そのため、PutRecordBatch の上限である「コールごとに最大 500 レコードまたは 4 MiB 」のどちらかに達した可能性が疑われます。
対処方法
- 以下、対処方法です。システムの特定により異なりますので、実際に試して確認下さい。
- バッファサイズを Max の3MiB からMin の1MiB に変更し、変換処理を行うLambda に渡すサイズを小さくします。
- バッファ間隔を小さくします。Max の15分からMin の60 sec とします。なお、Kinesis Data Firehose では、Lambda の呼び出し時間は最大 5 分までサポートのようです。
- 要件の見直しが可能であれば、サブスクリプションフィルタのパターンを設定して、不必要なログをフィルターします。
- 後は、再発の有無を確認します。