springboot整合spring retry 重试机制

2022年9月20日13:17:21

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

一 加入依赖

<dependency>
  <groupId>org.springframework.retry</groupId>
  <artifactId>spring-retry</artifactId>
</dependency>

<dependency>
  <groupId>org.aspectj</groupId>
  <artifactId>aspectjweaver</artifactId>
</dependency>

二 在主类上加入 @EnableRetry 注解
@EnableRetry //开启重试机制
@EnableAutoConfiguration //开启自动配置
@SpringBootApplication
public class WjKekingApplication {

public static void main(String[] args) {
SpringApplication.run(WjKekingApplication.class, args);
}
}
三 demo
package com.wj.project.keking.myTest.service;

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:抛出指定异常才会重试
 * •include:和value一样,默认为空,当exclude也为空时,默认所以异常
 * •exclude:指定不处理的异常
 * •maxAttempts:最大重试次数,默认3次
 * •backoff:重试等待策略,默认使用@Backoff,@Backoff的value默认为1000L,我们设置为2000L;multiplier(指定延迟倍数)默认为0,表示固定暂停1秒后进行重试,如果把multiplier设置为1.5,则第一次重试为2秒,第二次为3秒,第三次为4.5秒。
 */
@Retryable(value = Exception.class, maxAttempts = 3, backoff = @Backoff(delay = 2000L, multiplier = 1.5))
public int 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());
    return totalNum - num;
}

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

}
四 写一个简单的测试

import base.BaseTest;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;

public class RetryServiceTest extends BaseTest {

@Autowired
private RetryService retryService;

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

}

五 结果:
2018-07-28 01:12:09.836 INFO 31128 — [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 55413 (http) with context path ‘’
2018-07-28 01:12:09.843 INFO 31128 — [ main] c.w.p.k.myTest.service.RetryServiceTest : Started RetryServiceTest in 7.178 seconds (JVM running for 10.657)
2018-07-28 01:12:10.584 INFO 31128 — [ main] c.w.p.k.myTest.service.RetryService : 减库存开始01:12:10.584
2018-07-28 01:12:10.584 ERROR 31128 — [ main] c.w.p.k.myTest.service.RetryService : illegal
2018-07-28 01:12:12.588 INFO 31128 — [ main] c.w.p.k.myTest.service.RetryService : 减库存开始01:12:12.588
2018-07-28 01:12:12.588 ERROR 31128 — [ main] c.w.p.k.myTest.service.RetryService : illegal
2018-07-28 01:12:15.588 INFO 31128 — [ main] c.w.p.k.myTest.service.RetryService : 减库存开始01:12:15.588
2018-07-28 01:12:15.588 ERROR 31128 — [ main] c.w.p.k.myTest.service.RetryService : illegal
2018-07-28 01:12:15.589 WARN 31128 — [ main] c.w.p.k.myTest.service.RetryService : 减库存失败!!!01:12:15.589
库存为 :100000
2018-07-28 01:12:15.604 INFO 31128 — [ Thread-3] ConfigServletWebServerApplicationContext : Closing org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@1af2d44a: startup date [Sat Jul 28 01:12:03 CST 2018]; root of context hierarchy
2018-07-28 01:12:15.608 INFO 31128 — [ Thread-3] o.s.s.concurrent.ThreadPoolTaskExecutor : Shutting down ExecutorService ‘taskExecutor’

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

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

3 、非幂等情况下慎用

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

  • 作者:每天进步一点点呐
  • 原文链接:https://blog.csdn.net/Elvira_Sunset/article/details/124746878
    更新时间:2022年9月20日13:17:21 ,共 3441 字。