接口请求重试八种方法
请求三方接口需要加入重试机制
一、循环重试
在请求接口的代码块中加入循环,如果请求失败则继续请求,直到请求成功或达到最大重试次数。
int retryTimes = 3;
for(int i = 0;i < retryTimes;i++){try{//请求接口的代码break;}catch(Exception e){//处理异常Thread.sleep(1000);//为了避免频繁请求,延迟1秒后重试}
}
二、使用递归结构
在请求接口的方法中调用自身,如果请求失败则继续调用,直到请求成功或达到最大重试次数。
public void requestWithRetry(int retryTimes){if(retryTimes <= 0){return;}try{//请求接口的代码}catch(Exception e){//处理异常Thread.sleep(1000);//延迟1秒后重试requestWithRetry(retryTimes - 1);}
}
三、使用网络工具内置重试机制
HTTP 客户端通常内置了一些重试机制,只需要在创建对应的客户端实例的时候进行配置即可,以 Apache HTTPClient 为例:
- 4.5+ 版本:使用 HttpClients.custom().setRetryHandler() 方法来设置重试机制
- 5.x 版本:使用 HttpClients.custom().setRetryStrategy() 方法来设置重试机制
CloseableHttpClient httpClient = HttpClients.custom().setRetryHandler(new DefaultHttpRequestRetryHandler(3,true)).build();CloseableHttpClient httpClient = HttpClients.custom().setRetryStrategy(new DefaultHttpRequestRetryStrategy(3,NEG_ONE_SECOND)).build();
Apache HTTPClient 还支持自定义重试策略,可以可以实现 HTTPRequestRetryHandler 接口(4.5 + 版本)或者 RetryStrategy 接口(5.x 版本)
CloseableHttpClient httpClient = HttpClients.custom().setRetryStrategy((response,executionCount,context) -> {if(executionCount > 3){//如果重试次数超过3次,则放弃重试return false;}if(status >= 500 && statusCode < 600){//如果遇到服务器错误状态码,则进行重试return true;}//其他情况不进行重试return false;}).build();
四、使用Spring Retry库
Spring Retry 提供了一组注解和工具类,可以方便地为方法添加重试功能。
<dependency><groupId>org.springframework.retry</groupId><artifactId>spring-retry</artifactId><version>1.3.1</version>
</dependency>
Spring Retry 的使用有两种方式,一种是使用 RetryTemplate 来显式调用需要重试的方法,一种实用注解来自动触发重试。
显式调用
RetryTemplate retryTemplate = new RetryTemplate();//配置重试策略
RetryPolicy retryPolicy = new SimpleRetryPolicy(3);
retryTemplate.setRetryPolicy(retryPolicy);//最大重试次数为 3 次//配置重试间隔策略
FixedBackOffPolicy backOffPolicy = new FixedBackOffPolicy();
backOffPolicy.setBackOffPeriod(1000);//重试间隔为 1 秒
retryTemplate.setBackOffPolicy(backOffPolicy);//使用RetryTemplate调用方法,执行需要重试的代码块
retryTemplate.execute((RetryCallback<Void,Exception>) context - >{//请求接口的代码return null;
});
Spring Retry 是一个提供重试机制的库,可以方便地在 Spring 项目中使用。使用 @Retryable 注解标记需要重试的方法,如果方法抛出异常则会自动重试。
@Retryable(value=Exception.class,maxAttempts=3)
public void request(){//请求接口的代码
}
注解调用:
①、配置重试切面
@Configuration
@EnableRetry //启用重试功能
public class RetryConfig{//配置其他bean
}
②、注解标记需要重试的方法
@Retryable(maxAttempts=3)//指定了最大重试次数为 3 次
public void request(){//请求接口代码
}
③、调用被标记的方法
@Autowired
private HttpService httpService;httpService.request();
springboot中使用:
①、启动类开启 Spring Retry 功能
@SpringBootApplication
@EnableRetry // 启用Spring Retry功能
public class MyApplication {public static void main(String[] args) {SpringApplication.run(MyApplication.class, args);}
}
②、进行重试的方法上添加 @Retryable指定了重试的异常类型、最大重试次数和重试间隔
@Backoff 注解用于指定重试间隔策略,delay 属性表示每次重试之间的间隔时间。在这个例子中,每次重试之间的间隔时间为 1 秒
@Retryable 注解只能标记在 public 方法上。如果需要在非 public 方法上使用重试功能,可以使用代理模式实现
@Service
public class MyService {@Retryable(value = {MyException.class}, maxAttempts = 3, backoff = @Backoff(delay = 1000))public void doSomething() {// 需要进行重试的方法逻辑}
}
如果需要在重试过程中进行一些特定的操作,比如记录日志、发送消息等,可以在重试方法中使用 RetryContext 参数,它提供了一些有用的方法来获取重试的上下文信息。
@Service
public class MyService {@Retryable(value = {MyException.class}, maxAttempts = 3, backoff = @Backoff(delay = 1000))public void doSomething(RetryContext context) {// 获取重试次数int retryCount = context.getRetryCount();// 获取上一次异常Throwable lastThrowable = context.getLastThrowable();// 记录日志、发送消息等操作// ...// 需要进行重试的方法逻辑}
}
五、使用Resilience4j库
提供了重试、熔断、限流等多种机制
<dependency><groupId>io.github.resilience4j</groupId><artifactId>resilience4j-spring-boot2</artifactId><version>1.7.0</version>
</dependency>
1、显式调用
//创建一个 RetryRegistry 对象
RetryRegistry retryRegistry = RetryRegistry.ofDefalults();//配置RetryRegistry实例,使用 RetryConfig 类来自定义 Retry 的配置,包括最大重试次数、重试间隔等
RetryConfig config = RetryConfig.custom().maxAttempts(3)//最大重试次数为 3 次.waitDuration(Duration.ofMillis(1000))//重试间隔为 1 秒.retryOnResult(response -> response.getStatus() == 500)//返回结果的状态码为 500 时进行重试.retryOnException(e -> e instanceof WebServiceException)//抛出 WebServiceException 异常时进行重试.retryExceptions(IOException.class, TimeoutException.class).ignoreExceptions(BusinessException.class, OtherBusinessException.class)//忽略 BusinessException 和 OtherBusinessException 异常.failAfterMaxAttempts(true).build();//使用 Retry 来装饰和执行需要进行重试的代码块
CheckedFunction0<String> retryableSupplier = Retry.decorateCheckedSupplier(retry, () -> {// 需要进行重试的代码return "result";
});
2、注解调用
//SpringBoot项目中使用@Retryable注解来标记需要重试的方法
@Service
public class MyService{//指定了重试的异常类型为MyException,最大重试次数3次,重试间隔1秒@Retryable(value={MyException.class},maxAttempts=3,backoff=@Backoff(delay = 1000))public void doSomething(){//需要进行重试的方法逻辑}
}
六、自定义重试工具类
①、自定义一个是实现了Callback抽象类的具体回调类
public abstract class Callback{//执行重试逻辑public abstract RetryResult doProcess();//RetryResult封装重试结果
}
②、封装重试结果
public class RetryResult{private Boolean isRetry;//是否需要进行重试private Object obj;//重试的结果对象//构造方法和getter方法省略public static RetryResult ofResult(Boolean isRetry, Object obj){return new RetryResult(isRetry, obj);}public static RetryResult ofResult(Boolean isRetry){return new RetryResult(isRetry, null);}
}
③、执行
public class RetryExecutor{//接收一个重试次数和一个回调对象public static Object execute(int retryCount,Callback callback){for(int curRetryCount = 0;curRetryCount < retryCount;curRetryCount++){RetryResult retryResult = callback.doProcess();if(retryResult.isRetry()){continue;}return retryResult.getObj();}return null;}
}
使用这个自定义的重试工具类时,只需要实现一个继承自 Callback 的回调类,并在其中实现具体的重试逻辑。然后,通过调用 RetryExecutor.execute() 方法来执行重试操作。这里直接用了一个匿名的实现:
//最大重试次数
int maxRetryCount = 3;
Object result = RetryExecutor.execute(maxRetryCount, new Callback() {@Overridepublic RetryResult doProcess() {// 执行需要重试的逻辑// 如果需要重试,返回 RetryResult.ofResult(true)// 如果不需要重试,返回 RetryResult.ofResult(false, result)}
});
七、并发框架异步重试
使用ThreadPoolExecutor把请求接口转换成一个异步任务,将任务放入线程池中异步执行
并发地重试请求接口。
可以在任务执行完成后,判断任务执行结果,如果失败则继续重试
int maxRetryTimes = 3;
int currentRetryTimes = 0;ThreadPoolExecutor executor = new ThreadPoolExecutor(10,//核心线程数10,//最大线程数0L,//空闲线程存活时间TimeUnit.MILLISECONDS,//时间的单位new LinkedBlockingQueue<>()//任务队列
);//任务
Callable<String> task = () -> {//请求接口的代码return "result";
}Future<String> future;
while(currentRetryTimes < maxRetryTimes){try{future = executor.submit(task);String result = future.get();//获取任务结果//判断任务执行结果,如果任务执行成功,则跳出循环;如果任务执行失败,则继续重试,直到达到最大重试次数break;}catch(Exception e){currentRetryTimes++;try{Thread.sleep(1000);}catch(InterruptedException ex){Thread.currentThread().interrupt();}}
}
八、消息队列重试
保证重试的可靠性,不会因为服务中断,而导致重试任务的丢失,可以引入消息队列
直接把消息投递到消息队列里,通过对消息的消费,来实现重试机制。
//指定了消费者的相关配置,包括消费者组和订阅的主题
@Component
@RocketMQMessageListener(topic="myTopic",consumerGroup="myConsumerGroup")
public class MyConsumer implements RocketMQListener<String>{@Overridepublic void onMessage(String message){try{//请求接口的代码}catch(Exception e){//处理异常//如果请求失败,创建一个 RocketMQ 的生产者,并将请求重新发送到消息队列中,等待下一次处理DefaultMQProducer producer = new DefaultMQProducer("myProducerGroup");producer.setNamesrvAddr("127.0.0.1:9876");try{producer.start();}catch(Exception ex){//处理异常}finally{producer.shutdown();}}}
}
【注意】
- 合理设置重试次数和重试间隔时间,避免频繁地发送请求,同时也不要设置过大的重试次数,以免影响系统的性能和响应时间。
- 考虑接口幂等性:如果请求是写操作,而且下游的服务不保证请求的幂等性,那么在重试时需要谨慎处理,可以通过查询等幂等的方式进行重试
- 在重试过程中,需要考虑并发的问题。如果多个线程同时进行重试,可能会导致请求重复发送或请求顺序混乱等问题。可以使用锁或者分布式锁来解决并发问题。
- 在处理异常时,需要根据具体的异常类型来进行处理。有些异常是可以通过重试来解决的,例如网络超时、连接异常等;而有些异常则需要进行特殊的处理,例如数据库异常、文件读写异常等。
- 在使用重试机制时,需要注意不要陷入死循环。如果请求一直失败,重试次数一直增加,可能会导致系统崩溃或者资源耗尽等问题。
相关文章:
接口请求重试八种方法
请求三方接口需要加入重试机制 一、循环重试 在请求接口的代码块中加入循环,如果请求失败则继续请求,直到请求成功或达到最大重试次数。 int retryTimes 3; for(int i 0;i < retryTimes;i){try{//请求接口的代码break;}catch(Exception e){//处理…...
【Linux 基础】常用基础指令(上)
文章目录 一、 创建新用户并设置密码二、ls指令ls指令基本概念ls指令的简写操作 三、pwd指令四、cd指令五、touch指令六、rm指令七、mkdir指令八、rmdir 指令 一、 创建新用户并设置密码 ls /home —— 查看存在多少用户 whoami —— 查看当前用户名 adduser 用户名 —— 创建新…...
【RT-DETR有效改进】EfficientFormerV2移动设备优化的视觉网络(附对比试验效果图)
前言 大家好,我是Snu77,这里是RT-DETR有效涨点专栏。 本专栏的内容为根据ultralytics版本的RT-DETR进行改进,内容持续更新,每周更新文章数量3-10篇。 专栏以ResNet18、ResNet50为基础修改版本,同时修改内容也支持Re…...
《动手学深度学习(PyTorch版)》笔记4.4
注:书中对代码的讲解并不详细,本文对很多细节做了详细注释。另外,书上的源代码是在Jupyter Notebook上运行的,较为分散,本文将代码集中起来,并加以完善,全部用vscode在python 3.9.18下测试通过。…...
Linux/Academy
Enumeration nmap 首先扫描目标端口对外开放情况 nmap -p- 10.10.10.215 -T4 发现对外开放了22,80,33060三个端口,端口详细信息如下 结果显示80端口运行着http,且给出了域名academy.htb,现将ip与域名写到/et/hosts中,然后从ht…...
windows .vscode的json文件配置 CMake 构建项目 调试窗口中文设置等
一、CMake 和 mingw64的安装和环境配置 二、tasks.json和launch.json文件配置 tasks.json {"version": "2.0.0","options": {"cwd": "${workspaceFolder}/build"},"tasks": [{"type": "shell&q…...
uniapp canvas做的刮刮乐解决蒙层能自定义图片
最近给湖南中烟做元春活动,一个月要开发4个小活动,这个是其中一个难度一般,最难的是一个类似鲤鱼跃龙门的小游戏,哎,真实为难我这个“拍黄片”的。下面是主要代码。 <canvas :style"{width:widthpx,height:hei…...
利用SPI,结合数据库连接池durid进行数据服务架构灵活设计
接着上一篇文章业务开始围绕原始凭证展开,而展开的基础无疑是围绕着科目展开的。首先我们业务层面以财政部的小企业会计准则的一级科目引入软件中。下面我们来考虑如何将科目切入软件更加灵活,方便业务扩展、维护与升级。 SPI是首先想到的数据服务方式 为什么会想到它呢?首…...
自动驾驶的决策层逻辑
作者 / 阿宝 编辑 / 阿宝 出品 / 阿宝1990 自动驾驶意味着决策责任方的转移 我国2020至2025年将会是向高级自动驾驶跨越的关键5年。自动驾驶等级提高意味着对驾驶员参与度的需求降低,以L3级别为界,低级别自动驾驶环境监测主体和决策责任方仍保留于驾驶…...
排序算法——希尔排序算法详解
希尔排序算法详解 一. 引言1. 背景介绍1.1 数据排序的重要性1.2 希尔排序的由来 2. 排序算法的分类2.1 比较排序和非比较排序2.2 希尔排序的类型 二. 希尔排序基本概念1. 希尔排序的定义1.1 缩小增量排序1.2 插入排序的变种 2. 希尔排序的工作原理2.1 分组2.2 插入排序2.3 逐步…...
Docker 容器内运行 mysqldump 命令来导出 MySQL 数据库,自动化备份
备份容器数据库命令: docker exec 容器名称或ID mysqldump -u用户名 -p密码 数据库名称 > 导出文件.sql请替换以下占位符: 容器名称或ID:您的 MySQL 容器的名称或ID。用户名:您的 MySQL 用户名。密码:您的 MySQL …...
【Java万花筒】数字信号魔法:Java库的魅力解析
从傅立叶到矩阵:数字信号Java库全景剖析 前言 随着数字信号处理在科学、工程和数据分析领域的广泛应用,开发者对高效、灵活的工具的需求日益增长。本文旨在探讨几个与数字信号处理相关的Java库,通过介绍其特点、用途以及与已有库的关系&…...
面试高频知识点:2线程 2.1 线程池 2.1.2 JDK中常见的线程池实现有哪些?
1. Executors类 Executors类是线程池的工厂类,提供了一些静态方法用于创建不同类型的线程池。然而,它的使用并不推荐在生产环境中,因为它存在一些缺点,比如默认使用无界的任务队列,可能导致内存溢出。 2. ThreadPool…...
Azure Private endpoint DNS 记录是如何解析的
Private endpoint 从本质上来说是Azure 服务在Azure 虚拟网络中安插的一张带私有地址的网卡。 举例来说如果Storage account在没有绑定private endpoint之前,查询Storage account的DNS记录会是如下情况: Seq Name …...
windows 安装sql server 华为云文档
先安装net3.5,剩下安装sqlserver步骤看下面文档 安装SQL Server_弹性云服务器 ECS_最佳实践_搭建Microsoft SharePoint Server 2016_华为云 (huaweicloud.com)...
相同主题文章竟同时发表在同一个2区期刊 | 孟德尔随机化周报(1.10-1.16)
欢迎报名2024年郑老师团队课程课程! 郑老师科研统计培训,包括临床数据、公共数据分析课程,欢迎报名 孟德尔随机化,Mendilian Randomization,简写为MR,是一种在流行病学领域应用广泛的一种实验设计方法,利用…...
网络安全的使命:守护数字世界的稳定和信任
在数字化时代,网络安全的角色不仅仅是技术系统的守护者,更是数字社会的信任保卫者。网络安全的使命是保护、维护和巩固数字世界的稳定性、可靠性以及人们对互联网的信任。本文将深入探讨网络安全是如何履行这一使命的。 第一部分:信息资产的…...
【七、centos要停止维护了,我选择Almalinux】
搜索镜像 https://developer.aliyun.com/mirror/?serviceTypemirror&tag%E7%B3%BB%E7%BB%9F&keywordalmalinux dvd是有界面操作的,minimal是最小化只有命里行 镜像下载地址 安装和centos基本一样的,操作命令也是一样的,有需要我…...
架构师之路(十六)计算机网络(传输层)
前置知识(了解):计算机基础。 作为架构师,我们所设计的系统很少为单机系统,因此有必要了解计算机和计算机之间是怎么联系的。局域网的集群和混合云的网络有啥区别。系统交互的时候网络会存在什么瓶颈。 既然网络层已经…...
python 调用SumatraPDF 静默打印PDF
SumatraPDF 文档 https://www.sumatrapdfreader.org/docs/Command-line-arguments ⽆边框 noscale/缩⼩到合适⼤⼩(默认)shrink/合适⼤⼩ fit/compat 兼容 # 分为 Portrait (纵向)和 Landscape (横向)两类 https://github.com/sumatrapdfreader/sumatrap…...
nginx部署https域名ssl证书
1、在你服务器nginx文件夹下创建ssl文件夹存放证书文件和秘钥文件 把.crt和.key证书放上 2、在nginx.conf文件中配置 在nginx.conf文件中server下加入listen 443 ssl; server {listen 443 ssl;charset utf-8;index index.html index.htm index.jsp index.do;add_heade…...
Python学习之路-Django基础:HelloDjango
Python学习之路-Django基础:HelloDjango 简介 Django,发音为[dʒŋɡəʊ],是用python语言写的开源web开发框架,并遵循MVC设计。劳伦斯出版集团为了开发以新闻内容为主的网站,而开发出来了这个框架,于2005年7月在BSD…...
完成NAT实验
实验要求: 步骤一:配置vlan vlan b 2 3 interface GigabitEthernet 0/0/2 port link-type access port default vlan 2 interface GigabitEthernet 0/0/3 port link-type access port default vlan 3 interface GigabitEthernet 0/0/1 port link-type…...
uniapp 用web-view嵌套网页地址并传参
小程序登陆后把token和openId 对应传到pc端 pc端有两套一套pc端代码和适应移动端的代码 嵌套的是适应移动端的代码 1.uniapp <template><view class"main"><u-navbar :fixed"true" :autoBack"false" leftClick"goBack&quo…...
时序数据库Tdengine 批量插入避免因为主键ts时间重复导致数据被覆盖掉
目录 在Mybatis中使用 在数据库管理工具中使用 now100a 使用now() #{index}a 其中那这个 #{index}是<foreach>标签里的循环出来的index 在Mybatis中使用 <insert id"batchInsert" parameterType"java.util.List">insert into uri(id…...
【小白教程】幻兽帕鲁服务器一键搭建 | 支持更新 | 自定义配置
幻兽帕鲁刚上线就百万在线人数,官方服务器的又经常不稳定,所以这里给大家带来最快捷的搭建教程,废话不多说直接开始。 步骤一:准备服务器 服务器建议 Linux 系统,资源占用低,而且一键脚本只需要一条命令&am…...
Chatgpt的崛起之路
Chatgpt的崛起之路 背景与发展历程背景发展历程 技术原理第一阶段:训练监督策略模型第二阶段:训练奖励模型第三阶段:采用强化学习来增强模型的能力。 国内使用情况及应用的领域面临的数据安全挑战与建议ChatGPT获取数据产生的问题数据泄露问题…...
java截取视频最后一帧照片作为封面
引言 我们在日常工作中经常会遇到上传视频,而产品还会要求截取视频某一帧作为封面展示,对于这种情况新手还是比较头疼的,那我们直接世界上最简单的实现方案,必须是最简单,多一句啰嗦都不准点赞。 How to do 1.提前…...
ARM Cortex-A 内核的运行模式切换
ARM Cortex-A 内核的运行模式切换 ARM Cortex-A系列内核的处理器支持多种运行模式的切换。 不同的运行模式能满足不同的需求,如响应中断、运行操作系统内核、处理异常等。 目录 1 ARM Cortex-A 内核的处理器什么场景下有切换运行模式的需求 2 ARM Cortex-A 内核的处理…...
分布式因果推断在美团履约平台的探索与实践
美团履约平台技术部在因果推断领域持续的探索和实践中,自研了一系列分布式的工具。本文重点介绍了分布式因果树算法的实现,并系统地阐述如何设计实现一种分布式因果树算法,以及因果效应评估方面qini_curve/qini_score的不足与应对技巧。希望能…...
wordpress date/淘宝关键词怎么选取
单机1.0版包括6个class文件:TankClient.java : 主要执行部分,项目的大管家Tank.java : 实现Tank类,模拟坦克的运动Missile.java : 实现Missile类,模拟子弹的运动Explode.java : 实现Explode类,模拟爆炸的产生Wall.java…...
网页的网站建设/百度搜索引擎怎么弄
借助U盘的用PE安装操作系统时系统提示:无法创建新的系统分区 也无法定位现有系统分区 的解决办法、、、 --------------------------------- 具体原因是安装时加载到安装程序中的u盘变成了主引导盘而引起的。 解决方案一: 1、先格式化一下要装的那个盘&a…...
长沙网络公司网站/北京做网站的公司排行
win10系统很多设置与之前的系统不同,不少用户为了更改设置在绕弯子,近来有用户问到如何设置输入法的问题,那么Win10输入法要在哪里进行设置呢?其实很简单,win10风格大变,需要用心学习使用,毕竟现…...
程序员找工作的网站/关键词首页排名优化价格
pcr实验室污水处理设备厂家介绍中、高等院校、科研院所、食品药品检验、产品质检所、疾控中心、环境监测、农产品质检、检验检疫、粮油检测、动物疾控、血站、畜牧、医疗机构、医院、生物制药、石油化工、p1实验室、p2实验室、p3实验室、prc实验室企业等实验室、化验室废水处理…...
专业云南做网站/宁波网站seo公司
我们在a标签的css样式里加上属性 a{ text-decoration:none; }...
企业网站备案还是不用备案/晚上看b站
链接:https://ac.nowcoder.com/acm/contest/699/F来源:牛客网 题目描述 从前有个小哥哥Bill非常喜欢编程,但是让他更加心动的是班上那位小姐姐,为了取得小姐姐的欢心,Bill每天刷acm题,只想着找一个机会大发…...