View a markdown version of this page

重试行为 - AWS 软件开发工具包和工具

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

重试行为

重要

此页面上描述的行为需要选择加入,直到它成为默认行为。AWS_NEW_RETRIES_2026=true在您的环境中设置。如果没有此设置,您的 SDK 将使用 2026 年之前的重试行为,这在退避时间、重试配额成本和特定于服务的默认值方面有所不同。有关详细信息,请参阅公告博客文章

当对的请求因暂时性错误或限制而 AWS 服务 失败时,SDK 可以自动重试该请求。本页介绍如何配置重试及其内部工作方式。

  • 配置重试次数:选择重试模式,设置最大尝试次数,并了解配置优先级。

  • 重试的工作原理: 重试流程、错误分类、退避公式、重试配额机制和特定于服务的行为。

配置重试次数

您可以控制 SDK 使用哪种重试策略以及重试次数。

选择重试模式

重试模式决定了请求失败时 SDK 的行为。有三种模式可供选择:标准模式、自适应模式和传统模式。

标准 自适应 Legacy
重试配额 支持 因 SDK 而异
可以延迟初始请求
Error-type-specific 退缩 支持 因 SDK 而异
跨软件开发工具包实现标准化 支持
建议 所有工作负载的默认值 Single-resource,节流密集,耐延迟 仅向后兼容

标准模式(默认)

标准模式使用带抖动的指数退避重试失败的请求。它对瞬态错误(例如网络超时)使用较短的延迟,对限制错误(例如)使用更长的延迟。ThrottlingException

标准模式包括重试配额,一个令牌桶,用于每次重试时扣除令牌,并在请求成功时补充令牌。当可用令牌用完时,SDK 会在不重试的情况下返回错误,因此您的应用程序会快速失败,而不是等待不太可能成功的重试。这还可以减少重试流量,从而帮助更快地解决服务中断问题。在正常操作期间,配额保持已满且无效。重试配额永远不会延迟或阻止初始请求。只有重试次数会受到影响。有关更多信息,请参阅 重试配额(令牌桶)

除非您有特殊理由选择其他模式,否则请使用标准模式。

自适应模式

自适应模式包括标准模式下的所有内容,以及客户端速率限制器。速率限制器跟踪限制响应并调整 SDK 发送请求的速率。与标准模式不同,当检测到限制时,自适应模式可以延迟或阻止初始请求,而不仅仅是重试。

速率限制器按照 SDK 客户端实例运行。来自客户端的所有请求都具有相同的速率限制,无论它们针对哪个 API 操作或资源。

何时使用自适应模式:

  • 您的客户端以单个资源(例如,一个 DynamoDB 表)为目标,并且您希望频繁出现限制响应。这在自动工作流程、批处理器或大批量调用单个 API 操作的 AI 工作负载中很常见。

  • 您希望 SDK 在服务发出限制信号时自动减速。

何时不使用自适应模式:

  • 您的客户端向多个资源发送请求或为多个租户提供服务。限制一个资源会导致速率限制器减慢来自该客户端的所有请求,包括对未受影响的资源的请求。

  • 初始请求需要可预测的延迟。

不建议将自适应模式作为常规默认模式。

传统模式

传统模式是每个 SDK 在引入标准模式之前使用的重试行为。它不包括标准化的重试配额。某些 SDK(例如 Java)在传统模式下有自己的重试配额实现,但各个 SDK 的行为并不一致。如果没有标准化配额,则在服务中断期间,客户端会继续全速重试。这会在不太可能成功的请求上占用线程和连接,同时增加可能延迟服务恢复的负载。

传统模式因软件开发工具包而异。重试次数、退避时间、可重试错误集和限制行为因语言而异。在软件开发工具包之间移动时,依赖于传统重试行为的代码的行为可能会有所不同。

可用版本:Java、Python、Ruby、PHP、C++、CLI

不适用于:.NET、Go、Kotlin、Rust、Swift、 JavaScript

存在传统模式是为了向后兼容。如果您当前使用传统模式,请切换到标准模式。

重试设置

以下设置控制重试行为。你可以通过环境变量共享配置文件 (~/.aws/config) 或代码中的客户端配置来设置它们。

设置 它控制什么 环境变量 Config 文件密钥 默认
重试模式 使用哪种重试策略 AWS_RETRY_MODE retry_mode standard
最大尝试次数 包括初始请求在内的总尝试次数 AWS_MAX_ATTEMPTS max_attempts 3(参见备注)

最大尝试值为,3表示 SDK 会发出一个初始请求和最多两次重试。将最大尝试次数设置为,1以完全禁用重试次数。

注意

DynamoDB 和 DynamoDB Streams 客户端默认为最大尝试次数。4这些服务使用较短的基本退避延迟(25 毫秒而不是 50 毫秒)来匹配其低延迟特征。额外的尝试使最后一次重试的最大退避率与其他服务相当。您可以使用上表中显示的相同设置来覆盖此设置。

配置优先级

当您在多个位置指定相同的设置时,SDK 会使用以下优先顺序(从高到低)来解析该值:

  1. 代码中的显式客户端配置。直接在 SDK 客户端或其配置对象上设置的值。

  2. 环境变量例如,AWS_RETRY_MODEAWS_MAX_ATTEMPTS

  3. 共享配置文件retry_modemax_attempts键入~/.aws/config

  4. SDK 默认。该设置的内置默认值。

这遵循标准的 AWS SDK 配置优先级。在较高级别设置的值总是会覆盖在较低级别上设置的值。例如,如果您retry_mode=standard在中设置AWS_RETRY_MODE=adaptive为环境变量~/.aws/config,则 SDK 将使用自适应模式。

Language-specific 配置

本页面(retry_modemax_attempts)中描述的跨SDK设置适用于所有软件开发工具包。但是,在代码中配置重试的 API 因语言而异。有关特定语言的配置选项,例如自定义退避策略、其他可重试错误和重试配额调整,请参阅您的 SDK 开发者指南。

重试的工作原理

本节介绍 AWS SDK 如何处理失败的请求:哪些错误会触发重试、SDK 在两次尝试之间等待多长时间以及何时停止重试。

请求失败时会发生什么

当您通过 SDK 进行 API 调用时, AWS SDK 将遵循以下顺序:

  1. 仅限自适应模式SDK 会检查客户端速率限制器。如果检测到限制,SDK 可能会在发送请求之前延迟或阻止请求。

  2. SDK 将请求发送到 AWS 服务 终端节点。

  3. 如果服务返回成功响应,SDK 会将结果返回到您的代码中。

  4. 如果请求失败,SDK 会将错误分类为暂时错误、限制错误或不可重试错误。请参阅哪些错误会被重试

  5. 如果错误不可重试,SDK 会立即将错误返回到您的代码中。未尝试重试。

  6. 如果错误是可重试的,SDK 会检查它是否已达到最大尝试次数。如果是,它会将错误返回到您的代码中。

  7. 软件开发工具包会检查重试配额(令牌桶). 如果代币预算耗尽,SDK 不会重试,而是将错误返回到您的代码中。例外:对于Long-polling 操作,SDK 在返回错误之前仍会应用退避延迟。

  8. SDK 根据错误类型和重试尝试次数计算退避延迟。请参阅SDK 要等多久

  9. SDK 等待计算出的延迟,然后从步骤 2 开始再次发送请求。

SDK 会重复此循环,直到请求成功、达到最大尝试次数、用完重试配额或出现不可重试的错误。整个过程是自动的。您的应用程序要么看到成功响应,要么看到最终错误。

哪些错误会被重试

SDK 将每个失败的请求分为三类之一:暂时请求、限制请求或不可重试。此分类决定了 SDK 是否重试请求以及在重试之前等待多长时间。

分类基于服务响应中的错误代码HTTP 状态码。例如,带有错误代码的 HTTP 400 RequestTimeout 被归类为临时并重试。带有ValidationException的 HTTP 400 被归类为不可重试并立即返回。

错误分类

使用较短的基准延迟(50 ms)重试@@ 瞬态错误

错误代码
RequestTimeout
RequestTimeoutException
InternalError
IDPCommunicationError
I/O 失败(连接重置、DNS 解析失败、套接字超时)
(任何没有识别错误代码的 HTTP 500、502、503 或 504)

使用更长的基本延迟(1,000 ms)重试@@ 限制错误

错误代码
Throttling
ThrottlingException
ThrottledException
RequestThrottledException
TooManyRequestsException
ProvisionedThroughputExceededException
TransactionInProgressException
LimitExceededException
PriorRequestNotComplete
RequestThrottled
EC2ThrottledException
RequestLimitExceeded
SlowDown
BandwidthLimitExceeded

Non-retryable 错误(例如AccessDeniedExceptionValidationExceptionResourceNotFoundException)会立即返回到您的代码中。

注意

带有限制错误代码的 HTTP 5XX 被归类为限制错误,而不是暂时错误,即使 5XX 错误通常是暂时性的。SDK 首先匹配错误代码,然后回退到 HTTP 状态码。

限制错误意味着服务由于速率限制而主动拒绝了您的请求,因此 SDK 会等待更长的时间才能重试,让服务有时间恢复容量。SDK 要等多久有关具体延迟,请参阅。

SDK 要等多久

SDK 使用指数退避和完全抖动。平均而言,每次重试的等待时间都比上次更长,通过随机化来分散来自多个客户端的请求。

按错误类型划分的基本延迟

基本延迟取决于错误是瞬态的还是节流的:

错误类型 基础延迟 理由
瞬态(非节流) 50 毫秒 瞬态错误通常会在几毫秒内解决。短的基础延迟可实现快速恢复。
节流 1,000 ms 该服务对请求进行了速率限制。基础延迟越长,可以有时间恢复容量。

退避公式

SDK 使用以下公式计算每次重试延迟:

delay = random(0, 1) × min(20,000 ms, base_delay × 2^retry)

其中:

  • random(0, 1)返回介于 0 和 1 之间的均匀分布值

  • base_delay对于瞬态错误为 50 毫秒,对于节流错误为 1,000 毫秒

  • retry第一次重试(第二次整体请求尝试)从 0 开始

最大退避上限为 20 秒。无论尝试了多少次,个别延迟都不会超过 20 秒。

行之有效的例子

示例 1:暂时错误,最大尝试次数 3 次

步骤 发生了什么 Delay
尝试 1 初始请求。服务返回 HTTP 503。 (无)
尝试 2 SDK 会随机等待(0, 50 毫秒)。使用 503 重试失败。 0—50 毫秒(平均约为 25 毫秒)
尝试 3 SDK 会随机等待(0, 100 毫秒)。重试成功。 0—100 毫秒(平均约为 50 毫秒)

两次重试的总增加延迟平均约为 75 毫秒。

示例 2:限制错误,最大尝试次数 3 次

步骤 发生了什么 Delay
尝试 1 初始请求。服务退货429. Throttling (无)
尝试 2 SDK 会随机等待(0, 1,000 毫秒)。重试返回 429。 0—1,000 毫秒(平均约为 500 毫秒)
尝试 3 SDK 会随机等待(0, 2,000 毫秒)。重试成功。 0—2,000 毫秒(平均约为 1,000 毫秒)

两次重试的总增加延迟平均约为 1,500 毫秒。

示例 3:瞬态错误,达到退避上限

基本延迟为 50 ms 时,上限之前的计算延迟为:

重试尝试 计算出的最大延迟 20 秒后上限
1 50 毫秒 50 毫秒
2 100 毫秒 100 毫秒
5 800 毫秒 800 毫秒
9 12,800 毫秒 12,800 毫秒
10 25,600 毫秒 200000 ms

对于暂时性错误,上限在第 10 次重试(第 11 次尝试)时生效。对于基准为 1,000 ms 的节流错误,上限将在第 6 次重试时生效。

注意

默认情况下,最大尝试次数为 3 次(1 次初始请求 + 2 次重试),则永远不会达到退避上限。下表说明了如果增加幅度远max_attempts远超过默认值会发生什么。

为什么抖动很重要

随机乘数称为完全抖动。没有它,所有同时遇到错误的客户端都会同时重试,从而产生大量的重试流量(“雷鸣般的群体” 问题)。完全抖动在整个退避窗口中均匀地分布重试次数,因此服务会收到稳定的请求流,而不是同步的峰值。

例如,假设 1,000 个客户同时收到 503。完全抖动会将他们的第一次重试次数均匀分布在 50 毫秒的时间段内,而不是将所有 1,000 次重试次数均匀分布在 50 毫秒。

Server-directed 重试时机

有些在错误响应中 AWS 服务 包含x-amz-retry-after标题。标头值是以毫秒为单位的延迟。当存在此标头时,SDK 将使用服务器指定的延迟,限制为计算出的退避延迟的最小值和计算的退避延迟的最大值加上 5,000 ms。由于计算出的退避本身上限为 20 秒,因此服务器引导的最大有效延迟为 25 秒。SDK 不会对这个值应用抖动,因为服务应该会抖动它。这使服务能够在预期容量可用时准确地进行通信。

重试配额(令牌桶)

SDK 维护内部代币预算,用于跟踪成功请求与失败的比率。当故障普遍存在时,预算就会耗尽,SDK 会直接返回错误。您的应用程序会快速失败,而不是等待不太可能成功的重试。这还可以减少重试流量,帮助更快地解决服务中断问题。

重试配额的工作原理

代币预算一开始就满了。每次重试尝试都会扣除代币。重试成功后,SDK 会恢复该重试所消耗的令牌。当请求在第一次尝试时成功时(无需重试),SDK 会恢复 1 个令牌。当预算达到零时,SDK 会停止重试,并将错误直接返回到您的代码。

参数
预算容量 500 个代币
每次暂时(非限制)重试的成本 14 个代币
每次重试限制的费用 5 个代币
重试后成功恢复令牌 上次重试消耗量(14 或 5)
成功恢复令牌无需重试 1 个代币

瞬态重试的成本较高反映了它们的失败模式不同。诸如 500 和连接故障之类的暂时性错误通常表示存在服务范围的问题。在这种情况下,继续重试不太可能成功。它会增加您的通话延迟,占用客户资源,并可能延迟所有人的恢复。限制错误表明服务需要更多时间才能成功请求。为了提高成功的可能性,SDK 会在两次重试之间等待更长的时间。

配额何时会阻止重试

重试配额会随时跟踪代币,但只有在预算耗尽时才会阻止重试。在正常运行期间,几乎所有请求都会成功,并且预算仍然满额。配额对重试没有明显的影响。

成功的重试仅恢复其自身的代币成本(14 或 5 个令牌),而不会恢复同一个请求中较早失败的重试成本。例如,如果第一次重试失败,第二次重试成功,则预算净损失14个代币。当重试耗尽所有尝试但未成功时,预算消耗得最快,但是当请求需要多次重试才能成功时,预算也会逐渐耗尽。

默认情况下,最大尝试次数为 3 次,当超过大约 22% 的请求导致持续的暂时失败,或者超过大约 32% 的请求导致限制错误时,配额就会开始耗尽。低于这些比率时,成功的请求会比失败的重试耗尽预算的速度更快。

预算的起始余额为500个代币,提供了一个缓冲区,可以吸收短暂的失败。短暂的错误激增,即使是严重的错误,也不会阻止重试,除非它持续足够长的时间以耗尽缓冲区。

实际影响

  • 故障率低:配额无效。预算保持在或接近容纳能力。

  • 服务中断期间:如果您的请求中有很大一部分持续失败,则配额将耗尽,您的客户端会立即返回错误,而不是等待重试。这可以减少客户端延迟,释放线程和连接,并帮助服务更快地恢复。

  • 恢复:当服务恢复并且请求再次开始成功时,成功的重试会恢复其全部代币消耗,首次尝试成功将恢复 1 个令牌。预算会逐渐充满,重试会自动恢复。

  • 范围:代币预算通常限于单个 SDK 客户端实例。具体范围可能因 SDK 而异。它不在进程或主机之间共享。

Service-specific 行为

DynamoDB

DynamoDB 客户端使用针对 DynamoDB 的低延迟配置文件进行了优化的调整默认值:

设置 一般默认 DynamoDB 默认
瞬态(非节流)基本延迟 50 毫秒 25 毫秒
限制基本延迟 1,000 ms 1,000 ms
最大尝试次数 3 4

这些默认值适用于亚马逊 DynamoDB 和 DynamoDB Streams。

Long-polling 操作

某些 AWS 操作使用长轮询。他们可以保持连接处于打开状态,等待工作到达。这些操作会受到特殊的重试处理:

  • SQS.ReceiveMessage

  • SFN.GetActivityTask

  • SWF.PollForActivityTask

  • SWF.PollForDecisionTask

特殊行为:当重试配额耗尽且重试被阻止(中的第 7 步请求失败时会发生什么)时,SDK 在将错误返回到您的代码之前仍会应用退避延迟。

这很重要,因为长轮询操作通常是在紧密循环中调用的。您的代码会调用ReceiveMessage、处理所有消息,然后立即ReceiveMessage再次调用。如果不强制退缩,代币预算耗尽将导致 SDK 毫不延迟地返回错误。然后,您的轮询循环将立即发送下一个请求,从而激增客户端 CPU 使用率并产生额外的流量。强制退避延迟打破了这个周期,使客户端资源使用量和轮询率在故障期间保持可控性。

Support by AWS SDK 和工具

下表列出了每个 SDK 中更新后的重试行为的可用性。 SDK-specific 有关包括最低版本、之前和之后的默认值以及代码示例在内的详细信息,请参阅 GitHub 跟踪问题。