<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          SpringBoot技術(shù)實(shí)踐-SpringRetry重試框架

          共 14862字,需瀏覽 30分鐘

           ·

          2021-07-31 08:45

          一、環(huán)境搭建

          1. 加入SpringRetry依賴,SpringRetry使用AOP實(shí)現(xiàn),所以也需要加入AOP包

          <!-- SpringRetry -->
          <dependency>
          <groupId>org.springframework.retry</groupId>
          <artifactId>spring-retry</artifactId>
          </dependency>
          <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-aspects</artifactId>
          </dependency>
          復(fù)制代碼
          1. 官方文檔

            • www.baeldung.com/spring-retr…

          二、RetryTemplate

          2.1 RetryTemplate

          1. RetryTemplate封裝了Retry基本操作

            • org.springframework.retry.support.RetryTemplate

          2. RetryTemplate中可以指定監(jiān)聽、回退策略、重試策略等

          3. 只需要正常new RetryTemplate()即可使用

          2.2 RetryListener

          1. RetryListener指定了當(dāng)執(zhí)行過程中出現(xiàn)錯(cuò)誤時(shí)的回調(diào)

            • org.springframework.retry.RetryListener

          package org.springframework.retry;

          public interface RetryListener {

          /**
          * 任務(wù)開始執(zhí)行時(shí)調(diào)用,只調(diào)用一次
          */

          <T, E extends Throwable> boolean open(RetryContext context, RetryCallback<T, E> callback);

          /**
          * 任務(wù)執(zhí)行結(jié)束時(shí)(包含重試)調(diào)用,只調(diào)用一次
          */

          <T, E extends Throwable> void close(RetryContext context, RetryCallback<T, E> callback, Throwable throwable);

          /**
          * 出現(xiàn)錯(cuò)誤時(shí)回調(diào)
          */

          <T, E extends Throwable> void onError(RetryContext context, RetryCallback<T, E> callback, Throwable throwable);
          }
          復(fù)制代碼
          1. 配置之后在RetryTemplate中指定

          2.3 回退策略

          2.3.1 FixedBackOffPolicy

          1. 當(dāng)出現(xiàn)錯(cuò)誤時(shí)延遲多少時(shí)間繼續(xù)調(diào)用

          FixedBackOffPolicy fixedBackOffPolicy = new FixedBackOffPolicy();
          fixedBackOffPolicy.setBackOffPeriod(1000L);
          retryTemplate.setBackOffPolicy(fixedBackOffPolicy);
          復(fù)制代碼
          1. 配置之后在RetryTemplate中指定

          2.3.2 ExponentialBackOffPolicy

          1. 當(dāng)出現(xiàn)錯(cuò)誤時(shí)第一次按照指定延遲時(shí)間延遲后按照指數(shù)進(jìn)行延遲

          // 指數(shù)回退(秒),第一次回退1s,第二次回退2s,第三次4秒,第四次8秒
          ExponentialBackOffPolicy exponentialBackOffPolicy = new ExponentialBackOffPolicy();
          exponentialBackOffPolicy.setInitialInterval(1000L);
          exponentialBackOffPolicy.setMultiplier(2);
          retryTemplate.setBackOffPolicy(exponentialBackOffPolicy);
          復(fù)制代碼
          1. 配置之后在RetryTemplate中指定

          2.4 重試策略

          1. 重試策略主要指定出現(xiàn)錯(cuò)誤時(shí)重試次數(shù)

          // 重試策略
          SimpleRetryPolicy retryPolicy = new SimpleRetryPolicy();
          retryPolicy.setMaxAttempts(5);
          retryTemplate.setRetryPolicy(retryPolicy);
          復(fù)制代碼
          1. 配置之后在RetryTemplate中指定

          2.5 RetryCallback

          1. RetryCallback為retryTemplate.execute時(shí)執(zhí)行的回調(diào)

            • public final <T, E extends Throwable> T execute(RetryCallback<T, E> retryCallback) throws E

          2.6 核心使用

          1. 可以使用RetryTemplate完成簡單使用

          2. 配置retryTemplate

            • 指定回退策略為ExponentialBackOffPolicy

            • 指定重試策略為SimpleRetryPolicy

            • 指定監(jiān)聽器RetryListener

          import com.codecoord.util.PrintUtil;
          import org.springframework.context.annotation.Bean;
          import org.springframework.context.annotation.Configuration;
          import org.springframework.retry.RetryCallback;
          import org.springframework.retry.RetryContext;
          import org.springframework.retry.RetryListener;
          import org.springframework.retry.backoff.ExponentialBackOffPolicy;
          import org.springframework.retry.policy.SimpleRetryPolicy;
          import org.springframework.retry.support.RetryTemplate;

          @Configuration
          public class RetryTemplateConfig {

          /**
          * 注入retryTemplate
          */

          @Bean
          public RetryTemplate retryTemplate() {
          RetryTemplate retryTemplate = new RetryTemplate();

          /// 回退固定時(shí)間(秒)
          /* FixedBackOffPolicy fixedBackOffPolicy = new FixedBackOffPolicy();
          fixedBackOffPolicy.setBackOffPeriod(1000L);
          retryTemplate.setBackOffPolicy(fixedBackOffPolicy);*/


          // 指數(shù)回退(秒),第一次回退1s,第二次回退2s
          ExponentialBackOffPolicy exponentialBackOffPolicy = new ExponentialBackOffPolicy();
          exponentialBackOffPolicy.setInitialInterval(1000L);
          exponentialBackOffPolicy.setMultiplier(2);
          retryTemplate.setBackOffPolicy(exponentialBackOffPolicy);

          // 重試策略
          SimpleRetryPolicy retryPolicy = new SimpleRetryPolicy();
          retryPolicy.setMaxAttempts(5);
          retryTemplate.setRetryPolicy(retryPolicy);

          // 設(shè)置監(jiān)聽器,open和close分別在啟動(dòng)和結(jié)束時(shí)執(zhí)行一次
          RetryListener[] listeners = {
          new RetryListener() {
          @Override
          public <T, E extends Throwable> boolean open(RetryContext context, RetryCallback<T, E> callback) {
          PrintUtil.print("open");
          return true;
          }
          @Override
          public <T, E extends Throwable> void close(RetryContext context, RetryCallback<T, E> callback,
          Throwable throwable)
          {
          PrintUtil.print("close");
          }
          @Override
          public <T, E extends Throwable> void onError(RetryContext context, RetryCallback<T, E> callback,
          Throwable throwable)
          {
          PrintUtil.print("onError");
          }
          }
          };
          retryTemplate.setListeners(listeners);

          return retryTemplate;
          }
          }

          復(fù)制代碼
          1. 在controller中注入RetryTemplate使用,也可以是在service中

          @RestController
          public class SpringRetryController {
          @Resource
          private RetryTemplate retryTemplate;
          private static int count = 0;

          @RequestMapping("/retry")
          public Object retry() {
          try {
          count = 0;
          retryTemplate.execute((RetryCallback<Void, RuntimeException>) context -> {
          // 業(yè)務(wù)代碼
          // ....
          // 模擬拋出異常
          ++count;
          throw new RuntimeException("拋出異常");
          });
          } catch (RuntimeException e) {
          System.out.println("Exception");
          }

          return "retry = " + count;
          }
          }
          復(fù)制代碼
          1. 訪問retry接口,然后觀察日志輸出

          18:27:20.648 - http-nio-8888-exec-1 - open
          18:27:20.649 - http-nio-8888-exec-1 - retryTemplate.execute執(zhí)行
          18:27:20.649 - http-nio-8888-exec-1 - onError
          18:27:21.658 - http-nio-8888-exec-1 - retryTemplate.execute執(zhí)行
          18:27:21.658 - http-nio-8888-exec-1 - onError
          18:27:23.670 - http-nio-8888-exec-1 - retryTemplate.execute執(zhí)行
          18:27:23.670 - http-nio-8888-exec-1 - onError
          18:27:27.679 - http-nio-8888-exec-1 - retryTemplate.execute執(zhí)行
          18:27:27.679 - http-nio-8888-exec-1 - onError
          18:27:35.681 - http-nio-8888-exec-1 - retryTemplate.execute執(zhí)行
          18:27:35.681 - http-nio-8888-exec-1 - onError
          18:27:35.681 - http-nio-8888-exec-1 - close
          復(fù)制代碼

          三、EnableRetry

          1. @EnableRetry開啟重試,在類上指定的時(shí)候方法將默認(rèn)執(zhí)行,重試三次

          2. 定義service,開啟@EnableRetry注解和指定@Retryable,重試可以參考后面一節(jié)

          import org.springframework.retry.annotation.Retryable;

          public interface RetryService {

          /**
          * 重試方法調(diào)用
          */

          @Retryable
          void retryServiceCall();
          }

          復(fù)制代碼
          import org.springframework.retry.annotation.EnableRetry;
          import org.springframework.stereotype.Service;

          @EnableRetry
          @Service
          public class RetryServiceImpl implements RetryService {

          @Override
          public void retryServiceCall() {
          PrintUtil.print("方法調(diào)用..");
          throw new RuntimeException("手工異常");
          }
          }

          復(fù)制代碼
          1. controller中注入service

          @RequestMapping("/retryAnnotation")
          public Object retryAnnotation() {
          retryService.retryServiceCall();
          return "retryAnnotation";
          }
          復(fù)制代碼
          1. 將會默認(rèn)重試

          18:46:48.721 - http-nio-8888-exec-1 - 方法調(diào)用..
          18:46:49.724 - http-nio-8888-exec-1 - 方法調(diào)用..
          18:46:50.730 - http-nio-8888-exec-1 - 方法調(diào)用..
          java.lang.RuntimeException: 手工異常
          復(fù)制代碼

          四、Retryable

          1. 用于需要重試的方法上的注解

          2. 有以下幾個(gè)屬性

            • 不設(shè)置參數(shù)時(shí),默認(rèn)使用FixedBackOffPolicy(指定等待時(shí)間),重試等待1000ms

            • 設(shè)置delay,使用FixedBackOffPolicy(指定等待設(shè)置delay和maxDealy時(shí),重試等待在這兩個(gè)值之間均態(tài)分布)

            • 設(shè)置delay、maxDealy、multiplier,使用 ExponentialBackOffPolicy(指數(shù)級重試間隔的實(shí)現(xiàn)),multiplier即指定延遲倍數(shù),比如delay=5000L,multiplier=2,則第一次重試為5秒,第二次為10秒,第三次為20秒

            • value:指定發(fā)生的異常進(jìn)行重試

            • include:和value一樣,默認(rèn)空,當(dāng)exclude也為空時(shí),所有異常都重試

            • exclude:指定異常不重試,默認(rèn)空,當(dāng)include也為空時(shí),所有異常都重試

            • maxAttemps:重試次數(shù),默認(rèn)3

            • backoff:重試補(bǔ)償機(jī)制,默認(rèn)沒有

            • Retryable注解參數(shù)

            • @Backoff  注解 重試補(bǔ)償策略

          @Target({ ElementType.METHOD, ElementType.TYPE })
          @Retention(RetentionPolicy.RUNTIME)
          @Documented
          public @interface Retryable {

          /**
          * Retry interceptor bean name to be applied for retryable method. Is mutually
          * exclusive with other attributes.
          * @return the retry interceptor bean name
          */

          String interceptor() default "";

          /**
          * Exception types that are retryable. Synonym for includes(). Defaults to empty (and
          * if excludes is also empty all exceptions are retried).
          * @return exception types to retry
          */

          Class<? extends Throwable>[] value() default {};

          /**
          * Exception types that are retryable. Defaults to empty (and if excludes is also
          * empty all exceptions are retried).
          * @return exception types to retry
          */

          Class<? extends Throwable>[] include() default {};

          /**
          * Exception types that are not retryable. Defaults to empty (and if includes is also
          * empty all exceptions are retried).
          * If includes is empty but excludes is not, all not excluded exceptions are retried
          * @return exception types not to retry
          */

          Class<? extends Throwable>[] exclude() default {};

          /**
          * A unique label for statistics reporting. If not provided the caller may choose to
          * ignore it, or provide a default.
          *
          * @return the label for the statistics
          */

          String label() default "";

          /**
          * Flag to say that the retry is stateful: i.e. exceptions are re-thrown, but the
          * retry policy is applied with the same policy to subsequent invocations with the
          * same arguments. If false then retryable exceptions are not re-thrown.
          * @return true if retry is stateful, default false
          */

          boolean stateful() default false;

          /**
          * @return the maximum number of attempts (including the first failure), defaults to 3
          */

          int maxAttempts() default 3;

          /**
          * @return an expression evaluated to the maximum number of attempts (including the first failure), defaults to 3
          * Overrides {@link #maxAttempts()}.
          * @date 1.2
          */

          String maxAttemptsExpression() default "";

          /**
          * Specify the backoff properties for retrying this operation. The default is a
          * simple {@link Backoff} specification with no properties - see it's documentation
          * for defaults.
          * @return a backoff specification
          */

          Backoff backoff() default @Backoff();

          /**
          * Specify an expression to be evaluated after the {@code SimpleRetryPolicy.canRetry()}
          * returns true - can be used to conditionally suppress the retry. Only invoked after
          * an exception is thrown. The root object for the evaluation is the last {@code Throwable}.
          * Other beans in the context can be referenced.
          * For example:
          * <pre class=code>
          * {@code "message.contains('you can retry this')"}.
          * </pre>
          * and
          * <pre class=code>
          * {@code "@someBean.shouldRetry(#root)"}.
          * </pre>
          * @return the expression.
          * @date 1.2
          */

          String exceptionExpression() default "";

          /**
          * Bean names of retry listeners to use instead of default ones defined in Spring context
          * @return retry listeners bean names
          */

          String[] listeners() default {};

          }
          復(fù)制代碼
          @Target(ElementType.TYPE)
          @Retention(RetentionPolicy.RUNTIME)
          @Documented
          public @interface Backoff {

          /**
          * Synonym for {@link #delay()}.
          *
          * @return the delay in milliseconds (default 1000)
          */

          long value() default 1000;

          /**
          * A canonical backoff period. Used as an initial value in the exponential case, and
          * as a minimum value in the uniform case.
          * @return the initial or canonical backoff period in milliseconds (default 1000)
          */

          long delay() default 0;

          /**
          * The maximimum wait (in milliseconds) between retries. If less than the
          * {@link #delay()} then the default of
          * {@value org.springframework.retry.backoff.ExponentialBackOffPolicy#DEFAULT_MAX_INTERVAL}
          * is applied.
          *
          * @return the maximum delay between retries (default 0 = ignored)
          */

          long maxDelay() default 0;

          /**
          * If positive, then used as a multiplier for generating the next delay for backoff.
          *
          * @return a multiplier to use to calculate the next backoff delay (default 0 =
          * ignored)
          */

          double multiplier() default 0;

          /**
          * An expression evaluating to the canonical backoff period. Used as an initial value
          * in the exponential case, and as a minimum value in the uniform case. Overrides
          * {@link #delay()}.
          * @return the initial or canonical backoff period in milliseconds.
          * @date 1.2
          */

          String delayExpression() default "";

          /**
          * An expression evaluating to the maximimum wait (in milliseconds) between retries.
          * If less than the {@link #delay()} then the default of
          * {@value org.springframework.retry.backoff.ExponentialBackOffPolicy#DEFAULT_MAX_INTERVAL}
          * is applied. Overrides {@link #maxDelay()}
          *
          * @return the maximum delay between retries (default 0 = ignored)
          * @date 1.2
          */

          String maxDelayExpression() default "";

          /**
          * Evaluates to a vaule used as a multiplier for generating the next delay for
          * backoff. Overrides {@link #multiplier()}.
          *
          * @return a multiplier expression to use to calculate the next backoff delay (default
          * 0 = ignored)
          * @date 1.2
          */

          String multiplierExpression() default "";

          /**
          * In the exponential case ({@link #multiplier()} &gt; 0) set this to true to have the
          * backoff delays randomized, so that the maximum delay is multiplier times the
          * previous delay and the distribution is uniform between the two values.
          *
          * @return the flag to signal randomization is required (default false)
          */

          boolean random() default false;

          }
          復(fù)制代碼
          1. 在需要重試的方法上配置對應(yīng)的重試次數(shù)、重試異常的異常類型、設(shè)置回退延遲時(shí)間、重試策略、方法監(jiān)聽名稱

          @Component
          public class PlatformClassService {
          @Retryable(
          // 重試異常的異常類型
          value = {Exception.class},
          // 最大重試次數(shù)
          maxAttempts = 5,
          // 設(shè)置回退延遲時(shí)間
          backoff = @Backoff(delay = 500),
          // 配置回調(diào)方法名稱
          listeners = "retryListener"
          )

          public void call() {
          System.out.println("call...");
          throw new RuntimeException("手工異常");
          }
          }
          復(fù)制代碼
          // 初始延遲2秒,然后之后驗(yàn)收1.5倍延遲重試,總重試次數(shù)4
          @Retryable(value = {Exception.class}, maxAttempts = 4, backoff = @Backoff(delay = 2000L, multiplier = 1.5))
          復(fù)制代碼
          1. 監(jiān)聽方法,在配置類中進(jìn)行配置

          /**
          * 注解調(diào)用
          */

          @Bean
          public RetryListener retryListener() {
          return new RetryListener() {
          @Override
          public <T, E extends Throwable> boolean open(RetryContext context, RetryCallback<T, E> callback) {
          System.out.println("open context = " + context + ", callback = " + callback);
          // 返回true繼續(xù)執(zhí)行后續(xù)調(diào)用
          return true;
          }

          @Override
          public <T, E extends Throwable> void close(RetryContext context, RetryCallback<T, E> callback,
          Throwable throwable)
          {
          System.out.println("close context = " + context + ", callback = " + callback);
          }
          @Override
          public <T, E extends Throwable> void onError(RetryContext context, RetryCallback<T, E> callback,
          Throwable throwable)
          {
          System.out.println("onError context = " + context + ", callback = " + callback);
          }
          };
          }
          復(fù)制代碼
          1. 調(diào)用服務(wù)

          @RestController
          public class SpringRetryController {
          @Resource
          private PlatformClassService platformClassService;

          @RequestMapping("/retryPlatformCall")
          public Object retryPlatformCall() {
          try {
          platformClassService.call();
          } catch (Exception e) {
          return "嘗試調(diào)用失敗";
          }
          return "retryPlatformCall";
          }
          }
          復(fù)制代碼
          1. 調(diào)用結(jié)果


          作者:TianXinCoord
          鏈接:https://juejin.cn/post/6988384668500361229
          來源:掘金
          著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請注明出處。



          瀏覽 111
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  国产人妻精品一区二区三区不卡 | 欧美高清猛交xxx黑人猛交性乱 | 日本免费成人撸一区二区三区 | 黄色一级视频在线观看 | 毛片美女视频 |