Spring异常重试机制 - Spring Retry

目录

一 . 引入依赖

二 . 在启用类或业务类上添加@EnableRetry注解启用重试机制(在启用类上添加全局有效 , 在业务类上添加仅当前有效)

三 . 使用@Retryable实现重试

四 . 使用@Recover执行补偿方法

五 . 测试及结果

六 . 常用属性说明

七 . 常见问题


在业务场景中 , 有时候会遇到异常后需要重复尝试的操作 , 例如调用三方接口 , 发送邮件/短信 , 推送消息等等 . 
Spring 提供了Retry组件 , 很方便的解决了上述问题

项目源代码 : https://download.csdn.net/download/xingbaozhen1210/11384277

一 . 引入依赖

        
            org.springframework.retry
            spring-retry
            1.2.4.RELEASE
        

        
            org.aspectj
            aspectjweaver
            1.9.4
        

二 . 在启用类或业务类上添加@EnableRetry注解启用重试机制(在启用类上添加全局有效 , 在业务类上添加仅当前有效)

package cn.xing.demo.retry;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.retry.annotation.EnableRetry;

@SpringBootApplication
@EnableRetry//启用重试机制
public class RetryApplication {

    public static void main(String[] args) {
        SpringApplication.run(RetryApplication.class, args);
    }
}

三 . 使用@Retryable实现重试

    /** @Retryable() = @Retryable(maxAttempts = 3) , 出现任意异常后再重试2次 */
    @Retryable()
    public void work1() {
        System.out.println("执行方法1 : " + LocalDateTime.now());
        throw new RuntimeException();//模拟异常
    }

    /** 出现指定异常时(RuntimeException) , 再重试3次 , 每次延迟5s , 之后每次延迟翻倍*/
    @Retryable(include = {RuntimeException.class}, maxAttempts = 4, backoff = @Backoff(delay = 2000L, multiplier = 2))
    public void work2() {
        System.out.println("执行方法2 : " + LocalDateTime.now());
        throw new RuntimeException();//模拟异常
    }

四 . 使用@Recover执行补偿方法

即使重试之后 , 仍然因为各种原因导致失败 , 这时候就可以在补偿方法中记录异常或采用其他措施

    /** 出现指定异常时(NullPointerException) */
    @Retryable(include = NullPointerException.class)
    public void work3() {
        System.out.println("执行方法3 : " + LocalDateTime.now());
        throw new NullPointerException();//模拟异常
    }

    /** 当重试次数达到限定时 , 会执行@Recover注解的补偿方法 , 只有在入参与发生异常匹配时才会执行该补偿方法 */
    @Recover
    public void recover(NullPointerException e) {
        System.out.println("执行补偿方法 : " + LocalDateTime.now());
    }

五 . 测试及结果

package cn.xing.demo.retry;

import cn.xing.demo.retry.service.WorkService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@SpringBootTest
public class RetryTest {

    @Autowired
    private WorkService workService;

    @Test
    public void test1() {
        workService.work1();
    }

    @Test
    public void test2() {
        workService.work2();
    }

    @Test
    public void test3() {
        workService.work3();
    }
}

Spring异常重试机制 - Spring Retry_第1张图片

六 . 常用属性说明

@Retryable
    value : 指定发生的异常进行重试 
    include : 同value , 默认"" , 当exclude也为空时 , 所有异常都重试 
    exclude : 排除不重试的异常 , 默认"" , 当include也为空时 , 所有异常都重试
    maxAttemps : 尝试次数 , 默认3 . 注意该值包含第一次正常执行的次数 , 即失败之后重新尝试2次 , 一共执行3次
    backoff : 重试补偿机制 , 默认无 , 属性配置如下

@Backoff
    delay : 延迟指定时间后(单位毫秒)重试
    multiplier : 指定延迟的倍数 , 每次执行间隔加倍延迟 . 如delay=5000L,multiplier=2 , 第一次重 试为5S后 , 第二次为第一次的10S后 , 第三次为第二次的20S后

七 . 常见问题

1 . maxAttemps 参数为尝试次数 , 而非重试次数 . 即=3时 , 会重试2次 , =4时会重试3次 , 因为它包括了首次正常执行的计数
2 . retry利用了Spring AOP的原理 , 所以底层采用了代理的技术 , 所有同一个类内调用会使代理失效
    public void work1(){
        work2();
    }
    @Retryable()//work2方法不会执行重试
    public void work2(){
        //...
    }
3 . 有关非幂等的操作(如新增,修改等) , 不要使用重试 , 会影响数据一致性

你可能感兴趣的:(Java)