中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Retry重試機制是什么意思

發布時間:2021-06-26 10:11:49 來源:億速云 閱讀:159 作者:chen 欄目:大數據

這篇文章主要介紹“Retry重試機制是什么意思”,在日常操作中,相信很多人在Retry重試機制是什么意思問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”Retry重試機制是什么意思”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!

1.前言

在項目開發中,有的時候,總是避免不了調用第三方服務接口,有的時候可能因為網絡等情況的因素,我們需要重試幾次才能調用成功,所以就需要一重試機制來保證接口的正常訪問。

2.guava-retrying

這是谷歌guava提供的工具包,我們可以在項目中引入相應的包,很輕松實現重試訪問。guava-retrying中大量運用的策略模式,可以自定義各種執行重試策略。下面是簡單實用步驟。

①. pom引入
<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>19.0</version>
</dependency>
<dependency>
    <groupId>com.github.rholder</groupId>
    <artifactId>guava-retrying</artifactId>
    <version>2.0.0</version>
</dependency>
②. 基礎業務代碼

我這里實現一個對接口的簡單訪問,以此來模擬訪問第三方接口。

@GetMapping("/retrytest")
public Map<String, Object> retrytest(){
    Map<String, Object> resultMap = Maps.newHashMap();
    resultMap.put("id", 1001L);
    resultMap.put("msg", "測試");
    Map<String, Object> tokenMap = Maps.newHashMap();
    tokenMap.put("token", UUID.randomUUID().toString());
    resultMap.put("data", tokenMap);
    return resultMap;
}
③.Retryer Bean
  1. Retryer中定義重試的各種策略,在執行call方法的時候,會將這些重試策略一一使用。

  2. RetryListener是重試監聽器,可以監聽每次重試的過程。

  3. BlockStrategy是自定義阻塞策略。

@Bean
public Retryer<String> retry(){
    RetryListener retryListener = new RetryListener() {
        @Override
        public <V> void onRetry(Attempt<V> attempt) {
            try {
                if(attempt.hasException()){
                    log.error("---"+ Arrays.toString(attempt.getExceptionCause().getStackTrace()));
                }else {
                    log.info("---"+ attempt.get().toString());
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    };
    BlockStrategy blockStrategy = new BlockStrategy() {
        @Override
        public void block(long sleepTime) throws InterruptedException {
            LocalDateTime startTime = LocalDateTime.now();
            long start = System.currentTimeMillis();
            long end = start;
            log.info("[SpinBlockStrategy]...begin wait.");
            while (end - start <= sleepTime) {
                end = System.currentTimeMillis();
            }
            //使用Java8新增的Duration計算時間間隔
            Duration duration = Duration.between(startTime, LocalDateTime.now());
            log.info("[SpinBlockStrategy]...end wait.duration={}", duration.toMillis());
        }
    };
    Retryer<String> retryer = RetryerBuilder.<String>newBuilder()
            //retryIf 重試條件
            .retryIfException()
            .retryIfRuntimeException()
            .retryIfExceptionOfType(Exception.class)
            .retryIfException(Predicates.equalTo(new Exception()))
            //等待策略:每次請求間隔1s
            //  .withWaitStrategy(WaitStrategies.fixedWait(1, TimeUnit.SECONDS))
            //停止策略 : 嘗試請求3次
            .withStopStrategy(StopStrategies.stopAfterAttempt(3))
            //時間限制 : 某次請求不得超過2s , 類似: TimeLimiter timeLimiter = new SimpleTimeLimiter();
            .withAttemptTimeLimiter(AttemptTimeLimiters.fixedTimeLimit(2, TimeUnit.SECONDS))
            .withRetryListener(retryListener)
            .withBlockStrategy(blockStrategy)
            .build();
    return retryer;
}
④.Callable實現

編寫retryer調用call方法的具體實現邏輯。

@Slf4j
public class RetryCallable implements Callable<String> {

    private RestTemplate restTemplate;

    public RetryCallable(RestTemplate restTemplate) {
        this.restTemplate = restTemplate;
    }

    int times = 1;
    @Override
    public String call() {
        log.info("call times={}", times++);
        log.info("請求時間: {}", LocalDateTime.now());
        //對遠程地址的訪問
        return Objects.requireNonNull(
                restTemplate.getForObject("http://localhost:8080/retrytest", Object.class)).toString();
    }
}
⑤. 重試器 call調用
@GetMapping("/hello")
public Object hello(@RequestParam(required = false) String token){
    log.info("hello "+ token);
    Map result = null;
    String msg = "";
    try {
        //定義請求實現 利用重試器調用請求
        String callResult = retryer.call(new RetryCallable(restTemplate));
        result = new Gson().fromJson(callResult, Map.class);
    } catch (Exception e) {
        e.printStackTrace();
        msg = e.getMessage();
        log.warn("請求失敗:{}",e.getMessage());
    }
    HashMap<String, Object> resultData = Maps.newHashMap();
    resultData.put("data",result);
    resultData.put("token",token);
    resultData.put("msg",msg);
    return resultData;
}

調用接口測試

2019-10-12 13:46:23.863  INFO 68012 --- [nio-8080-exec-1] com.wj.retry.controller.HelloController  : hello f5b78e95-87f7-435e-b9be-04bcb88ad056
2019-10-12 13:46:23.865  INFO 68012 --- [pool-1-thread-1] com.wj.retry.controller.RetryCallable    : call times=1
2019-10-12 13:46:23.875  INFO 68012 --- [pool-1-thread-1] com.wj.retry.controller.RetryCallable    : 請求時間: 2019-10-12T13:46:23.874
2019-10-12 13:46:24.068  INFO 68012 --- [nio-8080-exec-1] com.wj.retry.RetryApplication            : ---{msg=測試, data={token=eacb4a99-9ef9-4581-b8e5-28fdabac1c52}, id=1001}

若失敗會調用多次(按照重試器中定義的策略)并,拋出異常
Retry重試機制是什么意思
Retry重試機制是什么意思

3.spring-retry

上面的實現會寫相對較多的代碼,若使用spring-retry則相對簡單多了,可以基于注解實現

①. pom配置
<dependency>
    <groupId>org.springframework.retry</groupId>
    <artifactId>spring-retry</artifactId>
</dependency>
②. 注解配置重試策略

@Retryable的參數說明:

  1. value:拋出指定異常才會重試

  2. include:和value一樣,默認為空,當exclude也為空時,默認所以異常

  3. exclude:指定不處理的異常

  4. maxAttempts:最大重試次數,默認3次

  5. backoff:重試等待策略,默認使用@Backoff,@Backoff的value默認為1000L,我們設置為2000L;multiplier(指定延遲倍數)默認為0,表示固定暫停1秒后進行重試,如果把multiplier設置為1.5,則第一次重試為2秒,第二次為3秒,第三次為4.5秒。

 @Retryable(value = Exception.class, maxAttempts = 3, backoff = @Backoff(delay = 2000L, multiplier = 1.5))
public Object retry(@RequestParam(required = false) String token) {
    String msg = "";
    log.info("springretry");
    log.info("請求時間: {}", LocalDateTime.now());
    String resultStr = Objects.requireNonNull(
            restTemplate.getForObject("http://localhost:8080/retrytest", Object.class)).toString();
    Map result = new Gson().fromJson(resultStr, Map.class);
    HashMap<String, Object> resultData = Maps.newHashMap();
    resultData.put("data",result);
    resultData.put("token",token);
    resultData.put("msg",msg);
    return resultData;
}

最后在啟動類上加上@EnableRetry注解開啟重試機制。ok,就這樣兩個步驟就完成了

4.舉例重試機制的運用

除了上面調用第三方服務接口可能會用到重試機制,在微服務項目中,服務之間的通信,重試機制可以說是隨處可見。

在springcloud中Ribbon,feign,Hystrix等組件都可以自己配置重試機制,來達到提高能正常通信的成功率。

此外,在各種消息中間件中也都有重試機制的體現,例如kafka,消息發送失敗可以重新發送,消息消費失敗了,也可以配置重試機制,可以最大程度達到消息的不丟失。

5.目標服務要考慮的問題

可以考慮這么一個事情,若目標邏輯執行時間過長,超出了重試的等待時間,客戶端就要發起重試,那么服務端就會出現重復調用執行的問題,所以,有重試機制就要考慮冪等性的問題。

到此,關于“Retry重試機制是什么意思”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

沙坪坝区| 连江县| 娱乐| 陵川县| 镇康县| 合肥市| 肃北| 新建县| 财经| 陆丰市| 兴国县| 通海县| 和顺县| 安庆市| 新余市| 称多县| 留坝县| 保山市| 剑河县| 丹巴县| 陆川县| 会昌县| 杭锦后旗| 广宗县| 峨边| 临泽县| 利津县| 武义县| 奇台县| 即墨市| 湾仔区| 茶陵县| 乌拉特前旗| 萨嘎县| 海门市| 太白县| 鄂尔多斯市| 文山县| 沛县| 萍乡市| 贵溪市|