

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

# 重试和超时
<a name="configure-retries-timeouts"></a>

 适用于 Go 的 AWS SDK 使您可以配置向 HTTP 服务发出的请求的重试行为。默认情况下，服务客户端使用 [retry.Standard](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/aws/retry#Standard) 作为其默认重试器。如果默认配置或行为不符合应用程序要求，可以调整重试器配置或提供自己的重试器实现。

 适用于 Go 的 AWS SDK 提供了一个 [AWS.retryer](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/aws#Retryer) 接口，该接口定义了实现重试实现所需的方法集。[该软件开发工具包提供了两种重试实现方式：[retry.](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/aws/retry#Standard) Standard 和 aws。 NoOpRetryer](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/aws#NoOpRetryer)。

## 标准重试器
<a name="standard-retryer"></a>

 [retry.Standard](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/aws/retry#Standard) 重试器是 SDK 客户端使用的默认 `aws.Retryer` 实现。标准重试器是一种速率受限的重试器，其最大尝试次数可配置，并能够调整请求回退策略。

 下表定义了此重试器的默认值：


| 属性 | 默认 | 
| --- | --- | 
| 最大尝试次数 | 3 | 
| 最大回退延迟 | 20 秒 | 

 如果在调用请求时发生可重试错误，标准重试器将使用其提供的配置来延迟请求，并随后重试请求。重试会增加请求的总体延迟，如果默认配置不符合应用程序要求，则必须配置重试器。

 有关标准重试器实现将哪些错误视为可重试错误的详细信息，请参阅 [retry](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/aws/retry) 程序包文档。

## NopRetryer
<a name="nopretryer"></a>

 那个 a [ws。 NopRetryer](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/aws#NopRetryer)如果您希望禁用所有重试尝试，则会提供此`aws.Retryer`实现。调用服务客户端操作时，此重试器只允许尝试执行一次请求，并且由此产生的任何错误都将返回给调用应用程序。

## 自定义行为
<a name="customizing-behavior"></a>

 SDK 提供一组帮助程序实用程序（用于包装 `aws.Retryer` 实现），并返回提供的重试器（用所需重试行为进行了包装）。您可以根据应用程序要求，覆盖所有客户端、每个客户端或每项操作的默认重试器。要查看演示如何执行此操作的其他示例，请参阅 [retry](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/aws/retry) 程序包文档示例。

**警告**  
 如果使用 `config.WithRetryer` 指定全局 `aws.Retryer` 实现，则必须确保每次调用都返回一个新的 `aws.Retryer` 实例。这将确保不会跨所有服务客户端创建一个全局重试令牌存储桶。

### 限制最大尝试次数
<a name="limiting-the-max-number-of-attempts"></a>

 你使用[重试。 AddWithMaxAttempts](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/aws/retry#AddWithMaxAttempts)封装`aws.Retryer`实现以将最大尝试次数设置为所需值。

**警告**  
 使用值为零的 `retry.AddWithMaxAttempts` 将允许 SDK 重试所有可重试错误，直到请求成功，或直到返回不可重试错误。**允许 SDK 无限次重试可能会导致工作负载失控和计费周期过长。**

```
import "context"
import "github.com/aws/aws-sdk-go-v2/aws/retry"
import "github.com/aws/aws-sdk-go-v2/config"
import "github.com/aws/aws-sdk-go-v2/service/s3"

// ...

// MaxAttempts will be infinite (will retry indefinitely)
cfg, err := config.LoadDefaultConfig(context.TODO(), config.WithRetryer(func() aws.Retryer {
    return retry.AddWithMaxAttempts(retry.NewStandard(), 0)
}))
if err != nil {
    return err
}

client := s3.NewFromConfig(cfg)
```

 请注意，使用 MaxAttempts 直接设置的功能选项实例化重试器的行为会略有不同。更具体地说，如果将值设置为小于或等于零，重试器将使用默认的最大尝试次数（即 3 次），而不是无限次重试：

```
import "context"
import "github.com/aws/aws-sdk-go-v2/aws/retry"
import "github.com/aws/aws-sdk-go-v2/config"
import "github.com/aws/aws-sdk-go-v2/service/s3"

// ...

// MaxAttempts will default to 3
cfg, err := config.LoadDefaultConfig(context.TODO(), config.WithRetryer(func() aws.Retryer {
    return retry.NewStandard(func(o *retry.StandardOptions) {
        o.MaxAttempts = 0
    })
}))
if err != nil {
    return err
}

client := s3.NewFromConfig(cfg)
```

### 限制最大回退延迟
<a name="limiting-the-max-back-off-delay"></a>

 你使用[重试。 AddWithMaxBackoffDelay](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/aws/retry#AddWithMaxBackoffDelay)封装`aws.Retryer`实现并限制在重试失败的请求之间允许的最大退出延迟。

 例如，您可以使用以下代码来包装标准客户端重试器，使其所需的最大延迟为五秒：

```
import "context"
import "time"
import "github.com/aws/aws-sdk-go-v2/aws/retry"
import "github.com/aws/aws-sdk-go-v2/config"
import "github.com/aws/aws-sdk-go-v2/service/s3"

// ...

cfg, err := config.LoadDefaultConfig(context.TODO(), config.WithRetryer(func() aws.Retryer {
    return retry.AddWithMaxBackoffDelay(retry.NewStandard(), time.Second*5)
}))
if err != nil {
    return err
}

client := s3.NewFromConfig(cfg)
```

### 重试其他 API 错误代码
<a name="retry-additional-api-error-codes"></a>

 你使用[重试。 AddWithErrorCodes](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/aws/retry#AddWithErrorCodes)封装`aws.Retryer`实现并包含其他 API 错误代码，这些错误代码应被视为可重试。

 例如，您可以使用以下代码来包装标准客户端重试器，以将 Amazon S3 `NoSuchBucketException` 异常包括在可重试的范围之内。

```
import "context"
import "time"
import "github.com/aws/aws-sdk-go-v2/aws/retry"
import "github.com/aws/aws-sdk-go-v2/config"
import "github.com/aws/aws-sdk-go-v2/service/s3"
import "github.com/aws/aws-sdk-go-v2/service/s3/types"

// ...

cfg, err := config.LoadDefaultConfig(context.TODO(), config.WithRetryer(func() aws.Retryer {
    return retry.AddWithErrorCodes(retry.NewStandard(), (*types.NoSuchBucketException)(nil).ErrorCode())
}))
if err != nil {
    return err
}

client := s3.NewFromConfig(cfg)
```

### 客户端速率限制
<a name="client-side-rate-limiting"></a>

 在标准重试策略中 适用于 Go 的 AWS SDK 引入了一种新的客户端速率限制机制，以适应现代的行为。 SDKs[这是由重试者选项上的[RateLimiter](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/aws/retry#RateLimiter)字段控制的行为。](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/aws/retry#StandardOptions)

 作为具有设定容量的令牌存储桶 RateLimiter 运行，其中操作尝试失败会消耗令牌。如果重试尝试消耗的令牌多于可用令牌，则会导致操作失败。[QuotaExceededError](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/aws/ratelimit#QuotaExceededError)

 默认实现的参数化如下（如何修改每种设置）：
+  容量为 500（ StandardOptions 使用时设置 RateLimiter 的值 [NewTokenRateLimit](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/aws/ratelimit#NewTokenRateLimit)） 
+  超时导致的重试消耗 10 个代币（设置为 RetryTimeoutCost 开启 StandardOptions） 
+  由其他错误导致的重试消耗 5 个代币（设置为 RetryCost开启 StandardOptions） 
+  第一次尝试成功的操作会添加 1 个令牌（设置为 “ NoRetryIncrement 启 StandardOptions用”） 
  +  第二次或以后的尝试成功的操作不会重新增加任何令牌 

 如果您发现默认行为不符合应用程序的需求，可以使用 [ratelimit.None](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/aws/ratelimit#pkg-variables) 将其禁用。

#### 示例：修改后的速率限制器
<a name="example-modified-rate-limiter"></a>

```
import (
    "context"

    "github.com/aws/aws-sdk-go-v2/aws"
    "github.com/aws/aws-sdk-go-v2/aws/ratelimit"
    "github.com/aws/aws-sdk-go-v2/aws/retry"
    "github.com/aws/aws-sdk-go-v2/config"
)

// ...

cfg, err := config.LoadDefaultConfig(context.Background(), config.WithRetryer(func() aws.Retryer {
    return retry.NewStandard(func(o *retry.StandardOptions) {
        // Makes the rate limiter more permissive in general. These values are
        // arbitrary for demonstration and may not suit your specific
        // application's needs.
        o.RateLimiter = ratelimit.NewTokenRateLimit(1000)
        o.RetryCost = 1
        o.RetryTimeoutCost = 3
        o.NoRetryIncrement = 10
    })
}))
```

#### 示例：使用 ratelimit.None 没有速率限制
<a name="example-no-rate-limit-using-ratelimitnone"></a>

```
import (
    "context"

    "github.com/aws/aws-sdk-go-v2/aws"
    "github.com/aws/aws-sdk-go-v2/aws/ratelimit"
    "github.com/aws/aws-sdk-go-v2/aws/retry"
    "github.com/aws/aws-sdk-go-v2/config"
)

// ...

cfg, err := config.LoadDefaultConfig(context.Background(), config.WithRetryer(func() aws.Retryer {
    return retry.NewStandard(func(o *retry.StandardOptions) {
        o.RateLimiter = ratelimit.None
    })
}))
```

## 超时
<a name="timeouts"></a>

 调用服务客户端操作时，您可以使用 [context](https://golang.org/pkg/context/) 程序包来设置超时或截止日期。使用[上下文。 WithDeadline](https://golang.org/pkg/context/#WithDeadline)封装您的应用程序上下文并将截止日期设置为必须完成调用操作的特定时间。在特定`time.Duration`使用[上下文之后设置超时。 WithTimeout](https://golang.org/pkg/context/#WithTimeout)。调用服务 API 时，SDK 会将提供的 `context.Context` 传递给 HTTP 传输客户端。如果调用操作时，传递给 SDK 的上下文已取消或变成已取消状态，SDK 将不会进一步重试请求，并将返回到调用应用程序。如果提供给 SDK 的上下文变成已取消状态，则必须在应用程序中适当处理上下文取消。

### 设置超时值
<a name="setting-a-timeout"></a>

 以下示例代码演示了如何为服务客户端操作设置超时值。

```
import "context"
import "time"

// ...

ctx := context.TODO() // or appropriate context.Context value for your application

client := s3.NewFromConfig(cfg)

// create a new context from the previous ctx with a timeout, e.g. 5 seconds
ctx, cancel := context.WithTimeout(ctx, 5*time.Second)
defer cancel()

resp, err := client.GetObject(ctx, &s3.GetObjectInput{
    // input parameters
})
if err != nil {
    // handle error
}
```