在AWS SDK for Java 2.x 中配置重试行为 - AWS SDK for Java 2.x

本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。

在AWS SDK for Java 2.x 中配置重试行为

对 AWS 服务的调用偶尔会由于意想不到的原因而失败。某些错误 [例如节流(超出允许的速率限制)或临时性错误] 是暂时的,如果重试调用,可能会成功。AWS SDK for Java 2.x 具有内置机制,可检测此类错误并自动重试所有客户端默认启用的调用。

本页介绍其工作原理、如何配置不同的模式以及如何定制重试行为。

重试策略

重试策略是 SDK 中用于实现重试的一种机制。每个 SDK 客户端在构建时都会生成一个重试策略,该策略在客户端构建完成后就无法再修改。

重试策略负责完成以下任务。

  • 将异常归类为可重试或不可重试。

  • 计算下一次重试之前建议等待的延迟时间。

  • 维护一个令牌存储桶,该存储桶提供了一种机制,可以在很大一部分请求失败且重试也失败时停止重试。

注意

在 SDK 版本 2.26.0 发布重试 strategy(策略)之前,SDK 中的重试机制由重试 policy(策略)提供。重试 policy(策略) API 由 software.amazon.awssdk.core.retry 软件包中的核心 RetryPolicy 类组成,而 software.amazon.awssdk.retries 软件包包含重试 strategy(策略) API 元素。

重试策略(retry strategy)API 的引入,是 AWS 为统一各 SDK 核心组件的接口和行为而作出的全局努力的一部分。

适用于 Java 的 SDK 2.x 有三种内置的重试策略:标准、传统和自适应。所有三种重试策略都已预先配置为对一组可重试的异常进行重试。可重试错误的示例包括套接字超时、服务端节流、并发或乐观锁失败以及暂时性服务错误。

标准重试策略

对于正常使用案例,标准重试策略是推荐的 RetryStrategy 实现。与 AdaptiveRetryStrategy 不同,标准策略通常适用于所有重试使用案例。

默认情况下,标准重试策略执行以下操作。

  • 根据构建时配置的条件进行重试。您可以使用 StandardRetryStrategy.Builder#retryOnException 进行调整。

  • 重试 2 次,总共 3 次尝试。您可以使用 StandardRetryStrategy.Builder#maxAttempts(int) 进行调整。

  • 对于非节流异常,使用 BackoffStrategy#exponentialDelay 退避策略,基本延迟为 100 毫秒,最大延迟为 20 秒。您可以使用 StandardRetryStrategy.Builder#backoffStrategy 进行调整。

  • 对于节流异常,使用 BackoffStrategy#exponentialDelay 退避策略,基本延迟为 1 秒,最大延迟为 20 秒。您可以使用 StandardRetryStrategy.Builder#throttlingBackoffStrategy 进行调整。

  • 在下游服务频繁失败的情况下,执行断路(禁用重试)。始终执行第一次尝试,仅禁用重试。使用 StandardRetryStrategy.Builder#circuitBreakerEnabled 进行调整。

传统重试策略

传统重试策略RetryStrategy,适用于普通使用案例,但它已被弃用,取而代之的是 StandardRetryStrategy。当您未指定另一个策略时,这是客户端使用的默认重试策略。

该策略的特点是对节流和非节流异常采取不同的处理方式,对于节流异常,退避的基本延迟(500 毫秒)大于非节流异常的基本延迟(100 毫秒),并且节流异常不会影响令牌存储桶状态。

在 AWS 内部大规模使用该策略的经验表明,该策略并不比标准重试策略表现得更好。此外,该策略无法保护下游服务免受重试风暴的影响,并可能导致客户端资源匮乏。

默认情况下,传统重试策略执行以下操作。

  • 根据构建时配置的条件进行重试。您可以使用 LegacyRetryStrategy.Builder#retryOnException 进行调整。

  • 重试 3 次,总共 4 次尝试。您可以使用 LegacyRetryStrategy.Builder#maxAttempts(int) 进行调整。

  • 对于非节流异常,使用 BackoffStrategy#exponentialDelay 退避策略,基本延迟为 100 毫秒,最大延迟为 20 秒。您可以使用 LegacyRetryStrategy.Builder#backoffStrategy. 进行调整。

  • 对于节流异常,使用 BackoffStrategy#exponentialDelay 退避策略,基本延迟为 500 毫秒,最大延迟为 20 秒。您可以使用 LegacyRetryStrategy.Builder#throttlingBackoffStrategy 进行调整。

  • 在下游服务频繁失败的情况下,执行断路(禁用重试)。断路永远不会阻止成功的第一次尝试。您可以通过 LegacyRetryStrategy.Builder#circuitBreakerEnabled 调整此行为。

  • 断路器的状态不受节流异常的影响。

自适应重试策略

自适应重试策略RetryStrategy,适用于资源限制程度高的使用案例。

自适应重试策略包括标准策略的所有功能,并添加了客户端速率限制器,用于衡量节流请求相较于非节流请求的比率。该策略使用此衡量标准来减慢请求速度,目的是尽量保持在安全的带宽范围内,理想情况下可完全避免触发节流错误。

默认情况下,自适应重试策略执行以下操作。

  • 根据构建时配置的条件进行重试。您可以使用 AdaptiveRetryStrategy.Builder#retryOnException 进行调整。

  • 重试 2 次,总共 3 次尝试。您可以使用 AdaptiveRetryStrategy.Builder#maxAttempts(int) 进行调整。

  • 使用动态的退避延迟,该延迟根据下游资源当前的负载动态调整。

  • 在下游服务出现大量失败时,执行断路(禁用重试)。断路可能会阻止在中断情况下进行第二次尝试,从而保护下游服务。

警告

自适应重试策略假设客户端使用单个资源(例如,一个 DynamoDB 表或一个 Amazon S3 存储桶)。

如果您使用单个客户端处理多个资源,则当客户端访问所有其他资源时,与一个资源相关的节流或中断会导致延迟增加和出现故障。当您使用自适应重试策略时,我们建议您为每种资源使用一个客户端。

在所有客户端都对资源使用自适应重试策略的情况下,我们建议您也使用此策略。

重要

Java SDK 2.26.0 发布的重试策略包括新的 RetryMode.ADAPTIVE_V2 枚举值。ADAPTIVE_V2 模式修复了一个错误:当之前已检测到节流错误时,未能使第一次尝试延迟。

在 2.26.0 版本中,用户可以通过环境变量、系统属性或配置文件设置将模式设置为 adaptive,从而自动获得 ADAPTIVE_V2 模式行为。这些设置没有 adaptive_v2 值。有关如何设置模式的信息,请参阅以下 指定策略 部分。

用户可以通过使用 RetryMode.ADAPTIVE 在代码中设置模式来获取之前的行为。

摘要:重试策略默认值的比较

下表显示每种重试策略的属性的默认值。

策略 最大尝试次数 非节流错误的基本延迟 节流错误的基本延迟 令牌存储桶大小 每个非节流重试的令牌成本 每个节流重试的令牌成本
Standard 3 100 毫秒 1000 毫秒 500 5 5
传统 4 100 毫秒 500 毫秒 500 5 0
自适应 3 100 毫秒 100 毫秒 500 5 5
注意

对于所有重试策略,DynamoDB 客户端使用默认的最大重试次数为 8,该值高于上表中为其他 AWS 服务客户端显示的值。

指定策略

您可以通过四种方式为服务客户端指定策略。

在代码中

在构建客户端时,您可以使用重试策略配置 lambda 表达式。以下代码段配置了在 DynamoDB 服务客户端上使用默认值的标准重试策略。

DynamoDbClient client = DynamoDbClient.builder() .overrideConfiguration(o -> o.retryStrategy(RetryMode.STANDARD)) .build();

您可以指定 RetryMode.LEGACYRetryMode.ADAPTIVE 来代替 RetryMode.STANDARD

作为配置文件设置

包括 retry_mode 作为共享 AWS 配置文件中的配置文件设置。指定 standardlegacyadaptive 作为值。如果设置为配置文件设置,则在配置文件处于活动状态时创建的所有服务客户端都使用具有默认值的指定重试策略。您可以通过在代码中配置重试策略来覆盖此设置,如前所示。

使用以下配置文件,所有服务客户端都使用标准重试策略。

[profile dev] region = us-east-2 retry_mode = standard

作为 JVM 系统属性

您可以使用系统属性 aws.retryMode 为所有服务客户端配置重试策略,除非在代码中覆盖此设置。指定 standardlegacyadaptive 作为值。

调用 Java 时使用 -D 开关,如以下命令所示。

java -Daws.retryMode=standard ...

或者,在创建任何客户端之前在代码中设置系统属性,如以下代码段所示。

public void main(String[] args) { // Set the property BEFORE any AWS service clients are created. System.setProperty("aws.retryMode", "standard"); ... }

使用环境变量

您也可以使用值为 standardlegacyadaptiveAWS_RETRY_MODE 环境变量。与配置文件设置或 JVM 系统属性一样,除非您在代码中配置客户端,否则环境变量会将所有服务客户端配置为指定的重试模式。

以下命令将当前 shell 会话的重试模式设置为 standard

export AWS_RETRY_MODE=standard

自定义策略

您可以通过设置最大尝试次数、退避策略和可重试的异常来自定义任何重试策略。您可以自定义何时构建重试策略或何时构建客户端,方法是使用允许进一步完善已配置策略的覆盖生成器。

自定义最大尝试次数

您可以配置客户端构造期间的最大尝试次数,如以下语句所示。以下语句将客户端的默认重试策略自定义为最多 5 次尝试,第一次尝试加上 4 次重试。

DynamoDbClient client = DynamoDbClient.builder() .overrideConfiguration(o -> o.retryStrategy(b -> b.maxAttempts(5))) .build();

或者,您可以生成策略并将其提供给客户端,如以下代码示例所示。以下代码将标准的最多 3 次尝试替换为 10 次,并使用自定义策略配置 DynamoDB 客户端。

StandardRetryStrategy strategy = AwsRetryStrategy.standardRetryStrategy() .toBuilder() .maxAttempts(10) .build(); DynamoDbClient client = DynamoDbClient.builder() .overrideConfiguration(o -> o.retryStrategy(strategy)) .build();
警告

我们建议您为每个客户端配置一个唯一的 RetryStrategy 实例。如果共享 RetryStrategy 实例,则一个客户端出现故障可能会影响另一个客户端的重试行为。

您也可以使用外部设置,而不是使用代码来设置所有客户端的最大尝试次数。您可以按照指定策略部分所述来配置此设置。

自定义可重试异常

您可以配置其他异常,以便在客户端构造期间触发重试。提供这种自定义是为了应对边缘情况,在这些情况下,引发的异常并未包含在默认的可重试异常集合中。

retryOnExceptionretryOnExceptionOrCause 方法在现有的可重试异常集合中添加新的异常类型;这不会取代默认的异常集合。通过这种方式,您可以扩展重试行为,同时维持 SDK 的默认重试功能。

如果 SDK 引发直接异常,或者异常作为“原因”封装在另一个异常中,则 retryOnExceptionOrCause 方法会添加一个可重试的异常。

以下代码段显示了用于自定义重试异常的方法(retryOnExceptionretryOnExceptionOrCause)。如果 SDK 引发直接异常,或者异常已封装,则 retryOnExceptionOrCause 方法会添加一个可重试的异常。

DynamoDbClient client = DynamoDbClient.builder() .overrideConfiguration(o -> o.retryStrategy( b -> b.retryOnException(EdgeCaseException.class) .retryOnExceptionOrCause(WrappedEdgeCaseException.class))) .build();
重要

无论重试策略配置如何,当您调用 subscribeToShard 方法时,都会为 Kinesis 异步客户端禁用重试。

自定义退避策略

您可以制定退避策略并将其提供给客户端。

以下代码构建了 BackoffStrategy,它会替换默认标准策略的指数延迟退避策略。

BackoffStrategy backoffStrategy = BackoffStrategy.exponentialDelay(Duration.ofMillis(150), // The base delay. Duration.ofSeconds(15)); // The maximum delay. DynamoDbClient client = DynamoDbClient.builder() .overrideConfiguration(o -> o.retryStrategy( b -> b.backoffStrategy(backoffStrategy))) .build();

RetryPolicy 迁移到 RetryStrategy

RetryPolicy(重试策略 API)将在可预见的将来得到支持。如果您当前使用 RetryPolicy 的实例来配置客户端,则系统的行为将与之前完全一致。Java SDK 在后台将其改写为 RetryStrategy。新的重试策略接口提供的功能与 RetryPolicy 相同,但创建和配置方式有所不同。