综合编程

Spring Retry 请求重试指南

微信扫一扫,分享到朋友圈

Spring Retry 请求重试指南

在实际开发中, 例如在系统请求其他系统或资源的外部调用、操作时,由于网络故障等问题会造成短时间内失败。 我们希望当操作失败时,将使用重试策略来重试该操作。

2 添加依赖

<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
<version>1.1.5.RELEASE</version>
</dependency>
复制代码

3 完整依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.devin</groupId>
<artifactId>java-tutorial</artifactId>
<version>1.0-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<dependencies>
<!-- Web依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 重试依赖 -->
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
</dependency>
<!-- Aop依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
</dependencies>
</project>
复制代码

4 开启重试

在启动类中添加 @EnableRetry
注解来启用全局重试。

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.retry.annotation.EnableRetry;
@SpringBootApplication
@EnableRetry
@Slf4j
public class SpringRertyApplication {
public static void main(String[] args) {
SpringApplication.run(SpringRertyApplication.class, args);
log.info("Spring Retry start ok!!!!")
}
}
复制代码

5 通过注解@Retryable实现重试

5.1 添加@Retryable注解

在需要重试的方法上添加 @Retryable
注解

@Retryable(
maxAttempts = 5,
backoff = @Backoff (delay = 1000L),
value = {
RuntimeException.class
}
)
public boolean retryMethod(String requestId) {
log.info("Processing request: {}", requestId);
throw new RuntimeException("Failed Request");
}
复制代码

示例中,仅当方法抛出 RuntimeException
时才尝试重试。 将最多进行 5
次重试,并延迟 1000
毫秒。
默认 @Retryable
不带任何属性,则该方法失败并发生异常,则重试最多3次,延迟一秒钟。

5.2 添加@Recover注解

如果所有重试结果均失败,那么最后抛出的异常将没有任何错误处理逻辑,我们可以使用注解 @Recover
来解决这个问题,例如:

@Recover
public boolean retryMethod(RuntimeException ex, String requestId) {
log.error("Recovering request {} - {}", requestId,ex.getMessage());
return false;
}
复制代码

注意
:方法名、返回值类型、参数值必须一致才生效。

5.3 配置打印重试日志

application.properties
添加以下内容

logging.level.org.springframework.retry.support=debug
复制代码

5.4 测试

@Slf4j
@Component
public class RetryAnnotationTest implements ApplicationRunner {
@Resource
private RetryAnnotationService retryAnnotationService;
@Override
public void run(ApplicationArguments args) throws Exception {
boolean result = retryAnnotationService.retryMethod(RandomUtil.randomNumbers(10));
log.info("result = {}",result);
}
}
复制代码

5.5 执行结果

2020-03-25 14:50:59.099 DEBUG [aop-spel,,,] 11212 --- [           main] o.s.retry.support.RetryTemplate          : Retry: count=0
2020-03-25 14:50:59.102  INFO [aop-spel,,,] 11212 --- [           main] c.s.s.r.a.RetryAnnotationService         : Processing request: 4521824259
2020-03-25 14:51:00.104 DEBUG [aop-spel,,,] 11212 --- [           main] o.s.retry.support.RetryTemplate          : Checking for rethrow: count=1
2020-03-25 14:51:00.104 DEBUG [aop-spel,,,] 11212 --- [           main] o.s.retry.support.RetryTemplate          : Retry: count=1
2020-03-25 14:51:00.104  INFO [aop-spel,,,] 11212 --- [           main] c.s.s.r.a.RetryAnnotationService         : Processing request: 4521824259
2020-03-25 14:51:01.104 DEBUG [aop-spel,,,] 11212 --- [           main] o.s.retry.support.RetryTemplate          : Checking for rethrow: count=2
2020-03-25 14:51:01.104 DEBUG [aop-spel,,,] 11212 --- [           main] o.s.retry.support.RetryTemplate          : Retry: count=2
2020-03-25 14:51:01.104  INFO [aop-spel,,,] 11212 --- [           main] c.s.s.r.a.RetryAnnotationService         : Processing request: 4521824259
2020-03-25 14:51:02.106 DEBUG [aop-spel,,,] 11212 --- [           main] o.s.retry.support.RetryTemplate          : Checking for rethrow: count=3
2020-03-25 14:51:02.106 DEBUG [aop-spel,,,] 11212 --- [           main] o.s.retry.support.RetryTemplate          : Retry: count=3
2020-03-25 14:51:02.106  INFO [aop-spel,,,] 11212 --- [           main] c.s.s.r.a.RetryAnnotationService         : Processing request: 4521824259
2020-03-25 14:51:03.106 DEBUG [aop-spel,,,] 11212 --- [           main] o.s.retry.support.RetryTemplate          : Checking for rethrow: count=4
2020-03-25 14:51:03.106 DEBUG [aop-spel,,,] 11212 --- [           main] o.s.retry.support.RetryTemplate          : Retry: count=4
2020-03-25 14:51:03.106  INFO [aop-spel,,,] 11212 --- [           main] c.s.s.r.a.RetryAnnotationService         : Processing request: 4521824259
2020-03-25 14:51:03.106 DEBUG [aop-spel,,,] 11212 --- [           main] o.s.retry.support.RetryTemplate          : Checking for rethrow: count=5
2020-03-25 14:51:03.107 DEBUG [aop-spel,,,] 11212 --- [           main] o.s.retry.support.RetryTemplate          : Retry failed last attempt: count=5
2020-03-25 14:51:03.107 ERROR [aop-spel,,,] 11212 --- [           main] c.s.s.r.a.RetryAnnotationService         : Recovering request 4521824259 - Failed Request
复制代码

6 通过RetryTemplate实现重试

6.1 创建RetryTemplate配置

@Configuration
@ConditionalOnProperty(name = "retry.template.enable", havingValue = "true")
public class RetryConfig {
/**
* 多少毫秒以后重试
*/
@Value("${retry.template.backOff.period:5000}")
private Long backOffPeriod;
/**
* 重试次数
*/
@Value("${retry.template.max.attempts:3}")
private Integer maxAttempts;
@Bean
public RetryTemplate retryTemplate() {
RetryTemplate retryTemplate = new RetryTemplate();
//定义重试时间
FixedBackOffPolicy fixedBackOffPolicy = new FixedBackOffPolicy();
fixedBackOffPolicy.setBackOffPeriod(backOffPeriod);
retryTemplate.setBackOffPolicy(fixedBackOffPolicy);
//定义重试次数
SimpleRetryPolicy retryPolicy = new SimpleRetryPolicy();
retryPolicy.setMaxAttempts(maxAttempts);
retryTemplate.setRetryPolicy(retryPolicy);
return retryTemplate;
}
}
复制代码

6.2 重试配置

application.properties
添加以下内容

retry.template.enable=true
retry.template.backOff.period:300
retry.template.max.attempts:5
复制代码

6.3 使用RetryTemplate

@Slf4j
@Component
public class RetryTemplateTest implements ApplicationRunner {
@Resource
private RetryTemplate retryTemplate;
@Override
public void run(ApplicationArguments args) {
try {
boolean result = retryMethod(RandomUtil.randomNumbers(10));
log.info("Request Result={}", result);
} catch (RequestRetryException e) {
log.error("Request Exception - message:{}", e.getMessage());
}
}
private boolean retryMethod(String requestId) throws RequestRetryException {
return retryTemplate.execute(context -> {
log.info("Processing request - Param={} - Retry: count={}", requestId, context.getRetryCount());
//TODO 业务逻辑处理
throw new RequestRetryException("Request Retry");
}, context -> {
log.info("Recovering request - Param={} - Retry: count={}", requestId, context.getRetryCount());
//TODO 错误逻辑处理
return false;
});
}
}
复制代码

6.4 执行结果

2020-03-25 15:19:24.112  INFO [aop-spel,,,] 4120 --- [           main] c.s.s.r.template.RetryTemplateTest    : Processing request - Param=5581499424 - Retry: count=0
2020-03-25 15:19:24.414  INFO [aop-spel,,,] 4120 --- [           main] c.s.s.r.template.RetryTemplateTest    : Processing request - Param=5581499424 - Retry: count=1
2020-03-25 15:19:24.715  INFO [aop-spel,,,] 4120 --- [           main] c.s.s.r.template.RetryTemplateTest    : Processing request - Param=5581499424 - Retry: count=2
2020-03-25 15:19:25.015  INFO [aop-spel,,,] 4120 --- [           main] c.s.s.r.template.RetryTemplateTest    : Processing request - Param=5581499424 - Retry: count=3
2020-03-25 15:19:25.315  INFO [aop-spel,,,] 4120 --- [           main] c.s.s.r.template.RetryTemplateTest    : Processing request - Param=5581499424 - Retry: count=4
2020-03-25 15:19:25.316  INFO [aop-spel,,,] 4120 --- [           main] c.s.s.r.template.RetryTemplateTest    : Recovering request - Param=5581499424 - Retry: count=5
2020-03-25 15:19:25.316  INFO [aop-spel,,,] 4120 --- [           main] c.s.s.r.template.RetryTemplateTest    : Request Result=false
复制代码

鼓励宅家抗击疫情 P站向全球访客提供限时免费的高级订阅访问

上一篇

前端Nginx那些事

下一篇

你也可能喜欢

评论已经被关闭。

插入图片

热门栏目

Spring Retry 请求重试指南

长按储存图像,分享给朋友