本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。
重试和超时
适用于 Go 的 AWS SDK 使您可以配置向 HTTP 服务发出的请求的重试行为。默认情况下,服务客户端使用 retry.Standard
适用于 Go 的 AWS SDK 提供了一个 AWS.retryer
标准重试器
retry.Standardaws.Retryer 实现。标准重试器是一种速率受限的重试器,其最大尝试次数可配置,并能够调整请求回退策略。
下表定义了此重试器的默认值:
| 属性 | 默认 |
|---|---|
|
最大尝试次数 |
3 |
|
最大回退延迟 |
20 秒 |
如果在调用请求时发生可重试错误,标准重试器将使用其提供的配置来延迟请求,并随后重试请求。重试会增加请求的总体延迟,如果默认配置不符合应用程序要求,则必须配置重试器。
有关标准重试器实现将哪些错误视为可重试错误的详细信息,请参阅 retry
NopRetryer
那个 a ws。 NopRetryeraws.Retryer实现。调用服务客户端操作时,此重试器只允许尝试执行一次请求,并且由此产生的任何错误都将返回给调用应用程序。
自定义行为
SDK 提供一组帮助程序实用程序(用于包装 aws.Retryer 实现),并返回提供的重试器(用所需重试行为进行了包装)。您可以根据应用程序要求,覆盖所有客户端、每个客户端或每项操作的默认重试器。要查看演示如何执行此操作的其他示例,请参阅 retry
警告
如果使用 config.WithRetryer 指定全局 aws.Retryer 实现,则必须确保每次调用都返回一个新的 aws.Retryer 实例。这将确保不会跨所有服务客户端创建一个全局重试令牌存储桶。
限制最大尝试次数
你使用重试。 AddWithMaxAttemptsaws.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)
限制最大回退延迟
你使用重试。 AddWithMaxBackoffDelayaws.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 错误代码
你使用重试。 AddWithErrorCodesaws.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)
客户端速率限制
在标准重试策略中 适用于 Go 的 AWS SDK 引入了一种新的客户端速率限制机制,以适应现代的行为。 SDKs这是由重试者选项上的RateLimiter
作为具有设定容量的令牌存储桶 RateLimiter 运行,其中操作尝试失败会消耗令牌。如果重试尝试消耗的令牌多于可用令牌,则会导致操作失败。QuotaExceededError
默认实现的参数化如下(如何修改每种设置):
-
容量为 500( StandardOptions 使用时设置 RateLimiter 的值 NewTokenRateLimit
) -
超时导致的重试消耗 10 个代币(设置为 RetryTimeoutCost 开启 StandardOptions)
-
由其他错误导致的重试消耗 5 个代币(设置为 RetryCost开启 StandardOptions)
-
第一次尝试成功的操作会添加 1 个令牌(设置为 “ NoRetryIncrement 启 StandardOptions用”)
-
第二次或以后的尝试成功的操作不会重新增加任何令牌
-
如果您发现默认行为不符合应用程序的需求,可以使用 ratelimit.None
示例:修改后的速率限制器
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 没有速率限制
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 }) }))
超时
调用服务客户端操作时,您可以使用 contexttime.Duration使用上下文之后设置超时。 WithTimeoutcontext.Context 传递给 HTTP 传输客户端。如果调用操作时,传递给 SDK 的上下文已取消或变成已取消状态,SDK 将不会进一步重试请求,并将返回到调用应用程序。如果提供给 SDK 的上下文变成已取消状态,则必须在应用程序中适当处理上下文取消。
设置超时值
以下示例代码演示了如何为服务客户端操作设置超时值。
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 }