全部產品
Search
文件中心

Alibaba Cloud SDK:重試機制

更新時間:Dec 24, 2025

原版 Java SDK 重試機制介紹。

說明

新增重試機制及流控策略(基於流控策略的優雅退避機制)。

核心庫 aliyun-java-sdk-core 從 4.6.0 版本開始支援重試機制,以及提供基於流控策略的優雅退避方案(基於流控策略的優雅退避機制)。Maven 依賴如下:

<dependency>
    <groupId>com.aliyun</groupId>
    <artifactId>aliyun-java-sdk-core</artifactId>
    <version>4.6.0</version>
</dependency>

重試機制

關閉重試

預設不開啟重試,您也可以主動配置重試策略為 None,有以下兩種方式:

// Client 層級配置,關閉重試
client.setSysRetryPolicy(RetryPolicy.none());

// Request 層級配置重試策略,優先順序大於 Client 層級
request.setSysRetryPolicy(RetryPolicy.none());

重試策略

重試策略提供三種:

  1. 指定異常(Exception)

  2. 指定狀態代碼(Http StatusCode)

  3. 指定服務端返回頭(Http Response Headers)

三種方式互不影響,即三種之間是或關係,觸發任何一種 State 則進行重試或者不重試。也就是說,策略可以是觸發重試的策略也可以是限制重試的策略。

觸發重試和限制重試參考以下配置方式:

  • 建立重試策略集合:

    Set<RetryCondition> retryConditions = new HashSet<RetryCondition>();
    
    // Condition 舉例
    // 觸發重試的 statusCode 配置,例:當狀態代碼返回 500 或 501 時進行重試
    Set<Integer> statusCodes = new HashSet<Integer>();
    statusCodes.add(500); // http statusCode
    statusCodes.add(501); // http statusCode
    // 加入到觸發重試策略中
    retryConditions.add(StatusCodeCondition.create(statusCodes));
    
    // 觸發重試的 exception 配置,例:當遇到 SocketTimeoutException 或 IOException 時進行重試
    Set<Class<? extends Exception>> exceptions = new HashSet<Class<? extends Exception>>();
    exceptions.add(SocketTimeoutException.class); // exception
    exceptions.add(IOException.class); // exception
    // 加入到觸發重試策略中
    retryConditions.add(ExceptionsCondition.create(exceptions));
  • 建立限制重試集合:

    Set<RetryCondition> throttlingConditions = new HashSet<RetryCondition>();
    
    // Condition 舉例
    // 限制重試的 statusCode 配置,例如:當狀態代碼返回 429 時禁止進行重試
    Set<Integer> code = new HashSet<Integer>();
    code.add(429); // http statusCode,限制策略,此處表示遇到 429 則限制重試
    // 加入到限制重試策略中
    throttlingConditions.add(StatusCodeCondition.create(code));
  • 最後將 Conditions 配置到 RetryPolicy 中:

    RetryPolicy retryPolicy = RetryPolicy.builder()
                    .maxNumberOfRetries(3) // 最大重試次數
                    .maxDelayTimeMillis(20 * 1000) // 最大稍候再試時間,單位為 ms,超過這個時間則不再重試
                    .retryConditions(retryConditions) // 觸發重試策略
                    .throttlingConditions(throttlingConditions) // 限制重試策略
                    .build();

其中每次重試的間隔時間,則是根據指數退避演算法計算出,也就是使用的 EqualJitter 演算法計算出下次重試等待時間。

重試 Conditions 高階設定

官方提供了三種 Condition,這裡做更加詳細的介紹。

  1. StatusCodeCondition

    1. 存放的是整數集合,根據集合中的 HTTP 狀態代碼,與此次調用的返回的真實的狀態代碼做比較,然後判斷是否進行重試或者限制重試。

  2. ExceptionsCondition

    1. 存放的是 Exception 集合,根據集合中的 Exception 類型,與此次調用的返回的拋出的異常做比較,然後判斷是否進行重試或者限制重試。

  3. HeadersCondition

    1. 存放的是個 Map,該結構稍微複雜,Map 的 key 值匹配的是返回頭 Headers 的 key 值,Map 的 value 需要實現 Pattern(com.aliyuncs.policy.retry.pattern.Pattern) 介面,表示對 Headers 相應 key 對應的 value 做運算式匹配,例如:包含某個字串、等於某個數值等。

    2. 官方實現了兩個 Pattern,一個是 AliyunThrottlingPattern(基於阿里雲的流控策略,基於流控策略的優雅退避機制),另一個是 SimplePattern(直接比較 value 字串是否相等)

    3. 可自訂實現 Pattern 介面,其中三個函數需要實現:

      1. meetState(),表示匹配上的原則;

      2. escapeTime(),表示逃脫時間,僅用於限制重試策略上,若該值不等於 -1,則表示在該時間內不進行重試,但也不會直接限制重試,而是等待到可以重試時,再進行重試。若該值大於最大稍候再試時間,則直接返回不再等待。

      3. readFormHeadersContent(String content),這個函數表示給待匹配的值進行賦值,可直接摘抄 SimplePattern 類的實現。

  4. 自訂 Condition

    1. 使用者可實現自己的 Condition,只需要實現 RetryCondition 介面,需要實現兩個介面函數:

      1. meetState(RetryPolicyContext var1),根據上下文判斷是否符合匹配狀態;

      2. escapeTime(RetryPolicyContext var1),計算逃脫時間,僅用於限制重試策略上,觸發重試策略則預設 -1。

完整程式碼範例

程式碼範例:

package com.aliyun.sample;

import com.aliyuncs.CommonRequest;
import com.aliyuncs.CommonResponse;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.exceptions.ServerException;
import com.aliyuncs.exceptions.ThrottlingException;
import com.aliyuncs.policy.retry.RetryPolicy;
import com.aliyuncs.policy.retry.conditions.ExceptionsCondition;
import com.aliyuncs.policy.retry.conditions.RetryCondition;
import com.aliyuncs.policy.retry.conditions.StatusCodeCondition;
import com.aliyuncs.profile.DefaultProfile;

import java.io.IOException;
import java.net.SocketTimeoutException;
import java.util.HashSet;
import java.util.Set;

public class Sample {
    public static void main(String[] args) {
        // 建立DefaultAcsClient執行個體並初始化
        DefaultProfile profile = DefaultProfile.getProfile(
                // 地區ID
                "cn-hangzhou",
                // 從環境變數擷取RAM使用者的AccessKey ID
                System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID"),
                // 從環境變數擷取RAM使用者的AccessKey SECRET
                System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET"));
        IAcsClient client = new DefaultAcsClient(profile);
        // Client 層級配置重試策略
        client.setSysRetryPolicy(RetryPolicy.none());
        // 以CommonRequest為樣本,當前配置亦適用於產品SDK,即<APIName>Request
        CommonRequest request = new CommonRequest();
        // Request 層級配置重試策略,優先順序大於 Client 層級
        request.setSysRetryPolicy(RetryPolicy.defaultRetryPolicy(true));

        // 觸發重試的 statusCode 配置
        Set<RetryCondition> retryConditions = new HashSet<RetryCondition>();
        Set<Integer> statusCodes = new HashSet<Integer>();
        statusCodes.add(500); // http statusCode
        statusCodes.add(501); // http statusCode
        retryConditions.add(StatusCodeCondition.create(statusCodes));

        // 觸發重試的 exception 配置
        Set<Class<? extends Exception>> exceptions = new HashSet<Class<? extends Exception>>();
        exceptions.add(SocketTimeoutException.class); // exception
        exceptions.add(IOException.class); // exception
        retryConditions.add(ExceptionsCondition.create(exceptions));

        // 限制重試的 statusCode 配置
        Set<RetryCondition> throttlingConditions = new HashSet<RetryCondition>();
        Set<Integer> code = new HashSet<Integer>();
        code.add(429); // http statusCode,限制策略,此處表示遇到 429 則限制重試
        throttlingConditions.add(StatusCodeCondition.create(code));

        RetryPolicy retryPolicy = RetryPolicy.builder()
                .maxNumberOfRetries(3) // 最大重試次數
                .maxDelayTimeMillis(20 * 1000) // 最大稍候再試時間,超過這個時間則不再重試
                .retryConditions(retryConditions) // 重試觸發策略
                .enableAliyunThrottlingControl(true) // 使用阿里雲流控策略進行控制
                .throttlingConditions(throttlingConditions) // 也可以自己寫限制策略
                .build();

        try {
            // 以CommonRequest為樣本,當前配置亦適用於產品SDK,即<APIName>Request
            CommonResponse response = client.getCommonResponse(request);
            System.out.println(response.getData());
        } catch (ServerException e) {
            e.printStackTrace();
        } catch (ClientException e) {
            e.printStackTrace();
            if (ThrottlingException.class.isAssignableFrom(e.getCause().getClass())) {
                // 流控異常包在 ClientException 中
            }
        }
    }
}