重试 - AWS SDK for Kotlin

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

重试

调用 AWS 服务 偶尔会返回意外异常。如果重试呼叫,某些类型的错误(例如限制或暂时错误)可能会成功。

本页介绍如何使用配置自动重试。 AWS SDK for Kotlin

默认重试配置

默认情况下,每个服务客户端都会自动配置标准重试策略。默认配置最多会尝试失败三次的呼叫(初次尝试加上两次重试)。每次呼叫之间的中间延迟配置为指数退避和随机抖动,以避免重试风暴。此配置适用于大多数用例,但在某些情况下可能不适合,例如高吞吐量系统。

只有在SDK出现可重试的错误时才会重试。可重试错误的示例包括套接字超时、服务端限制、并发或乐观锁定失败以及暂时性服务错误。参数缺失或无效、身份验证/安全错误和配置错误异常均视为不可重试。

您可以通过设置最大尝试次数、延迟和退避次数以及令牌桶配置来自定义标准重试策略。

最大尝试次数

在构造客户端期间,您可以自定义retryStrategyDSL区块中的默认最大尝试次数 (3)。

val dynamoDb = DynamoDbClient.fromEnvironment { retryStrategy { maxAttempts = 5 } }

上一个片段中显示了 DynamoDB 服务客户端,SDKAPI尝试调用最多失败五次(初次尝试加上四次重试)。

您可以通过将最大尝试次数设置为一次来完全禁用自动重试,如以下代码段所示。

val dynamoDb = DynamoDbClient.fromEnvironment { retryStrategy { maxAttempts = 1 // The SDK makes no retries. } }

延迟和退缩

如果需要重试,则默认的重试策略会等待,然后再进行后续尝试。第一次重试的延迟很小,但是对于以后的重试,延迟会呈指数级增长。最大延迟量是有上限的,这样它就不会变得太大。

最后,随机抖动会应用于所有尝试之间的延迟。抖动有助于减轻可能导致重试风暴的大型舰队的影响。(有关指数回退和抖动的更深入讨论,请参阅这篇AWS 架构博客文章。)

延迟参数可在delayProviderDSL模块中配置。

val dynamoDb = DynamoDbClient.fromEnvironment { retryStrategy { delayProvider { initialDelay = 100.milliseconds maxBackoff = 5.seconds } } }

使用上一个片段所示的配置,客户端将第一次重试尝试最多延迟 100 毫秒。任何重试尝试之间的最大间隔为 5 秒。

以下参数可用于调整延迟和退缩。

参数 默认值 描述
initialDelay 10 毫秒 第一次重试的最大延迟时间。施加抖动时,实际延迟量可能会更少。
jitter 1.0(完全抖动)

随机减少计算延迟的最大振幅。默认值为 1.0 意味着计算出的延迟可以减少到不超过 100% 的任意值(例如,降至 0)。值为 0.5 意味着计算出的延迟最多可以减少一半。因此,10 毫秒的最大延迟可以减少到 5 毫秒到 10 毫秒之间的任何值。值为 0.0 表示不施加任何抖动。

重要

️ 抖动配置是一项高级功能。通常不建议自定义此行为。

maxBackoff 20 秒 适用于任何尝试的最大延迟时间。设置此值可以限制在后续尝试之间发生的指数级增长,并防止计算出的最大值过大。此参数限制了在应用抖动之前计算出的延迟。如果应用抖动,则可能会进一步缩短延迟。
scaleFactor 1.5

随后的最大延迟将增加的指数基数。例如,假定 a 为 initialDelay 10ms,a 为 scaleFactor 1.5,则将计算出以下最大延迟:

  • 重试 1:10ms × 1.5= 10ms

  • 重试 2:10ms × 1.5¹ = 15ms

  • 重试 3:10ms × 1.5² = 22.5ms

  • 重试 4:10ms × 1.5³ = 33.75ms

当施加抖动时,每次延迟的实际量可能会更少。

重试令牌桶

您可以通过调整默认令牌桶配置来进一步修改标准重试策略的行为。重试令牌存储桶有助于减少不太可能成功或可能需要更多时间才能解决的重试,例如超时和限制失败。

重要

令牌存储桶配置是一项高级功能。通常不建议自定义此行为。

每次重试尝试(可选包括初次尝试)都会减少令牌桶中的一些容量。减少的金额取决于尝试的类型。例如,重试瞬态错误可能很便宜,但重试超时或限制错误可能会更昂贵。

成功尝试将容量返回到存储桶。存储桶的增量不得超过其最大容量,也不得减至零以下。

根据useCircuitBreakerMode设置的值,尝试将容量减少到零以下会导致以下结果之一:

  • 如果设置为TRUE,则会引发异常 — 例如,如果重试次数过多,而更多的重试不太可能成功。

  • 如果设置为FALSE,则会有延迟,例如,延迟到存储桶再次有足够的容量。

令牌桶参数可在tokenBucketDSL区块中配置:

val dynamoDb = DynamoDbClient.fromEnvironment { retryStrategy { tokenBucket { maxCapacity = 100 refillUnitsPerSecond = 2 } } }

以下参数可用于调整重试令牌存储桶:

参数 默认值 描述
initialTryCost 0 初始尝试时要从存储桶中减少的金额。默认值 0 表示容量不会减少,因此初始尝试不会停止或延迟。
initialTrySuccessIncrement 1 初始尝试成功时要增加容量的量。
maxCapacity 500 令牌桶的最大容量。可用代币的数量不能超过此数字。
refillUnitsPerSecond 0 每秒向存储桶重新添加的容量。值为 0 表示不会自动重新添加任何容量。(例如,只有成功的尝试才会增加容量)。值必须useCircuitBreakerMode为 0 TRUE。
retryCost 5 暂时失败后尝试从存储桶中减少的金额。如果尝试成功,则将相同的金额重新递增回存储桶。
timeoutRetryCost 10 超时或限制失败后尝试从存储桶中减少的金额。如果尝试成功,则将相同的金额重新递增回存储桶。
useCircuitBreakerMode TRUE 确定尝试减少容量会导致存储桶容量降至零以下时的行为。何时TRUE,令牌存储桶将抛出一个异常,表示不再存在重试容量。何时FALSE,令牌桶将延迟尝试,直到重新填充了足够的容量。

自适应重试

作为标准重试策略的替代方案,自适应重试策略是一种高级方法,它寻求理想的请求速率以最大限度地减少限制错误。

重要

自适应重试是一种高级重试模式。通常不建议使用这种重试策略。

自适应重试包括标准重试的所有功能。它添加了一个客户端速率限制器,用于衡量受限制请求与非限制请求的比率。它还会限制流量以尝试保持在安全带宽内,理想情况下会导致节流错误为零。

该速率会实时适应不断变化的服务条件和交通模式,并可能相应地增加或降低流量速率。至关重要的是,在高流量场景中,速率限制器可能会延迟初始尝试。

您可以通过为retryStrategy方法提供附加参数来选择自适应重试策略。速率限制器参数可在rateLimiterDSL模块中配置。

val dynamoDb = DynamoDbClient.fromEnvironment { retryStrategy(AdaptiveRetryStrategy) { maxAttempts = 10 rateLimiter { minFillRate = 1.0 smoothing = 0.75 } } }
注意

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

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