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

接口请求重试八种方法

请求三方接口需要加入重试机制

在这里插入图片描述

一、循环重试

在请求接口的代码块中加入循环,如果请求失败则继续请求,直到请求成功或达到最大重试次数。

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();}}}
}

【注意】

  • 合理设置重试次数和重试间隔时间,避免频繁地发送请求,同时也不要设置过大的重试次数,以免影响系统的性能和响应时间。
  • 考虑接口幂等性:如果请求是写操作,而且下游的服务不保证请求的幂等性,那么在重试时需要谨慎处理,可以通过查询等幂等的方式进行重试
  • 在重试过程中,需要考虑并发的问题。如果多个线程同时进行重试,可能会导致请求重复发送或请求顺序混乱等问题。可以使用锁或者分布式锁来解决并发问题。
  • 在处理异常时,需要根据具体的异常类型来进行处理。有些异常是可以通过重试来解决的,例如网络超时、连接异常等;而有些异常则需要进行特殊的处理,例如数据库异常、文件读写异常等。
  • 在使用重试机制时,需要注意不要陷入死循环。如果请求一直失败,重试次数一直增加,可能会导致系统崩溃或者资源耗尽等问题。

相关文章:

接口请求重试八种方法

请求三方接口需要加入重试机制 一、循环重试 在请求接口的代码块中加入循环&#xff0c;如果请求失败则继续请求&#xff0c;直到请求成功或达到最大重试次数。 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移动设备优化的视觉网络(附对比试验效果图)

前言 大家好&#xff0c;我是Snu77&#xff0c;这里是RT-DETR有效涨点专栏。 本专栏的内容为根据ultralytics版本的RT-DETR进行改进&#xff0c;内容持续更新&#xff0c;每周更新文章数量3-10篇。 专栏以ResNet18、ResNet50为基础修改版本&#xff0c;同时修改内容也支持Re…...

《动手学深度学习(PyTorch版)》笔记4.4

注&#xff1a;书中对代码的讲解并不详细&#xff0c;本文对很多细节做了详细注释。另外&#xff0c;书上的源代码是在Jupyter Notebook上运行的&#xff0c;较为分散&#xff0c;本文将代码集中起来&#xff0c;并加以完善&#xff0c;全部用vscode在python 3.9.18下测试通过。…...

Linux/Academy

Enumeration nmap 首先扫描目标端口对外开放情况 nmap -p- 10.10.10.215 -T4 发现对外开放了22,80,33060三个端口&#xff0c;端口详细信息如下 结果显示80端口运行着http&#xff0c;且给出了域名academy.htb&#xff0c;现将ip与域名写到/et/hosts中&#xff0c;然后从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做的刮刮乐解决蒙层能自定义图片

最近给湖南中烟做元春活动&#xff0c;一个月要开发4个小活动&#xff0c;这个是其中一个难度一般&#xff0c;最难的是一个类似鲤鱼跃龙门的小游戏&#xff0c;哎&#xff0c;真实为难我这个“拍黄片”的。下面是主要代码。 <canvas :style"{width:widthpx,height:hei…...

利用SPI,结合数据库连接池durid进行数据服务架构灵活设计

接着上一篇文章业务开始围绕原始凭证展开,而展开的基础无疑是围绕着科目展开的。首先我们业务层面以财政部的小企业会计准则的一级科目引入软件中。下面我们来考虑如何将科目切入软件更加灵活,方便业务扩展、维护与升级。 SPI是首先想到的数据服务方式 为什么会想到它呢?首…...

自动驾驶的决策层逻辑

作者 / 阿宝 编辑 / 阿宝 出品 / 阿宝1990 自动驾驶意味着决策责任方的转移 我国2020至2025年将会是向高级自动驾驶跨越的关键5年。自动驾驶等级提高意味着对驾驶员参与度的需求降低&#xff0c;以L3级别为界&#xff0c;低级别自动驾驶环境监测主体和决策责任方仍保留于驾驶…...

排序算法——希尔排序算法详解

希尔排序算法详解 一. 引言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 数据库,自动化备份

备份容器数据库命令&#xff1a; docker exec 容器名称或ID mysqldump -u用户名 -p密码 数据库名称 > 导出文件.sql请替换以下占位符&#xff1a; 容器名称或ID&#xff1a;您的 MySQL 容器的名称或ID。用户名&#xff1a;您的 MySQL 用户名。密码&#xff1a;您的 MySQL …...

【Java万花筒】数字信号魔法:Java库的魅力解析

从傅立叶到矩阵&#xff1a;数字信号Java库全景剖析 前言 随着数字信号处理在科学、工程和数据分析领域的广泛应用&#xff0c;开发者对高效、灵活的工具的需求日益增长。本文旨在探讨几个与数字信号处理相关的Java库&#xff0c;通过介绍其特点、用途以及与已有库的关系&…...

面试高频知识点:2线程 2.1 线程池 2.1.2 JDK中常见的线程池实现有哪些?

1. Executors类 Executors类是线程池的工厂类&#xff0c;提供了一些静态方法用于创建不同类型的线程池。然而&#xff0c;它的使用并不推荐在生产环境中&#xff0c;因为它存在一些缺点&#xff0c;比如默认使用无界的任务队列&#xff0c;可能导致内存溢出。 2. ThreadPool…...

Azure Private endpoint DNS 记录是如何解析的

Private endpoint 从本质上来说是Azure 服务在Azure 虚拟网络中安插的一张带私有地址的网卡。 举例来说如果Storage account在没有绑定private endpoint之前&#xff0c;查询Storage account的DNS记录会是如下情况&#xff1a; Seq Name …...

windows 安装sql server 华为云文档

先安装net3.5,剩下安装sqlserver步骤看下面文档 安装SQL Server_弹性云服务器 ECS_最佳实践_搭建Microsoft SharePoint Server 2016_华为云 (huaweicloud.com)...

相同主题文章竟同时发表在同一个2区期刊 | 孟德尔随机化周报(1.10-1.16)

欢迎报名2024年郑老师团队课程课程&#xff01; 郑老师科研统计培训&#xff0c;包括临床数据、公共数据分析课程&#xff0c;欢迎报名 孟德尔随机化,Mendilian Randomization&#xff0c;简写为MR&#xff0c;是一种在流行病学领域应用广泛的一种实验设计方法&#xff0c;利用…...

网络安全的使命:守护数字世界的稳定和信任

在数字化时代&#xff0c;网络安全的角色不仅仅是技术系统的守护者&#xff0c;更是数字社会的信任保卫者。网络安全的使命是保护、维护和巩固数字世界的稳定性、可靠性以及人们对互联网的信任。本文将深入探讨网络安全是如何履行这一使命的。 第一部分&#xff1a;信息资产的…...

【七、centos要停止维护了,我选择Almalinux】

搜索镜像 https://developer.aliyun.com/mirror/?serviceTypemirror&tag%E7%B3%BB%E7%BB%9F&keywordalmalinux dvd是有界面操作的&#xff0c;minimal是最小化只有命里行 镜像下载地址 安装和centos基本一样的&#xff0c;操作命令也是一样的&#xff0c;有需要我…...

架构师之路(十六)计算机网络(传输层)

前置知识&#xff08;了解&#xff09;&#xff1a;计算机基础。 作为架构师&#xff0c;我们所设计的系统很少为单机系统&#xff0c;因此有必要了解计算机和计算机之间是怎么联系的。局域网的集群和混合云的网络有啥区别。系统交互的时候网络会存在什么瓶颈。 既然网络层已经…...

python 调用SumatraPDF 静默打印PDF

SumatraPDF 文档 https://www.sumatrapdfreader.org/docs/Command-line-arguments ⽆边框 noscale/缩⼩到合适⼤⼩&#xff08;默认&#xff09;shrink/合适⼤⼩ fit/compat 兼容 # 分为 Portrait (纵向)和 Landscape (横向)两类 https://github.com/sumatrapdfreader/sumatrap…...

在软件开发中正确使用MySQL日期时间类型的深度解析

在日常软件开发场景中&#xff0c;时间信息的存储是底层且核心的需求。从金融交易的精确记账时间、用户操作的行为日志&#xff0c;到供应链系统的物流节点时间戳&#xff0c;时间数据的准确性直接决定业务逻辑的可靠性。MySQL作为主流关系型数据库&#xff0c;其日期时间类型的…...

Linux链表操作全解析

Linux C语言链表深度解析与实战技巧 一、链表基础概念与内核链表优势1.1 为什么使用链表&#xff1f;1.2 Linux 内核链表与用户态链表的区别 二、内核链表结构与宏解析常用宏/函数 三、内核链表的优点四、用户态链表示例五、双向循环链表在内核中的实现优势5.1 插入效率5.2 安全…...

页面渲染流程与性能优化

页面渲染流程与性能优化详解&#xff08;完整版&#xff09; 一、现代浏览器渲染流程&#xff08;详细说明&#xff09; 1. 构建DOM树 浏览器接收到HTML文档后&#xff0c;会逐步解析并构建DOM&#xff08;Document Object Model&#xff09;树。具体过程如下&#xff1a; (…...

生成 Git SSH 证书

&#x1f511; 1. ​​生成 SSH 密钥对​​ 在终端&#xff08;Windows 使用 Git Bash&#xff0c;Mac/Linux 使用 Terminal&#xff09;执行命令&#xff1a; ssh-keygen -t rsa -b 4096 -C "your_emailexample.com" ​​参数说明​​&#xff1a; -t rsa&#x…...

leetcodeSQL解题:3564. 季节性销售分析

leetcodeSQL解题&#xff1a;3564. 季节性销售分析 题目&#xff1a; 表&#xff1a;sales ---------------------- | Column Name | Type | ---------------------- | sale_id | int | | product_id | int | | sale_date | date | | quantity | int | | price | decimal | -…...

select、poll、epoll 与 Reactor 模式

在高并发网络编程领域&#xff0c;高效处理大量连接和 I/O 事件是系统性能的关键。select、poll、epoll 作为 I/O 多路复用技术的代表&#xff0c;以及基于它们实现的 Reactor 模式&#xff0c;为开发者提供了强大的工具。本文将深入探讨这些技术的底层原理、优缺点。​ 一、I…...

Maven 概述、安装、配置、仓库、私服详解

目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...

python执行测试用例,allure报乱码且未成功生成报告

allure执行测试用例时显示乱码&#xff1a;‘allure’ &#xfffd;&#xfffd;&#xfffd;&#xfffd;&#xfffd;ڲ&#xfffd;&#xfffd;&#xfffd;&#xfffd;ⲿ&#xfffd;&#xfffd;&#xfffd;Ҳ&#xfffd;&#xfffd;&#xfffd;ǿ&#xfffd;&am…...

NXP S32K146 T-Box 携手 SD NAND(贴片式TF卡):驱动汽车智能革新的黄金组合

在汽车智能化的汹涌浪潮中&#xff0c;车辆不再仅仅是传统的交通工具&#xff0c;而是逐步演变为高度智能的移动终端。这一转变的核心支撑&#xff0c;来自于车内关键技术的深度融合与协同创新。车载远程信息处理盒&#xff08;T-Box&#xff09;方案&#xff1a;NXP S32K146 与…...

Chrome 浏览器前端与客户端双向通信实战

Chrome 前端&#xff08;即页面 JS / Web UI&#xff09;与客户端&#xff08;C 后端&#xff09;的交互机制&#xff0c;是 Chromium 架构中非常核心的一环。下面我将按常见场景&#xff0c;从通道、流程、技术栈几个角度做一套完整的分析&#xff0c;特别适合你这种在分析和改…...