Spring Retry重试框架的使用讲解

目录
  • 命令式
  • 声明式(注解方式)
  • 1. 用法
  • 2. RetryTemplate
  • 3. RecoveryCallback
  • 4. Listeners
  • 5. 声明式重试

重试的使用场景比较多,比如调用远程服务时,由于网络或者服务端响应慢导致调用超时,此时可以多重试几次。用定时任务也可以实现重试的效果,但比较麻烦,用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重试的资料请关注我们其它相关文章!

(0)

相关推荐

  • 详解重试框架Spring retry实践

    spring retry是从spring batch独立出来的一个能功能,主要实现了重试和熔断.对于重试是有场景限制的,不是什么场景都适合重试,比如参数校验不合法.写操作等(要考虑写是否幂等)都不适合重试.远程调用超时.网络突然中断可以重试.在微服务治理框架中,通常都有自己的重试与超时配置,比如dubbo可以设置retries=1,timeout=500调用失败只重试1次,超过500ms调用仍未返回则调用失败.在spring retry中可以指定需要重试的异常类型,并设置每次重试的间隔以及如果重

  • Spring重试支持Spring Retry的方法

    本文介绍了Spring重试支持Spring Retry的方法,分享给大家,具体如下: 第一步.引入maven依赖 <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.3.RELEASE</version> </parent> &l

  • SpringRetry重试框架的具体使用

    目录 一.环境搭建 二.RetryTemplate 2.1 RetryTemplate 2.2 RetryListener 2.3 回退策略 2.3.1 FixedBackOffPolicy 2.3.2 ExponentialBackOffPolicy 2.4 重试策略 2.5 RetryCallback 2.6 核心使用 三.EnableRetry 四.Retryable spring retry主要实现了重试和熔断. 不适合重试的场景: 参数校验不合法.写操作等(要考虑写是否幂等)都不适合重

  • spring retry实现方法请求重试的使用步骤

    目录 1 spring-retry是什么? 2 使用步骤 2.1 引入maven库 2.2 在spring启动类上开启重试功能 2.3 公共业务代码 2.4 传统的重试做法 2.5 使用spring-retry的命令式编码 2.5.1 定义重试监听器 2.5.2 定义重试配置 2.5.3 命令式编码 2.6使用spring-retry的注解式编码 3 SpringBoot整合spring-retry 3.1 添加@EnableRetry注解 3.2 接口实现 3.3 添加@Retryable注解

  • Spring Retry重试框架的使用讲解

    目录 命令式 声明式(注解方式) 1. 用法 2. RetryTemplate 3. RecoveryCallback 4. Listeners 5. 声明式重试 重试的使用场景比较多,比如调用远程服务时,由于网络或者服务端响应慢导致调用超时,此时可以多重试几次.用定时任务也可以实现重试的效果,但比较麻烦,用Spring Retry的话一个注解搞定所有.话不多说,先看演示. 首先引入依赖 <dependency> <groupId>org.springframework.retry

  • Spring Boot中使用Spring Retry重试框架的操作方法

    目录 Spring Retry 在SpringBoot 中的应用 Maven依赖 注解使用 开启Retry功能 注解@Retryable 注解@Recover 注解@CircuitBreaker RetryTemplate RetryTemplate配置 使用RetryTemplate RetryPolicy BackOffPolicy RetryListener 参考 Spring Retry 在SpringBoot 中的应用 Spring Retry提供了自动重新调用失败的操作的功能.这在错

  • Spring Retry 重试实例详解

    spring-retry是什么? spring-retry是spring提供的一个重试框架,原本自己实现的重试机制,现在spring帮封装好提供更加好的编码体验. 重试的使用场景比较多,比如调用远程服务时,由于网络或者服务端响应慢导致调用超时,此时可以多重试几次.用定时任务也可以实现重试的效果,但比较麻烦,用Spring Retry的话一个注解搞定所有.话不多说,先看演示. 首先引入依赖 <dependency> <groupId>org.springframework.retry

  • Spring boot使用spring retry重试机制的方法示例

    当我们调用接口的时候由于网络原因可能失败,再尝试就成功了,这就是重试机制.非幂等的情况下要小心使用重试. tips:幂等性 HTTP/1.1中对幂等性的定义是:一次和多次请求某一个资源对于资源本身应该具有同样的结果(网络超时等问题除外).也就是说,其任意多次执行对资源本身所产生的影响均与一次执行的影响相同. 注解方式使用Spring Retry (一)Maven依赖 <!-- 重试机制 --> <dependency> <groupId>org.springframew

  • 从零搭建脚手架之集成Spring Retry实现失败重试和熔断器模式(实战教程)

    目录 背景 实战 添加依赖 启用重试 @Recover @CircuitBreaker 高级实战 方式一 @CircuitBreaker + RetryTemplate 方式二 @CircuitBreaker + @Retryable 参考 背景 在我们的大多数项目中,会有一些场景需要重试操作,而不是立即失败,让系统更加健壮且不易发生故障. 场景如下: 瞬时网络抖动故障 服务器重启 偶发死锁 某些上游的异常或者响应码,需要进行重试 远程调用 从数据库中获取或存储数据 以上皆为瞬时故障. 也会有一

  • Spring的异常重试框架Spring Retry简单配置操作

    相关api见:点击进入 /* * Copyright 2014 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * *

  • Spring框架中一个有用的小组件之Spring Retry组件详解

    1.概述 Spring Retry 是Spring框架中的一个组件, 它提供了自动重新调用失败操作的能力.这在错误可能是暂时发生的(如瞬时网络故障)的情况下很有帮助. 在本文中,我们将看到使用Spring Retry的各种方式:注解.RetryTemplate以及回调. 2.Maven依赖 让我们首先将spring-retry依赖项添加到我们的pom.xml文件中: <dependency> <groupId>org.springframework.retry</groupI

  • Spring Boot中使用Spring-Retry重试框架的实现

    目录 Maven依赖 注解使用 开启Retry功能 注解@Retryable 注解@Recover 注解@CircuitBreaker RetryTemplate RetryTemplate配置 使用RetryTemplate RetryPolicy BackOffPolicy RetryListener 参考 Spring Retry提供了自动重新调用失败的操作的功能.这在错误可能是暂时的(例如瞬时网络故障)的情况下很有用. 从2.2.0版本开始,重试功能已从Spring Batch中撤出,成

随机推荐