Springboot 使用 Guava 的重试Retry ,轻便灵活

简介: Springboot 使用 Guava 的重试Retry ,轻便灵活

前言



重试,我承认是冷饭重炒了。 之前写过一些关于重试相关的实践介绍文章:


Spring的Retry《Springboot 整合Retry 实现重试机制》:


使用DelayQueue 实现了更加动态灵活的 延迟重试:


《Springboot 指定重发的次数和延迟时间,定时异步执行 重发任务》:


今天,再给大家带来一个又轻又灵活的重试框架整合 ,就是Guava 的重试Retry 。


正文



先给大家看看这个Guava的Retry的几个核心玩法 :


1. 出现异常时重试 ;


出现指定异常时重试;


出现指定异常,里面的提示语或者code等于指定值时重试等。


2.方法返回值等于指定值时重试 ,(String、Integer、Boolean等等都可以,甚至对象等)


3.等待多少秒重试;


固定等待多少秒重试;


随机范围内等待多少秒重试;


不等待秒数直接重试;


增长式等待秒数重试等


4.到达重试多少次数后停止;


不停止,一直重试;


一定时间内,一直重试,然后再停止;


5.重试监听器,每次重试调用监听器里面的方法(可以多个,按照顺序调用)


下面我们来实战一下,写点代码熟悉一下:


1.pom.xml文件引入相关jar:


<dependency>

   <groupId>com.github.rholder</groupId>

   <artifactId>guava-retrying</artifactId>

   <version>2.0.0</version>

</dependency>


2.新建一个 RetryUtil.java :


写一个业务方法,举例 :


public Boolean shopping(){}


这个方法我们业务要求,如果购买下单不成功就进行重试 :


核心方法,通过RetryerBuilder建造一个重试器:


Retryer<Boolean> retryer = RetryerBuilder.<Boolean>newBuilder()

这个重试器,可以设置各种各样的触发条件、要求,也就是我们文章开头提到的各种玩法。


贴一个写好的代码例子:


import com.github.rholder.retry.*;
import com.google.common.base.Predicates;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit;
/**
 * @Author JCccc
 * @Description
 * @Date 2021/10/12 9:26
 */
public class RetryUtil {
    private final Logger log = LoggerFactory.getLogger(this.getClass());
    public Boolean shopping() throws Exception {
        //定义重试机制
        Retryer<Boolean> retryer = RetryerBuilder.<Boolean>newBuilder()
                //retryIf 重试条件
                .retryIfException()
                .retryIfRuntimeException()
                .retryIfExceptionOfType(Exception.class)
                .retryIfException(Predicates.equalTo(new Exception()))
                .retryIfResult(Predicates.equalTo(false))
                //等待策略:每次请求间隔1s
                //fixedWait 固定X秒后重试
                //noWait不等时间直接重试
                //incrementingWait 第一个参数为第一次重试时间,后面会通过设置间隔递增秒数重试
                //randomWait 随机等待设置范围内的时间重试
                .withWaitStrategy(WaitStrategies.fixedWait(1, TimeUnit.SECONDS))
                //停止策略 : 尝试请求6次
                .withStopStrategy(StopStrategies.stopAfterAttempt(6))
                .withRetryListener(new MyRetryListener())
                .withRetryListener(new MyRetryListener2())
                .build();
        //定义请求实现
        Callable<Boolean> callable = new Callable<Boolean>() {
            int times = 1;
            @Override
            public Boolean call() throws Exception {
                log.info("重试调用={}", times);
                times++;
                return placeOrder();
            }
        };
        //利用重试器调用请求
        return retryer.call(callable);
    }
    /**
     * 下单业务方法 模拟
     *
     * @return
     */
    public Boolean placeOrder() {
        int number = new Random().nextInt(11);
        System.out.println("number:"+number);
        if (7 < number) {
            //模拟下单成功
            log.info("下单成功");
            return true;
        }
        log.info("下单失败");
        return false;
    }
    private static class MyRetryListener implements RetryListener {
        @Override
        public <V> void onRetry(Attempt<V> attempt) {
            System.out.println("回调监听器 一,当前是第:"+attempt.getAttemptNumber()+ "次执行");
        }
    }
    private static class MyRetryListener2 implements RetryListener {
        @Override
        public <V> void onRetry(Attempt<V> attempt) {
            System.out.println("回调监听器 二:记录日志"+attempt.getAttemptNumber());
        }
    }
    public static void main(String[] args) throws Exception {
        RetryUtil retryUtil = new RetryUtil();
        Boolean result = retryUtil.shopping();
        System.out.println(result);
    }
}


其实代码里,注释也已经很明白。我在代码里面模拟了一个简单的下单逻辑,如果下单方法返回的数字大于7,代表下单成功,其他情况都需要重试。


代码简述


image.pngimage.pngimage.png


运行一下,看看结果:


可以看到每次重试都会按顺序调用我配置的两个监听器里面的方法;


前面两次下单返回数字都小于7,所以继续触发重试,第三次下单成功结束重试。


image.png


接着我们继续探索一下,这里的重试监听器,可以看到我们的接受参数是


Attempt


这玩意,其实里面也记录整个重试过程中各种元素。


获取触发重试的异常的原因:


public Throwable getExceptionCause() throws IllegalStateException;


配合 attempt.hasException()使用 ,如果异常存在,那么就拿出异常原因,这样在监听器里面我们就能扩展一些业务逻辑了。


获取当前重试的次数:


public long getAttemptNumber() ;


同样,如果我们业务逻辑需要,在重试次数打到某一个数进行业务扩展时,这个方法就可以用上了,当然用来记录方法重试次数时也是用得上的。


获取距离第一次重试的延迟:


public long getDelaySinceFirstAttempt();


获取重试返回的结果:


public V getResult() throws IllegalStateException;


那么同样,还有关于重试器里的方法,大家感兴趣也是可以点进源码里面,自己探索一下:


image.png


以上这几个策略配置器,支持的方法远不止我代码里面介绍的,其实还有很多,例如间隔设置,使用斐波那契增量计算时间等等。

相关文章
|
4月前
|
缓存 NoSQL Java
SpringBoot:第五篇 集成Guava(本地缓存+分布式缓存)
SpringBoot:第五篇 集成Guava(本地缓存+分布式缓存)
69 0
|
4月前
|
NoSQL Java Redis
SpringBoot 中使用布隆过滤器 Guava、Redission实现2
SpringBoot 中使用布隆过滤器 Guava、Redission实现
57 0
|
4月前
|
NoSQL Java Redis
SpringBoot 中使用布隆过滤器 Guava、Redission实现 1
SpringBoot 中使用布隆过滤器 Guava、Redission实现
121 0
|
Java
Java:SpringBoot 整合Spring-Retry实现错误重试
Java:SpringBoot 整合Spring-Retry实现错误重试
116 0
|
前端开发 Java 程序员
如何在SpringBoot中优雅地重试调用第三方API?
如何在SpringBoot中优雅地重试调用第三方API?
253 0
springboot +aop使用guavaretryer 的重试机制
1. 最近在公司在进行rpc 调用的时候,对方的服务不太稳定. 需求就是要间隔多长时间,多少次来重试。达到最大值之后就不在重试。
springboot +aop使用guavaretryer 的重试机制
Springboot 整合Retry 实现重试机制
Springboot 整合Retry 实现重试机制
401 0
Springboot 整合Retry 实现重试机制
|
15天前
|
Java Linux
Springboot 解决linux服务器下获取不到项目Resources下资源
Springboot 解决linux服务器下获取不到项目Resources下资源
|
23天前
|
Java API Spring
SpringBoot项目调用HTTP接口5种方式你了解多少?
SpringBoot项目调用HTTP接口5种方式你了解多少?
75 2