我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Spring Retry重试框架的使用讲解

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

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>

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

命令式


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

业务代码:


@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");
    }
}

声明式(注解方式)


@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修饰的方法一样,除了第一个参数外

@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重试的资料请关注编程网其它相关文章!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Spring Retry重试框架的使用讲解

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Spring Retry重试框架的使用讲解

重试的使用场景比较多,比如调用远程服务时,由于网络或者服务端响应慢导致调用超时,此时可以多重试几次。用定时任务也可以实现重试的效果,但比较麻烦,用Spring Retry的话一个注解搞定所有,感兴趣的可以了解一下
2022-11-13

Spring Retry重试框架如何使用

这篇“Spring Retry重试框架如何使用”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“Spring Retry重试框架
2023-07-04

Spring Boot中怎么使用Spring-Retry重试框架

这篇文章主要介绍“Spring Boot中怎么使用Spring-Retry重试框架”,在日常操作中,相信很多人在Spring Boot中怎么使用Spring-Retry重试框架问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希
2023-06-30

Spring Boot中怎么使用Spring Retry重试框架

今天小编给大家分享一下Spring Boot中怎么使用Spring Retry重试框架的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解
2023-06-30

SpringRetry重试框架的使用讲解

重试的使用场景比较多,比如调用远程服务时,由于网络或者服务端响应慢导致调用超时,此时可以多重试几次。用定时任务也可以实现重试的效果,但比较麻烦,用SpringRetry的话一个注解搞定所有,感兴趣的可以了解一下
2023-01-06

Spring Retry重试怎么使用

本篇内容介绍了“Spring Retry重试怎么使用”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!spring-retry是什么?sprin
2023-07-04

使用Spring-Retry解决SpringBoot应用程序中的重试问题

重试的使用场景比较多,比如调用远程服务时,由于网络或者服务端响应慢导致调用超时,此时可以多重试几次。用定时任务也可以实现重试的效果,但比较麻烦,用SpringRetry的话一个注解搞定所有,感兴趣的可以了解一下
2023-05-16

一文详解Spring security框架的使用

Spring Security是一个基于Spring框架的安全认证和授权框架,它提供了一套全面的安全解决方案,可以在Web应用、移动应用和Web服务等不同场景下使用。本文就来详细聊聊它的使用吧
2023-03-23

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录