在实际工作中,遇到过由于网络波动或者其他问题导致调用第三方接口出现连接超时或者其他错误,需要对其进行循环重试操作
实现循环重试功能的常规操作
模拟使用一个不能调用的url地址,导致报错,进行重试
public String retry1(String code) {
for (int i = 0; i < 3; i++) {
try {
LOGGER.info("start to retry1-count: {}", count.getAndIncrement());
String result = restTemplate.getForObject("https://www.baidu1.com", String.class);
LOGGER.info("start to retry1-result:{}", result);
break;
} catch (RestClientException ignored) {
}
}
return "retry1";
}
使用spring-retry实现重试功能
使用spring-retry实现重试功能有两种方式,一种是基于@Retryable注解实现,另一种是使用RetryTemplate
一、基于@Retryable注解的方式实现重试
pom.xml
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
</dependency>
Application.java
@SpringBootApplication
@EnableRetry //启用重试功能
public class SpringRetryApplication {
public static void main(String[] args) {
SpringApplication.run(SpringRetryApplication.class, args);
}
}
AnnotationRetryServiceImpl.java
在被重试的方法加上@Retryable(),就能在指定的异常出现情况下重试,而当失败次数到达指定次数后,就会调用@Recover注解的方法,进行恢复。
@Resource
private RestTemplate restTemplate;
@Override
@Retryable(value = {Exception.class}, backoff = @Backoff(multiplier = 1.5)) // 添加重试功能
public String retry1(String code) {
LOGGER.info("start to retry1-count: {}", count.getAndIncrement());
String result = restTemplate.getForObject("https://www.baidu1.com", String.class);
LOGGER.info("start to retry1-result:{}", result);
return result;
}
@Recover
public String recover1(Exception t, String code) {
LOGGER.info("SampleRetryService.recover1-{}:{}", code, t.getClass().getName());
return "recover1";
}
@Retryable()注解参数的相关介绍
value:抛出指定异常才会重试include:和value一样,默认为空,当exclude也为空时,默认所有异常exclude:指定不处理的异常maxAttempts:最大重试次数,默认3次backoff:重试等待策略,默认使用@Backoff,@Backoff的value默认为1000L,我们设置为2000L;multiplier(指定延迟倍数)默认为0,表示固定暂停1秒后进行重试,如果把multiplier设置为1.5,则第一次重试为2秒,第二次为3秒,第三次为4.5秒。@Recover需要注意的是- 方法的返回值必须与
@Retryable方法一致 - 方法的第一个参数,必须是Throwable类型的,建议是与
@Retryable配置的异常一致,后面的参数与@Recover方法中的参数保持一致即可 - 该回调方法与重试方法写在同一个实现类里面
一、基于RetryTemplate方式实现重试
pom.xml
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
</dependency>
RetryTemplateRetryServiceImpl.java
@Resource
private RestTemplate restTemplate;
@Override
public String retry2(int code) {
RetryTemplate retryTemplate = new RetryTemplate();
// 调用retryTemplate.execute方法,第一个参数是执行需要重试的功能,第二个参数是失败次数到达指定次数后,调用的恢复方法
return retryTemplate.execute(retry -> {
LOGGER.info("start to retry2-count: {}", count.getAndIncrement());
return restTemplate.getForObject("https://www.baidu1.com", String.class);
}, retry -> {
LOGGER.info("SampleRetryService.recover2-{}:{}", code, retry.getClass().getName());
return "retry2";
});
}
完整的代码放到了gitee上 spring-retry-demo