怎么进行Spring-Retry的使用

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

如何使用Spring-Retry?针对这个问题,本文详细介绍了相应的分析和解答,希望能帮助更多想要解决这个问题的朋友找到更简单易行的方法。

1 Spring-Retry的简介

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

依赖关系

groupIdorg.springframework.retry/groupId

artifactIdspring-重试/artifactId

version1.2.2.RELEASE/version

/dependency

2 Spring中的应用

@Slf4j

publicclassRetryDemo{

publicationstatibooleanretrymethod(Integerparam){ 0

inti=newRandom()。nextInt(参数);

Log.info('随机生成的数字:{} ',I);

if(1==I){ 0

Log.info ('1,返回true。);

returntrue

} else if(i1){ 0

Log.info('小于1,引发参数异常。);

throwneville galargumentexception('参数异常');

} else if(i1i 10){ 0

Log.info('大于1,小于10,抛出参数异常。);

returnfalse

}else{

//用于其他

Log.info('大于10,引发自定义异常。);

ThrownewRemoteAccessException('大于10,抛出自定义异常');

nbsp;       }
    }
}

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的使用问题的解答就分享到这里了,希望

内容来源网络,如有侵权,联系删除,本文地址:https://www.230890.com/zhan/84019.html

(0)

相关推荐

  • JavaWeb学生成绩管理系统功能有哪些

    技术JavaWeb学生成绩管理系统功能有哪些小编给大家分享一下JavaWeb学生成绩管理系统功能有哪些,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一

    攻略 2021年11月23日
  • 二项式反演 学习笔记

    技术二项式反演 学习笔记 二项式反演 学习笔记概念
    二项式反演其实就是利用容斥的思想处理一些通过求“至少或至多”来解决“恰好”的问题。
    形式
    \[\begin{align*}
    f(n)=\sum_{i=

    礼包 2021年12月23日
  • 互联网中元宇宙到底是什么东西

    技术互联网中元宇宙到底是什么东西这篇文章将为大家详细讲解有关互联网中元宇宙到底是什么东西,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。 元宇宙也称为形上宇宙

    攻略 2021年11月2日
  • eclipse中的默认编码方式是什么(eclipse编码格式在哪里)

    技术eclipse编码方法是什么本篇内容介绍了“eclipse编码方法是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成

    攻略 2021年12月23日
  • 怎么使用JavaScript异步操作中串行和并行

    技术怎么使用JavaScript异步操作中串行和并行这篇文章主要讲解了“怎么使用JavaScript异步操作中串行和并行”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“怎么

    攻略 2021年11月19日
  • 直流电源符号,直流电和交流电怎么区分

    技术直流电源符号,直流电和交流电怎么区分直流电(DC)和交流电(AC)直流电源符号,都知道其定义,但很抽象,具体在发电机中是怎么工作的呢,下面我们来分享一下直流电与交流电的工作原理。工具/原料手摇发电机方法/步骤简单讲,

    生活 2021年10月23日