

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

# 中的重試次數 適用於 Kotlin 的 AWS SDK
<a name="retries"></a>

呼叫 AWS 服務 偶爾會傳回未預期的例外狀況。如果重試呼叫，某些類型的錯誤可能會成功，例如限流或暫時性錯誤。

此頁面說明如何自動 適用於 Kotlin 的 AWS SDK 處理重試，以及如何為您的應用程式自訂重試行為。

## 了解重試行為
<a name="retries-understanding"></a>

下列各節說明 SDK 如何決定何時重試請求，以及哪些例外狀況被視為可重試。

### 預設重試組態
<a name="retries-default"></a>

根據預設，每個服務用戶端都會自動設定[標準重試策略](https://docs.aws.amazon.com/smithy-kotlin/api/latest/runtime-core/aws.smithy.kotlin.runtime.retries/-standard-retry-strategy/index.html)。預設組態會嘗試最多失敗三次的呼叫 （初次嘗試加上兩次重試）。每個呼叫之間的介入延遲會設定為指數退避和隨機抖動，以避免重試風暴。此組態適用於大多數使用案例，但在某些情況下可能不適合，例如高輸送量系統。

開發套件只會在可重試的錯誤上重試。可重試錯誤的範例包括通訊端逾時、服務端限流、並行或樂觀鎖定失敗，以及暫時性服務錯誤。遺失或無效的參數、身分驗證/安全錯誤，以及錯誤設定例外狀況都視為無法重試。

您可以設定最大嘗試次數、延遲和退避，以及字符儲存貯體組態，來自訂標準重試策略。

### 哪些例外狀況可以重試？
<a name="retries-default-policy-details"></a>

 適用於 Kotlin 的 AWS SDK 使用預先設定的重試政策，決定哪些例外狀況可以重試。服務用戶端組態具有`retryPolicy`屬性，可指定套用至重試的政策。如果未指定自訂值，則預設值為 [AwsRetryPolicy](https://docs.aws.amazon.com/sdk-for-kotlin/api/latest/aws-http/aws.sdk.kotlin.runtime.http.retries/-aws-retry-policy/)。

下列例外狀況由 判斷為可重試`AwsRetryPolicy`：

#### 依錯誤碼重試
<a name="retries-retryable-by-error-code"></a>

任何`ServiceException`具有 `sdkErrorMetadata.errorCode`的 ：
+ `BandwidthLimitExceeded`
+ `EC2ThrottledException`
+ `IDPCommunicationError`
+ `LimitExceededException`
+ `PriorRequestNotComplete`
+ `ProvisionedThroughputExceededException`
+ `RequestLimitExceeded`
+ `RequestThrottled`
+ `RequestThrottledException`
+ `RequestTimeout`
+ `RequestTimeoutException`
+ `SlowDown`
+ `ThrottledException`
+ `Throttling`
+ `ThrottlingException`
+ `TooManyRequestsException`
+ `TransactionInProgressException`

#### 可透過 HTTP 狀態碼重試
<a name="retries-retryable-by-status-code"></a>

任何`ServiceException`具有 `sdkErrorMetadata.statusCode`的 ：
+ 500 （內部服務錯誤）
+ 502 （無效的閘道）
+ 503 （服務無法使用）
+ 504 （閘道逾時）

#### 依錯誤類型重試
<a name="retries-retryable-by-error-type"></a>

任何`ServiceException`具有 `sdkErrorMetadata.errorType`的 ：
+ `ErrorType.Server` （例如內部服務錯誤）
+ `ErrorType.Client` （例如無效的請求、找不到資源、存取遭拒等）

#### 可由 SDK 中繼資料重試
<a name="retries-retryable-by-metadata"></a>

下列任何`SdkBaseException`位置：
+ `sdkErrorMetadata.isRetryable` 是 `true`（例如用戶端逾時、聯網/通訊端錯誤等）
+ `sdkErrorMetadata.isThrottling` 是 `true`（例如在短時間內提出太多請求）

如需每個服務用戶端可能擲回之例外狀況的完整清單，請參閱[服務特定的 API 參考文件](https://docs.aws.amazon.com/#products)。

### 檢查例外狀況是否可重試
<a name="retries-check-exception-retryable"></a>

若要判斷 SDK 是否將例外狀況視為可重試，請檢查抓取例外狀況的 `isRetryable` 屬性：

```
try {
    dynamoDbClient.putItem {
        tableName = "MyTable"
        item = mapOf("id" to AttributeValue.S("123"))
    }
} catch (e: SdkBaseException) {
    println("Exception occurred: ${e.message}")
    
    if (e.sdkErrorMetadata.isRetryable) {
        println("This exception is retryable - SDK will automatically retry")
        println("If you're seeing this, retries may have been exhausted")
    } else {
        println("This exception is not retryable - fix the underlying issue")
        
        // Common non-retryable scenarios.
        when {
            e.message?.contains("ValidationException") == true -> 
                println("Check your request parameters")
            e.message?.contains("AccessDenied") == true -> 
                println("Check your IAM permissions")
            e.message?.contains("ResourceNotFound") == true -> 
                println("Verify the resource exists")
        }
    }
}
```

### 當重試失敗時，哪些例外狀況會到達您的程式碼
<a name="retries-exception-types-during-retries"></a>

當開發套件的重試機制無法解決問題時，您的應用程式程式碼會擲回例外狀況。了解這些例外狀況類型可協助您實作適當的錯誤處理。這些*不是*觸發重試的例外狀況，這些例外狀況是由 SDK 在內部處理。

當重試用盡或停用時，您的程式碼會擷取以下類型的例外狀況：

重試耗盡後的服務例外狀況  
當所有重試嘗試都失敗時，您的程式碼會擷取導致最後一次重試嘗試失敗的最終服務例外狀況 ( 的子類別`AwsServiceException`)。這可能是調節錯誤、伺服器錯誤，或 SDK 無法透過重試解決的其他服務特定例外狀況。

重試耗盡後的網路例外狀況  
當網路問題在所有重試嘗試中持續存在時，您的程式碼會擷取`ClientException`執行個體是否有連線逾時、DNS 解析失敗，以及開發套件無法解決的其他連線問題。

使用下列模式來處理應用程式中的這些例外狀況：

```
try {
    s3Client.getObject { 
        bucket = "amzn-s3-demo-bucket"
        key = "my-key" 
    }
} catch (e: AwsServiceException) {
    // Service-side errors that persisted through all retries.
    println("Service error after retries: ${e.errorDetails?.errorCode} - ${e.message}")
    
    // Handle specific service errors that couldn't be resolved.
    if (e.errorDetails?.errorCode == "ServiceQuotaExceededException" || 
        e.errorDetails?.errorCode == "ThrottlingException") {
        println("Rate limiting persisted - consider longer delays or quota increase")
    }
} catch (e: ClientException) {
    // Client-side errors (persistent network issues, DNS resolution failures, etc.)
    println("Client error after retries: ${e.message}")
}
```

## 自訂重試行為
<a name="retries-customizing"></a>

下列各節說明如何針對特定使用案例自訂 SDK 的重試行為。

### 設定最大嘗試次數
<a name="retires-max-attempts"></a>

您可以在用戶端建構期間自訂 [`retryStrategy` DSL 區塊](https://docs.aws.amazon.com/smithy-kotlin/api/latest/runtime-core/aws.smithy.kotlin.runtime.retries/-standard-retry-strategy/-config/-builder/index.html)中的預設最大嘗試次數 (3)。

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

使用上一個程式碼片段中顯示的 DynamoDB 服務用戶端，軟體開發套件會嘗試失敗最多五次的 API 呼叫 （初次嘗試加上四次重試）。

您可以將最大嘗試次數設定為一個，完全停用自動重試，如下列程式碼片段所示。

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

### 設定延遲和退避
<a name="retries-delays-backoff"></a>

如果需要重試，預設重試策略會先等待，再進行後續嘗試。第一次重試的延遲很小，但之後重試會呈指數增長。延遲的最大數量受到限制，因此不會太大。

最後，隨機抖動會套用至所有嘗試之間的延遲。抖動有助於減輕可能導致重試風暴的大型機群的影響。（如需指數退避和抖動的深入討論，請參閱此[AWS 架構部落格文章](https://aws.amazon.com/blogs/architecture/exponential-backoff-and-jitter/)。)

延遲參數可在 [`delayProvider` DSL 區塊](https://docs.aws.amazon.com/smithy-kotlin/api/latest/runtime-core/aws.smithy.kotlin.runtime.retries.delay/-exponential-backoff-with-jitter/-config/index.html)中設定。

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

使用上一個程式碼片段中顯示的組態，用戶端會將第一次重試嘗試延遲最多 100 毫秒。任何重試嘗試之間的時間上限為 5 秒。

下列參數可用於調校延遲和退避。


| 參數 | 預設值 | Description | 
| --- | --- | --- | 
| initialDelay | 10 毫秒 | 第一次重試的延遲量上限。套用抖動時，實際延遲量可能較少。 | 
| jitter | 1.0 （全抖動） |  隨機減少計算延遲的最大振幅。預設值 1.0 表示計算的延遲可以減少到 100% 的任何數量 （例如，低至 0)。值為 0.5 表示計算的延遲最多可減少一半。因此，最大延遲 10 毫秒可以減少到 5 毫秒到 10 毫秒之間的任何位置。值 0.0 表示不會套用抖動。  ️抖動組態是一項進階功能。通常不建議自訂此行為。   | 
| maxBackoff | 20 秒 | 套用至任何嘗試的最大延遲量。設定此值會限制後續嘗試之間發生的指數成長，並防止計算出的最大值過大。此參數會限制套用抖動之前計算的延遲。如果套用，抖動可能會進一步減少延遲。 | 
| scaleFactor | 1.5 | 將增加後續最大延遲的指數基礎。例如，假設 `initialDelay`為 10 毫秒，而 `scaleFactor`為 1.5，則會計算下列最大延遲：[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_tw/sdk-for-kotlin/latest/developer-guide/retries.html)套用抖動時，每個延遲的實際數量可能較少。 | 

### 設定重試權杖儲存貯體
<a name="retries-token-bucket"></a>

您可以調整預設字符儲存貯體組態，進一步修改標準重試策略的行為。重試字符儲存貯體有助於減少不太可能成功或可能需要更多時間才能解決的重試，例如逾時和限流失敗。

**重要**  
字符儲存貯體組態是一項進階功能。通常不建議自訂此行為。

每次重試嘗試 （選擇性包括初次嘗試） 都會從字符儲存貯體減少一些容量。減少的數量取決於嘗試的類型。例如，重試暫時性錯誤可能很便宜，但重試逾時或限流錯誤可能更昂貴。

成功的嘗試會將容量傳回至儲存貯體。儲存貯體不可增加到超過其最大容量，也不能減少到零以下。

根據 `useCircuitBreakerMode`設定的值， 嘗試將容量減少到零以下會導致下列其中一個結果：
+ 如果設定為 TRUE，則會擲回例外狀況 – 例如，如果發生太多重試次數，而且不太可能成功執行更多重試次數。
+ 如果設定為 FALSE，則會有延遲 – 例如，延遲直到儲存貯體再次有足夠的容量。

**注意**  
當斷路器啟用 （權杖儲存貯體達到零容量） 時，軟體開發套件會擲回`ClientException`具有「超過重試容量」訊息的 。這是用戶端例外狀況，而不是 `AwsServiceException`，因為它源自開發套件的重試邏輯，而不是 AWS 服務。例外狀況會立即擲回，而不嘗試操作，有助於防止在服務中斷期間重試風暴。

權杖儲存貯體參數可在 [`tokenBucket` DSL 區塊](https://docs.aws.amazon.com/smithy-kotlin/api/latest/runtime-core/aws.smithy.kotlin.runtime.retries.delay/-standard-retry-token-bucket/-config/index.html)中設定：

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

下列參數可用於調校重試字符儲存貯體：


| 參數 | 預設值 | Description | 
| --- | --- | --- | 
| initialTryCost | 0 | 初始嘗試從儲存貯體減少的數量。預設值 0 表示不會減少任何容量，因此初始嘗試不會停止或延遲。 | 
| initialTrySuccessIncrement | 1 | 初始嘗試成功時增加容量的數量。 | 
| maxCapacity | 500 | 字符儲存貯體的最大容量。可用的字符數量不能超過此數量。 | 
| refillUnitsPerSecond | 0 | 每秒重新新增至儲存貯體的容量。值為 0 表示不會自動新增任何容量。（例如，只有成功嘗試會導致容量增加）。值 0 useCircuitBreakerMode 必須為 TRUE。 | 
| retryCost | 5 | 暫時性失敗後嘗試從儲存貯體減少的數量。如果嘗試成功，相同的數量會重新遞增回儲存貯體。 | 
| timeoutRetryCost | 10 | 逾時或限流失敗後嘗試從儲存貯體減少的數量。如果嘗試成功，相同的數量會重新遞增回儲存貯體。 | 
| useCircuitBreakerMode | TRUE | 決定當嘗試減少容量會導致儲存貯體的容量低於零時的行為。當 TRUE 時，字符儲存貯體會擲回例外狀況，表示不再有重試容量。FALSE 時，字符儲存貯體會延遲嘗試，直到重新填充足夠的容量為止。 | 

如需重試案例期間擲回的例外狀況類型詳細資訊，包括斷路器例外狀況，請參閱 [當重試失敗時，哪些例外狀況會到達您的程式碼](#retries-exception-types-during-retries)。

### 設定適應性重試
<a name="retries-adaptive-retries"></a>

作為標準重試策略的替代方案，自適應重試策略是一種進階方法，可尋求理想的請求速率，以將限流錯誤降至最低。

**重要**  
自適應重試是一種進階重試模式。通常不建議使用此重試策略。

自適應重試包含標準重試的所有功能。它會新增用戶端速率限制器，測量節流請求相較於非節流請求的速率。它也會限制流量以嘗試保持在安全頻寬內，理想情況下會導致零限流錯誤。

速率會即時適應不斷變化的服務條件和流量模式，並可能相應地增加或減少流量速率。最重要的是，速率限制器可能會延遲高流量情況下的初始嘗試。

您可以為 `retryStrategy`方法提供額外的參數，以選取自適應重試策略。速率限制器參數可在 [`rateLimiter` DSL 區塊](https://docs.aws.amazon.com/smithy-kotlin/api/latest/runtime-core/aws.smithy.kotlin.runtime.retries.delay/-adaptive-rate-limiter/-config/index.html)中設定。

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

**注意**  
自適應重試策略假設用戶端針對單一資源 （例如，一個 DynamoDB 資料表或一個 Amazon S3 儲存貯體） 運作。  
如果您將單一用戶端用於多個資源，當用戶端存取所有其他資源時，與一個資源相關聯的限流或中斷會導致延遲增加和失敗。當您使用自適應重試策略時，我們建議您為每個資源使用單一用戶端。