使用Spring Boot的Spring重试模块示例

在本Spring引导教程中,学习如何使用spring retry模块工具构建应用程序,在该方法中,我们必须调用某些有时会期望出现异常的方法,并且必须重试请求。

在这种情况下,如果必须在任何后端服务调用上实现任何重试功能,通常我们将使用循环和中断条件来实现,并继续重试至某些重试限制。但是这种解决方案容易出错。

Spring为我们提供了一个围绕这个叫做spring-retry的简单框架,可以使用注解进行配置。我们可以定义重试限制,后备方法等。

目录

1。 为什么我们需要重试?
2。 Spring重试 
3。 Spring重试示例 
4。 测试应用程序 
5。 摘要

1.为什么我们需要重试?

在我们的大多数项目中,通常会遇到一些场景,如果它是第一次下降,则可以重试很少的操作。例如,假设在调用任何后端外部服务的过程中,该服务可能由于诸如网络中断,服务器关闭,网络故障,死锁等原因而关闭。在这种情况下,通常在发送任何外部外部服务之前,我们尝试重试该操作几次客户端程序的特定错误,以使处理更健壮,更不容易出错。

有时,它有助于自动重试失败的操作,以防后续尝试成功执行。我想你们所有人都已经遇到了这个问题,并且作为一种解决方法,您很可能会通过循环并在达到重试限制后中断该循环来解决此问题,但是现在借助spring-retry模块,我们不必编写这样的代码来处理重试方案。

2.Spring重试

spring系列的spring-retry是另一个实用程序模块,可以帮助我们以标准方式处理任何特定操作的重试。在spring-retry中,所有配置都是基于简单注解的。

2.1。Spring重试注解

  • @EnableRetry –在spring boot项目中启用spring retry
  • @Retryable –表示可以重试的任何方法
  • @Recover –指定后备方法!

3。 Spring重试示例

3.1。开发环境

我们将使用以下技术堆栈在下面的pur示例应用中尝试spring-retry。

  • Java,Eclipse,Maven作为开发环境
  • Spring-boot作为应用程序框架
  • spring-retry模块作为重试模块
  • AspectJ作为spring-retry的依赖

3.2。演示概述

  1. 创建一个Spring引导项目以公开一次示例Rest API,它将调用一个容易失败的后端操作,我们将模拟这种失败情况以启动重试。
  2. 一个服务类实际上将调用远程api,并在失败时发送异常,我们将基于此自定义异常设计重试,就像一旦收到此异常,我们将重试3次并最终返回客户端。在这3次尝试中,如果我们从后端服务获得成功响应,则将返回该成功响应,否则将调用标准后备方法。

3.3。创建Spring-boot项目

第一步,我们将从spring初始化程序站点创建一个spring boot项目,在此我们将测试spring重试功能。

要做到这一点,我们需要去https://start.spring.io/并选择依赖网络重试。下载包含框架项目的zip文件,然后导入到maven。

Spring Boot初始化器

3.4。Maven依赖

Spring初始化器会在项目中自动添加spring-boot-starter-data-restspring-boot-starter-security依赖。为了进行测试,我们不需要这些,因此我们将从中删除这两个依赖项pom.xml

另外,spring-retry取决于框架项目中未包含的Aspectj,因此我们将在pom.xml文件中添加以下依赖项。

pom.xml
<dependency>
    <groupId>org.springframework.retry</groupId>
    <artifactId>spring-retry</artifactId>
    <version>${version}</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-aspects</artifactId>
    <version>${version}</version>
</dependency>

3.5。创建Rest API端点

创建一个示例Rest控制器,该控制器将调用后端服务类,在该类中我们将模拟异常,并且spring-retry模块将自动重试。

MyRestController.java
package com.example.springretry;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class MyRestController {
    @Autowired
    BackendAdapter backendAdapter;
    @GetMapping("/retry")
    @ExceptionHandler({ Exception.class })
    public String validateSPringRetryCapability(@RequestParam(required = false) boolean simulateretry,
                                @RequestParam(required = false) boolean simulateretryfallback)
    {
        System.out.println("===============================");
        System.out.println("Inside RestController mathod..");
        return backendAdapter.getBackendResponse(simulateretry, simulateretryfallback);
    }
}

在Rest Api中,我们将添加两个可选的请求参数。

  • Simulationretry –模拟异常情况的参数,以便spring可以重试。
  • simulateretryfallback -正如我们在模拟异常,后重试某些时候,我们可以期待一个成功的后端调用或全部重试下降。在这种情况下,我们将使用后退方法来获取硬编码/错误响应。现在,此参数将确保所有重试都将失败,并且我们将仅回退路径。

3.6。@EnableRetry注解

为了启用spring-retry,我们需要在Spring Boot Application类中放置一个注解。因此,打开SpringRetryApplication课程并添加@EnableRetry课程级别。

SpringRetryApplication.java
package com.example.springretry;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.retry.annotation.EnableRetry;
@EnableRetry
@SpringBootApplication
public class SpringRetryApplication {
    public static void main(String[] args) {
        SpringApplication.run(SpringRetryApplication.class, args);
    }
}

3.7。后端服务适配器接口和实现

现在,我们将创建一个用于调用外部服务的接口/实现。在这里,我们实际上不会调用任何外部服务调用,而是通过添加一些随机逻辑来模拟成功/失败方案,如下所示。

BackendAdapter.java
package com.example.springretry;
import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Recover;
import org.springframework.retry.annotation.Retryable;
public interface BackendAdapter {
    @Retryable(value = { RemoteServiceNotAvailableException.class }, maxAttempts = 3, backoff = @Backoff(delay = 1000))
    public String getBackendResponse(boolean simulateretry, boolean simulateretryfallback);
    @Recover
    public String getBackendResponseFallback(RuntimeException e);
}
BackendAdapterImpl.java
package com.example.springretry;
import java.util.Random;
import org.springframework.stereotype.Service;
@Service
public class BackendAdapterImpl implements BackendAdapter {
    @Override
    public String getBackendResponse(boolean simulateretry, boolean simulateretryfallback) {
        if (simulateretry) {
            System.out.println("Simulateretry is true, so try to simulate exception scenario.");
            if (simulateretryfallback) {
                throw new RemoteServiceNotAvailableException(
                        "Don't worry!! Just Simulated for Spring-retry..Must fallback as all retry will get exception!!!");
            }
            int random = new Random().nextInt(4);
            System.out.println("Random Number : " + random);
            if (random % 2 == 0) {
                throw new RemoteServiceNotAvailableException("Don't worry!! Just Simulated for Spring-retry..");
            }
        }
        return "Hello from Remote Backend!!!";
    }
    @Override
    public String getBackendResponseFallback(RuntimeException e) {
        System.out.println("All retries completed, so Fallback method called!!!");
        return "All retries completed, so Fallback method called!!!";
    }
}
  • @Retryable –这是之后的主要注解@EnableRetry。这个注解告诉我们,如果我们RemoteServiceNotAvailableException从方法中获取信息,则在发送响应之前最多重试3次。另外,每次重试都会引入1秒的延迟。
  • @Recover –后备方法中的值表示如果3次重试后我们未获得任何成功响应,则响应将来自此后备方法。确保将预期的异常作为参数传递,否则spring将很难找到确切的方法。
  • 在调用远程服务的实际方法中,我们添加了一些自定义逻辑来基于simulateretrysimulateretryfallback参数控制Exception 。代码很简单,只要满足条件就返回期望的异常重试,否则我们将返回成功响应。此外,我们还基于“随机数”添加了一些随机逻辑,以模拟故障的随机性。
  • 后备方法实现发送简单的后备响应。

4.测试应用程序

测试部分非常简单。我们将在REST请求中传递适当的参数以模拟重试请求。

4.1。重试-成功还是失败

让我们从'http://localhost:8080/retry?simulateretry=true&simulateretryfallback=false'浏览器开始。基于该参数,我们期望后端服务调用中出现异常,与此同时simulateretryfallback=false,我们依赖于随机逻辑(随机%2 == 0 –>甚至是随机数),我们可以期望重试时成功响应。

因此,一旦我们在浏览器中命中了请求,我们可能会在后端获得异常,并且spring将多次重试相同的方法。结果可能是来自后端的成功响应。这是我尝试重试的我的请求之一中的几行日志。

安慰
===============================
Inside RestController method..
Simulateretry is true, so try to simulate exception scenario.
Random Number : 1
===============================
Inside RestController mathod..
Simulateretry is true, so try to simulate exception scenario.
Random Number : 2
Simulateretry is true, so try to simulate exception scenario.
Random Number : 2
Simulateretry is true, so try to simulate exception scenario.
Random Number : 0
All retries completed, so Fallback method called!!!

第一次我找到了成功,第二次我进入了后备道路。

4.2。重试-仅回退

现在尝试使用'http://localhost:8080/retry?simulateretry=true&simulateretryfallback=true',每次我们抛出RuntimeException时,从代码重试限制后,您都会得到后备响应。这是我的最后几行代码,它在发送响应之前尝试了3次。

安慰
===============================
Inside RestController method..
Simulateretry is true, so try to simulate exception scenario.
Simulateretry is true, so try to simulate exception scenario.
Simulateretry is true, so try to simulate exception scenario.
All retries completed, so Fallback method called!!!

5。 Spring重试摘要

因此,我们已经知道可以使用spring retry模块轻松实现基于Exception的重试。因此,下次如果您需要这种要求,则可以使用这种方法。如果您对此有任何疑问,请在下面评论。

参考文献:

Spring重试github repo和文档。

3

 发表评论

saigon has written 1445 articles

One thought on “使用Spring Boot的Spring重试模块示例

Leave a Reply