ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

使用springboot的Retry重试机制

2021-07-06 12:30:59  阅读:204  来源: 互联网

标签:info Retry log class 重试 new public springboot


  1. 项目中很多时候会用到重试,比如在网络出现异常的时候调用第三方接口就会出现异常,在这个时候有个可以自动重试的方法就非常方便了。而springboot的Retryable就跟好的解决了这个问题。

  2. 老规矩先上需要导入的包

     <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-web</artifactId>
     </dependency>
     <dependency>
      	 <groupId>org.springframework.retry</groupId>
         <artifactId>spring-retry</artifactId>
     </dependency>
     <dependency>
         <groupId>org.aspectj</groupId>
         <artifactId>aspectjweaver</artifactId>
     </dependency>	 
    
  3. 在项目的启动类上加上一个开始重试的注解@EnableRetry

    @EnableRetry
    @SpringBootApplication
    public class App {
        public static void main(String[] args) {
            SpringApplication.run(App.class,args);
        }
    }
    
  4. 创建一个测试的controller和service以及service的实现类

    @Api(tags = "测试")
    @RestController
    @RequestMapping("/test")
    public class TestController {
        @Autowired
        private TestServices testServices;
        
        @ApiOperation(value = "自动重试")
        @GetMapping("/runRetry")
        public Result<String> runRetry(){
            testServices.saveVideo(new Test());
            return Result.success();
        	}
    }
    
    public interface TestServices {
        void saveVideo(Test test);
    }
    
    @Slf4j
    @Service
    public class TestServicesImpl implements TestServices {
    
        //指定使用自定义名为taskExecutor的线程池来执行该任务,如果没有就不填使用springboot自带的 
        @Async("taskExecutor")
        @Retryable(value = Exception.class,maxAttempts = 4,backoff = @Backoff(delay = 4000L,multiplier = 2))
        @Override
        public void saveVideo(Test test) {
            String startTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(System.currentTimeMillis()));
            log.info("任务开始:{}",startTime);
            test.getStatus();
            String endTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(System.currentTimeMillis()));
            log.info("任务结束:{}",endTime);
        }
    
        @Recover
        public void recover() {
            log.error("任务结束出现异常:连接超时");
        }
    }
    
    public class Test {
        public boolean getStatus(){
            RestTemplate restTemplate=new RestTemplate();
            restTemplate.getForObject("192.168.6.100",String.class);
            return false;
        }
    }
    
  5. 重点解释一下@Retryable的参数
    value:代发触发的条件,值得是拦截捕获的异常。
    maxAttempts:重试的最大次数。
    delay:每次重试的时间间隔,单位是毫秒。
    multiplier:是重试间隔的增长系数,比如时间间隔为4秒 系数为2,那么第二次的重试的间隔就是4秒,第三次就是8秒,第四次就是16秒.
    @Recover 注解注释的方法 就是当重试次数全部完成依然还为解决,就会执行@Recover修饰的方法

  6. 看一下控制台的打印
    在这里插入图片描述

  7. 可以看到控制台打印的时间间隔,刚好就是相隔4.8.16秒。最后也走了recover方法。

  8. 最后说几个重点也是我自己给自己挖的坑
    1.逻辑代码最好不要用try catch捕获异常,即使捕获了记得要再次抛出。

     try {
    	 	String startTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(System.currentTimeMillis()));
            log.info("任务开始:{}",startTime);
            test.getStatus();
            String endTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(System.currentTimeMillis()));
            log.info("任务结束:{}",endTime);
        } catch (IllegalArgumentException Ie){
            log.info("restTemplate出现异常 任务结束出现异常:{}",Ie.getMessage());
            Ie.printStackTrace();
        } catch (IORuntimeException Io){
            log.info("IORuntimeException出现异常 任务结束出现异常:{}",Io.getMessage());
            Io.printStackTrace();
        } catch (Exception e) {
            log.info("任务结束出现异常:{}",e.getMessage());
            e.printStackTrace();
        }
    

    2.这是我最之前写的,因为把异常捕获了,所以就一直触发不了@Retryable。找了很久的原因才找到。真的是自己坑自己。
    3.使用@Retryable修饰方法的类,一定要通过@Autowired注入进去,不能手动的new,目的就是为了加入spring boot的管理中,否则就是无效。

  9. 本次分享就到这里。如有理解错误的地方欢迎指出讨论。

标签:info,Retry,log,class,重试,new,public,springboot
来源: https://blog.csdn.net/weixin_43671737/article/details/118516738

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有