美文网首页封装组件
封装guava重试神器

封装guava重试神器

作者: 脱缰的小马 | 来源:发表于2020-08-20 10:50 被阅读0次

    一:引入guava依赖
    com.github.rholder -> guava-retrying 2.0.0-AONE-SNAPSHOT
    二:封装调用工具类

    package common.utils.guava;
    
    import com.github.rholder.retry.*;
    import com.google.common.base.Predicates;
    
    import java.util.concurrent.Callable;
    import java.util.concurrent.TimeUnit;
    
    /**
     * @mhh
     * guava重试工具
     * @param <T>
     */
    public class GuavaRetryer<T> {
    
        private Retryer<T> retryer;
    
        public GuavaRetryer(){
    
        }
        /**
         * 初始化重试实例
         * @param sleepTime  重试间隔时间,单位:秒
         * @param retryTimes 失败重试次数
         * @param callerName 调用接口名称
         */
        public GuavaRetryer(Integer sleepTime, Integer retryTimes,String callerName,String dingTalkToken){
            retryer = RetryerBuilder.<T>newBuilder()
                    .retryIfException()                                 //抛出runtime异常、checked异常时都会重试,但是抛出error不会重试。
                    .retryIfResult(Predicates.equalTo(null))    //返回null也需要重试
                    .withWaitStrategy(WaitStrategies.fixedWait(sleepTime, TimeUnit.SECONDS))    //重调策略
                    .withStopStrategy(StopStrategies.stopAfterAttempt(retryTimes))              //尝试次数
                    .withRetryListener(new MyRetryListener(callerName,dingTalkToken))
                    .build();
        }
    
        /**
         * 初始化重试实例
         * @param sleepTime  重试间隔时间,单位:秒
         * @param retryTimes 失败重试次数
         * @param retryListener 重试监听实例
         */
        public GuavaRetryer(Integer sleepTime, Integer retryTimes, RetryListener retryListener){
            retryer = RetryerBuilder.<T>newBuilder()
                    .retryIfException()                                 //抛出runtime异常、checked异常时都会重试,但是抛出error不会重试。
                    .retryIfResult(Predicates.equalTo(null))    //返回null也需要重试
                    .withWaitStrategy(WaitStrategies.fixedWait(sleepTime, TimeUnit.SECONDS))    //重调策略
                    .withStopStrategy(StopStrategies.stopAfterAttempt(retryTimes))              //尝试次数
                    .withRetryListener(retryListener)
                    .build();
        }
    
    
        /**
         * 执行可重试方法
         * @param callable
         * @return
         * @throws Exception
         */
        public T executeWithRetry(Callable<T> callable) throws Exception {
            if(retryer == null){
                throw new Exception("未初始化重试参数!");
            }
            T result= retryer.call(callable);
            return result;
        }
    
        /**
         * 执行可重试方法
         * @param callable
         * @return
         * @throws Exception
         */
        public T executeWithRetry(Integer sleepTime, Integer retryTimes,Callable<T> callable,
                                  String callerName,String dingTalkToken) throws Exception {
            retryer = RetryerBuilder.<T>newBuilder()
                    .retryIfException()                                 //抛出runtime异常、checked异常时都会重试,但是抛出error不会重试。
                    .retryIfResult(Predicates.equalTo(null))    //返回null也需要重试
                    .withWaitStrategy(WaitStrategies.fixedWait(sleepTime, TimeUnit.SECONDS))    //重调策略
                    .withStopStrategy(StopStrategies.stopAfterAttempt(retryTimes))              //尝试次数
                    .withRetryListener(new MyRetryListener(callerName,dingTalkToken))
                    .build();
            T result= retryer.call(callable);
            return result;
        }
    
        /**
         * 执行可重试方法
         * @param callable
         * @return
         * @throws Exception
         */
        public T executeWithRetry(Integer sleepTime, Integer retryTimes,Callable<T> callable,
                                  MyRetryListener myRetryListener) throws Exception {
            retryer = RetryerBuilder.<T>newBuilder()
                    .retryIfException()                                 //抛出runtime异常、checked异常时都会重试,但是抛出error不会重试。
                    .retryIfResult(Predicates.equalTo(null))    //返回null也需要重试
                    .withWaitStrategy(WaitStrategies.fixedWait(sleepTime, TimeUnit.SECONDS))    //重调策略
                    .withStopStrategy(StopStrategies.stopAfterAttempt(retryTimes))              //尝试次数
                    .withRetryListener(myRetryListener)
                    .build();
            T result= retryer.call(callable);
            return result;
        }
    
    
    
    }
    
    

    三:封装回调监听器

    package common.utils.guava;
    import com.github.rholder.retry.Attempt;
    import com.github.rholder.retry.RetryListener;
    import common.helper.DingTalkHelper;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    
    public class MyRetryListener implements RetryListener {
    
        private final static Logger LOGGER = LoggerFactory.getLogger(MyRetryListener.class);
    
        private String callerName;
    
        private String dingTalkToken;
    
        public MyRetryListener(){
        }
    
        public MyRetryListener(String callerName,String dingTalkToken){
            this.callerName = callerName;
            this.dingTalkToken = dingTalkToken;
        }
    
        @Override
        public <T> void onRetry(Attempt<T> attempt) {
            Long attempNumber = attempt.getAttemptNumber();
            Long delay = attempt.getDelaySinceFirstAttempt();
            Boolean hasException = attempt.hasException();
            Boolean hasResult =  attempt.hasResult();
    
            String msg = String.format("重试接口:%s,重试次数=%s,距离第一次重试的延迟=%s,是否有异常=%s,是否有返回结果=%s",
                    callerName,attempNumber,delay,hasException,hasResult);
            LOGGER.info(msg);
    
            if (attempt.hasException()) {
                String causeBy = attempt.getExceptionCause().toString();
                String errorMsg = String.format("重试接口:%s,异常原因=%s",callerName,causeBy);
                String title = "外部接口重试调用监控";
                String sendMsg = msg + "\n" + errorMsg;
                LOGGER.error(errorMsg);
                DingTalkHelper.sendMarkdownMsg(dingTalkToken, title, sendMsg);
            }
        }
    }
    
    

    四:使用例子

    package common.utils.guava;
    
    import com.github.rholder.retry.Attempt;
    
    public class RetryTester {
    
        public static void main(String[] arg) throws Exception {
            /*GuavaRetryer<String> guavaRetryer = new GuavaRetryer(3,3,"测试接口");
            String result1 = guavaRetryer.executeWithRetry(() -> {
                String obj = "测试调用重试接口失败";
                throw new Exception(obj);
                //return obj;
            });*/
            GuavaRetryer<String> guavaRetryer = new GuavaRetryer();
            /*String result2 = guavaRetryer.executeWithRetry(3,3,"测试接口",() -> {
                Thread.sleep(2000);
                String obj = "测试调用重试接口失败";
                throw new Exception(obj);
                //return obj;
            });*/
            String result3 = guavaRetryer.executeWithRetry(3,3,() -> {
                Thread.sleep(2000);
                String obj = "测试调用重试接口失败";
                throw new Exception(obj);
                //return obj;
            },new MyRetryListener(){
                @Override
                public <T> void onRetry(Attempt<T> attempt) {
                    Long attempNumber = attempt.getAttemptNumber();
                    Long delay = attempt.getDelaySinceFirstAttempt();
                    Boolean hasException = attempt.hasException();
                    Boolean hasResult =  attempt.hasResult();
                    System.out.println("重试结果:"+attempNumber+","+delay+","+hasException+","+hasResult);
                }
            });
    
    
        }
    }
    
    

    相关文章

      网友评论

        本文标题:封装guava重试神器

        本文链接:https://www.haomeiwen.com/subject/ihiorktx.html