Resilience4j之重试Retry

2023-04-30 14:39:13 浏览数 (2)

    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说明:

  1. maxAttempts设置重试3次
  2. waitDuration设置等待时间(ms),俩次重试之间的等待时间,List-1中是间隔1s
  3. retryOnResult,根据返回结果来自定义是否要重试
  4. retryOnException,依据返回的exception类型判断是否要retry
  5. retryExceptions,根据抛出的类判断是否要retry
  6. 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中可以看出

  1. 调用BackendService了三次
  2. 俩次调用之间隔1s
  3. 三次都失败之后,返回默认值

    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;
    }

0 人点赞