返回顶部
首页 > 资讯 > 后端开发 > Python >SpringRetry重试实例详解
  • 413
分享到

SpringRetry重试实例详解

SpringRetry重试SpringRetry重试机制 2022-11-13 19:11:39 413人浏览 八月长安

Python 官方文档:入门教程 => 点击学习

摘要

spring-retry是什么? spring-retry是spring提供的一个重试框架,原本自己实现的重试机制,现在spring帮封装好提供更加好的编码体验。 重试的使用场景比较

spring-retry是什么?

spring-retry是spring提供的一个重试框架,原本自己实现的重试机制,现在spring帮封装好提供更加好的编码体验。

重试的使用场景比较多,比如调用远程服务时,由于网络或者服务端响应慢导致调用超时,此时可以多重试几次。用定时任务也可以实现重试的效果,但比较麻烦,用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 重试内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: SpringRetry重试实例详解

本文链接: https://lsjlt.com/news/170377.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • SpringRetry重试实例详解
    spring-retry是什么? spring-retry是spring提供的一个重试框架,原本自己实现的重试机制,现在spring帮封装好提供更加好的编码体验。 重试的使用场景比较...
    99+
    2022-11-13
    Spring Retry 重试 Spring Retry 重试机制
  • SpringRetry重试框架的使用讲解
    目录重试框架Spring-Retry是什么Spring-Retry如何使用测试属性说明重试全部失败的回调方法重试框架Spring-Retry是什么 Spring Retry是一个在S...
    99+
    2023-01-06
    Spring Retry Spring Retry重试 Spring Retry重试框架
  • SpringRetry重试框架的具体使用
    目录一、环境搭建二、RetryTemplate2.1 RetryTemplate2.2 RetryListener2.3 回退策略2.3.1 FixedBackOffPolicy2....
    99+
    2024-04-02
  • Vue超详细讲解重试机制示例
    重试指的是当加载出错时,有能力重新发起加载组件的请求。 异步组件加载失败后的重试机制,与请求服务端接口失败后的重试机制一样。所以,先来讨论接口请求失败后的重试机制是如何实现的, 为此...
    99+
    2023-01-05
    Vue重试机制 Vue重试
  • MySQL 去重实例操作详解
    目录前言1.创建测试数据2.distinct 使用2.1 单列去重2.2 多列去重2.3 聚合函数+去重3.group by 使用3.1 单列去重3.2 多列去重3.3 聚合函数 + group by4.distinct...
    99+
    2022-07-18
    MySQL 去重操作 MySQL 去重
  • MySQL 去重实例操作详解
    目录前言1.创建测试数据2.distinct 使用2.1 单列去重2.2 多列去重2.3 聚合函数+去重3.group by 使用3.1 单列去重3.2 多列去重3.3 聚合函数 +...
    99+
    2024-04-02
  • Kotlin操作符重载实例详解
    目录算数运算操作符重载复合运算操作符重载一元运算操作符重载比较操作符重载集合和区域的约定迭代运算符重载解构声明总结算数运算操作符重载 在kotlin中我定义一个类 data clas...
    99+
    2024-04-02
  • Python retrying 重试机制详解
    目录循环加判断retrying总结 我们在程序开发中,经常会需要请求一些外部的接口资源,而且我们不能保证每次请求一定会成功,所以这些涉及到网络请求的代码片段就需要加上重试机制。下面来...
    99+
    2024-04-02
  • Golang 单元测试和基准测试实例详解
    目录前言Go 单元测试单元测试覆盖率基准测试前言 多人协作的项目里,要保证代码的质量,自然离不开单元测试。开发完一个功能后肯定要对所写的代码进行测试,测试没有问题之后再合并到代码库供...
    99+
    2024-04-02
  • Android wifi 调试详解及简单实例
    Android wifi 调试 前言: 做android开发的时候,经常遇到的一个问题就是真机调试次数多了,会导致usb口,损坏,而且长期给手机充电也会损坏手机,所以我想了想是...
    99+
    2022-06-06
    调试 Android
  • Java Benchmark 基准测试的实例详解
    Java Benchmark 基准测试的实例详解import java.util.Arrays; import java.util.concurrent.TimeUnit; import org.openjdk.jmh.annotatio...
    99+
    2023-05-31
    java benchmark bench
  • Java 重载、重写、构造函数的实例详解
    Java 重载、重写、构造函数的实例详解方法重写重写只能出现在继承关系之中。当一个类继承它的父类方法时,都有机会重写该父类的方法。一个特例是父类的方法被标识为final。重写的主要优点是能够定义某个子类型特有的行为。class Animal...
    99+
    2023-05-31
    java 重载 重写
  • Echarts如何重新渲染实例详解
    当我点击饼图时,出现相应的内容,并重新渲染饼图展示内容 饼图点击事件this.conechart.on('click', (params) => {    ...
    99+
    2022-06-01
    Echarts 渲染
  • Python重试库 Tenacity详解(推荐)
    目录1 Tenacity描述2 如果发生异常就重试3 设置停止重试的条件设置重试的最大次数还可以设置stop 时间停止重试条件 进行组合4 设置重试的间隔5 重试触发的条件针对具体的...
    99+
    2024-04-02
  • Oracle表中重复数据去重的方法实例详解
    Oracle表中重复数据去重的方法实例详解 我们在项目中肯定会遇到一种情况,就是表中没有主键 有重复数据 或者有主键 但是部分字段有重复数据 而我们需要过滤掉重复数据 下面是一种解决方法 del...
    99+
    2024-04-02
  • Java实现手写线程池实例并测试详解
    前言 在之前的文章中介绍过线程池的核心原理,在一次面试中面试官让手写线程池,这块知识忘记的差不多了,因此本篇文章做一个回顾。 希望能够加深自己的印象以及帮助到其他的小伙伴儿们 在线程...
    99+
    2023-02-22
    Java手写线程池 Java 线程池
  • Guava Retryer实现接口重试的示例
    目录前言 Guava Retryer 引入依赖 快速开始 指数退避(Exponential Backoff) 斐波那契退避(Fibonacci Backoff) 重试监听器 小结 前...
    99+
    2024-04-02
  • Python运算符重载详解及实例代码
    Python运算符重载 Python语言提供了运算符重载功能,增强了语言的灵活性,这一点与C++有点类似又有些不同。鉴于它的特殊性,今天就来讨论一下Python运算符重载。 Pyth...
    99+
    2022-06-04
    详解 运算符 实例
  • Android 中ViewPager重排序与更新实例详解
    Android 中ViewPager重排序与更新实例详解最近的项目中有栏目订阅功能,在更改栏目顺序以后需要更新ViewPager。类似于网易新闻的频道管理。 在重新排序之后调用了PagerAdapter的notifyDataSetChang...
    99+
    2023-05-31
    android viewpager age
  • 实例详解Android解决按钮重复点击问题
     为了防止用户或者测试MM疯狂的点击某个button,写个方法防止按钮连续点击。具体实例代码如下所示: public class BaseActivity ext...
    99+
    2022-06-06
    按钮 Android
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作