<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                企業??AI智能體構建引擎,智能編排和調試,一鍵部署,支持知識庫和私有化部署方案 廣告
                該功能由 [`Guava-Retrying`](https://github.com/rholder/guava-retrying) 源改而來 > 在很多業務場景中,為了排除系統中的各種不穩定因素,以及邏輯上的錯誤,并最大概率保證獲得預期的結果,重試機制都是必不可少的。 > 尤其是調用遠程服務,在高并發場景下,很可能因為服務器響應延遲或者網絡原因,造成我們得不到想要的結果,或者根本得不到響應。這個時候,一個優雅的重試調用機制,可以讓我們更大概率保證得到預期的響應。 [TOC] # 如何優雅地設計重試實現 1. 什么條件下重試 2. 什么條件下停止 3. 如何停止重試 4. 停止重試等待多久 5. 如何等待 6. 請求時間限制 7. 如何結束 8. 如何監聽整個重試過程 # 源碼修改 AttemptTimeLimiters.java 調用原版guava18 SimpleTimeLimiter() 改為 AttemptTimeLimiters.java 調用升級guava29 SimpleTimeLimiter(ExecutorService) **** # 構造重試 繼續上一章網絡重試,自定義如下: ``` Retryer<RawResponse> retry = RetryerBuilder.<RawResponse>newBuilder() // 重試條件 .retryIfException() .retryIfResult(reRetryPredicate) // 等待策略:請求間隔1s .withWaitStrategy(WaitStrategies.fixedWait(1, TimeUnit.SECONDS)) // 停止策略:嘗試請求3次 .withStopStrategy(StopStrategies.stopAfterAttempt(3)) // 時間限制:請求限制2s .withAttemptTimeLimiter(AttemptTimeLimiters.fixedTimeLimit(2, TimeUnit.SECONDS)) // 重試監聽 .withRetryListener(reRetryListener) // .build(); ``` 重試條件 ``` // 拋出runtime異常、checked異常時都會重試,但是拋出error不會重試 .retryIfException() // 拋出runtime異常時重試,checked異常和error都不重試。 .retryIfRuntimeException() // 特定異常時重試 .retryIfExceptionOfType(NullPointerException.class) .retryIfException(Predicates.or(Predicates.instanceOf(NullPointerException.class),Predicates.instanceOf(IOException.class))) // 返回指定結果時重試 .retryIfResult(Predicates.equalTo(false)) ``` 了解重試條件后,通過自定義結果、異常可以靈活的應用在業務當中 ***** 網絡請求:如當返回不等于200時重試 ``` protected Predicate<RawResponse> reRetryPredicate = raw -> { return raw.statusCode() != 200; }; ``` 業務邏輯:如當返回result為空時、當返回值=-3時(統一返回章節中-3=重試) ``` protected Predicate<Result> reRetryPredicate = result -> { if (ObjectUtils.isEmpty(result)) { return true; } else if (result.getCode() == -3) { return true; } return false; }; ``` # 測試示例 ``` @Test public void retry() { // 構造重試 Retryer<Result> retry = RetryerBuilder.<Result>newBuilder() // 重試條件 .retryIfException() // 返回指定結果時重試 .retryIfResult((@Nullable Result result) -> { if (ObjectUtils.isEmpty(result)) { return true; } else if (result.getCode() == -3) { return true; } return false; }) // 等待策略:每次請求間隔1s .withWaitStrategy(WaitStrategies.fixedWait(1, TimeUnit.SECONDS)) // 停止策略 : 嘗試請求2次 .withStopStrategy(StopStrategies.stopAfterAttempt(2)) // 時間限制 : 請求限制2s .withAttemptTimeLimiter(AttemptTimeLimiters.fixedTimeLimit(5, TimeUnit.SECONDS)) .withRetryListener(new RetryListener() { @Override public <V> void onRetry(Attempt<V> attempt) { long number = attempt.getAttemptNumber(); long delay = attempt.getDelaySinceFirstAttempt(); boolean isError = attempt.hasException(); boolean isResult = attempt.hasResult(); if (attempt.hasException()) { if (attempt.getExceptionCause().getCause() instanceof RunException) { RunException runException = (RunException) attempt.getExceptionCause().getCause(); log.warn("onException causeBy:{} {}", runException.getErrorCode(), runException.getMessage()); } else { log.warn("onException causeBy:{}", attempt.getExceptionCause().toString()); } } else { if (attempt.hasResult()) { try { V result = attempt.get(); if (result instanceof Result) { log.warn("onRetry number:{} error:{} result:{} statusCode:{} delay:{}", number, isError, isResult, ((Result) result).getCode(), delay); } } catch (ExecutionException e) { log.error("onResult exception:{}", e.getCause().toString()); throw new RunException(RunExc.RETRY, "test retry"); } } } } }) .build(); try { Result result = retry.call(() -> { // 構造請求 RequestBuilder req = Requests.post(url).params(Parameter.of("configKey", "appLaunch")); // 請求重試 RawResponse response = RequestsHelper.retry(req); // 獲取結果 TestRetryResponse result1 = response.readToJson(TestRetryResponse.class); // 驗證結果,如果結果正確則返回,錯誤則重試 if (result1.getCode() == 0) { return R.succ(result1.getData()); } else { return R.fail(Result.RETRY, result1.getMsg()); } }); // 驗證結果,如果結果正確則返回,錯誤則重試 log.info(JSON.toJSONString(R.succ(result.getData()))); } catch (ExecutionException | RetryException e) { throw new RunException(RunExc.RETRY, "test retry"); } } ``` # 驗證結果 述示例代碼可知,遠程請求調用,對業務、網絡均模擬重試操作。這類是比較常見的業務場景。在某些特殊場景下需要對某些請求、業務需要做重試。如: 網絡A:重試3次,每次等待1秒,限制2秒 業務B:重試2次,每次等待1秒,限制5秒 1、當網絡A異常時: ``` [FastBoot][ WARN][08-11 14:23:53]-->[pool-6-thread-1:1079595][onRetry(HttpRetryer.java:76)] | - onRetry number:1 error:false result:true statusCode:404 delay:180 [FastBoot][ WARN][08-11 14:23:54]-->[pool-6-thread-1:1080701][onRetry(HttpRetryer.java:76)] | - onRetry number:2 error:false result:true statusCode:404 delay:1285 [FastBoot][ WARN][08-11 14:23:55]-->[pool-6-thread-1:1081792][onRetry(HttpRetryer.java:76)] | - onRetry number:3 error:false result:true statusCode:404 delay:2375 [FastBoot][ WARN][08-11 14:23:55]-->[http-nio-9090-exec-10:1081793][onRetry(ApIController.java:129)] | - onException causeBy:2000 請求錯誤:http retry error [FastBoot][ WARN][08-11 14:23:56]-->[pool-6-thread-1:1082901][onRetry(HttpRetryer.java:76)] | - onRetry number:1 error:false result:true statusCode:404 delay:98 [FastBoot][ WARN][08-11 14:23:58]-->[pool-6-thread-1:1084004][onRetry(HttpRetryer.java:76)] | - onRetry number:2 error:false result:true statusCode:404 delay:1200 [FastBoot][ WARN][08-11 14:23:59]-->[pool-6-thread-1:1085138][onRetry(HttpRetryer.java:76)] | - onRetry number:3 error:false result:true statusCode:404 delay:2334 [FastBoot][ WARN][08-11 14:23:59]-->[http-nio-9090-exec-10:1085139][onRetry(ApIController.java:129)] | - onException causeBy:2000 請求錯誤:http retry error [FastBoot][ERROR][08-11 14:23:59]-->[http-nio-9090-exec-10:1085143][runException(GlobalExceptionAdvice.java:134)] | - runException ...... com.xiesx.FastBoot.core.exception.RunException: 重試失敗:test retry error ``` 2、當網絡A異常時,業務B限制2秒時(注意:這里只打印2個,因為B做了限制2秒,A會重試1秒\*3次,超出B限制) ``` [FastBoot][ WARN][08-11 14:23:53]-->[pool-6-thread-1:1079595][onRetry(HttpRetryer.java:76)] | - onRetry number:1 error:false result:true statusCode:404 delay:180 [FastBoot][ WARN][08-11 14:23:54]-->[pool-6-thread-1:1080701][onRetry(HttpRetryer.java:76)] | - onRetry number:2 error:false result:true statusCode:404 delay:1285 [FastBoot][ WARN][08-11 14:23:55]-->[http-nio-9090-exec-10:1081793][onRetry(ApIController.java:129)] | - onException causeBy:2000 請求錯誤:http retry error [FastBoot][ WARN][08-11 14:23:56]-->[pool-6-thread-1:1082901][onRetry(HttpRetryer.java:76)] | - onRetry number:1 error:false result:true statusCode:404 delay:98 [FastBoot][ WARN][08-11 14:23:58]-->[pool-6-thread-1:1084004][onRetry(HttpRetryer.java:76)] | - onRetry number:2 error:false result:true statusCode:404 delay:1200 [FastBoot][ WARN][08-11 14:23:59]-->[http-nio-9090-exec-10:1085139][onRetry(ApIController.java:129)] | - onException causeBy:2000 請求錯誤:http retry error [FastBoot][ERROR][08-11 14:23:59]-->[http-nio-9090-exec-10:1085143][runException(GlobalExceptionAdvice.java:134)] | - runException ...... com.xiesx.FastBoot.core.exception.RunException: 重試失敗:test retry error ``` 3、網絡A正常:業務B錯誤(A重試1次、B重復2次) ``` [FastBoot][ WARN][08-11 14:40:18]-->[pool-7-thread-1:2064857][onRetry(HttpRetryer.java:76)] | - onRetry number:1 error:false result:true statusCode:200 delay:1397 [FastBoot][ WARN][08-11 14:40:19]-->[http-nio-9090-exec-4:2065102][onRetry(ApIController.java:138)] | - onRetry number:1 error:false result:true statusCode:-3 delay:1642 [FastBoot][ WARN][08-11 14:40:20]-->[pool-7-thread-1:2066165][onRetry(HttpRetryer.java:76)] | - onRetry number:1 error:false result:true statusCode:200 delay:49 [FastBoot][ WARN][08-11 14:40:20]-->[http-nio-9090-exec-4:2066166][onRetry(ApIController.java:138)] | - onRetry number:2 error:false result:true statusCode:-3 delay:2707 [FastBoot][ERROR][08-11 14:40:20]-->[http-nio-9090-exec-4:2066168][runException(GlobalExceptionAdvice.java:134)] | - runException ...... com.xiesx.FastBoot.core.exception.RunException: 重試失敗:test retry error ``` 4、網絡A、B正常 (AB重復1次、即首次) ``` [FastBoot][ WARN][08-11 14:48:38]-->[pool-8-thread-1:2564941][onRetry(HttpRetryer.java:76)] | - onRetry number:1 error:false result:true statusCode:200 delay:159 [FastBoot][ WARN][08-11 14:48:38]-->[http-nio-9090-exec-1:2564946][onRetry(ApIController.java:138)] | - onRetry number:1 error:false result:true statusCode:0 delay:164 ``` 重試成功返回: ``` { "code":0, "msg":"操作成功", "data":{ }, "success":true } ``` 重試失敗返回: ``` { "code": 7000, "msg": "重試失敗:test retry error", "success": false } ```
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看