本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。
重试行为
重要
此页面上描述的行为需要选择加入,直到它成为默认行为。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 会使用以下优先顺序(从高到低)来解析该值:
这遵循标准的 AWS SDK 配置优先级。在较高级别设置的值总是会覆盖在较低级别上设置的值。例如,如果您retry_mode=standard在中设置AWS_RETRY_MODE=adaptive为环境变量~/.aws/config,则 SDK 将使用自适应模式。
Language-specific 配置
本页面(retry_mode和max_attempts)中描述的跨SDK设置适用于所有软件开发工具包。但是,在代码中配置重试的 API 因语言而异。有关特定语言的配置选项,例如自定义退避策略、其他可重试错误和重试配额调整,请参阅您的 SDK 开发者指南。
重试的工作原理
本节介绍 AWS SDK 如何处理失败的请求:哪些错误会触发重试、SDK 在两次尝试之间等待多长时间以及何时停止重试。
请求失败时会发生什么
当您通过 SDK 进行 API 调用时, AWS SDK 将遵循以下顺序:
-
仅限自适应模式:SDK 会检查客户端速率限制器。如果检测到限制,SDK 可能会在发送请求之前延迟或阻止请求。
-
SDK 将请求发送到 AWS 服务 终端节点。
-
如果服务返回成功响应,SDK 会将结果返回到您的代码中。
-
如果请求失败,SDK 会将错误分类为暂时错误、限制错误或不可重试错误。请参阅哪些错误会被重试。
-
如果错误不可重试,SDK 会立即将错误返回到您的代码中。未尝试重试。
-
如果错误是可重试的,SDK 会检查它是否已达到最大尝试次数。如果是,它会将错误返回到您的代码中。
-
软件开发工具包会检查重试配额(令牌桶). 如果代币预算耗尽,SDK 不会重试,而是将错误返回到您的代码中。例外:对于Long-polling 操作,SDK 在返回错误之前仍会应用退避延迟。
-
SDK 根据错误类型和重试尝试次数计算退避延迟。请参阅SDK 要等多久。
-
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 错误(例如AccessDeniedException、ValidationException、ResourceNotFoundException)会立即返回到您的代码中。
注意
带有限制错误代码的 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 跟踪问题。
| SDK | 支持 | GitHub 追踪问题 |
|---|---|---|
| 适用于 Java 2.x 的 SDK | 是 | 追踪问题 |
| 适用于 Python (Boto3) 的 SDK |
是 | 追踪问题 |
| 适用于.NET 4.x 的 SDK | 是 | 追踪问题 |
| 适用于 PowerShell V5 的工具 | 是 | 追踪问题 |
| 适用于 JavaScript 3.x 的软件开发工具包 | 是 | 追踪问题 |
| 适用于 PHP 3.x 的 SDK | 是 | 追踪问题 |
| 适用于 Kotlin 的 SDK | 是 | 追踪问题 |
| 适用于 Rust 的 SDK | 是 | 追踪问题 |
| 适用于 Swift 的 SDK | 查看追踪问题 | 追踪问题 |
| 适用于 Ruby 3.x 的 SDK | 查看追踪问题 | 追踪问题 |
| 适用于 Go V2 (1.x) 的 SDK | 查看追踪问题 | 追踪问题 |
| 适用于 C++ 的 SDK | 查看追踪问题 | 追踪问题 |
| AWS CLI v2 | 查看追踪问题 | 追踪问题 |