springboot整合spring-retry的实现示例
作者:软件老王 发布时间:2022-01-13 01:25:53
1、背景
本系统调用外围系统接口(http+json),但是发现有时外围系统服务不太稳定,有时候会出现返回一串xml或者gateway bad的信息,导致调用失败,基于这一原因,采用基于springboot,整合spring-retry的重试机制到系统工程中,demo已经放到github上。
2、解决方案
简要说明:demo工程基于springboot,为了方便验证,采用swagger进行测试验证。
2.1 pom文件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.0</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.laowang</groupId>
<artifactId>springretry</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springretry</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--retry-->
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
</dependency>
<!--swagger-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.7.0</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.7.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
重点说明:aop的gav必须有,否则会跑不起来。
<!--retry-->
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
</dependency>
2.2 applicat启动类
package com.laowang.springretry;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.retry.annotation.EnableRetry;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
@EnableRetry
@EnableSwagger2
@SpringBootApplication
public class SpringretryApplication {
public static void main(String[] args) {
SpringApplication.run(SpringretryApplication.class, args);
}
}
说明:两个标签而已
@EnableRetry
@EnableSwagger2
2.3 controller类
/**
* @description: TODO
* @author Administrator
* @date 2021/6/2 14:55
* @version 1.0
*/
package com.laowang.springretry.controller;
import com.laowang.springretry.service.RetryService;
import io.swagger.annotations.Api;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@Api("重试测试类")
@RestController
public class RetryController {
@Autowired
RetryService retryService;
@GetMapping("/testRetry")
public String testRetry(int code) throws Exception {
int result = retryService.retryTest(code);
return "result:" + result;
}
}
2.4 service测试类(重点)
/**
* @description: TODO
* @author Administrator
* @date 2021/6/2 12:23
* @version 1.0
*/
package com.laowang.springretry.service;
import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Recover;
import org.springframework.retry.annotation.Retryable;
import org.springframework.stereotype.Service;
import java.time.LocalTime;
@Service
public class RetryServiceImpl implements RetryService {
@Override
@Retryable(value = Exception.class, maxAttempts = 3, backoff = @Backoff(delay = 2000, multiplier = 1.5))
public int retryTest(int code) throws Exception {
System.out.println("retryTest被调用,时间:" + LocalTime.now());
if (code == 0) {
throw new Exception("异常抛出!");
}
System.out.println("retryTest被调用,情况对头了!");
return 200;
}
@Recover
public int recover(Exception e) {
System.out.println("回调方法执行,可以记录日志到数据库!!!!");
//记日志到数据库 或者调用其余的方法
return 400;
}
}
**说明:**三个标签
@Retryable注解
被注解的方法发生异常时会重试
value:指定发生的异常进行重试
include:和value一样,默认空,当exclude也为空时,所有异常都重试
exclude:指定异常不重试,默认空,当include也为空时,所有异常都重试
maxAttemps:重试次数,默认3
backoff:重试补偿机制,默认没有
@Backoff注解说明
delay:指定延迟后重试
multiplier:指定延迟的倍数,比如delay=2000,multiplier=1.5时,第二次重试与第一次执行间隔:2秒;第三次重试与第二次重试间隔:3秒;第四次重试与第三次重试间隔:4.5秒。。。
@Recover
当重试到达指定次数时,被注解的方法将被回调,可以在该方法中进行日志处理。需要注意的是发生的异常和入参类型一致时才会回调
2.5 项目启动
执行运行application,启动成功,默认端口号:8080
2.6 使用swagger进行验证
(1)swagger访问地址:
http://localhost:8080/swagger-ui.html
(2)先验证成功返回
先测试正常调用试试,code=1
调用返回:
(3)重试机制:code=0(重点)
为了更好的说明问题,参数配置增大一些:
@Retryable(value = Exception.class, maxAttempts = 5, backoff = @Backoff(delay = 2000, multiplier = 2))
执行效果
说明:
从执行效果看,总共执行5次,第二次跟第一次之间是2秒;第三次跟第二次之间是2*2=4秒;第四次与第三次之间是:2 乘以2乘以2=8秒,第五次与第四次之间是:2 乘以2乘以2乘以2=16秒,符合预期。
执行完成后,进入 @Recover标签内容,可以进行日志记录,以便后续定位问题。
github项目地址:https://github.com/ruanjianlaowang/springretry
来源:https://blog.csdn.net/wjg8209/article/details/117751194


猜你喜欢
- 本文研究的主要是Spring的事务机制的相关内容,具体如下。JAVA EE传统事务机制通常有两种事务策略:全局事务和局部事务。全局事务可以跨
- 本文实例分析了Android多线程。分享给大家供大家参考,具体如下:在Android下面也有多线程的概念,在C/C++中,子线程可以是一个函
- Android ListView填充数据的方法因为多人开发,为了是自己开发的模块方便融合到主框架中,同时也为了减小apk的大小,要求尽可能少
- 目录1. 新建产品,在官网新建产品2. 获取app id,点击产品设置,拿到App ID3. 集成SDK,在Android项目的 app/b
- 介绍Spring Cache是一个框架,实现了基于注解的缓存功能,只需要简单地加一个注解,就能实现缓存功能。Spring Cache提供了一
- 前言CMake是一个跨平台的安装编译工具,可以用简单的语句来描述所有平台的安装(编译过程)。CMake可以说已经成为大部分C++开源项目标配
- 本文介绍了Android中js和原生交互的示例代码,分享给大家,具体如下:加载webview的类public class MainActiv
- 体验了一下美团外卖的底部导航栏,感觉动画很流畅,分割线被顶起,还有图标的动画,可能用的lottie,觉得分割线被顶起可以自己写动画,所以试着
- 单线程实现文件分割在老的FAT32文件系统中,最大的单个文件大小必须保存在4G内,对于经常看电影的我这个是不能允许的。不过现在Windows
- 实现思路其实很简单,就是一个自定义的LinearLayout,并且textView能够循环垂直滚动,而且条目可以点击,显示区域最多显示2个条
- 本文实例为大家分享了Android悬浮窗菜单的具体代码,供大家参考,具体内容如下MainActivity.java代码:package si
- 闹钟闹不醒的可以自己去调整下,这个最是最基本的MainActivitypublic class MainActivity extends A
- 首先,ListView不能直接用,要自定义一个,然后重写onMeasure()方法:@Override protected vo
- 一、JDBC概述1、数据的持久化持久化(persistence):把数据保存到可掉电式存储设备中以供之后使用。大多数情况下,特别是企业级应用
- C#对文件的操作相当方便,主要涉及到四个类:File、FileInfo、Directory、DirectoryInfo,前两个提供了针对文件
- 先谈一谈struts2实现文件的上传和下载实例实现的原理:Struts 2是通过Commons FileUpload文件上传。Commons
- 还是有一些小问题....懒得改了,但大体思路还是清晰的,首先定义一个运算符栈,一个数栈。关于优先级,两个括号(,)优先级最低,其次是+、-,
- 开发工具:VS2017语言:C#DotNet版本:.Net FrameWork 4.0及以上使用的DLL工具名称:GemBox.Spread
- 1、效果展示2、布局文件<?xml version="1.0" encoding="utf-8"
- 带参数的try(){}语法含义带资源的try语句(try-with-resource)最简形式为try(Resource res = xxx