spring retry 重试机制

当我们调用一个接口可能由于网络等原因造成第一次失败,再去尝试就成功了,这就是重试机制,spring支持重试机制,并且在Spring Cloud中可以与Hystaix结合使用,可以避免访问到已经不正常的实例。 但是切记非幂等情况下慎用重试

加入依赖

org.springframework.retry spring-retry 

在主类上加入 @EnableRetry 注解

1
2
3
4
5
6
7
8
9
@EnableRetry   //开启重试机制
@EnableAutoConfiguration //开启自动配置
@SpringBootApplication
public class SpringBootApplication {

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

测试用例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Recover;
import org.springframework.retry.annotation.Retryable;
import org.springframework.stereotype.Service;

import java.time.LocalTime;

@Service
public class RetryService {

    private final static Logger logger = LoggerFactory.getLogger(RetryService.class);

    private final int totalNum = 100000;

    @Retryable(value = Exception.class, maxAttempts = 3, backoff = @Backoff(delay = 2000L, multiplier = 1.5))
    public void retry(int num) {
        logger.info("减库存开始" + LocalTime.now());
        try {
            int i = 1 / 0;
        } catch (Exception e) {
            logger.error("illegal");
        }
        if (num <= 0) {
            throw new IllegalArgumentException("数量不对");
        }
        logger.info("减库存执行结束" + LocalTime.now());
    }

    @Recover
    public void recover(Exception e) {
        logger.warn("减库存失败!!!" + LocalTime.now());
    }


}
1
2
3
4
5
6
7
8
9
10
11
public class RetryServiceTest extends BaseTest {

    @Autowired
    private RetryService retryService;

    @Test
    public void retry() {
        int count = retryService.retry(-1);
        System.out.println("库存为 :" + count);
    }
}

结果:

1
2
3
4
5
6
7
8
9
2019-07-10 09:52:08.691  INFO 21433 --- [  XNIO-2 task-1] c.c.c.serviceImpl.TestServiceImpl        : 减库存开始09:52:08.691
2019-07-10 09:52:08.691 ERROR 21433 --- [  XNIO-2 task-1] c.c.c.serviceImpl.TestServiceImpl        : illegal
2019-07-10 09:52:10.695  INFO 21433 --- [  XNIO-2 task-1] c.c.c.serviceImpl.TestServiceImpl        : 减库存开始09:52:10.695
2019-07-10 09:52:10.696 ERROR 21433 --- [  XNIO-2 task-1] c.c.c.serviceImpl.TestServiceImpl        : illegal
2019-07-10 09:52:13.701  INFO 21433 --- [  XNIO-2 task-1] c.c.c.serviceImpl.TestServiceImpl        : 减库存开始09:52:13.701
2019-07-10 09:52:13.709 ERROR 21433 --- [  XNIO-2 task-1] c.c.c.serviceImpl.TestServiceImpl        : illegal
2019-07-10 09:52:18.212  INFO 21433 --- [  XNIO-2 task-1] c.c.c.serviceImpl.TestServiceImpl        : 减库存开始09:52:18.212
2019-07-10 09:52:18.214 ERROR 21433 --- [  XNIO-2 task-1] c.c.c.serviceImpl.TestServiceImpl        : illegal
2019-07-10 09:52:18.214  WARN 21433 --- [  XNIO-2 task-1] c.c.c.serviceImpl.TestServiceImpl        : 减库存失败!!!09:52:18.214

注解说明

@Retryable的参数说明:

  • value:抛出指定异常才会重试
  • include:和value一样,默认空,当exclude也为空时,所有异常都重试
  • exclude:指定不处理的异常
  • maxAttempts:最大重试次数,默认3次
  • backoff:重试等待策略,默认使用@Backoff

@Backoff注解

  • delay:指定延迟后重试
  • multiplier(指定延迟倍数)默认为0,表示固定暂停1秒后进行重试,如果把multiplier设置为1.5,则第一次重试为2秒,第二次为3秒,第三次为4.5秒。

@Recover注解

  • 当重试到达指定次数时,被注解的方法将被回调,可以在该方法中进行日志处理。需要注意的是发生的异常和入参类型一致时才会回调。

注意

  • 使用了@Retryable的方法不能在本类被调用,不然重试机制不会生效。也就是要标记为@Service,然后在其它类使用@Autowired注入或者@Bean去实例才能生效。

  • 要触发@Recover方法,那么在@Retryable方法上不能有返回值,只能是void才能生效。

  • 非幂等情况下慎用

  • 使用了@Retryable的方法里面不能使用try…catch包裹,要在方法上抛出异常,不然不会触发。

参考:https://my.oschina.net/wangjunBlog/blog/1889015

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值