大数跨境
0
0

SpringBoot高并发!业务方法重试就该使用它

SpringBoot高并发!业务方法重试就该使用它 Spring全家桶实战案例
2024-08-05
0
导读:环境:SpringBoot3.2.51. 简介业务功能重试机制通常在项目中是非常有必要的,特别是在处理外部系统

环境:SpringBoot3.2.5



1. 简介

业务功能重试机制通常在项目中是非常有必要的,特别是在处理外部系统调用(如HTTP请求、数据库操作、消息队列等)时。这些操作可能因网络波动、服务暂时不可用等原因而失败。重试机制可以提高系统的健壮性和用户体验,通过自动重试可以减少因单次失败导致的整体业务中断。本篇文章将介绍一款非常优秀的重试框架Fast-Retry。

Fast-Retry是一个高性能任务重试框架,支持百万级别任务的并发重试处理。与主流的Spring-Retry, Guava-Retry等同步重试框架不同,Fast-Retry是一个支持异步重试框架,支持异步任务的重试、超时等待、回调。Spring-Retry, Guava-Retry均无法支持大批量任务的重试,因为会占用过多线程资源导致大量任务在等待处理,随着任务数的增加,系统吞吐量大大降低,性能指数级降低,Fast-Retry的性能是前者的指数倍。

Fast-Retry,Spring-Retry,Guava-Retry性能对比

测试条件

  • 测试线程池: 8个固定线程

  • 单个任务逻辑: 轮询5次,隔2秒重试一次,总耗时10秒

  • 未测预计公式:当我们使用线程池的时候, 一般线程池中 总任务处理耗时 = 任务数/并发度 x 单个任务重试耗时

2. 实战案例

2.1 引入依赖

<dependency>  <groupId>io.github.burukeyou</groupId>  <artifactId>fast-retry-all</artifactId>  <version>0.2.0</version></dependency>

配置开启重试功能

@SpringBootApplication@EnableFastRetrypublic class SpringbootRetryApplication {}

接下来就可以通过@FastRetry注解配置类或方法。

2.2 基于编程重试

public String process() throws Exception {  // 自定义结果重试策略,如果返回结果不是"success"则进行重试  RetryResultPolicy<String> resultPolicy = result -> !result.equals("success");  FastRetryer<String> retryer = FastRetryBuilder.<String>builder()      // 重试次数      .attemptMaxTimes(2)       // 重试间隔      .waitRetryTime(1, TimeUnit.SECONDS)      // 发生异常后是否重试      .retryIfException(true)      // 什么类型的异常进行重试      .retryIfExceptionOfType(RuntimeException.class)      .exceptionRecover(true)      // 自定义结果重试策略      .resultPolicy(resultPolicy)      .build();  CompletableFuture<String> future = retryer.submit(() -> {    int r = new Random().nextInt(10) ;    System.out.printf("执行业务方法, 随机值: %d%n", r) ;    if (r != 1) {      // 抛出异常,也会重试      // throw new RuntimeException("错误的参数: " + r) ;      return "dead" ;    }    return "success" ;  });  return future.get();}

运行结果

成功

执行业务方法, 随机值: 5执行业务方法, 随机值: 4执行业务方法, 随机值: 1结果: success

失败

超过重试次数后抛出异常,并且方法执行的最终结果返回:null。

2.3 基于注解

基于注解方式使用起来与spring-retry差不多。一个注解搞定

@FastRetry(  retryWait = @RetryWait(delay = 2),   exceptionRecover = false,   maxAttempts = 2,  retryStrategy = PackRetryPolicy.class)public String business(Long id, String name) {  int r = new Random().nextInt(10) ;  System.out.printf("执行业务方法, 随机值: %d%n", r) ;  if (r != 1) {    throw new RuntimeException("错误的参数: " + r) ;  }  return "success" ;}

自定义方法返回结果重试策略

public class PackRetryPolicy implements RetryResultPolicy<String> {  public boolean canRetry(String t) {    return !t.equals("success") ;  }}

结果重试策略可以有多个。

2.4 异步任务重试

@FastRetry(  retryWait = @RetryWait(delay = 2),   maxAttempts = 2,   retryStrategy = PackRetryPolicy.class)public CompletableFuture<String> asyncBusiness(Long id, String name) {  return CompletableFuture.supplyAsync(() -> {    System.out.println("async 执行业务方法...") ;    int r = new Random().nextInt(10) ;    if (r != 1) {      // throw new RuntimeException("错误的参数: " + r) ;      return "1" ;    }    return "success" ;  }) ;}

输出结果

async 执行业务方法...async 执行业务方法...async 执行业务方法...发生错误: com.burukeyou.retry.core.exceptions.FastRetryTimeOutException:   The maximum retry count has been exceeded after 2 times. Stop retry

同样的代码,如果换成spring-retry,如下:

// spring-retry的注解@Retryable(maxAttempts = 2)public CompletableFuture<String> asyncBusiness(Long id, String name) {  // 方法体与上面基本,一样只不过其中抛出的是异常}

输出结果

async 执行业务方法...发生错误: java.lang.RuntimeException: 错误的参数: 3

没有进行重试,说明spring-retry不支持异步任务。

在spring-retry中你可以在注解中配置recover,指定一个恢复的方法(或降级的方法),在fast-retry中没有这样的功能。如下spring-retry示例:

@Retryable(maxAttempts = 2, recover = "businessRecover")public String business(Long id, String name) {}@Recoverprivate String businessRecover(Throwable th, Long id, String name) {}

当重试次数用尽后,将调用我们这里配置的businessRecover方法,同时在该方法中还可以获取具体的异常信息。

以上是本篇文章的全部内容,如对你有帮助帮忙点赞+转发+收藏

推荐文章

Controller接口地址还能这样玩?

当心!SpringBoot在以下几种情况将导致代理失效

完美!SpringBoot + HTML模板高效生成PDF文档

强大!SpringBoot结合STOMP简化数据实时通信

SpringBoot3必须掌握的5个强大功能,其中JVM优化技巧太厉害了

SpringBoot3.2开始Controller参数验证@Validated新功能

SpringBoot自带Controller接口监控,赶紧用起来

Java开发人员必须掌握的11种干净代码最佳实践

请牢记SpringBoot这7个强大的隐藏Bean

警惕!SpringBoot错误发布事件,造成死锁Deadlock

SpringBoot非常实用的一个功能,你肯定不知道

【声明】内容源于网络
0
0
Spring全家桶实战案例
Java全栈开发,前端Vue2/3全家桶;Spring, SpringBoot 2/3, Spring Cloud各种实战案例及源码解读
内容 832
粉丝 0
Spring全家桶实战案例 Java全栈开发,前端Vue2/3全家桶;Spring, SpringBoot 2/3, Spring Cloud各种实战案例及源码解读
总阅读38
粉丝0
内容832