Spring Retry 重试()

  本篇文章为你整理了Spring Retry 重试()的详细内容,包含有 Spring Retry 重试,希望能帮助你了解 Spring Retry 重试。

  重试的使用场景比较多,比如调用远程服务时,由于网络或者服务端响应慢导致调用超时,此时可以多重试几次。用定时任务也可以实现重试的效果,但比较麻烦,用Spring Retry的话一个注解搞定所有。话不多说,先看演示。

  首先引入依赖

  

 dependency 

 

   groupId org.springframework.retry /groupId

   artifactId spring-retry /artifactId

   version 1.3.4 /version

   /dependency

   dependency

   groupId org.aspectj /groupId

   artifactId aspectjweaver /artifactId

   version 1.9.9.1 /version

   /dependency

 

  使用方式有两种:命令式和声明式

  

/**

 

   * 命令式的方式使用Spring Retry

  @GetMapping("/hello")

  public String hello(@RequestParam("code") Integer code) throws Throwable {

   RetryTemplate retryTemplate = RetryTemplate.builder()

   .maxAttempts(3)

   .fixedBackoff(1000)

   .retryOn(RemoteAccessException.class)

   .build();

   retryTemplate.registerListener(new MyRetryListener());

   String resp = retryTemplate.execute(new RetryCallback String, Throwable () {

   @Override

   public String doWithRetry(RetryContext context) throws Throwable {

   return helloService.hello(code);

   return resp;

  }

 

  定义一个RetryTemplate,然后调用execute方法,可配置项比较多,不一一列举

  真正使用的时候RetryTemplate可以定义成一个Bean,例如:

  

@Configuration

 

  public class RetryConfig {

   @Bean

   public RetryTemplate retryTemplate() {

   RetryTemplate retryTemplate = RetryTemplate.builder()

   .maxAttempts(3)

   .fixedBackoff(1000)

   .withListener(new MyRetryListener())

   .retryOn(RemoteAccessException.class)

   .build();

   return retryTemplate;

  }

 

  业务代码:

  

/**

 

   * 命令式的方式使用Spring Retry

  @Override

  public String hello(int code) {

   if (0 == code) {

   System.out.println("出错了");

   throw new RemoteAccessException("出错了");

   System.out.println("处理完成");

   return "ok";

  }

 

  监听器实现:

  

package com.example.retry.listener;

 

  import org.springframework.retry.RetryCallback;

  import org.springframework.retry.RetryContext;

  import org.springframework.retry.RetryListener;

  public class MyRetryListener implements RetryListener {

   @Override

   public T, E extends Throwable boolean open(RetryContext context, RetryCallback T, E callback) {

   System.out.println("open");

   return true;

   @Override

   public T, E extends Throwable void close(RetryContext context, RetryCallback T, E callback, Throwable throwable) {

   System.out.println("close");

   @Override

   public T, E extends Throwable void onError(RetryContext context, RetryCallback T, E callback, Throwable throwable) {

   System.out.println("error");

  }

 

  声明式(注解方式)

  

/**

 

   * 注解的方式使用Spring Retry

  @Retryable(value = Exception.class, maxAttempts = 2, backoff = @Backoff(value = 1000, delay = 2000, multiplier = 0.5))

  @Override

  public String hi(int code) {

   System.out.println("方法被调用");

   int a = 1/code;

   return "ok";

  @Recover

  public String hiRecover(Exception ex, int code) {

   System.out.println("重试结束");

   return "asdf";

  }

 

  这里需要主要的几点

  @EnableRetry(proxyTargetClass = true/false)

  @Retryable 修饰的方法必须是public的,而且不能是同一个类中调用

  @Recover 修饰的方法签名必须与@Retryable修饰的方法一样,除了第一个参数外

  

/**

 

   * 注解的方式使用Spring Retry

  @GetMapping("/hi")

  public String hi(@RequestParam("code") Integer code) {

   return helloService.hi(code);

  }

 

  1. 用法

  声明式

  

@Configuration

 

  @EnableRetry

  public class Application {

  @Service

  class Service {

   @Retryable(RemoteAccessException.class)

   public void service() {

   // ... do something

   @Recover

   public void recover(RemoteAccessException e) {

   // ... panic

  }

 

  命令式

  

RetryTemplate template = RetryTemplate.builder()

 

   .maxAttempts(3)

   .fixedBackoff(1000)

   .retryOn(RemoteAccessException.class)

   .build();

  template.execute(ctx - {

   // ... do something

  });

 

  2. RetryTemplate

  为了自动重试,Spring Retry 提供了 RetryOperations 重试操作策略

  

public interface RetryOperations {

 

   T T execute(RetryCallback T retryCallback) throws Exception;

   T T execute(RetryCallback T retryCallback, RecoveryCallback T recoveryCallback)

   throws Exception;

   T T execute(RetryCallback T retryCallback, RetryState retryState)

   throws Exception, ExhaustedRetryException;

   T T execute(RetryCallback T retryCallback, RecoveryCallback T recoveryCallback,

   RetryState retryState) throws Exception;

  }

 

  基本回调是一个简单的接口,允许插入一些要重试的业务逻辑:

  

public interface RetryCallback T {

 

   T doWithRetry(RetryContext context) throws Throwable;

  }

 

  回调函数被尝试,如果失败(通过抛出异常),它将被重试,直到成功或实现决定中止。

  RetryOperations最简单的通用实现是RetryTemplate

  

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;

  });

 

  从Spring Retry 1.3开始,RetryTemplate支持流式配置:

  

RetryTemplate.builder()

 

   .maxAttempts(10)

   .exponentialBackoff(100, 2, 10000)

   .retryOn(IOException.class)

   .traversingCauses()

   .build();

  RetryTemplate.builder()

   .fixedBackoff(10)

   .withinMillis(3000)

   .build();

  RetryTemplate.builder()

   .infiniteRetry()

   .retryOn(IOException.class)

   .uniformRandomBackoff(1000, 3000)

   .build();

 

  3. RecoveryCallback

  当重试耗尽时,RetryOperations可以将控制传递给不同的回调:RecoveryCallback。

  

Foo foo = template.execute(new RetryCallback Foo () {

 

   public Foo doWithRetry(RetryContext context) {

   // business logic here

   new RecoveryCallback Foo () {

   Foo recover(RetryContext context) throws Exception {

   // recover logic here

  });

 

  4. Listeners

  

public interface RetryListener {

 

   void open(RetryContext context, RetryCallback T callback);

   void onSuccess(RetryContext context, T result);

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

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

  }

 

  在最简单的情况下,open和close回调在整个重试之前和之后,onSuccess和onError应用于个别的RetryCallback调用,onSuccess方法在成功调用回调之后被调用。

  5. 声明式重试

  有时,你希望在每次业务处理发生时都重试一些业务处理。这方面的典型例子是远程服务调用。Spring Retry提供了一个AOP拦截器,它将方法调用封装在RetryOperations实例中。RetryOperationsInterceptor执行被拦截的方法,并根据提供的RepeatTemplate中的RetryPolicy在失败时重试。

  你可以在 @Configuration 类上添加一个 @EnableRetry 注解,并且在你想要进行重试的方法(或者类)上添加 @Retryable 注解,还可以指定任意数量的重试监听器。

  

@Configuration

 

  @EnableRetry

  public class Application {

   @Bean

   public Service service() {

   return new Service();

   @Bean public RetryListener retryListener1() {

   return new RetryListener() {...}

   @Bean public RetryListener retryListener2() {

   return new RetryListener() {...}

  @Service

  class Service {

   @Retryable(RemoteAccessException.class)

   public service() {

   // ... do something

  }

 

  可以使用 @Retryable 的属性类控制 RetryPolicy 和 BackoffPolicy

  

@Service

 

  class Service {

   @Retryable(maxAttempts=12, backoff=@Backoff(delay=100, maxDelay=500))

   public service() {

   // ... do something

  }

 

  如果希望在重试用尽时采用替代代码返回,则可以提供恢复方法。方法应该声明在与@Retryable实例相同的类中,并标记为@Recover。返回类型必须匹配@Retryable方法。恢复方法的参数可以包括抛出的异常和(可选地)传递给原始可重试方法的参数(或者它们的部分列表,只要在需要的最后一个之前不省略任何参数)。

  

@Service

 

  class Service {

   @Retryable(RemoteAccessException.class)

   public void service(String str1, String str2) {

   // ... do something

   @Recover

   public void recover(RemoteAccessException e, String str1, String str2) {

   // ... error handling making use of original args if required

  }

 

  若要解决可选择用于恢复的多个方法之间的冲突,可以显式指定恢复方法名称。

  

@Service

 

  class Service {

   @Retryable(recover = "service1Recover", value = RemoteAccessException.class)

   public void service1(String str1, String str2) {

   // ... do something

   @Retryable(recover = "service2Recover", value = RemoteAccessException.class)

   public void service2(String str1, String str2) {

   // ... do something

   @Recover

   public void service1Recover(RemoteAccessException e, String str1, String str2) {

   // ... error handling making use of original args if required

   @Recover

   public void service2Recover(RemoteAccessException e, String str1, String str2) {

   // ... error handling making use of original args if required

  }

 

  https://github.com/spring-projects/spring-retry

  以上就是Spring Retry 重试()的详细内容,想要了解更多 Spring Retry 重试的内容,请持续关注盛行IT软件开发工作室。

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: