当前位置: 首页 > news >正文

使用Guava Retrying优雅的实现业务异常重试

上次写过一篇如何使用spring retry来实现业务重试的文章:https://blog.csdn.net/Kingsea442/article/details/135341747

尽管 Spring Retry 工具能够优雅地实现重试,但它仍然存在两个不太友好的设计:

  1. 重试实体被限定为 Throwable 子类,这意味着重试针对的是可捕获的功能异常,但实际上我们可能希望依赖某个数据对象实体作为重试实体,但是 Spring Retry 框架必须强制将其转换为 Throwable 子类。
  2. 重试根源的断言对象使用的是 doWithRetry 的 Exception 异常实例,这不符合正常内部断言的返回设计。
    Spring Retry 建议使用注解来对方法进行重试,重试逻辑是同步执行的。重试的“失败”是指 Throwable 异常,如果你要通过返回值的某个状态来判断是否需要重试,则可能需要自己判断返回值并手动抛出异常。

Guava Retrying

开源地址:https://github.com/rholder/guava-retrying

Guava Retrying 是基于 Google 的核心类库 Guava 的重试机制实现的一个库,它提供了一种通用方法,可以使用 Guava 谓词匹配增强的特定停止、重试和异常处理功能来重试任意 Java 代码。这个库支持多种重试策略,比如指定重试次数、指定重试时间间隔等。此外,它还支持谓词匹配来确定是否应该重试,以及在重试时应该做些什么。Guava Retrying 的最大特点是它能够灵活地与其他 Guava 类库集成,这使得它非常易于使用。

pom依赖:

	// maven依赖<dependency><groupId>com.github.rholder</groupId><artifactId>guava-retrying</artifactId><version>2.0.0</version></dependency>// gradle依赖:compile "com.github.rholder:guava-retrying:2.0.0"

测试demo


public static void main(String[] args) {Callable<Boolean> callable = new Callable<Boolean>() {@Overridepublic Boolean call() throws Exception {// do something useful herelog.info("call...");throw new RuntimeException();}};Retryer<Boolean> retryer = RetryerBuilder.<Boolean>newBuilder()//retryIf 重试条件.retryIfException().retryIfRuntimeException().retryIfExceptionOfType(Exception.class).retryIfException(Predicates.equalTo(new Exception())).retryIfResult(Predicates.equalTo(false))//等待策略:每次请求间隔1s.withWaitStrategy(WaitStrategies.fixedWait(1, TimeUnit.SECONDS))//停止策略 : 尝试请求6次.withStopStrategy(StopStrategies.stopAfterAttempt(6))//时间限制 : 某次请求不得超过2s .withAttemptTimeLimiter(AttemptTimeLimiters.fixedTimeLimit(2, TimeUnit.SECONDS))//注册一个自定义监听器(可以实现失败后的兜底方法).withRetryListener(new MyRetryListener()).build();try {retryer.call(callable);} catch (Exception ee) {ee.printStackTrace();}
}

当发生重试之后,假如我们需要做一些额外的处理动作,比如发个告警邮件啥的,那么可以使用RetryListener。每次重试之后,guava-retrying会自动回调我们注册的监听。可以注册多个RetryListener,会按照注册顺序依次调用。

public class MyRetryListener implements RetryListener {@Overridepublic <V> void onRetry(Attempt<V> attempt) {// 第几次重试System.out.print("[retry]time=" + attempt.getAttemptNumber());// 距离第一次重试的延迟System.out.print(",delay=" + attempt.getDelaySinceFirstAttempt());// 重试结果: 是异常终止, 还是正常返回System.out.print(",hasException=" + attempt.hasException());System.out.print(",hasResult=" + attempt.hasResult());// 是什么原因导致异常if (attempt.hasException()) {System.out.print(",causeBy=" + attempt.getExceptionCause().toString());// do something useful here} else {// 正常返回时的结果System.out.print(",result=" + attempt.getResult());}System.out.println();}
}

RetryerBuilder是一个factory创建者,可以定制设置重试源且可以支持多个重试源,可以配置重试次数或重试超时时间,以及可以配置等待时间间隔,创建重试者Retryer实例。

RetryerBuilder的重试源支持Exception异常对象 和自定义断言对象,通过retryIfException 和retryIfResult设置,同时支持多个且能兼容。
retryIfException,抛出runtime异常、checked异常时都会重试,但是抛出error不会重试。

retryIfRuntimeException只会在抛runtime异常的时候才重试,checked异常和error都不重试。

retryIfExceptionOfType允许我们只在发生特定异常的时候才重试,比如NullPointerException和IllegalStateException都属于runtime异常,也包括自定义的error。

retryIfResult可以指定你的Callable方法在返回值的时候进行重试。

StopStrategy:停止重试策略,提供以下方式:

StopAfterDelayStrategy: 设定一个最长允许的执行时间;比如设定最长执行10s,无论任务执行次数,只要重试的时候超出了最长时间,则任务终止,并返回重试异常
NeverStopStrategy: 用于需要一直轮训知道返回期望结果的情况。
StopAfterAttemptStrategy: 设定最大重试次数,如果超出最大重试次数则停止重试,并返回重试异常。
WaitStrategy: 等待时长策略(控制时间间隔)
FixedWaitStrategy: 固定等待时长策略。
RandomWaitStrategy: 随机等待时长策略(可以提供一个最小和最大时长,等待时长为其区间随机值)
IncrementingWaitStrategy: 递增等待时长策略(提供一个初始值和步长,等待时间随重试次数增加而增加)。
ExponentialWaitStrategy: 指数等待时长策略
FibonacciWaitStrategy: 等待时长策略
ExceptionWaitStrategy: 异常时长等待策略
CompositeWaitStrategy: 复合时长等待策略

总结

Guava Retryer 工具与 Spring Retry 类似,都是通过定义重试者角色来包装正常逻辑重试。然而,Guava Retryer 在策略定义方面更优秀。它不仅支持设置重试次数和重试频度控制,还能够兼容多个异常或自定义实体对象的重试源定义,从而提供更多的灵活性。这使得 Guava Retryer 能够适用于更多的业务场景,比如网络请求、数据库访问等。此外,Guava Retryer 还具有很好的可扩展性,可以很方便地与其他 Guava 类库集成使用。

相关文章:

使用Guava Retrying优雅的实现业务异常重试

上次写过一篇如何使用spring retry来实现业务重试的文章&#xff1a;https://blog.csdn.net/Kingsea442/article/details/135341747 尽管 Spring Retry 工具能够优雅地实现重试&#xff0c;但它仍然存在两个不太友好的设计&#xff1a; 重试实体被限定为 Throwable 子类&#…...

java SSM物业管理系统myeclipse开发mysql数据库springMVC模式java编程计算机网页设计

一、源码特点 java SSM物业管理系统是一套完善的web设计系统&#xff08;系统采用SSM框架进行设计开发&#xff0c;springspringMVCmybatis&#xff09;&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和 数据库&#xff0c;系统主要采用B/…...

Hive使用shell调用命令行特殊字符处理

1.场景分析 数据处理常用hive -e的方式&#xff0c;通过脚本操作数仓&#xff0c;过程中常常遇到特殊字符的处理&#xff0c;如单双引号、反斜杠、换行符等&#xff0c;现将特殊字符用法总结使用如下&#xff0c;可直接引用&#xff0c;避免自行测试的繁琐。 2.特殊字符处理 …...

服务器里面很卡,打开文件卡住了一般是什么问题,怎么解决

随着互联网业务的快速发展&#xff0c;各项业务都绕不开服务器。在日常使用中&#xff0c;服务器有着非常重要的作用。而我们日常使用中&#xff0c;也会遇到各种各样的问题。最近就有遇到用户联系咨询德迅云安全&#xff0c;询问自己服务器突然很卡&#xff0c;打开文件都卡住…...

linux 测试网络传输速度

在linux和macos中看不到文件复制速度,往往不清楚smb或者afp的传输速度。 dd命令可以测试磁盘io速度,当然也可以测试网络传输速度。 首先要挂载afp或者smb,此步略过。 然后准备好一定体积的测试文件(最好大点,比如1G以上),使用以下命令测试传输速度: dd if=/smb/TestI…...

GO——锁

公平锁和非公平锁 参考&#xff1a;https://blog.csdn.net/weixin_39309402/article/details/106466843 公平锁&#xff1a; 多个线程排队去获取锁优点 所有线程都能获取到资源 缺点 除第一个线程&#xff0c;其他队列中的线程&#xff08;阻塞中&#xff09;都需要唤醒&…...

分析一个项目(微信小程序篇)三

目录 接下来分析接口方面&#xff1a; home接口&#xff1a; categories接口&#xff1a; details接口&#xff1a; login接口&#xff1a; 分析一个项目讲究的是如何进行对项目的解析分解&#xff0c;进一步了解项目的整体结构&#xff0c;熟悉项目的结构&#xff0c;能够…...

element+vue 之图片放大器

1.安装插件 npm install vue-photo-zoom-pro2.main.js导入 // 放大镜 import VuePhotoZoomPro from vue-photo-zoom-pro Vue.use(VuePhotoZoomPro)3.页面使用 <vue-photo-zoom-pro:url"imgUrl":out-zoomer"true":scale"2"style"width:…...

Vue学习笔记3--全局事件总线

Vue学习笔记3—全局事件总线 1.全局事件总线可以实现任意组件间通信 X需具备的条件&#xff1a; 所有的组件都要能看见X可以调用$on $off $emitVue.prototype.x {a:1, b:2} 可以被所有组件看见VueComponent.protoype.proto Vue.prototype组件实例对象(vc)可以访问到Vue原型上…...

科学和统计分析软件GraphPad Prism mac介绍说明

GraphPad Prism for Mac是一款科学和统计分析软件&#xff0c;旨在帮助研究者、科学家和学生更轻松地处理和可视化数据。 GraphPad Prism for Mac是一款功能强大、易于使用的科学和统计分析软件&#xff0c;适用于各种类型的数据处理和可视化需求。无论您是进行基础研究、临床试…...

[学习笔记]刘知远团队大模型技术与交叉应用L1-NLPBig Model Basics

本节主要介绍NLP和大模型的基础知识。提及了词表示如何从one-hot发展到Word Embedding。语言模型如何从N-gram发展成预训练语言模型PLMs。然后介绍了大模型在NLP任务上的表现&#xff0c;以及它遵循的基本范式。最后介绍了本课程需要用到的编程环境和GPU服务器。 一篇NLP方向的…...

概率论与数理统计————古典概型、几何概型和条件概率

一、古典概型 特点 &#xff08;1&#xff09;有限性&#xff1a;试验S的样本空间的有限集合 &#xff08;2&#xff09; 等可能性&#xff1a;每个样本点发生的概率是相等的 公式&#xff1a;P&#xff08;A&#xff09; A为随机事件的样本点数&#xff1b;S是样本…...

C#编程-使用事件

使用事件 事件是一个动作或发生的事情,例如:鼠标点击、按键、鼠标移动或系统产生的通知。应用程序可以在事件发生的时候做出响应。通知的一个示例是中断。事件是对象发生的消息以表示事件的发生。事件是进程内通信的有效方法。它们对对象时有用的,因为它们标识了单个状态改…...

Dijsktra算法理解笔记

Dijsktra算法理解笔记 学习了柳神的笔记 感谢柳神 Dijkstra算法是处理图问题中的最短路径的问题 最短路径问题可以大致分为两个方向 单源最短路径全局最短路径 以此为基准可以将最短路径算法这样划分&#xff1a; 单源最短路径 Dijkstra &#xff1a;不能求负权边Bellman-F…...

电流检测方法

电路检测电路常用于&#xff1a;高压短路保护、电机控制、DC/DC换流器、系统功耗管理、二次电池的电流管理、蓄电池管理等电流检测等场景。 对于大部分应用&#xff0c;都是通过感测电阻两端的压降测量电流。 一般使用电流通过时的压降为数十mV&#xff5e;数百mV的电阻值&…...

Linux scp命令 服务器之间通讯

目录 一. scp命令简介二. 本地服务器文件传输到远程服务器三. 本地服务器文件夹传输到远程服务器 一. scp命令简介 scp&#xff08;Secure Copy Protocol&#xff09;是用于在Unix或Linux系统之间安全地复制文件或目录的命令。 它使用SSH&#xff08;Secure Shell&#xff09;…...

C语言中的命名规则(期末版)

一、概述 命名规则是编程语言中的重要组成部分&#xff0c;它决定了变量、函数、常量等标符的命名方式。在C语言中&#xff0c;良好的命名规则可以增加代码的可读性和可维护性&#xff0c;提高程序的质量和开发效率。本文将详细介绍C语言中的命名规则&#xff0c;包括标识符的…...

远程开发之vscode端口转发

远程开发之vscode端口转发 涉及的软件forwarded port 通过端口转发&#xff0c;实现在本地电脑上访问远程服务器上的内网的服务。 涉及的软件 vscode、ssh forwarded port 在ports界面中的port字段&#xff0c;填需要转发的IP:PORT&#xff0c;即可转发远程服务器中的内网端…...

超简单的node爬虫小案例

同前端爬取参数一样&#xff0c;输入三个参数进行爬取 注意点也一样&#xff1a; 注意分页的字段需要在代码里面定制化修改&#xff0c;根据你爬取的接口&#xff0c;他的业务规则改代码中的字段。比如我这里总条数叫total&#xff0c;人家的不一定。返回的数据我这里是data.r…...

(每日持续更新)jdk api之FileFilter基础、应用、实战

博主18年的互联网软件开发经验&#xff0c;从一名程序员小白逐步成为了一名架构师&#xff0c;我想通过平台将经验分享给大家&#xff0c;因此博主每天会在各个大牛网站点赞量超高的博客等寻找该技术栈的资料结合自己的经验&#xff0c;晚上进行用心精简、整理、总结、定稿&…...

生成xcframework

打包 XCFramework 的方法 XCFramework 是苹果推出的一种多平台二进制分发格式&#xff0c;可以包含多个架构和平台的代码。打包 XCFramework 通常用于分发库或框架。 使用 Xcode 命令行工具打包 通过 xcodebuild 命令可以打包 XCFramework。确保项目已经配置好需要支持的平台…...

conda相比python好处

Conda 作为 Python 的环境和包管理工具&#xff0c;相比原生 Python 生态&#xff08;如 pip 虚拟环境&#xff09;有许多独特优势&#xff0c;尤其在多项目管理、依赖处理和跨平台兼容性等方面表现更优。以下是 Conda 的核心好处&#xff1a; 一、一站式环境管理&#xff1a…...

DeepSeek 赋能智慧能源:微电网优化调度的智能革新路径

目录 一、智慧能源微电网优化调度概述1.1 智慧能源微电网概念1.2 优化调度的重要性1.3 目前面临的挑战 二、DeepSeek 技术探秘2.1 DeepSeek 技术原理2.2 DeepSeek 独特优势2.3 DeepSeek 在 AI 领域地位 三、DeepSeek 在微电网优化调度中的应用剖析3.1 数据处理与分析3.2 预测与…...

模型参数、模型存储精度、参数与显存

模型参数量衡量单位 M&#xff1a;百万&#xff08;Million&#xff09; B&#xff1a;十亿&#xff08;Billion&#xff09; 1 B 1000 M 1B 1000M 1B1000M 参数存储精度 模型参数是固定的&#xff0c;但是一个参数所表示多少字节不一定&#xff0c;需要看这个参数以什么…...

测试markdown--肇兴

day1&#xff1a; 1、去程&#xff1a;7:04 --11:32高铁 高铁右转上售票大厅2楼&#xff0c;穿过候车厅下一楼&#xff0c;上大巴车 &#xffe5;10/人 **2、到达&#xff1a;**12点多到达寨子&#xff0c;买门票&#xff0c;美团/抖音&#xff1a;&#xffe5;78人 3、中饭&a…...

postgresql|数据库|只读用户的创建和删除(备忘)

CREATE USER read_only WITH PASSWORD 密码 -- 连接到xxx数据库 \c xxx -- 授予对xxx数据库的只读权限 GRANT CONNECT ON DATABASE xxx TO read_only; GRANT USAGE ON SCHEMA public TO read_only; GRANT SELECT ON ALL TABLES IN SCHEMA public TO read_only; GRANT EXECUTE O…...

[Java恶补day16] 238.除自身以外数组的乘积

给你一个整数数组 nums&#xff0c;返回 数组 answer &#xff0c;其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法&#xff0c;且在 O(n) 时间复杂度…...

中医有效性探讨

文章目录 西医是如何发展到以生物化学为药理基础的现代医学&#xff1f;传统医学奠基期&#xff08;远古 - 17 世纪&#xff09;近代医学转型期&#xff08;17 世纪 - 19 世纪末&#xff09;​现代医学成熟期&#xff08;20世纪至今&#xff09; 中医的源远流长和一脉相承远古至…...

搭建DNS域名解析服务器(正向解析资源文件)

正向解析资源文件 1&#xff09;准备工作 服务端及客户端都关闭安全软件 [rootlocalhost ~]# systemctl stop firewalld [rootlocalhost ~]# setenforce 0 2&#xff09;服务端安装软件&#xff1a;bind 1.配置yum源 [rootlocalhost ~]# cat /etc/yum.repos.d/base.repo [Base…...

Modbus RTU与Modbus TCP详解指南

目录 1. Modbus协议基础 1.1 什么是Modbus? 1.2 Modbus协议历史 1.3 Modbus协议族 1.4 Modbus通信模型 🎭 主从架构 🔄 请求响应模式 2. Modbus RTU详解 2.1 RTU是什么? 2.2 RTU物理层 🔌 连接方式 ⚡ 通信参数 2.3 RTU数据帧格式 📦 帧结构详解 🔍…...