前言
日常开发中 不仅仅在rpc调用的时候 需要重试啥的
有时候 接第三方系统 也得做一些重试的处理
之前一直都是自己利用function写了一个工具类
现在把自己写的基本思路 和 guava retry 和spring retry 一起记录一下 方便后续自己选择使用
https://github.com/rholder/guava-retrying
https://github.com/spring-projects/spring-retry
https://www.cnblogs.com/jelly12345/p/15292568.html
示例
利用function简略封装
- RetryUtils
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
38
39
40
41
42
43package com.ming.example.retry;
import java.util.function.Supplier;
/**
* 重试工具类
*
* @author ming
* @date 2022-03-22 10:54:41
*/
public class RetryUtils {
/**
* 提供重试次数和间隔设置
*
* @param function 执行的函数 带返回值的
* @param count 重试次数 本身会执行一次也就是执行 count+1次还未成功 则抛出runTimeException
* @param interval 间隔时长 单位ms
* @author ming
* @date 2022-03-22 13:45:40
*/
public static <T> T retry(Supplier<T> function, int count, long interval) {
//当前执行次数
int executeNumber = 0;
while (executeNumber <= count) {
try {
return function.get();
} catch (Exception e) {
e.printStackTrace();
System.out.println("执行函数当前第" + executeNumber + "次!");
}
try {
Thread.sleep(interval);
} catch (InterruptedException e) {
e.printStackTrace();
}
executeNumber++;
}
throw new RuntimeException("执行" + count + "次,无法成功调用!");
}
} - 调用方式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19public static int FLAG = 0;
/**
* 自己通过 function 去写一个公共处理重试的逻辑
* 写起来简单 但是很多地方 很僵硬 只适合对特定的一系列重试的处理
*
* @author ming
* @date 2022-03-22 13:54:16
*/
public void myFunction() {
System.out.println(RetryUtils.retry(() -> {
if (FLAG < 3) {
FLAG++;
throw new RuntimeException("测试异常,当前标记值为" + FLAG);
}
return FLAG;
}, 3, 1000L));
}
guava-retrying
pom配置
1
2
3
4
5<dependency>
<groupId>com.github.rholder</groupId>
<artifactId>guava-retrying</artifactId>
<version>2.0.0</version>
</dependency>调用方式
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
38
39
40
41
42
43
44
45
46
47public static int FLAG = 0;
/**
* guava retry
* 依旧的简单粗暴 和spring retry 主要的区别就是 增加了对于结果判断来重置重试 retryIfResult
*https://github.com/rholder/guava-retrying
* @author ming
* @date 2022-03-22 15:52:26
*/
public void guava() {
Retryer<Integer> retry = RetryerBuilder.<Integer>newBuilder()
//配置重试监听器
// .withRetryListener()
//配置重试等待策略 默认是立即重试
// .withWaitStrategy()
//设置停止策略 默认不停止
// .withStopStrategy()
//配置阻塞策略 默认是sleep
// .withBlockStrategy()
//设置每一次重试的时间限制
// .withAttemptTimeLimiter()
//如果出现Exception 则重试
// .retryIfException()
//如果出现RuntimeException则重试
// .retryIfRuntimeException()
//如果出现指定的异常类型 则重试
// .retryIfExceptionOfType()
//如果返回结果满足表达式则重试
// .retryIfResult()
.retryIfResult(integer -> integer == null || integer <= 0)
.retryIfExceptionOfType(IOException.class)
.retryIfRuntimeException()
.withWaitStrategy(WaitStrategies.fixedWait(1, TimeUnit.SECONDS))
.build();
Integer result = retry.call(() -> {
if (FLAG < 2) {
FLAG++;
System.out.println("测试异常,当前标记值为" + FLAG);
throw new RuntimeException("测试异常,当前标记值为" + FLAG);
}
return FLAG;
});
System.out.println("执行结果:" + result);
}
spring-retry
pom依赖
1
2
3
4
5
6
7
8
9
10<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
<version>${version}</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>${version}</version>
</dependency>调用方式
RetryTemplate方式调用
1 | /** |
注解调用方式
1 |
|
总结
自己实现 可以按照对应的需求 实现的更加精细 示例只是个例子 需要自己去额外的处理其他的细节
guava-retrying和spring-retry 大多数使用方式一样 区别较大的地方 就是guava-retrying 支持根据结果去继续重试