本文翻译自国外论坛 medium,原文地址:https://levelup.gitconnected.com/how-i-deleted-more-than-1000-lines-of-code-using-spring-retry-9118de29060

使用 Spring Retry 重构代码的综合指南。

问题介绍

在我的日常工作中,我主要负责开发一个庞大的金融应用程序。当客户发送请求时,我们使用他们的用户 ID 从第三方服务获取他们的帐户信息,保存交易并更新缓存中的详细信息。尽管整个流程看起来足够简单,但这些下游系统中的每一个都是不可靠的。我们必须在每一层上实现重试,并且我们必须以一种可以控制重试次数和每次重试之间的延迟的方式来实现,这样我们就不会超载下游系统。由于我无法共享实际代码,我会创建一个演示系统来做简单表示:

由于我们必须在每一层上实现重试,因此我们必须编写大量样板代码,这不仅容易出错,而且难以维护。由于每个下游系统都有自己的重试要求,因此我们最终添加了越来越多的代码,最终就像在现有垃圾之上添加垃圾一样。随着时间的推移,代码变得非常脆弱,即使是很小的变化也会破坏整个系统。

推荐博主开源的 H5 商城项目waynboot-mall,这是一套全部开源的微商城项目,包含三个项目:运营后台、H5 商城前台和服务端接口。实现了商城所需的首页展示、商品分类、商品详情、商品 sku、分词搜索、购物车、结算下单、支付宝/微信支付、收单评论以及完善的后台管理等一系列功能。 技术上基于最新得 Springboot3.0、jdk17,整合了 MySql、Redis、RabbitMQ、ElasticSearch 等常用中间件。分模块设计、简洁易维护,欢迎大家点个 star、关注博主。

github 地址:https://github.com/wayn111/waynboot-mall

解决方案

为了解决这个问题我们决定使用 Spring Retry。

Spring Retry 项目地址:https://github.com/spring-projects/spring-retry

Spring Retry 是 Spring Batch 的一个子项目,它提供了一组注解和接口,我们可以使用它们向代码添加重试逻辑。它提供了一种向代码添加重试逻辑的声明性方法。

作为本文的一部分,我们将了解如何使用 Spring Retry 重写现有代码,以及它如何帮助我将代码库减少 1000 行。在展示新代码时,我将解释每个代码的注解和用例。

在研究重构的代码之前,让我们先了解一下在项目中设置 Spring 重试所涉及的步骤。

Let’s start hacking!

1. 设置 Spring 重试

将以下依赖项添加到我们的 pom.xml 文件中:

<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
<version>2.0.0</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>5.2.8.RELEASE</version>
</dependency>
  1. 在 spring 配置上启用 Spring 重试,并使用以下注解:
@Configuration
@EnableRetry
public class ApplicationConfig { }

2. 重构代码

既然我们已经设置了 Spring Retry,那么让我们开始重构代码。

  1. 以下是一个查询用户全名的代码示例,左边是老代码,右边是使用了 Spring Retry 的新代码。

使用 @Retryable 注解,我们通过 retryFor 属性指定要重试的异常数组,使用 maxAttempts 属性,可以指定要重试的次数。

  1. 具有指数退避的缓存重试

一下图片是一个添加缓存的代码示例中,我指定要在 JedisConnectionException 上重试,每次重试之间的延迟应为 1000 毫秒,并且延迟应呈指数增长。

使用 @Retryable 注解,我们可以使用重试退避 backoff 属性,还可以指定每次重试之间的延迟 delay。

  1. 外部化重试配置

我们可以轻松地将重试配置外部化到属性文件中。当我们想要重用配置并更改它们而无需重新部署应用程序时,这非常有用。就我而言,我创建了一个 retry.properties 文件并添加了以下属性:

retry.maxAttempts=2

在我的 spring 配置中包含属性文件:

// <<Other annotations>>
@PropertySource("classpath:retryConfig.properties")
public class ApplicationConfig { }

以下图片是一个先获取 MySql 连接,再查数据的例子,我再代码中使用了该外部化配置属性:

  1. 消除错误时的重复操作,使用 RetryListenerSupport 重试

在前面的先获取 MySql 连接,再查数据的例子中,我想获取以下事件的指标:

  • 连接 MySql 数据库时,发出指标
  • 连接 MySql 数据库失败时,发出指标
  • 当用尽所有重试次数时,发出指标

再 Spring Retry 中,我可以使用 RetryListenerSupport 将所有代码添加到一个位置,而不是在连接到 Mysql 数据库的所有代码的每个重试块中添加相同的代码。

使用 RetryTemplate 上的 registerListener 方法注册 RetryListenerSupport:

@Configuration
public class ApplicationConfig { @Bean
public RetryTemplate installTemplate() {
RetryTemplate retryTemplate = new RetryTemplate();
retryTemplate.registerListener(new DefaultListenerSupport());
return retryTemplate;
}
}

RetryListenerSupport 提供了三种方法,我们可以重写它们来添加自定义逻辑:

  • onError — 当出现错误时调用此方法
  • close——当所有重试都用尽时调用该方法
  • open — 重试开始时调用该方法

现在让我们看看重构后的代码:

总结

在本文中,我们了解了如何使用 Spring Retry 来减少样板代码并使代码更具可读性和可维护性。通过 Spring Retry,相信你也能够消除超过 1000 行代码。

关注公众号【waynblog】每周分享技术干货、开源项目、实战经验、高效开发工具等,您的关注将是我的更新动力!

我是如何使用Spring Retry减少1000 行代码的更多相关文章

  1. (转)如何基于FFMPEG和SDL写一个少于1000行代码的视频播放器

    原文地址:http://www.dranger.com/ffmpeg/ FFMPEG是一个很好的库,可以用来创建视频应用或者生成特定的工具.FFMPEG几乎为你把所有的繁重工作都做了,比如解码.编码. ...

  2. 1000行代码徒手写正则表达式引擎【1】--JAVA中正则表达式的使用

    简介: 本文是系列博客的第一篇,主要讲解和分析正则表达式规则以及JAVA中原生正则表达式引擎的使用.在后续的文章中会涉及基于NFA的正则表达式引擎内部的工作原理,并在此基础上用1000行左右的JAVA ...

  3. Spring Boot 中 10 行代码构建 RESTful 风格应用

    RESTful ,到现在相信已经没人不知道这个东西了吧!关于 RESTful 的概念,我这里就不做过多介绍了,传统的 Struts 对 RESTful 支持不够友好 ,但是 SpringMVC 对于 ...

  4. 1000行代码实现MVVM (类似Angular1.x.x , Vue)

    最近花了近半个多月的时间, 自己纯手工写了一个很小型的类angularjs/vue的mvvm 库. 目前已经用于公司一个项目. 项目托管在github https://github.com/leonw ...

  5. delphi 自我删除和线程池(1000行代码,需要仔细研究)

    unit Unit4; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms ...

  6. 爬数据,能让你少写1000行代码的捷径! | Python 正则表达式

    ▌春暖花开,又到了出门游玩拍拍拍吃吃吃的好季节了! 说到拍照摄影,你会构图吗?就是在照片有限的空间内处理人.景.物的关系,并将三者安排在画面中最佳的位置,以形成画面特定结构的方法. 学院君就是一个「拍 ...

  7. 学会lambda表达式,能让你少敲1000行代码!

    01.什么是 lambda 表达式 1. 函数式接口 在聊起 lambda 表达式之前,我们不得不提起函数式接口:一个接口只包含唯一的方法,那么它就是函数式接口.例如: public class La ...

  8. 自己动手实践 spring retry 重试框架

    前序 马上过年了,预祝大家,新年快乐,少写bug 什么是spring retry? spring retry是从spring batch独立出来的一个能功能,主要实现了重试和熔断. 什么时候用? 远程 ...

  9. 3行代码快速实现Spring Boot Oauth2服务

    这里的3行代码并不是指真的只需要写3行代码,而是基于我已经写好的一个Spring Boot Oauth2服务.仅仅需要修改3行数据库配置信息,即可得到一个Spring Boot Oauth2服务. 项 ...

  10. Spring Retry 在SpringBoot 中的应用

    Spring Boot中使用Spring-Retry重试框架 Spring Retry提供了自动重新调用失败的操作的功能.这在错误可能是暂时的(例如瞬时网络故障)的情况下很有用. 从2.2.0版本开始 ...

随机推荐

  1. C语言访问数据对象在内存中真实位模式的一个方法

    在判定机器采用大端还是小端存储时,可以按字节输出某数据对象的机器表示的位模式.机器表示的位模式即某数据对象在内存中的二进制串.下面是一个访问数据对象位模式的方法: //传入一个数据对象,从低地址到高地 ...

  2. 计算机网络 vlan

    目录 一.vlan的概念 二.vlan的优势 三.vlan的种类 四.静态vlan的配置 五.trunk的概念和配值 六.实验 一.vlan的概念 在传统的以太网中,所有的用户都是同一个广播域,当数据 ...

  3. Iframe在Vue中的状态保持技术

    引言 Iframe是一个历史悠久的HTML元素,根据MDN WEB DOCS官方介绍,Iframe定义为HTML内联框架元素,表示嵌套的Browsing Context,它能够将另一个HTML页面嵌入 ...

  4. Hackathon 代码黑客马拉松采访复盘

    AIGC Hackathon 2023 北京站 我参加了选手采访提纲,这里我感觉有些点可以分享给大家.之前复盘的链接: 下面是采访我的回答内容: 1. 请向大家简单介绍一下自己吧? 子木,社区名称为程 ...

  5. cv学习总结(11.14-11.20)

    本周主要完成了assignment2中的connected_layer部分的代码,跟assignment1中的two_layer_net相比,虽然整体思路都是实现全连接的网络,但是connect_la ...

  6. OCR -- 文本检测 - 训练DB文字检测模型

    百度飞桨(PaddlePaddle) - PP-OCRv3 文字检测识别系统 预测部署简介与总览 百度飞桨(PaddlePaddle) - PP-OCRv3 文字检测识别系统 Paddle Infer ...

  7. 00.Webstrom的基本入门设置

    1.取消红框类自动打开项目 2.打开轮滚缩放代码 3.设置代码字体,这里选择的是Consolas 推荐免费字体:https://files.cnblogs.com/files/huadaxia/jet ...

  8. K8S in Action 读后感(概念简介)

    一.K8S的用武之地 今天,大型单体应用正被逐渐拆分成小的.可独立运行的组件,我们称之为微服务.微服务彼此之间解耦,所以它们可以被独立开发.部署.升级.伸缩.这使得我们可以对每一个微服务实现快速迭代, ...

  9. 使用Python实现学生信息管理系统

    本文介绍了一个简单的学生信息管理系统,包括管理员登录.重置学生密码.添加.删除和修改学生信息.查询学生信息以及对学生成绩进行排序等功能.该系统使用Python编写,基于控制台交互 实现思路 该系统分为 ...

  10. java接口返回图片链接或pdf链接如何设置在线预览还是下载

    之前文章说到了如何通过将文件转成图片或者pdf来实现在线预览,一般来说在线预览图片或者pdf都是存储在图片服务器上的,在通过接口调用把文件返回给前端,但是把文件返回给前端效果一般是有两种:在线预览和下 ...