目录
  • 二、retrytemplate
    • 2.1 retrytemplate
    • 2.2 retrylistener
      • 2.3.1 fixedbackoffpolicy
      • 2.3.2 exponentialbackoffpolicy
      • 2.5 retrycallback
        • 三、enableretry
          • 四、retryable

            spring retry主要实现了重试和熔断。

            不适合重试的场景:

            参数校验不合法、写操作等(要考虑写是否幂等)都不适合重试。

            适合重试的场景:

            远程调用超时、网络突然中断等可以重试。

            在spring retry中可以指定需要重试的异常类型,并设置每次重试的间隔以及如果重试失败是继续重试还是熔断(停止重试)。

            一、环境搭建

            加入springretry依赖,springretry使用aop实现,所以也需要加入aop包

            <!-- springretry -->
            <dependency>
               <groupid>org.springframework.retry</groupid>
               <artifactid>spring-retry</artifactid>
            </dependency>
            <dependency>
               <groupid>org.springframework</groupid>
               <artifactid>spring-aspects</artifactid>
            </dependency>

            二、retrytemplate

            2.1 retrytemplate

            • retrytemplate封装了retry基本操作
              • org.springframework.retry.support.retrytemplate
            • retrytemplate中可以指定监听、回退策略、重试策略等
            • 只需要正常new retrytemplate()即可使用

            2.2 retrylistener

            retrylistener指定了当执行过程中出现错误时的回调

            org.springframework.retry.retrylistener

            package org.springframework.retry;
            
            public interface retrylistener {
            
             /**
              * 任务开始执行时调用,只调用一次
              */
             <t, e extends throwable> boolean open(retrycontext context, retrycallback<t, e> callback);
            
             /**
              * 任务执行结束时(包含重试)调用,只调用一次
              */
             <t, e extends throwable> void close(retrycontext context, retrycallback<t, e> callback, throwable throwable);
            
             /**
              * 出现错误时回调
              */
             <t, e extends throwable> void onerror(retrycontext context, retrycallback<t, e> callback, throwable throwable);
            }
            
            

            配置之后在retrytemplate中指定

            2.3 回退策略

            2.3.1 fixedbackoffpolicy

            当出现错误时延迟多少时间继续调用

            fixedbackoffpolicy fixedbackoffpolicy = new fixedbackoffpolicy();
            fixedbackoffpolicy.setbackoffperiod(1000l);
            retrytemplate.setbackoffpolicy(fixedbackoffpolicy);

            配置之后在retrytemplate中指定

            2.3.2 exponentialbackoffpolicy

            当出现错误时第一次按照指定延迟时间延迟后按照指数进行延迟

            // 指数回退(秒),第一次回退1s,第二次回退2s,第三次4秒,第四次8秒
            exponentialbackoffpolicy exponentialbackoffpolicy = new exponentialbackoffpolicy();
            exponentialbackoffpolicy.setinitialinterval(1000l);
            exponentialbackoffpolicy.setmultiplier(2);
            retrytemplate.setbackoffpolicy(exponentialbackoffpolicy);

            配置之后在retrytemplate中指定

            2.4 重试策略

            重试策略主要指定出现错误时重试次数

            // 重试策略
            simpleretrypolicy retrypolicy = new simpleretrypolicy();
            retrypolicy.setmaxattempts(5);
            retrytemplate.setretrypolicy(retrypolicy);
            
            

            配置之后在retrytemplate中指定

            2.5 retrycallback

            retrycallback为retrytemplate.execute时执行的回调

            public final <t, e extends throwable> t execute(retrycallback<t, e> retrycallback) throws e
            
            

            2.6 核心使用

            可以使用retrytemplate完成简单使用
            配置retrytemplate

            • 指定回退策略为exponentialbackoffpolicy
            • 指定重试策略为simpleretrypolicy
            • 指定监听器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();
            
                    /// 回退固定时间(秒)
                   /* fixedbackoffpolicy fixedbackoffpolicy = new fixedbackoffpolicy();
                    fixedbackoffpolicy.setbackoffperiod(1000l);
                    retrytemplate.setbackoffpolicy(fixedbackoffpolicy);*/
            
                    // 指数回退(秒),第一次回退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);
            
                    // 设置监听器,open和close分别在启动和结束时执行一次
                    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;
                }
            }

            在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 -> {
                            // 业务代码
                            // ....
                            // 模拟抛出异常
                            ++count;
                            throw new runtimeexception("抛出异常");
                        });
                    } catch (runtimeexception e) {
                        system.out.println("exception");
                    }
            
                    return "retry = " + count;
                }
            }

            访问retry接口,然后观察日志输出

            18:27:20.648 – http-nio-8888-exec-1 – open
            18:27:20.649 – http-nio-8888-exec-1 – retrytemplate.execute执行
            18:27:20.649 – http-nio-8888-exec-1 – onerror
            18:27:21.658 – http-nio-8888-exec-1 – retrytemplate.execute执行
            18:27:21.658 – http-nio-8888-exec-1 – onerror
            18:27:23.670 – http-nio-8888-exec-1 – retrytemplate.execute执行
            18:27:23.670 – http-nio-8888-exec-1 – onerror
            18:27:27.679 – http-nio-8888-exec-1 – retrytemplate.execute执行
            18:27:27.679 – http-nio-8888-exec-1 – onerror
            18:27:35.681 – http-nio-8888-exec-1 – retrytemplate.execute执行
            18:27:35.681 – http-nio-8888-exec-1 – onerror
            18:27:35.681 – http-nio-8888-exec-1 – close

            三、enableretry

            @enableretry开启重试,在类上指定的时候方法将默认执行,重试三次
            定义service,开启@enableretry注解和指定@retryable,重试可以参考后面一节

            import org.springframework.retry.annotation.retryable;
            
            public interface retryservice {
            
                /**
                 * 重试方法调用
                 */
                @retryable
                void retryservicecall();
            }
            
            
            import org.springframework.retry.annotation.enableretry;
            import org.springframework.stereotype.service;
            
            @enableretry
            @service
            public class retryserviceimpl implements retryservice {
            
                @override
                public void retryservicecall() {
                    printutil.print("方法调用..");
                    throw new runtimeexception("手工异常");
                }
            }

            controller中注入service

            @requestmapping("/retryannotation")
            public object retryannotation() {
                retryservice.retryservicecall();
                return "retryannotation";
            }
            
            

            将会默认重试

            18:46:48.721 – http-nio-8888-exec-1 – 方法调用..
            18:46:49.724 – http-nio-8888-exec-1 – 方法调用..
            18:46:50.730 – http-nio-8888-exec-1 – 方法调用..
            java.lang.runtimeexception: 手工异常

            四、retryable

            用于需要重试的方法上的注解
            有以下几个属性

            retryable注解参数

            • value:指定发生的异常进行重试
            • include:和value一样,默认空,当exclude也为空时,所有异常都重试
            • exclude:指定异常不重试,默认空,当include也为空时,所有异常都重试
            • maxattemps:重试次数,默认3
            • backoff:重试补偿机制,默认没有

            @backoff  注解 重试补偿策略

            • 不设置参数时,默认使用fixedbackoffpolicy(指定等待时间),重试等待1000ms
            • 设置delay,使用fixedbackoffpolicy(指定等待设置delay和maxdealy时,重试等待在这两个值之间均态分布)
            • 设置delay、maxdealy、multiplier,使用 exponentialbackoffpolicy(指数级重试间隔的实现),multiplier即指定延迟倍数,比如delay=5000l,multiplier=2,则第一次重试为5秒,第二次为10秒,第三次为20秒
            @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 {};
            
            }
            @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;
            }

            在需要重试的方法上配置对应的重试次数、重试异常的异常类型、设置回退延迟时间、重试策略、方法监听名称

            @component
            public class platformclassservice {
                @retryable(
                    // 重试异常的异常类型
                    value = {exception.class},
                    // 最大重试次数
                    maxattempts = 5,
                    // 设置回退延迟时间
                    backoff = @backoff(delay = 500),
                    // 配置回调方法名称
                    listeners = "retrylistener"
                )
                public void call() {
                    system.out.println("call...");
                    throw new runtimeexception("手工异常");
                }
            }
            // 初始延迟2秒,然后之后验收1.5倍延迟重试,总重试次数4
            @retryable(value = {exception.class}, maxattempts = 4, backoff = @backoff(delay = 2000l, multiplier = 1.5))
            
            

            监听方法,在配置类中进行配置

            /**
              * 注解调用
              */
            @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继续执行后续调用
                        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);
                    }
                };
            }

            调用服务

            @restcontroller
            public class springretrycontroller {
                @resource
                private platformclassservice platformclassservice;
                
                @requestmapping("/retryplatformcall")
                public object retryplatformcall() {
                    try {
                        platformclassservice.call();
                    } catch (exception e) {
                        return "尝试调用失败";
                    }
                    return "retryplatformcall";
                }
            }

            调用结果

            到此这篇关于springretry重试框架的具体使用的文章就介绍到这了,更多相关springretry重试框架内容请搜索www.887551.com以前的文章或继续浏览下面的相关文章希望大家以后多多支持www.887551.com!