タイトルの通りですが、aws-sdk-javaで利用するClientConfigurationのリトライポリシーのデフォルトは、DynamoDBだけ異なるようです。
DynamoDBを利用していて、500エラーに遭遇する機会が増えてきており、その際に調べていて知りました。
はじめに
AWS の利用全般における、エラー再試行と、再試行におけるエクスポネンシャルバックオフとジッターについては、下記の公式ドキュメントにまとめられています。
また、その中でも DynamoDB については、下記のブログ記事にまとめられています。
この記事、かなり詳しく書かれてますので、DynamoDB を使っている場合、一読しておくとよさそうです。
リトライポリシーの違いについて
先に結論ですが、デフォルトのリトライポリシーの設定値を以下の表にまとめました。違いは「エラー時のリトライ試行数」と「ベース遅延(非スロットル系エラー)」ですね。
DynamoDB | それ以外 | |
---|---|---|
エラー時のリトライ試行数 | 10回 | 3回 |
ベース遅延(非スロットル系エラー) | 25ミリ秒 | 100ミリ秒 |
ベース遅延(スロットル系エラー) | 500ミリ秒 | 500ミリ秒 |
最大遅延 | 20秒 | 20秒 |
(コードを読んで確認しただけなので、見逃しはあるかもしれません)
ClientConfigurationとリトライポリシー
aws-sdk-java において、各AWSサービスへのアクセスを行う各クライアントは、 ClientConfiguration に指定された設定が適用されます。
リトライポリシーについてもそれらの設定の一部となっています。
デフォルト値については、GitHub を見るのが確実だと思います。
リトライポリシーについては、 PredefinedRetryPolicies.DEFAULT
がデフォルトなようですね。
public static final RetryPolicy DEFAULT_RETRY_POLICY = PredefinedRetryPolicies.DEFAULT;
ところで、クライアントの作成は、各サービスごとに用意されたビルダーを使って生成することが多いと思います。
DynamoDB であれば次のように AmazonDynamoDBAsyncClientBuilder
を使う形ですね(実際にはメソッドチェーンを使った流れるようなインタフェースで書くことが多いですが、説明のために分けて書いています)
AmazonDynamoDBAsyncClientBuilder builder = AmazonDynamoDBAsyncClientBuilder.standard();
// builder に対して Credentials, Region, ClientConfiguration 等をセットしていく
AmazonDynamoDB client = builder.build();
こちらのビルダー内部では、ClientConfiguration を作成するファクトリを使っており、DynamoDB の場合は AmazonDynamoDBClientConfigurationFactory が該当します。
上記クラスを見るとわかりますが、リトライポリシーだけ、 PredefinedRetryPolicies.DEFAULT
ではなく PredefinedRetryPolicies.DYNAMODB_DEFAULT
という専用のデフォルト値を使うように指定されています。
@Override protected ClientConfiguration getDefaultConfig() { return super.getDefaultConfig().withRetryPolicy(PredefinedRetryPolicies.DYNAMODB_DEFAULT); }
こういった実装になっていることで、エラー時のリトライ試行数、ベース遅延(非スロットル系エラー)に関して、DynamoDBとそれ以外でデフォルト値が異なっています。
なぜデフォルト値がDynamoDBだけ異なるか?
これは、公開されている情報だけではっきりとした理由はわかりませんでした。
特性上、短期間でのリトライを繰り返すことで、自己修復によってリクエストが成功する可能性の高いサービスだから、ということでしょうか…。
実際に使っていく場合は、デフォルトの設定だけでなく、運用していくワークロードに応じて適切な設定値を決めていくことが大事だとは思いますが、こういった違いがあることを知っておくと設定値を決める参考にもなるかしれません。
ClientConfigurationの上書き設定時は注意
リトライポリシー以外にもタイムアウトの設定など ClientConfiguration は様々な設定を定義できます。
そのため、リトライポリシーはデフォルト値を使っていても、無意識のうちにリトライポリシーが PredefinedRetryPolicies.DYNAMODB_DEFAULT
から PredefinedRetryPolicies.DEFAULT
に入れ替わっていないか、気をつけるとよさそうです。
例えば、以下のコードでは、独自に new した ClientConfiguration をセットするため、リトライポリシーは PredefinedRetryPolicies.DEFAULT
になります。
ClientConfiguration config = new ClientConfiguration() .withConnectionTimeout(30 * 1000); AmazonDynamoDB client = AmazonDynamoDBAsyncClientBuilder.standard() .withClientConfiguration(config) .build();
回避する場合は、下記のようにリトライポリシーも明示的に再設定してあげましょう。
ClientConfiguration config = new ClientConfiguration() .withRetryPolicy(PredefinedRetryPolicies.DYNAMODB_DEFAULT) .withConnectionTimeout(30 * 1000); AmazonDynamoDB client = AmazonDynamoDBAsyncClientBuilder.standard() .withClientConfiguration(config) .build();