欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java接口請求重試機制的幾種常見方法

 更新時間:2023年11月06日 09:58:29   作者:fking86  
Java接口請求重試機制是保證系統(tǒng)穩(wěn)定性和容錯能力的重要手段之一,當接口請求發(fā)生失敗或暫時性錯誤時,通過重試機制可以提高請求的成功率,本文將詳細介紹Java接口請求重試機制的幾種常見方法,需要的朋友可以參考下

1.幾種方法

1.1循環(huán)重試

它的基本思路是:

  1. 定義重試次數,如最大重試5次
  2. 發(fā)送請求,如果失敗則進入重試邏輯
  3. 在循環(huán)內部,記錄當前已重試次數,如當前已重試2次
  4. 判斷當前重試次數是否達到最大次數,如果達到則終止循環(huán),否則進行重試
  5. 在循環(huán)內部,可以添加定時重試間隔,也可以使用指數退避算法
  6. 發(fā)送重試請求,重復判斷是否成功,直到成功、達到最大次數或其他終止條件

示例

public class Retry {

  private static final int MAX_RETRIES = 5;

  public static Response request() throws Exception {
    int retries = 0;
    while (true) {
      try {
        // 發(fā)送請求,返回響應
        Response response = HttpClient.sendRequest();

        // 請求成功則返回響應
        if (response.isSuccess()) {
          return response; 
        }

      } catch (Exception e) {
        // 請求失敗進行重試
      }

      // 判斷是否超過最大重試次數
      if (++retries >= MAX_RETRIES) {
        throw new Exception("Exceeded max retries");
      }

      // 增加間隔后重試
      int interval = (int) (Math.random() * 1000); 
      Thread.sleep(interval);
    }
  }

  public static void main(String[] args) throws Exception {
    Response response = request();
    // ...
  }

}

1.2 使用Spring Retry庫

使用 Spring Retry 庫可以很方便地實現接口請求的重試機制。

1.2.1 添加 Maven 依賴

<dependency>
    <groupId>org.springframework.retry</groupId>
    <artifactId>spring-retry</artifactId>
    <version>1.3.1</version>
</dependency>

1.2.2 添加 @EnableRetry 注解啟用重試功能

1.2.3 在需要重試的方法上添加 @Retryable 注解

@Retryable(value = Exception.class, maxAttempts = 3, backoff = @Backoff(delay = 5000))
public User getUser(String id) {
  // 遠程調用接口 
}

@Retryable 定義了重試規(guī)則:- value - 重試的異常類型

- maxAttempts - 最大重試次數

- backoff - 重試等待策略

1.2.4. 還可以自定義 RetryTemplate 進行更復雜的重試控制

RetryTemplate template = new RetryTemplate();

template.execute(context -> {
  // 可在此處自定義重試邏輯
  
  return remoteClient.invoke(); 
});

Spring Retry 為接口請求重試提供了完善和易用的解決方案,可以靈活控制各種重試參數,適用于復雜系統(tǒng)的容錯要求。

1.3 并發(fā)框架異步重試

使用并發(fā)框架的異步請求方式可以較簡單地實現接口請求的重試機制。以CompletableFuture為例:

1.3.1 發(fā)送請求使用CompletableFuture封裝:

CompletableFuture<Response> future = CompletableFuture.supplyAsync(() -> {
  return service.call();
});

1.3.2 當請求失敗時,使用retryAsync自動完成重試:

future = future.exceptionally(e -> {
  return service.retryAsync(); 
});

1.3.3 可以鏈式調用,自定義重試邏輯:

future
  .exceptionally(e -> {
     // 處理異常
  })
  .thenApplyAsync(resp -> {
     // 處理響應
  })
  .retryAsync(retryCount, delay); 

主要優(yōu)點是:

  • 線程安全的異步請求
  • 自動重試失敗任務
  • 簡潔的鏈式編程方式
  • 避免阻塞主線程

使用并發(fā)框架可以便捷地實現異步重試機制,提高系統(tǒng)容錯性。其他框架如RxJava也有類似的重試機制。

1.4 消息隊列重試

使用消息隊列可以實現接口請求的異步重試機制。

基本思路是:

  • 接口請求發(fā)送失敗后,將請求信息封裝為消息,發(fā)送到請求重試的隊列中。

  • 消息消費者從隊列中獲取失敗的請求,根據策略進行重試。

  • 重復重試直到成功、重試次數用盡或其他終止條件。

  • 成功后將消息移除隊列,失敗則保留消息供再次重試。

主要步驟:

  • 創(chuàng)建請求重試隊列,如“request.retry.queue”

  • 接口請求失敗后,生成重試消息,發(fā)送到隊列

  • 消費者啟動線程從隊列中取消息重試

  • 根據重試策略進行定時重試或最大重試數

  • 成功則確認消息,失敗則重新入隊

使用消息隊列進行重試有利于:

  • 異步重試,不阻塞主線程
  • 可靠地完成重試任務
  • 靈活控制重試策略

示例

// 1. 創(chuàng)建隊列
Queue retryQueue = new Queue("request.retry.queue");

// 2. 請求失敗,發(fā)送重試消息  
public void request() {
  try {
    // 調用接口
    httpClient.post(url, payload);
  } catch (Exception e) {
    // 發(fā)送重試消息
    Message msg = new Message(url, payload, maxRetries);
    retryQueue.send(msg);
  }
}

// 3. 消費者線程進行重試
class RetryConsumer implements Runnable {

  public void run() {
    while (true) {
      Message msg = retryQueue.take();
      
      for (int i = 0; i < msg.getMaxRetries(); i++) {
        try {
          // 重試請求
          httpClient.post(msg.getUrl(), msg.getPayload());
          // 請求成功,結束循環(huán)
          break;
        } catch (Exception e) {
          // 等待后繼續(xù)重試
        }  
      }
      
      // 重試完成后,確認消息
      retryQueue.confirm(msg);
    }
  }
}

這就是使用消息隊列實現接口重試的基本流程,可以根據需求擴展重試策略、異常處理等邏輯。

1.5 自定義重試工具類

使用自定義的重試工具類來實現接口請求的重試機制,提高代碼的復用性和可維護性。

重試工具類的實現思路:

  • 提供重試方法,參數包括請求函數、重試策略等
  • 在重試方法內部執(zhí)行循環(huán)請求
  • 每次請求失敗時,根據策略等待一段時間
  • 記錄當前重試次數,與最大次數比較
  • 請求成功或者達到最大重試次數則結束循環(huán)

示例:

public class RetryUtil {

  public static <T> T retry(RetryCallable<T> callable, RetryPolicy policy) {
    int retries = 0; 
    while(true) {
      try {
        return callable.call();  
      } catch(Exception e) {
        if (retries >= policy.maxRetries) {
          throw e;
        }
        // 等待
        policy.delay();
        // 重試次數加1
        retries++;
      }
    }
  }

}

// 執(zhí)行請求的函數接口
interface RetryCallable<T> {
  T call(); 
}

// 重試策略 
class RetryPolicy {
  int maxRetries;
  int delay; 
}

// 使用示例
RetryUtil.retry(() -> {
  // 接口請求
  return httpClient.get(url); 
}, policy);

這樣可以提高重試相關邏輯的復用性,避免寫重復代碼。

1.6 使用遞歸結構

使用遞歸結構也可以實現接口請求的重試機制。

基本思路是設計一個遞歸函數,在函數內部發(fā)送請求,如果失敗則繼續(xù)遞歸調用自身再次重試。

示例:

public class RetryRequest {

  private static final int MAX_RETRIES = 3;
  
  public static Response request(int retries) {
    
    try {
      // 發(fā)送請求
      Response response = HttpClient.get("http://example.com");
      return response;
      
    } catch (Exception e) {
      
      // 處理異常
      
      // 判斷是否需要重試
      if (retries < MAX_RETRIES) {
        // 增加重試次數
        retries++; 
        // 延遲1秒鐘
        Thread.sleep(1000); 
        // 遞歸調用自身進行重試
        return request(retries);
      }
      
      // 重試失敗
      throw new RuntimeException("Request failed after " + MAX_RETRIES + " retries!");
      
    }
  }
  
  public static void main(String[] args) {  
    Response response = request(0);
    // 處理響應
  }

}

主要邏輯是通過遞歸不斷調用自身來實現重試。優(yōu)點是邏輯較簡單清晰,缺點是遞歸層次過深時可能會導致堆棧溢出。需要合理設置最大遞歸深度,也可以通過循環(huán)改寫遞歸來避免深層遞歸。

1.7 使用Resilience4j

Resilience4j是一個很好的Java重試庫,可以用它來實現接口請求的重試機制。

主要步驟:

1.7.1添加Resilience4j依賴

<dependency>
  <groupId>io.github.resilience4j</groupId>
  <artifactId>resilience4j-retry</artifactId>
</dependency>

1.7.2 定義重試邏輯

RetryConfig config = RetryConfig.custom()
  .maxAttempts(3)
  .waitDuration(Duration.ofMillis(500))
  .build();

Retry retry = Retry.of("backend", config);

1.7.3 使用重試邏輯調用接口

String result = retry.executeSupplier(() -> {

  // 發(fā)送請求
  return backendService.callAPI(); 

});

1.7.4 自定義重試異常predicate

RetryConfig config = RetryConfig.custom()
  .retryOnException(e -> isRetryable(e))
  .build();

Resilience4j提供了線程安全的重試 decorator,可以通過配置靈活控制重試策略,很好地支持了接口請求重試。

1.8 使用網絡工具重試

我們常用的一些網絡工具來做重試

示例

public class RetryExample {

  private static final int MAX_RETRIES = 3;

  public static String request(String url) throws Exception {

    int retries = 0; 
    
    while (true) {
      
      try {
        // 使用HttpClient發(fā)送請求
        return HttpClientUtils.get(url);
        
      } catch (Exception e) {

        if (retries >= MAX_RETRIES) {
          throw e;
        }
        
        // 增加重試次數
        retries++;

        // 延遲1秒鐘
        TimeUnit.SECONDS.sleep(1);

      }
    }
  }
    
  public static void main(String[] args) throws Exception {
    String result = request("http://example.com/api");
    System.out.println(result);
  }

}

// 網絡工具類 
class HttpClientUtils {

  public static String get(String url) throws IOException {
    // 發(fā)送GET請求并返回結果
  }

}

主要通過循環(huán)和網絡工具類來實現重試邏輯,延時控制也可以用Random來實現指數退避。這種 utilities + 循環(huán) 的組合可以實現靈活可復用的重試機制。

2.注意事項

接口請求重試時需要注意以下幾點:

2.1 冪等性
接口需要是冪等的,多次調用結果相同,避免重復執(zhí)行帶來副作用。

2.2 資源競爭
重試可能對服務端造成更大壓力,需要考慮限流等措施。

2.3 超時設置
合理設置重試最大次數和總超時時間,避免長時間等待。

2.4 重試條件
明確哪些異常情況下需要重試,不能無腦重試所有錯誤。

2.5 數據一致性
請求成功后要冪等更新狀態(tài),避免重復數據。

2.6 異步機制
重試過程不要阻塞主業(yè)務線程。

2.7 退避策略
失敗后延遲一段時間再重試,可選避免集群重試。

2.8 日志記錄
記錄重試的次數、錯誤原因等信息,方便排查問題。

2.9 容錯機制
重試失敗后的降級處理,避免級聯失敗。

總結

接口請求重試機制對保證系統(tǒng)高可用非常關鍵,需要根據業(yè)務需求選擇合適的重試策略。常用的組合策略包括帶最大次數的定時/指數退避重試、故障轉移重試等。重試機制需要綜合設置以達到容錯效果 yet又避免產生過大的系統(tǒng)負載。

相關文章

  • Java如何取掉json數據中值為null的屬性字段

    Java如何取掉json數據中值為null的屬性字段

    這篇文章主要介紹了Java如何取掉json數據中值為null的屬性字段,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-03-03
  • 如何獲取java類中的屬性注釋

    如何獲取java類中的屬性注釋

    在開發(fā)中,有時需要獲取Java類的屬性注釋,尤其是當JPA生成的表缺少注釋時,可以通過jdk自帶的tools.jar工具包來實現,方法類似于生成javadoc文檔,需要在pom.xml文件中導入tools.jar的依賴,該jar文件一般位于JAVA_HOME/lib目錄下
    2024-09-09
  • Spring源碼如何修改Bean的屬性用到的相關類

    Spring源碼如何修改Bean的屬性用到的相關類

    這篇文章主要介紹了Spring源碼如何修改Bean的屬性用到的相關類,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-05-05
  • Spring實戰(zhàn)之清除緩存操作示例

    Spring實戰(zhàn)之清除緩存操作示例

    這篇文章主要介紹了Spring實戰(zhàn)之清除緩存操作,結合實例形式詳細分析了spring清除緩存操作具體步驟、配置、領域模型及相關使用技巧,需要的朋友可以參考下
    2020-01-01
  • Java基礎之this關鍵字的使用

    Java基礎之this關鍵字的使用

    今天給大家?guī)淼氖顷P于Java基礎的相關知識,文章圍繞著this關鍵字的使用展開,文中有非常詳細的介紹及代碼示例,需要的朋友可以參考下
    2021-06-06
  • java實現可安裝的exe程序實例詳解

    java實現可安裝的exe程序實例詳解

    這篇文章主要介紹了java實現可安裝的exe程序實例詳解的相關資料,通過此文希望能幫助到大家,讓大家實現這樣的功能,需要的朋友可以參考下
    2017-10-10
  • @AutoConfigurationPackage與@ComponentScan注解區(qū)別

    @AutoConfigurationPackage與@ComponentScan注解區(qū)別

    這篇文章主要介紹了@AutoConfigurationPackage與@ComponentScan注解區(qū)別,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-06-06
  • Java基于BIO實現文件上傳功能

    Java基于BIO實現文件上傳功能

    這篇文章主要為大家詳細介紹了Java基于BIO實現文件上傳功能,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-11-11
  • Spring Boot Starter 自動裝配原理全解析

    Spring Boot Starter 自動裝配原理全解析

    Spring Boot Starter 的核心設計理念是 約定優(yōu)于配置,其核心實現基于 自動配置(Auto-Configuration) 和 條件化注冊(Conditional Registration),這篇文章主要介紹了Spring Boot Starter 自動裝配原理全解析,需要的朋友可以參考下
    2025-04-04
  • Servlet 過濾器詳細介紹

    Servlet 過濾器詳細介紹

    這篇文章介紹了Servlet 過濾器,有需要的朋友可以參考一下
    2013-10-10

最新評論