亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

聊聊Java中接口重試機(jī)制的幾種解決方案

 更新時(shí)間:2025年07月28日 10:38:18   作者:The-Venus  
接口請(qǐng)求重試機(jī)制是保證系統(tǒng)穩(wěn)定性和容錯(cuò)能力的重要手段之一,當(dāng)接口請(qǐng)求發(fā)生失敗或暫時(shí)性錯(cuò)誤時(shí),通過(guò)重試機(jī)制可以提高請(qǐng)求的成功率,本文將詳細(xì)介紹接口請(qǐng)求重試機(jī)制的幾種常見(jiàn)方法,感興趣的可以了解一下

1.前言

接口請(qǐng)求重試機(jī)制是保證系統(tǒng)穩(wěn)定性和容錯(cuò)能力的重要手段之一。當(dāng)接口請(qǐng)求發(fā)生失敗或暫時(shí)性錯(cuò)誤時(shí),通過(guò)重試機(jī)制可以提高請(qǐng)求的成功率。本文將詳細(xì)介紹接口請(qǐng)求重試機(jī)制的幾種常見(jiàn)方法。

2.幾種方法

2.1循環(huán)重試

它的基本思路是:

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

示例

public class Retry {

  private static final int MAX_RETRIES = 5;

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

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

      } catch (Exception e) {
        // 請(qǐng)求失敗進(jìn)行重試
      }

      // 判斷是否超過(guò)最大重試次數(shù)
      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();
    // ...
  }

}

2.2 使用Spring Retry庫(kù)

使用 Spring Retry 庫(kù)可以很方便地實(shí)現(xiàn)接口請(qǐng)求的重試機(jī)制。

2.2.1 添加 Maven 依賴

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

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

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

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

@Retryable 定義了重試規(guī)則:- value - 重試的異常類型
- maxAttempts - 最大重試次數(shù)
- backoff - 重試等待策略

2.2.4. 還可以自定義 RetryTemplate 進(jìn)行更復(fù)雜的重試控制

RetryTemplate template = new RetryTemplate();

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

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

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

使用并發(fā)框架的異步請(qǐng)求方式可以較簡(jiǎn)單地實(shí)現(xiàn)接口請(qǐng)求的重試機(jī)制。以CompletableFuture為例:

2.3.1 發(fā)送請(qǐng)求使用CompletableFuture封裝:

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

2.3.2 當(dāng)請(qǐng)求失敗時(shí),使用retryAsync自動(dòng)完成重試:

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

2.3.3 可以鏈?zhǔn)秸{(diào)用,自定義重試邏輯:

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

主要優(yōu)點(diǎn)是:

  • 線程安全的異步請(qǐng)求
  • 自動(dòng)重試失敗任務(wù)
  • 簡(jiǎn)潔的鏈?zhǔn)骄幊谭绞?/li>
  • 避免阻塞主線程

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

2.4 消息隊(duì)列重試

使用消息隊(duì)列可以實(shí)現(xiàn)接口請(qǐng)求的異步重試機(jī)制。

基本思路是:

  • 接口請(qǐng)求發(fā)送失敗后,將請(qǐng)求信息封裝為消息,發(fā)送到請(qǐng)求重試的隊(duì)列中。
  • 消息消費(fèi)者從隊(duì)列中獲取失敗的請(qǐng)求,根據(jù)策略進(jìn)行重試。
  • 重復(fù)重試直到成功、重試次數(shù)用盡或其他終止條件。
  • 成功后將消息移除隊(duì)列,失敗則保留消息供再次重試。

主要步驟:

  • 創(chuàng)建請(qǐng)求重試隊(duì)列,如“request.retry.queue”
  • 接口請(qǐng)求失敗后,生成重試消息,發(fā)送到隊(duì)列
  • 消費(fèi)者啟動(dòng)線程從隊(duì)列中取消息重試
  • 根據(jù)重試策略進(jìn)行定時(shí)重試或最大重試數(shù)
  • 成功則確認(rèn)消息,失敗則重新入隊(duì)

使用消息隊(duì)列進(jìn)行重試有利于:

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

示例

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

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

// 3. 消費(fèi)者線程進(jìn)行重試
class RetryConsumer implements Runnable {

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

這就是使用消息隊(duì)列實(shí)現(xiàn)接口重試的基本流程,可以根據(jù)需求擴(kuò)展重試策略、異常處理等邏輯。

2.5 自定義重試工具類

使用自定義的重試工具類來(lái)實(shí)現(xiàn)接口請(qǐng)求的重試機(jī)制,提高代碼的復(fù)用性和可維護(hù)性。

重試工具類的實(shí)現(xiàn)思路:

  1. 提供重試方法,參數(shù)包括請(qǐng)求函數(shù)、重試策略等
  2. 在重試方法內(nèi)部執(zhí)行循環(huán)請(qǐng)求
  3. 每次請(qǐng)求失敗時(shí),根據(jù)策略等待一段時(shí)間
  4. 記錄當(dāng)前重試次數(shù),與最大次數(shù)比較
  5. 請(qǐng)求成功或者達(dá)到最大重試次數(shù)則結(jié)束循環(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();
        // 重試次數(shù)加1
        retries++;
      }
    }
  }

}

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

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

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

這樣可以提高重試相關(guān)邏輯的復(fù)用性,避免寫重復(fù)代碼。

2.6 使用遞歸結(jié)構(gòu)

使用遞歸結(jié)構(gòu)也可以實(shí)現(xiàn)接口請(qǐng)求的重試機(jī)制。

基本思路是設(shè)計(jì)一個(gè)遞歸函數(shù),在函數(shù)內(nèi)部發(fā)送請(qǐng)求,如果失敗則繼續(xù)遞歸調(diào)用自身再次重試。

示例:

public class RetryRequest {

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

}

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

2.7 使用Resilience4j

Resilience4j是一個(gè)很好的Java重試庫(kù),可以用它來(lái)實(shí)現(xiàn)接口請(qǐng)求的重試機(jī)制。

主要步驟:

2.7.1添加Resilience4j依賴

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

2.7.2 定義重試邏輯

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

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

2.7.3 使用重試邏輯調(diào)用接口

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

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

});

2.7.4 自定義重試異常predicate

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

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

2.8 使用網(wǎng)絡(luò)工具重試

我們常用的一些網(wǎng)絡(luò)工具來(lái)做重試

示例

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ā)送請(qǐng)求
        return HttpClientUtils.get(url);
        
      } catch (Exception e) {

        if (retries >= MAX_RETRIES) {
          throw e;
        }
        
        // 增加重試次數(shù)
        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);
  }

}

// 網(wǎng)絡(luò)工具類 
class HttpClientUtils {

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

}

主要通過(guò)循環(huán)和網(wǎng)絡(luò)工具類來(lái)實(shí)現(xiàn)重試邏輯,延時(shí)控制也可以用Random來(lái)實(shí)現(xiàn)指數(shù)退避。這種 utilities + 循環(huán) 的組合可以實(shí)現(xiàn)靈活可復(fù)用的重試機(jī)制。

3.注意事項(xiàng)

接口請(qǐng)求重試時(shí)需要注意以下幾點(diǎn):

3.1 冪等性
接口需要是冪等的,多次調(diào)用結(jié)果相同,避免重復(fù)執(zhí)行帶來(lái)副作用。

3.2 資源競(jìng)爭(zhēng)
重試可能對(duì)服務(wù)端造成更大壓力,需要考慮限流等措施。

3.3 超時(shí)設(shè)置
合理設(shè)置重試最大次數(shù)和總超時(shí)時(shí)間,避免長(zhǎng)時(shí)間等待。

3.4 重試條件
明確哪些異常情況下需要重試,不能無(wú)腦重試所有錯(cuò)誤。

3.5 數(shù)據(jù)一致性
請(qǐng)求成功后要冪等更新?tīng)顟B(tài),避免重復(fù)數(shù)據(jù)。

3.6 異步機(jī)制
重試過(guò)程不要阻塞主業(yè)務(wù)線程。

3.7 退避策略
失敗后延遲一段時(shí)間再重試,可選避免集群重試。

3.8 日志記錄
記錄重試的次數(shù)、錯(cuò)誤原因等信息,方便排查問(wèn)題。

3.9 容錯(cuò)機(jī)制
重試失敗后的降級(jí)處理,避免級(jí)聯(lián)失敗。

總結(jié)

接口請(qǐng)求重試機(jī)制對(duì)保證系統(tǒng)高可用非常關(guān)鍵,需要根據(jù)業(yè)務(wù)需求選擇合適的重試策略。常用的組合策略包括帶最大次數(shù)的定時(shí)/指數(shù)退避重試、故障轉(zhuǎn)移重試等。重試機(jī)制需要綜合設(shè)置以達(dá)到容錯(cuò)效果又避免產(chǎn)生過(guò)大的系統(tǒng)負(fù)載。

到此這篇關(guān)于聊聊Java中接口重試機(jī)制的幾種解決方案的文章就介紹到這了,更多相關(guān)Java接口重試機(jī)制內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • SpringBoot輕松整合MongoDB的全過(guò)程記錄

    SpringBoot輕松整合MongoDB的全過(guò)程記錄

    這篇文章主要給大家介紹了關(guān)于SpringBoot輕松整合MongoDB的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-01-01
  • Springcould多模塊搭建Eureka服務(wù)器端口過(guò)程詳解

    Springcould多模塊搭建Eureka服務(wù)器端口過(guò)程詳解

    這篇文章主要介紹了Springcould多模塊搭建Eureka服務(wù)器端口過(guò)程詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-11-11
  • SpringBoot實(shí)現(xiàn)埋點(diǎn)監(jiān)控

    SpringBoot實(shí)現(xiàn)埋點(diǎn)監(jiān)控

    本文主要介紹了SpringBoot實(shí)現(xiàn)埋點(diǎn)監(jiān)控,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-01-01
  • 解析 MyBatis 中 Mapper 生效的來(lái)龍去脈

    解析 MyBatis 中 Mapper 生效的來(lái)龍去脈

    這篇文章主要介紹了解析 MyBatis 中 Mapper 生效的前因后果,介紹了mybatis基本使用及源碼分析,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-08-08
  • java批量導(dǎo)入Excel數(shù)據(jù)超詳細(xì)實(shí)例

    java批量導(dǎo)入Excel數(shù)據(jù)超詳細(xì)實(shí)例

    這篇文章主要給大家介紹了關(guān)于java批量導(dǎo)入Excel數(shù)據(jù)的相關(guān)資料,EXCEL導(dǎo)入就是文件導(dǎo)入,操作代碼是一樣的,文中給出了詳細(xì)的代碼示例,需要的朋友可以參考下
    2023-08-08
  • 詳解java IO流之緩沖流的使用

    詳解java IO流之緩沖流的使用

    本文主要介紹了java的IO流中的緩沖流的使用,緩沖流分為字節(jié)和字符緩沖流。分享了有關(guān)它們的實(shí)例代碼,具有一定的參考價(jià)值,下面跟著小編一起來(lái)看下吧
    2017-01-01
  • 解決java文件流處理異常 mark/reset not supported問(wèn)題

    解決java文件流處理異常 mark/reset not supported問(wèn)題

    這篇文章主要介紹了解決java文件流處理異常 mark/reset not supported問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-10-10
  • 解決參數(shù)命名不規(guī)范,造成使用@NotNull進(jìn)行校驗(yàn)出現(xiàn)的問(wèn)題

    解決參數(shù)命名不規(guī)范,造成使用@NotNull進(jìn)行校驗(yàn)出現(xiàn)的問(wèn)題

    這篇文章主要介紹了解決參數(shù)命名不規(guī)范,造成使用@NotNull進(jìn)行校驗(yàn)出現(xiàn)的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-01-01
  • Java探索之string字符串的應(yīng)用代碼示例

    Java探索之string字符串的應(yīng)用代碼示例

    這篇文章主要介紹了Java探索之string字符串的應(yīng)用代碼示例,具有一定參考價(jià)值,需要的朋友可以了解下。
    2017-10-10
  • java對(duì)接微信支付之JSAPI支付(微信公眾號(hào)支付)

    java對(duì)接微信支付之JSAPI支付(微信公眾號(hào)支付)

    這篇文章主要給大家介紹了關(guān)于java對(duì)接微信支付之JSAPI支付(微信公眾號(hào)支付)的相關(guān)資料,微信JSAPI支付是近年來(lái)非常流行的一種支付方式,它使用了微信支付的SDK和demo來(lái)實(shí)現(xiàn)支付接口的對(duì)接,需要的朋友可以參考下
    2023-07-07

最新評(píng)論