Spring retry 和 guava retryer重试、@async 异步执行注解

Spring retry 和 guava retryer重试、@async 异步执行注解

spring retry

  • 依赖

    
    <dependency>
        <groupId>org.springframework.retrygroupId>
        <artifactId>spring-retryartifactId>
    dependency>
    <dependency>
        <groupId>org.aspectjgroupId>
        <artifactId>aspectjweaverartifactId>
    dependency>
    <dependency>
        <groupId>com.alibabagroupId>
        <artifactId>fastjsonartifactId>
        <version>1.2.46version>
    dependency>
    
    
  • 代码实现

    • 异常类

      package com.retry.demo.springretry.exception;
      
      import lombok.Builder;
      import lombok.Getter;
      
      @Builder
      @Getter
      public class RetryException extends RuntimeException {
          private String code;
          private String message;
      }
      
    • 主类

      package net.fanci.stars;
      
      import net.fanci.stars.listener.PropertiesListener;
      import org.springframework.boot.SpringApplication;
      import org.springframework.boot.autoconfigure.SpringBootApplication;
      import org.springframework.context.annotation.Bean;
      import org.springframework.retry.annotation.EnableRetry;
      import org.springframework.scheduling.annotation.EnableAsync;
      import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
      
      import java.util.concurrent.Executor;
      
      @SpringBootApplication
      @EnableRetry
      public class StarsParentApplication {
          
          public static void main(String[] args) {
      //        SpringApplication.run(StarsParentApplication.class, args);
              SpringApplication application = new SpringApplication(StarsParentApplication.class);
              //加载配置文件
              application.addListeners(new PropertiesListener("config.properties"));
              application.run(args);
          }
      
          @Bean(name = "threadPoolTaskExecutor")
          public Executor threadPoolTaskExecutor() {
              return new ThreadPoolTaskExecutor();
          }
          
      }
      
    • 重试类

      package com.retry.demo.springretry.serivce;
      
      import com.retry.demo.springretry.exception.RetryException;
      import lombok.extern.slf4j.Slf4j;
      import org.springframework.retry.annotation.Backoff;
      import org.springframework.retry.annotation.Recover;
      import org.springframework.retry.annotation.Retryable;
      import org.springframework.stereotype.Service;
      
      @Service
      @Slf4j
      public class RetryServiceImpl implements RetryService {
      
          int i = 1;
      	
          // 需要指定 maxDelay
          @Override
          @Retryable(include = {RetryException.class}, maxAttempts = 4, backoff = @Backoff(delay = 3000l,maxDelay = 60 * 1000L, multiplier = 1))
          public String retry() {
              log.info("测试retry");
              //生产环境此处应该为调用第三方接口,判断接口返回code
              if (i == 3) {
                  return i++ + "";
              }
              i++;
              log.info("============" + i);
              RetryException retryException = RetryException.builder().code("9999").message("连接超时").build();
              throw retryException;
          }
      
      
          @Recover
          public String recover(RetryException e) {
              log.info(e.getMessage());
              return "6";
          }
      }
      

guava retryer

  • 依赖

    
    <dependency>
        <groupId>com.github.rholdergroupId>
        <artifactId>guava-retryingartifactId>
        <version>2.0.0version>
    dependency>
    
    
  • 实现类

    package com.retry.demo.guavaretrying;
    
    import com.github.rholder.retry.*;
    import com.google.common.base.Predicates;
    import lombok.extern.slf4j.Slf4j;
    
    import java.util.concurrent.Callable;
    import java.util.concurrent.ExecutionException;
    import java.util.concurrent.TimeUnit;
    import java.util.function.Predicate;
    
    /**
     * @author xxx
     * @create 2018/08/12 13:29
     * @description
     */
    @Slf4j
    public class demos {
    
        public static void main(String[] args) {
    
            /**
             * 根据结果判断是否重试:
             * 通过 counter 控制返回结果,返回结果不是 success 就进行重试,知道 counter = 5 的时候返回 success
             */
    //        test1();
    
            /**
             * 根据异常判断是否重试:
             * 如果 counter < 5 则抛出异常,等于 5 则正常返回,停止重试
             */
    //        test2();
    
            /**
             * 重试策略——设定无限重试:
             * 在有异常情况下,无限重试,直到返回正常有效结果
             */
    //        test3();
    
            /**
             * 重试策略——设定最大的重试次数:
             * 在有异常情况下,最多重试3次,如果超过3次则会抛出异常
             */
    //        test4();
    
            /**
             * 等待策略——设定重试等待固定时长策略:
             * 设定每次重试等待间隔固定为100ms
             */
    //        test5();
    
            /**
             * 等待策略——设定重试等待时长固定增长策略:
             * 设定初始等待时长值,并设定固定增长步长,但不设定最大等待时长
             * 等待时长依次为200ms、300ms、400ms、500ms
             */
    //        test6();
    
            /**
             * 等待策略——设定重试等待时长按斐波那契数列增长策略:
             * 根据multiplier值按照指数级增长等待时长,并设定最大等待时长
             * 等待时长依次为200ms、400ms、800ms、1000ms
             */
    //        test7();
    
            /**
             * 等待策略——设定重试等待时长按指数增长策略:
             * 根据multiplier值按照斐波那契数列增长等待时长,并设定最大等待时长,斐波那契数列:1、1、2、3、5、8、13、21、34、……
             * 等待时长依次为100ms、100ms、200ms、300ms
             */
    //        test8();
    
            /**
             * 等待策略——组合重试等待时长策略:
             * 组合ExponentialWaitStrategy和FixedWaitStrategy策略
             * 等待时长依次为100(50+50)ms、150(100+50)ms、250(200+50)ms、450(400+50)ms
             */
    //        test9();
    
            /**
             * 定义两个监听器,分别打印重试过程中的细节,未来可更多的用于异步日志记录,亦或是特殊处理:
             * RetryListener会根据注册顺序执行
             */
            test10();
    
        }
    
        private static void test10() {
            Callable<String> callable = new Callable<String>() {
                int counter = 0;
    
                @Override
                public String call() throws Exception {
                    counter++;
                    log.info("counter--------{}", counter);
                    if (counter < 5) {
                        throw new RuntimeException("error");
                    } else {
                        return "success";
                    }
                }
            };
            // 监听器 1
            RetryListener retryListener1 = new RetryListener() {
                @Override
                public <V> void onRetry(Attempt<V> attempt) {
                    // 第几次重试,(注意:第一次重试其实是第一次调用)
                    log.info("[retry]time=" + attempt.getAttemptNumber());
    
                    // 距离第一次重试的延迟
                    log.info(",delay=" + attempt.getDelaySinceFirstAttempt());
    
                    // 重试结果: 是异常终止, 还是正常返回
                    log.info(",hasException=" + attempt.hasException());
                    log.info(",hasResult=" + attempt.hasResult());
    
                    // 是什么原因导致异常
                    if (attempt.hasException()) {
                        log.info(",causeBy=" + attempt.getExceptionCause().toString());
                    } else {
                        // 正常返回时的结果
                        log.info(",result=" + attempt.getResult());
                    }
    
                    // 增加了额外的异常处理代码
                    try {
                        V result = attempt.get();
                        log.info(",rude get=" + result);
                    } catch (ExecutionException e) {
                        log.error("this attempt produce exception." + e.getCause().toString());
                    }
                }
            };
            // 监听器 2
            RetryListener retryListener2 = new RetryListener() {
                @Override
                public <V> void onRetry(Attempt<V> attempt) {
                    log.info("myRetryListener2 : [retry]time=" + attempt.getAttemptNumber());
                }
            };
            Retryer<String> retryer = RetryerBuilder.<String>newBuilder()
                    .retryIfRuntimeException()
                    .withStopStrategy(StopStrategies.neverStop())
                    .withRetryListener(retryListener1)
                    .withRetryListener(retryListener2)
                    .build();
    
            try {
                String result = retryer.call(callable);
                log.info("result:{}", result);
            } catch (ExecutionException e) {
                e.printStackTrace();
            } catch (RetryException e) {
                e.printStackTrace();
            }
        }
    
        private static void test9() {
            Callable<String> callable = new Callable<String>() {
                int counter = 0;
    
                @Override
                public String call() throws Exception {
                    counter++;
                    log.info("counter--------{}", counter);
                    if (counter < 5) {
                        throw new RuntimeException("error");
                    } else {
                        return "success";
                    }
                }
            };
    
            Retryer<String> retryer = RetryerBuilder.<String>newBuilder()
                    .retryIfRuntimeException()
                    .withStopStrategy(StopStrategies.neverStop())
                    .withWaitStrategy(WaitStrategies.join(WaitStrategies.exponentialWait(25, 500, TimeUnit.MILLISECONDS)
                            , WaitStrategies.fixedWait(50, TimeUnit.MILLISECONDS)))
                    .build();
    
            try {
                String result = retryer.call(callable);
                log.info("result:{}", result);
            } catch (ExecutionException e) {
                e.printStackTrace();
            } catch (RetryException e) {
                e.printStackTrace();
            }
        }
    
        private static void test8() {
            Callable<String> callable = new Callable<String>() {
                int counter = 0;
    
                @Override
                public String call() throws Exception {
                    counter++;
                    log.info("counter--------{}", counter);
                    if (counter < 5) {
                        throw new RuntimeException("error");
                    } else {
                        return "success";
                    }
                }
            };
    
            Retryer<String> retryer = RetryerBuilder.<String>newBuilder()
                    .retryIfRuntimeException()
                    .withStopStrategy(StopStrategies.neverStop())
                    .withWaitStrategy(WaitStrategies.fibonacciWait(100, 1000, TimeUnit.MILLISECONDS))
                    .build();
    
            try {
                String result = retryer.call(callable);
                log.info("result:{}", result);
            } catch (ExecutionException e) {
                e.printStackTrace();
            } catch (RetryException e) {
                e.printStackTrace();
            }
        }
    
        private static void test7() {
            Callable<String> callable = new Callable<String>() {
                int counter = 0;
    
                @Override
                public String call() throws Exception {
                    counter++;
                    log.info("counter--------{}", counter);
                    if (counter < 5) {
                        throw new RuntimeException("error");
                    } else {
                        return "success";
                    }
                }
            };
    
            Retryer<String> retryer = RetryerBuilder.<String>newBuilder()
                    .retryIfRuntimeException()
                    .withStopStrategy(StopStrategies.neverStop())
                    .withWaitStrategy(WaitStrategies.exponentialWait(100, 1000, TimeUnit.MILLISECONDS))
                    .build();
    
            try {
                String result = retryer.call(callable);
                log.info("result:{}", result);
            } catch (ExecutionException e) {
                e.printStackTrace();
            } catch (RetryException e) {
                e.printStackTrace();
            }
        }
    
        private static void test6() {
            Callable<String> callable = new Callable<String>() {
                int counter = 0;
    
                @Override
                public String call() throws Exception {
                    counter++;
                    log.info("counter--------{}", counter);
                    if (counter < 5) {
                        throw new RuntimeException("error");
                    } else {
                        return "success";
                    }
                }
            };
    
            Retryer<String> retryer = RetryerBuilder.<String>newBuilder()
                    .retryIfRuntimeException()
                    .withStopStrategy(StopStrategies.neverStop())
                    .withWaitStrategy(WaitStrategies.incrementingWait(200, TimeUnit.MILLISECONDS, 100, TimeUnit.MILLISECONDS))
                    .build();
    
            try {
                String result = retryer.call(callable);
                log.info("result:{}", result);
            } catch (ExecutionException e) {
                e.printStackTrace();
            } catch (RetryException e) {
                e.printStackTrace();
            }
        }
    
        private static void test5() {
            Callable<String> callable = new Callable<String>() {
                int counter = 0;
    
                @Override
                public String call() throws Exception {
                    counter++;
                    log.info("counter--------{}", counter);
                    if (counter < 5) {
                        throw new RuntimeException("error");
                    } else {
                        return "success";
                    }
                }
            };
    
            Retryer<String> retryer = RetryerBuilder.<String>newBuilder()
                    .retryIfRuntimeException()
                    .withStopStrategy(StopStrategies.neverStop())
                    .withWaitStrategy(WaitStrategies.fixedWait(100, TimeUnit.MILLISECONDS))
                    .build();
    
            try {
                String result = retryer.call(callable);
                log.info("result:{}", result);
            } catch (ExecutionException e) {
                e.printStackTrace();
            } catch (RetryException e) {
                e.printStackTrace();
            }
        }
    
        private static void test4() {
            Callable<String> callable = new Callable<String>() {
                int counter = 0;
    
                @Override
                public String call() throws Exception {
                    counter++;
                    log.info("counter--------{}", counter);
                    if (counter < 5) {
                        throw new RuntimeException("error");
                    } else {
                        return "success";
                    }
                }
            };
    
            Retryer<String> retryer = RetryerBuilder.<String>newBuilder()
                    .retryIfRuntimeException()
                    .withStopStrategy(StopStrategies.stopAfterAttempt(3))
                    .withWaitStrategy(WaitStrategies.fixedWait(100, TimeUnit.MILLISECONDS))
                    .build();
    
            try {
                String result = retryer.call(callable);
                log.info("result:{}", result);
            } catch (ExecutionException e) {
                e.printStackTrace();
            } catch (RetryException e) {
                e.printStackTrace();
            }
        }
    
        private static void test3() {
            Callable<String> callable = new Callable<String>() {
                int counter = 0;
    
                @Override
                public String call() throws Exception {
                    counter++;
                    log.info("counter--------{}", counter);
                    if (counter < 5) {
                        throw new RuntimeException("error");
                    } else {
                        return "success";
                    }
                }
            };
    
            Retryer<String> retryer = RetryerBuilder.<String>newBuilder()
                    .retryIfRuntimeException()
                    .withStopStrategy(StopStrategies.neverStop())
                    .build();
    
            try {
                String result = retryer.call(callable);
                log.info("result:{}", result);
            } catch (ExecutionException e) {
                e.printStackTrace();
            } catch (RetryException e) {
                e.printStackTrace();
            }
        }
    
        private static void test2() {
            Callable<String> callable = new Callable<String>() {
                int counter = 0;
    
                @Override
                public String call() throws Exception {
                    counter++;
                    log.info("counter--------{}", counter);
                    if (counter < 5) {
                        throw new RuntimeException("error");
                    } else {
                        return "success";
                    }
                }
            };
    
            Retryer<String> retryer = RetryerBuilder.<String>newBuilder()
                    .retryIfRuntimeException()
                    .withStopStrategy(StopStrategies.neverStop())
                    .build();
    
            try {
                retryer.call(callable);
            } catch (ExecutionException e) {
                e.printStackTrace();
            } catch (RetryException e) {
                e.printStackTrace();
            }
        }
    
        private static void test1() {
            Callable<String> callable = new Callable<String>() {
                int counter = 0;
    
                @Override
                public String call() throws Exception {
                    counter++;
                    log.info("counter--------{}", counter);
                    if (counter < 5) {
                        return "error";
                    } else {
                        return "success";
                    }
                }
            };
    
            Retryer<String> retryer = RetryerBuilder.<String>newBuilder()
                    .retryIfResult(result -> !result.contains("success"))
                    .withStopStrategy(StopStrategies.neverStop())
                    .build();
    
            try {
                retryer.call(callable);
            } catch (ExecutionException e) {
                e.printStackTrace();
            } catch (RetryException e) {
                e.printStackTrace();
            }
        }
    
    }
    

@async

  • 在需要异步执行的方法上使用@async注解,其实就是线程

  • 在主类添加注解

    @SpringBootApplication
    @EnableAsync
    public class StarsParentApplication {
    
        public static void main(String[] args) {
    
        }
    }
    

你可能感兴趣的:(java)