Retry是Resilience4j的组件之一,提供重试的功能,重试不成功则返回默认值,具体如下
List-1
代码语言:javascript复制RetryConfig config = RetryConfig.custom()
//重试次数
.maxAttempts(3)
.waitDuration(Duration.ofMillis(1000))
.retryOnResult(response -> {
LOG.info("retryOnResult resg: {} ", response);
//remote service返回值equals,根据返回true/false进行判断是否重试
return BackendService.retryMsg.equals(response);
})
//依据remote service返回的exception类型判断是否要retry
.retryOnException(e -> e instanceof UnsupportedOperationException)
//依据remote service返回的exception.class判断是否要retry
.retryExceptions(IllegalArgumentException.class, TimeoutException.class)
//忽略remote service抛出的类,不进行retry
.ignoreExceptions(IllegalStateException.class)
.build();
// Create a RetryRegistry with a custom global configuration
RetryRegistry registry = RetryRegistry.of(config);
Retry myRetry = registry.retry("My retry");
List-1说明:
- maxAttempts设置重试3次
- waitDuration设置等待时间(ms),俩次重试之间的等待时间,List-1中是间隔1s
- retryOnResult,根据返回结果来自定义是否要重试
- retryOnException,依据返回的exception类型判断是否要retry
- retryExceptions,根据抛出的类判断是否要retry
- ignoreExceptions,设置忽略的异常类型
如下List-2,List-1定义好了Retry配置之后,用装饰者模式封装远程调用,再配合Try...recover...,这样重试都失败后,降级返回默认值
List-2
代码语言:javascript复制CheckedFunction0<String> stringCheckedFunction0 = Retry.decorateCheckedSupplier(myRetry, new CheckedFunction0<String>() {
@Override
public String apply() throws Throwable {
LOG.info("Call remote service");
return new BackendService().doSomething("Illegal msg");
}
});
Try<String> tryCall = Try.of(stringCheckedFunction0).recover(IllegalArgumentException.class, new Function<IllegalArgumentException, String>() {
@Override
public String apply(IllegalArgumentException e) {
LOG.warn("Recover from unsupported exception");
return "default value of unsupported exception";
}
});
String result = tryCall.get();
运行结果如下:
List-3
代码语言:javascript复制2023-04-23 22:00:42.973 [main] INFO com.mjduan.project.log.LOG info() 27 Call remote service
2023-04-23 22:00:42.981 [main] INFO com.mjduan.project.log.LOG info() 27 Receive msg:Illegal msg
2023-04-23 22:00:43.986 [main] INFO com.mjduan.project.log.LOG info() 27 Call remote service
2023-04-23 22:00:43.987 [main] INFO com.mjduan.project.log.LOG info() 27 Receive msg:Illegal msg
2023-04-23 22:00:44.988 [main] INFO com.mjduan.project.log.LOG info() 27 Call remote service
2023-04-23 22:00:44.989 [main] INFO com.mjduan.project.log.LOG info() 27 Receive msg:Illegal msg
2023-04-23 22:00:44.993 [main] WARN com.mjduan.project.log.LOG warn() 39 Recover from unsupported exception
2023-04-23 22:00:44.994 [main] INFO com.mjduan.project.log.LOG info() 27 Final value:default value of unsupported exception
List-3中可以看出
- 调用BackendService了三次
- 俩次调用之间隔1s
- 三次都失败之后,返回默认值
BackendService如下所示:
代码语言:javascript复制public class BackendService {
public static final String errorMsg = "throw exception";
public static final String hello = "hello world";
public static final String illegalMsg = "Illegal msg";
public static final String retryMsg = "retry msg";
public static final String accessMsg = "access msg";
public String doSomething(){
return hello;
}
public String doSomething(String msg){
LOG.info("Receive msg:{}",msg);
if (errorMsg.equals(msg)) {
throw new UnsupportedOperationException(msg);
}else if (illegalMsg.equals(msg)){
throw new IllegalArgumentException(msg);
}else if (retryMsg.equals(msg)){
return retryMsg;
}else if (accessMsg.equals(msg)){
throw new IllegalStateException("mock illegal state exception");
}
return hello;
}