温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

怎么进行Spring-Retry的使用

发布时间:2021-11-11 21:07:20 来源:亿速云 阅读:161 作者:柒染 栏目:开发技术

怎么进行Spring-Retry的使用,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。

1 Spring-Retry的简介

在日常的一些场景中, 很多需要进行重试的操作.而spring-retry是spring提供的一个基于spring的重试框架,非常简单好用.

2 Spring中的应用

1 导入maven坐标

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

2 添加被调用类

@Slf4j public class RetryDemo {     public static boolean retryMethod(Integer param) {         int i = new Random().nextInt(param);         log.info("随机生成的数:{}", i);         if (1 == i) {             log.info("为1,返回true.");             return true;         } else if (i < 1) {             log.info("小于1,抛出参数异常.");             throw new IllegalArgumentException("参数异常");         } else if (i > 1 && i < 10) {             log.info("大于1,小于10,抛出参数异常.");             return false;         } else {             //为其他             log.info("大于10,抛出自定义异常.");             throw new RemoteAccessException("大于10,抛出自定义异常");         }     } }

3 添加测试类

@Slf4j public class SpringRetryTest {     /**      * 重试间隔时间ms,默认1000ms      */     private long fixedPeriodTime = 1000L;     /**      * 最大重试次数,默认为3      */     private int maxRetryTimes = 3;     /**      * 表示哪些异常需要重试      * key一定要为Throwable异常的子类    Class<? extends Throwable>      * value为true表示需要重试      */     private Map<Class<? extends Throwable>, Boolean> exceptionMap = new HashMap<>();     @Test     public void test() {         // 1 添加异常的处理结果 true为需要重试 false为不需要重试         exceptionMap.put(RemoteAccessException.class, true);         // 2 构建重试模板实例         RetryTemplate retryTemplate = new RetryTemplate();         // 3 设置重试回退操作策略  设置重试间隔时间         FixedBackOffPolicy backOffPolicy = new FixedBackOffPolicy();         backOffPolicy.setBackOffPeriod(fixedPeriodTime);         // 4 设置重试策略  设置重试次数 设置异常处理结果         SimpleRetryPolicy retryPolicy = new SimpleRetryPolicy(maxRetryTimes, exceptionMap);         //5 重试模板添加重试策略 添加回退操作策略         retryTemplate.setRetryPolicy(retryPolicy);         retryTemplate.setBackOffPolicy(backOffPolicy);              // 6 调用方法         Boolean resp = retryTemplate.execute(                 // RetryCallback 重试回调方法                 retryContext -> {                     boolean result = RetryDemo.retryMethod(110);                     log.info("方法返回结果= {}", result);                     return result;                 },                 // RecoveryCallback 异常回调方法                 retryContext -> {                     //                     log.info("超过最大重试次数或者抛出了未定义的异常!!!");                     return false;                 }         );         log.info("接口返回结果 = {}",resp);     } } /*  // 查看结果  [main] INFO com.cf.demo.SpringRetry.SpringRetryTest - 超过最大重试次数或者抛出了未定义的异常!!!  [main] INFO com.cf.demo.SpringRetry.SpringRetryTest - 接口返回结果 = false */

从代码的书写注解可以看到,RetryTemplate对象是Spring-Retry框架的重试执行者, 由它添加重试策略,回退操作策略等(注释第五步).RetryTemplate执行重试方法(注释第六步),通过execute方法, 传入的参数是重试回调逻辑对象RetryCallback 和执行操作结束的恢复对象RecoveryCallback. 且可以切换添加的异常种类, 得知,只有添加过相应的异常,才会触发重试操作,否则直接调用RecoveryCallback对象方法.

RetryTemplate的部分源码:

 /**   * Keep executing the callback until it either succeeds or the policy dictates that we   * stop, in which case the recovery callback will be executed.   *   * @see RetryOperations#execute(RetryCallback, RecoveryCallback)   * @param retryCallback the {@link RetryCallback}   * @param recoveryCallback the {@link RecoveryCallback}   * @throws TerminatedRetryException if the retry has been manually terminated by a   * listener.   */  @Override  public final <T, E extends Throwable> T execute(RetryCallback<T, E> retryCallback,    RecoveryCallback<T> recoveryCallback) throws E {   return doExecute(retryCallback, recoveryCallback, null);  }

RetryTemplate添加重试策略源码:

 /**   * Setter for {@link RetryPolicy}.   *   * @param retryPolicy the {@link RetryPolicy}   */  public void setRetryPolicy(RetryPolicy retryPolicy) {   this.retryPolicy = retryPolicy;  }

RetryPolicy接口的实现类:

AlwaysRetryPolicy:允许无限重试,直到成功,可能会导致死循环

CircuitBreakerRetryPolicy:有熔断功能的重试策略,需设置3个参数openTimeout、resetTimeout和delegate

CompositeRetryPolicy:组合重试策略,有两种组合方式,乐观组合重试策略是指只要有一个策略允许即可以重试,
悲观组合重试策略是指只要有一个策略不允许即可以重试,但不管哪种组合方式,组合中的每一个策略都会执行

ExceptionClassifierRetryPolicy:设置不同异常的重试策略,类似组合重试策略,区别在于这里只区分不同异常的重试

NeverRetryPolicy:只允许调用RetryCallback一次,不允许重试

SimpleRetryPolicy:固定次数重试策略,默认重试最大次数为3次,RetryTemplate默认使用的策略

TimeoutRetryPolicy:超时时间重试策略,默认超时时间为1秒,在指定的超时时间内允许重试

RetryTemplate添加回退策略源码:

 /**   * Setter for {@link BackOffPolicy}.   *   * @param backOffPolicy the {@link BackOffPolicy}   */  public void setBackOffPolicy(BackOffPolicy backOffPolicy) {   this.backOffPolicy = backOffPolicy;  }

BackOffPolicy的实现类:

ExponentialBackOffPolicy:指数退避策略,需设置参数sleeper、initialInterval、maxInterval和multiplier,initialInterval指定初始休眠时间,默认100毫秒,maxInterval指定最大休眠时间,默认30秒,multiplier指定乘数,即下一次休眠时间为当前休眠时间*multiplier

ExponentialRandomBackOffPolicy:随机指数退避策略,引入随机乘数可以实现随机乘数回退

FixedBackOffPolicy:固定时间的退避策略,需设置参数sleeper和backOffPeriod,sleeper指定等待策略,默认是Thread.sleep,即线程休眠,backOffPeriod指定休眠时间,默认1秒

NoBackOffPolicy:无退避算法策略,每次重试时立即重试

UniformRandomBackOffPolicy:随机时间退避策略,需设置sleeper、minBackOffPeriod和maxBackOffPeriod,该策略在[minBackOffPeriod,maxBackOffPeriod之间取一个随机休眠时间,minBackOffPeriod默认500毫秒,maxBackOffPeriod默认1500毫秒

3 SpringBoot中的应用

1 导入maven坐标

 <dependency>     <groupId>org.springframework.retry</groupId>     <artifactId>spring-retry</artifactId>     <version>1.2.2.RELEASE</version>  </dependency>  <dependency>     <groupId>org.aspectj</groupId>     <artifactId>aspectjweaver</artifactId>     <version>1.9.1</version>  </dependency>

2 添加一个管理类

@Service @Slf4j public class SpringRetryDemo {     /**      * 重试所调用方法      * @return      */     // delay=2000L表示延迟2秒 multiplier=2表示两倍 即第一次重试2秒后,第二次重试4秒后,第三次重试8秒后     @Retryable(value = {RemoteAccessException.class}, maxAttempts = 3, backoff = @Backoff(delay = 2000L, multiplier = 2))     public boolean call(Integer param) {         return RetryDemo.retryMethod(param);     }     /**      * 超过最大重试次数或抛出没有指定重试的异常      * @param e      * @param param      * @return      */     @Recover     public boolean recover(Exception e, Integer param) {         log.info("请求参数为: ", param);         log.info("超过最大重试次数或抛出没有指定重试的异常, e = {} ", e.getMessage());         return false;     } }

3 启动类上添加注解@EnableRetry

@SpringBootApplication @EnableRetry public class DemoApplication {     public static void main(String[] args) {         SpringApplication.run(DemoApplication.class, args);     } }

4 添加测试类

@RunWith(SpringRunner.class) @SpringBootTest(classes = DemoApplication.class) @Slf4j public class DemoApplicationTests {     @Autowired     private SpringRetryDemo springRetryDemo;     @Test     public void testRetry() {         boolean result = springRetryDemo.call(110);         log.info("方法返回结果为: {}", result);     } } /* 运行结果:     随机生成的数:77     大于10,抛出自定义异常.     随机生成的数:23     大于10,抛出自定义异常.     随机生成的数:82     大于10,抛出自定义异常.     请求参数为:      超过最大重试次数或抛出没有指定重试的异常, e = 大于10,抛出自定义异常      方法返回结果为: false */

注解说明:
@Enableretry注解,启用重试功能(默认是否基于子类代理,默认是否, 即是基于Java接口代理)

@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @EnableAspectJAutoProxy(proxyTargetClass = false) @Import(RetryConfiguration.class) @Documented public @interface EnableRetry {  /**   * Indicate whether subclass-based (CGLIB) proxies are to be created as opposed   * to standard Java interface-based proxies. The default is {@code false}.   *   * @return whether to proxy or not to proxy the class   */  boolean proxyTargetClass() default false; }

@Retryable注解, 标记的方法发生异常时会重试

  • value  指定发生的异常进行重试

  • include  与value一样,默认为空,当exclude同时为空时,所有异常都重试

  • exclude  指定异常不重试,默认为空,当include同时为空,所有异常都重试

  • maxAttemps  重试次数,默认3

  • backoff  重试补充机制  默认是@Backoff()注解

@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).   * @return exception types 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()}.   * @since 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.   * @since 1.2   */  String exceptionExpression() default ""; }

@Backoff注解

  • delay  延迟多久后重试

  • multiplier  延迟的倍数

@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Import(RetryConfiguration.class) @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.   * @since 1.2   */  String delayExpression() default "";  /** <<<<<<< HEAD   * An expression evaluating to the maximum wait (in milliseconds) between retries.   * If less than the {@link #delay()} then ignored. =======   * 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. >>>>>>> Fix @Backoff JavaDocs - maxDelay   * Overrides {@link #maxDelay()}   *   * @return the maximum delay between retries (default 0 = ignored)   * @since 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)   * @since 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; }

@Recover注解

当重试达到规定的次数后,被注解标记的方法将被调用, 可以在此方法中进行日志的记录等操作.(该方法的入参类型,返回值类型需要和重试方法保持一致)

@Target({ ElementType.METHOD, ElementType.TYPE }) @Retention(RetentionPolicy.RUNTIME) @Import(RetryConfiguration.class) @Documented public @interface Recover { }

关于怎么进行Spring-Retry的使用问题的解答就分享到这里了,希望以上内容可以对大家有一定的帮助,如果你还有很多疑惑没有解开,可以关注亿速云行业资讯频道了解更多相关知识。

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI