ablog

不器用で落着きのない技術者のメモ

DataStax Java Driver を使って Amazon KeySpaces にアクセスする場合のリトライポリシーの設定方法

Java アプリから DataStax Java Driver を使って Amazon KeySpaces にアクセスする場合のリトライポリシーの設定方法

Retry Policies

The DataStax java driver will attempt to retry idempotent request transparently to the application. If you are seeing NoHostAvailableException when using Amazon Keyspaces, replacing the default retry policy with the ones provided in this repository will be beneficial.

GitHub - aws-samples/amazon-keyspaces-java-driver-helpers

DataStax Javaドライバーは、アプリケーションに対して透過的に冪等リクエストをリトライする。
Amazon Keyspaces で NoHostAvailableException が発生する場合、デフォルトのリトライポリシーをこのリポジトリで提供されているものに置き換えると効果的である。

AmazonKeyspacesRetryPolicy

The Amazon Keyspaces Retry Policy is an alternative to the DefaultRetryPolicy for the Cassandra Driver. The main difference from the DefaultRetryPolicy, is the AmazonKeyspacesRetryPolicy will retry request a configurable number of times. By default, we take a conservative approach of 3 retry attempts. This driver retry policy will not throw a NoHostAvailableException. Instead, this retry policy will pass back the original exception sent back from the service.

The following code shows how to include the AmazonKeyspacesRetryPolicy to existing configuration

   advanced.retry-policy {
     class =  com.aws.ssa.keyspaces.retry.AmazonKeyspacesRetryPolicy
     max-attempts = 3
}
GitHub - aws-samples/amazon-keyspaces-java-driver-helpers

Amazon Keyspaces のリトライポリシーは、Cassandra ドライバーの DefaultRetryPolicy の代替策。
DefaultRetryPolicy との主な違いは AmazonKeyspacesRetryPolicy はリトライ回数を指定できる点で、デフォルトで3回リトライし、NoHostAvailableException を throw せずサービス(Amazon KeySpaces)から返された元の例外を返す。

Throttling / RateLimiting

Retries maintain level of availability when receiving short burst of traffic, acute failure, or loss of connection, but sustained retries can further destabilize systems resulting in cascading failure. If you are using retries to limit traffic then you may want to consider a rate limiter. As reties continue to occur at a steady rate they increasingly add to the overall traffic sent to the database. When facing this scenario you should introduce rate-limiting. Rate limiters provide what is known as back pressure. You can achieve this by leveraging the Java Driver's Throttler Extension point. There are a few rate-limiters provided native with the driver, but in this repository we will provide some sample limiters that are designed for Amazon Keyspaces serverless capacity and service quotas.

GitHub - aws-samples/amazon-keyspaces-java-driver-helpers

リトライは短期間のトラフィックのバースト、障害、接続断の場合には可用性レベルを維持するが、リトライを繰り返すとシステムがさらに不安定になり、連鎖的な障害が発生する可能性がある。
リトライを使用してトラフィックを制限する場合は、レートリミッターの検討を推奨する。リトライが一定の割合で発生し続けると、データベースへのトラフィックがさらに増加する。このシナリオに直面した場合は、レート制限を導入する必要がある。レートリミッターは、所謂「バック プレッシャー」を提供する。これは、Java ドライバーのスロットラー拡張ポイントを活用することで実現できる。
ドライバーにネイティブで提供されるレートリミッターがいくつかあるが、このリポジトリでは、Amazon Keyspaces のサーバーレス容量とサービスクォータ用に設計されたサンプルリミッターをいくつか提供する。

AmazonKeyspacesFixedRateThrottler

This is a request throttler that limits the rate of requests per second. It can be used to match the current table provisioned rate if you have predictable or average capacity per request. The limit is configurable through the client driver configuration. The rate of request is controlled by Guava SmoothBursty Ratelimiter that allows two minutes of capacity to aggregate if not used. The second limiter is dynamically configured based on the number of connections defined in the pool setting that limits overall throughput during burst behavior. The limiter will control the number of cql request per second but expects the table to have proper capacity defined to achieve utilization. This is a blocking implementation, but has a configurable timeout.

GitHub - aws-samples/amazon-keyspaces-java-driver-helpers

AmazonKeyspacesFixedRateThrottler 秒間リクエスト数を制限する request throttler である。
リクエストごとに予測可能なキャパシティまたは平均キャパシティーがある場合、これを使用して、現在のテーブルにプロビジョニングされたレートと一致させることができる。この制限はクライアントドライバーで設定できる。
リクエストのレートは、Guava SmoothBursty Ratelimiter によって制御され、使用されない場合は 2 分間のキャパシティを集約できる。 2 番目のリミッターは、バースト動作中の全体のスループットを制限するプール設定で定義された接続数に基づいて動的に構成されます。
リミッターは 1 秒あたりの CQL リクエストの数を制御しますが、使用率を達成するためにテーブルに適切な容量が定義されていることを期待します。これはブロッキング実装ですが、タイムアウトは構成可能です。
このタイプのレート リミッターのよく知られた使用例は、一定のレートでのデータの一括ロードまたはバッチ処理です。以下の図では、リクエスト レートをテーブルの書き込み容量に固定することで、エラーなしでテーブルの容量を 100% 利用できます。このグラフを生成したワークロードは、1 秒あたりのリクエストを徐々に増加させ、テーブルのプロビジョニングされた容量のリクエスト レートの 3 倍まで定期的に増加させました。さらに、レート リミッターによってバーストが許可されるため、プロビジョニングされた容量が完全に利用されていない場合に発生する可能性がある、プロビジョニングされたテーブルのバースト キャパシティを使用できます。最終的に、プロビジョニング容量の青い線とプロビジョニングされた容量の緑の線は 1 対 1 になります。固定レート リミッターは、アカウントの現在のソフト テーブル クォータ内に収まるように、オンデマンド キャパシティ テーブルとともに使用することもできます。

To activate this throttler, modify the {@code advanced.throttler} section in the driver configuration, for example:

   datastax-java-driver {
      advanced.throttler = {
             class = com.aws.ssa.keyspaces.throttler.AmazonKeyspacesFixedRateThrottler
             max-requests-per-second = 1000
             number-of-hosts = 3
             register-timeout = 1 seconds
       }
   }
  • max-requests-per-second : controls the request rate. Blocks until available permits or timeout it reached
  • number-of-hosts : The number of hosts in the system.peers table. Depending on the endpoint type and region the number of hosts in the system.peers table may be different. This number is Used to validate throughput based on the number of connections specified in:advanced.connection.pool.local.size
  • register-timeout: timeout waiting for permits. Should be less than or equal to `basic.request.timeout'
GitHub - aws-samples/amazon-keyspaces-java-driver-helpers

この throttler を有効化にするには、ドライバー設定の {@code Advanced.throttler} セクションを変更する。以下は設定例。

   datastax-java-driver {
      advanced.throttler = {
             class = com.aws.ssa.keyspaces.throttler.AmazonKeyspacesFixedRateThrottler
             max-requests-per-second = 1000
             number-of-hosts = 3
             register-timeout = 1 seconds
       }
   }
  • max-requests-per-second : 秒間リクエスト率を制御する。利用可能な許可が得られるか、タイムアウトに達するまでブロックします
  • number-of-hosts : system.peers テーブル内のホストの数。エンドポイントのタイプとリージョンに応じて、system.peers テーブル内のホストの数が異なる場合があります。この数値は、advanced.connection.pool.local.size で指定された接続数に基づいてスループットを検証するために使用されます。
  • register-timeout: 許可待ちのタイムアウト。「basic.request.timeout」以下である必要がある。