Spring Retry重试框架

简介

Spring Retry源码地址

Spring Retry重试框架支持声明式(Declarative)和编程式(imperative)两种用法。

环境要求

Spring Retry requires Java 1.7 and Maven 3.0.5 (or greater).
建议java 1.8以上,使用lambda表达式简化代码。

声明式(Declarative)

声明式用法基于AOP切面编程,需要引入aspectjweaver或spring-boot-starter-aop
pom.xml

	<!-- Spring Retry -->
	<dependency>
	    <groupId>org.springframework.retry</groupId>
	    <artifactId>spring-retry</artifactId>
	</dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-aop</artifactId>
    </dependency>
@Configuration
@EnableRetry
public class Application {
    
    

}

@Service
class Service {
    
    
    @Retryable(RemoteAccessException.class)
    public void service() {
    
    
        // ... do something
    }
    @Recover
    public void recover(RemoteAccessException e) {
    
    
       // ... panic
    }
}

实际案例:

    @Override
    @Retryable(value = {
    
     Exception.class }, maxAttempts = 3, backoff = @Backoff(delay = 5000L, multiplier = 1))
    public Object restPostTest(Map map, String url) throws Exception {
    
    
        logger.info("调用第三方接口");
        RestTemplate restTemplate = new RestTemplate();
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        //设置访问的Entity
        HttpEntity entity = new HttpEntity<>(map, headers);
        ResponseEntity<String> result;
        JSONObject data = new JSONObject();
        //发起一个POST请求
        logger.info("发起一个POST请求");
        result = restTemplate.exchange(url, HttpMethod.POST, entity, String.class);
        data = JSONObject.parseObject(result.getBody());
        logger.info("返回结果{}",data);
        return data;
    }
    
    @Recover
    public Object recover(Exception e, Map map, String url) {
    
    
       // ... 放入消息队列或数据库
    }

@Retryable注解
被注解的方法发生异常时会重试
value:指定发生的异常进行重试
include:和value一样,默认空,当exclude也为空时,所有异常都重试
exclude:指定异常不重试,默认空,当include也为空时,所有异常都重试
maxAttemps:重试次数,默认3
backoff:重试补偿机制,默认没有

@Backoff注解
delay:指定延迟后重试
multiplier:指定延迟的倍数,比如delay=5000l,multiplier=2时,第一次重试为5秒后,第二次为10秒,第三次为20秒

@Recover
当重试到达指定次数时,被注解的方法将被回调,可以在该方法中进行日志处理。需要注意的是发生的异常和入参类型一致时才会回调。

说明:

  • 以上注解所在的类对象必须由spring容器接管,使用@Service、@Bean等方式。
  • @Retryable 和 @Recover标注的方法返回值必须保持一致!
  • @Recover方法参数,Exception e必须放在第一个参数位置且类型需与@Retryable抛出类型一致。
  • @Retryable方法内不可再使用try…catch捕获异常,防止异常无法被接收。

编程式(imperative)

RetryTemplate template = new RetryTemplate();

TimeoutRetryPolicy policy = new TimeoutRetryPolicy();
policy.setTimeout(30000L);

template.setRetryPolicy(policy);

Foo result = template.execute(new RetryCallback<Foo>() {
    
    

    public Foo doWithRetry(RetryContext context) {
    
    
        // Do stuff that might fail, e.g. webservice operation
        return result;
    }

});

链式用法结合lambda表达式简化代码

RetryTemplate template = RetryTemplate.builder()
				.maxAttempts(3)
				.fixedBackoff(1000)
				.retryOn(RemoteAccessException.class)
				.build();

template.execute(ctx -> {
    
    
    // ... do something
});

lambda部分未重写RetryCallback#doWithRetry的逻辑。

扫描二维码关注公众号,回复: 12177125 查看本文章
public interface RetryCallback<T> {
    
    

    T doWithRetry(RetryContext context) throws Throwable;

}

监听器:

public interface RetryListener {
    
    

    void open(RetryContext context, RetryCallback<T> callback);

    void onError(RetryContext context, RetryCallback<T> callback, Throwable e);

    void close(RetryContext context, RetryCallback<T> callback, Throwable e);
}

template.registerListener(new MethodInvocationRetryListenerSupport() {
    
    
      @Override
      protected <T, E extends Throwable> void doClose(RetryContext context,
          MethodInvocationRetryCallback<T, E> callback, Throwable throwable) {
    
    
        monitoringTags.put(labelTagName, callback.getLabel());
        Method method = callback.getInvocation()
            .getMethod();
        monitoringTags.put(classTagName,
            method.getDeclaringClass().getSimpleName());
        monitoringTags.put(methodTagName, method.getName());

        // register a monitoring counter with appropriate tags
        // ...
      }
    });

猜你喜欢

转载自blog.csdn.net/ory001/article/details/108546494