Spring Retry使用

Spring Retry使用由于场景需求 需要对项目依赖的部分外部接口添加响应超时重试机制 而 SpringRetry 可以满足该需求 因此进行相关资料查询 对于 SpringRetry 的使用 网上的资料主要是采用注解的方式实现 而对于依赖的外部接口的重试 为避免对将重试机制添加到业务逻辑中 优先采用 xml 配置的方式实现 本文主要对 https www baeldung com spring retry 中的教程进行翻译

由于场景需求,需要对项目依赖的部分外部接口添加响应超时重试机制,而Spring Retry可以满足该需求,因此进行相关资料查询。对于Spring Retry的使用,网上的资料主要是采用注解的方式实现,而对于依赖的外部接口的重试,为避免对将重试机制添加到业务逻辑中,优先采用xml配置的方式实现。本文主要对https://www.baeldung.com/spring-retry中的教程进行翻译。


Spring Retry提供了自动调用失败操作的功能,这有助于解决瞬时错误(如网络抖动)。Spring Retry提供对流程和基于策略行为的声明式控制,易于扩展和自定义。

本文主要介绍Spring Retry在Spring项目中实现重试机制,同时也会配置监听者获取额外的回调结果。

Maven坐标

 
    
    
      org.springframework.retry 
     
    
      spring-retry 
     
    
      1.2.4.RELEASE 
     
   

可以在https://search.maven.org/classic/#search%7Cga%7C1%7Cg%3A%22org.springframework.retry%22%20AND%20a%3A%22spring-retry%22查看Retry的最新版本

使能Spring Retry

可以通过两种方式使能Spring Retry。

1、@EnableRetry注解方式

@Configuration @EnableRetry public class AppConfig { ... }

2、xml文件配置

 
   

Retry实现方式

Retry的用法有三种,Annotation形式、RetryTemplate形式、XML形式。

注解方式

1、@Retryable

将@Retryable添加在需要重试的方法,即retryService()。

@Service public class MyService { @Retryable( value = { SQLException.class }, maxAttempts = 2, backoff = @Backoff(delay = 5000)) void retryService(String sql) throws SQLException{...} ... } /* value:抛出指定异常才会重试 include:和value一样,默认为空,当exclude也为空时,默认所以异常 exclude:指定不处理的异常 maxAttempts:最大重试次数,默认3次 backoff:重试等待策略,默认使用@Backoff,@Backoff的value默认为1000L,我们设置为2000L;multiplier(指定延迟倍数)默认为0,表示固定暂停1秒后进行重试,如果把multiplier设置为1.5,则第一次重试为2秒,第二次为3秒,第三次为4.5秒。 */

上面的示例中,在方法出现SQLException异常时,将会重试2次,每次间隔5000ms。如果@Retryable没有任何说明,默认在方法抛出异常时,将会重试3次,每次间隔1s。

2、@Recover

在@Retryable方法重试后依然失败,调用@Recover定义的一个单独恢复方法。

@Service public class MyService { ... @Recover void recover(SQLException e, String sql){...} }

如果retryService()方法抛出SQLException,将会调用recover()方法。合适的恢复处理程序的第一个参数类型为Throwable(可选)。 后续参数从失败方法的参数列表中填充,其顺序与失败方法的顺序相同,并且具有相同的返回类型。

RetryTemplate方式

1、RetryOperations

Spring Retry提供RetryOperations接口,提供一系列的execute()方法:

public interface RetryOperations { 
   
     T execute(RetryCallback 
    
      retryCallback) throws Exception; ... } 
     
   

其中,参数RetryCallback是在业务逻辑失败后执行的接口:

public interface RetryCallback 
   
     { T doWithRetry(RetryContext context) throws Throwable; } 
   

2、RetryTemplate配置

RetryTemplate是RetryOperations的实现类。在@Configuration类中可以配置RetryTemplate:

@Configuration public class AppConfig { //... @Bean public RetryTemplate retryTemplate() { RetryTemplate retryTemplate = new RetryTemplate(); FixedBackOffPolicy fixedBackOffPolicy = new FixedBackOffPolicy(); fixedBackOffPolicy.setBackOffPeriod(2000l); retryTemplate.setBackOffPolicy(fixedBackOffPolicy); SimpleRetryPolicy retryPolicy = new SimpleRetryPolicy(); retryPolicy.setMaxAttempts(2); retryTemplate.setRetryPolicy(retryPolicy); return retryTemplate; } }

RetryPolicy接口确定方法重试的规则。SimpleRetryPolicy类用于设置失败方法的固定重试次数。

BackOffPolicy接口用于控制不同的重试的间隔。FixedBackOffPolicy类设置失败方法以固定的时间间隔进行重试。

3、应用RetryTemplate

通过调用retryTemplate.execute()使方法具有重试功能:

retryTemplate.execute(new RetryCallback 
   
     () { @Override public Void doWithRetry(RetryContext arg0) { myService.templateRetryService(); ... } }); 
   

其中,templateRetryService()为需要调用失败后重试的方法。

可以采用lambda表达式代替匿名类:

retryTemplate.execute(arg0 -> { myService.templateRetryService(); return null; });

XML方式

Spring Retry可以通过xml使用Spring AOP命名空间配置。

1、添加xml文件

在classpath中添加retryadvic.xml。

 
    
    
     
      
      
     
     
      
     
     
      
      
     
     
      
      
       
         
      
     
     
      
      
      
      
      
      
     
   

这是通过xml配置了RetryTemplate。其中,MyService.xmlRetryService()为需要失败后重试的方法。retryPolicy定义重试次数和捕获的异常。backOffPolicy定义不同重试间的时间间隔等。(如上文的FixedBackOffPolicy类,ExponentialBackOffPolicy类未深入研究)

2、xml配置的应用

导入retryadvice.xml到classpath,并使能@AspectJ:

@Configuration @EnableRetry @EnableAspectJAutoProxy @ImportResource("classpath:/retryadvice.xml") public class AppConfig { ... }

同样,可以采用xml配置的方式完成:

 
    
    
    
    
    
   

监听者(Listeners)

注:笔者未验证这一章节

Listeners在重试时提供额外的回调。它们可以用于不同重试之间的各种横切关注点。

1、添加回调(Callbacks)

回调函数在RetryListener接口中提供:

public class DefaultListenerSupport extends RetryListenerSupport { @Override public 
   
     void close(RetryContext context, RetryCallback 
    
      callback, Throwable throwable) { logger.info("onClose"); ... super.close(context, callback, throwable); } @Override public 
     
       void onError(RetryContext context, RetryCallback 
      
        callback, Throwable throwable) { logger.info("onError"); ... super.onError(context, callback, throwable); } @Override public 
       
         boolean open(RetryContext context, RetryCallback 
        
          callback) { logger.info("onOpen"); ... return super.open(context, callback); } } 
         
        
       
      
     
   

打开和关闭回调出现在整个重试之前和之后,onError应用于各个RetryCallback调用。

2、注册Listener

接着,将Listiener(DefaultListenerSupport)注册到RetryTemplate bean:

@Configuration public class AppConfig { ... @Bean public RetryTemplate retryTemplate() { RetryTemplate retryTemplate = new RetryTemplate(); ... retryTemplate.registerListener(new DefaultListenerSupport()); return retryTemplate; } }

3、测试

@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration( classes = AppConfig.class, loader = AnnotationConfigContextLoader.class) public class SpringRetryTest { @Autowired private MyService myService; @Autowired private RetryTemplate retryTemplate; @Test(expected = RuntimeException.class) public void givenTemplateRetryService_whenCallWithException_thenRetry() { retryTemplate.execute(arg0 -> { myService.templateRetryService(); return null; }); } }

当运行测试用例时,下面的日志文本表示我们已经成功配置了RetryTemplate和Listener:

2017-01-09 20:04:10 [main] INFO o.b.s.DefaultListenerSupport - onOpen 2017-01-09 20:04:10 [main] INFO o.baeldung.springretry.MyServiceImpl - throw RuntimeException in method templateRetryService() 2017-01-09 20:04:10 [main] INFO o.b.s.DefaultListenerSupport - onError 2017-01-09 20:04:12 [main] INFO o.baeldung.springretry.MyServiceImpl - throw RuntimeException in method templateRetryService() 2017-01-09 20:04:12 [main] INFO o.b.s.DefaultListenerSupport - onError 2017-01-09 20:04:12 [main] INFO o.b.s.DefaultListenerSupport - onClose

注意事项(转载参考资料4)

1、使用了@Retryable的方法不能在本类被调用,不然重试机制不会生效。也就是要标记为@Service,然后在其它类使用@Autowired注入或者@Bean去实例才能生效。

2 、要触发@Recover方法,那么在@Retryable方法上不能有返回值,只能是void才能生效。

3 、非幂等情况下慎用

4 、使用了@Retryable的方法里面不能使用try…catch包裹,要在方法上抛出异常,不然不会触发

参考资料

1、https://www.baeldung.com/spring-retry(原文链接)

https://github.com/eugenp/tutorials/tree/master/spring-all(源代码链接)

2、https://www.jianshu.com/p/cc7abf

3、https://www.jianshu.com/p/58e753ca0151

4、https://my.oschina.net/wangjunBlog/blog/

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/215663.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月18日 下午1:43
下一篇 2026年3月18日 下午1:44


相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号