SpringBoot:SpringBoot中调用失败如何重试

一、引言

  在实际的应用中,我们经常需要调用第三方API来获取数据或执行某些操作。然而,由于网络不稳定、第三方服务异常等原因,API调用可能会失败。为了提高系统的稳定性和可靠性,我们通常会考虑实现重试机制。

  Spring Retry为Spring应用程序提供了方法级别的重试机制,帮助开发者处理由于网络不稳定、服务不可用、数据库临时性问题、外部依赖故障等原因导致的瞬时性故障。通过配置重试策略,可以确保应用程序在特定情况下能够自动进行重试,从而提高系统的健壮性和可用性。

  本文将深入探讨如何在Spring Boot项目中优雅地使用Spring Retry重试调用第三方API,并结合代码示例,展示具体实现方式。

二、重试机制的必要性

  提高系统的可用性:在网络通信、数据库操作、远程服务调用等场景中,由于网络抖动、服务暂时不可用或超时等原因,单次操作可能会失败。引入重试机制可以在这些情况下自动重新尝试操作,从而提高系统的可用性和容错能力。

  优化用户体验:对于用户来说,遇到操作失败时,他们期望系统能够自动处理并恢复,而不是需要他们手动重新尝试。重试机制可以在用户无感知的情况下自动进行,从而提供更好的用户体验。

  减少人工干预:在没有重试机制的情况下,一旦操作失败,可能需要人工进行干预和修复。这不仅增加了运维成本,而且可能导致响应延迟。重试机制可以自动处理大多数可恢复的失败情况,减少人工干预的需要。

  降低故障率:有些故障是暂时的,例如网络短暂中断或数据库连接超时。在这种情况下,立即重试操作很可能会成功。重试机制可以在这些情况下自动重试,从而降低故障率。

三、使用场景

  远程调用和网络通信:由于网络不稳定或服务不可用,可能会出现连接问题,Spring Retry可以帮助处理这类问题。

  数据库交互:执行SQL查询或更新操作时,数据库服务器可能会出现临时性的问题,如死锁或连接丢失,Spring Retry可以提供重试机制。

  外部依赖:如果应用程序依赖于外部服务、硬件设备或其他不可控因素,而这些依赖可能会偶尔出现故障或不可用状态,Spring Retry可以确保应用程序能够自动进行重试。

  并发控制:在多线程环境中,可能会出现竞争条件或并发问题,导致某些操作失败,Spring Retry可以帮助处理这类并发问题。

  复杂的业务逻辑:某些业务逻辑可能需要多次尝试才能成功,Spring Retry提供了重试机制来支持这类业务逻辑。

四、Spring Retry在项目中应用

1. 添加依赖

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId>
</dependency><dependency><groupId>org.springframework.retry</groupId><artifactId>spring-retry</artifactId>
</dependency>

2. 在需要重试的方法上添加@Retryable注解,并指定可重试的异常类型、最大重试次数等参数

@Retryable(value = {SomeException.class}, maxAttempts = 2, backoff = @Backoff(delay = 2000))
@Overridepublic void testRetry() {// 业务场景System.out.println("执行业务了...");// 模拟执行可能会失败的操作 ...throw new SomeException("run failed"); // 示例:抛出异常以触发重试}// 定义自定义异常类(如果需要)public static class SomeException extends RuntimeException {public SomeException(String message) {super(message);}}
@RestController
public class RetryController {@Autowiredprivate RetryService retryService;@RequestMapping("/retry/test")public Object retryTest() {retryService.testRetry();return "success";}
}

3. 运行结果

在这里插入图片描述
4. 注解说明

@Retryable 注解

  value:可重试的异常类型。含义同include。默认为空(如果excludes也为空,则重试所有异常)

  include:可重试的异常类型。默认为空(如果excludes也为空,则重试所有异常)

  exclude:无需重试的异常类型。默认为空(如果includes也为空,则重试所有异常)

  maxAttempts:最大重试次数(包括第一次失败),默认为3次

  backoff:重试等待策略,下面会在@Backoff中介绍

  recover:表示重试次数到达最大重试次数后的回调方法

@Backoff 注解

value
  默认为1000L,重试之间的基础延迟时间(以毫秒为单位)。当没有设置 delay时,value将作为首次重试的延迟时间。之后,如果multiplier不为0,则后续的延迟时间会根据 value和multiplier来计算

delay
  默认为0,首次重试之前的延迟时间(以毫秒为单位)。如果设置为0,则不等待直接进行首次重试。如果同时设置了value和delay,则delay优先。

maxDelay
  默认为0,重试之间延迟时间的上限(以毫秒为单位)。如果计算出的延迟时间超过了这个值,则实际的延迟时间将被限制为maxDelay。这个参数用于防止延迟时间无限增长,从而避免过长的等待时间。

multipler
  默认为0.0。用于计算递增等待时间的乘数。例如,如果设置为1.5,则每次重试的等待时间将是前一次的1.5倍。
  示例:backoff = @Backoff(delay = 200, multiplier = 1.5),在这个例子中,首次重试会等待200毫秒,第二次会等待300毫秒(200毫秒1.5),第三次会等待450毫秒(300毫秒1.5),以此类推。

delayExpression
  评估标准退避期的表达式。在指数情况下用作初始值*,在均匀情况下用作最小值。覆盖 delay。

maxDelayExpression
  该表达式计算重试之间的最大等待时间(以毫秒为单位)。 如果小于delay,那么将应用30000L为默认值。覆盖maxDelay。

multiplierExpression
  评估为用作乘数的值,以生成退避的下一个延迟。覆盖multiplier。 返回一个乘数表达式,用于计算下一个退避延迟

random
  默认为false,在指数情况下multiplier > 0将此值设置为true可以使后退延迟随机化,从而使最大延迟乘以前一延迟,并且两个值之间的分布是均匀的。

五、重试还是失败,如何解决?

除了重试,我们可能还希望在多次重试失败后执行降级操作,以避免一直等待不确定的恢复时间。

@Recover注解

可以使用@Recover注解来指定一个方法来处理所有由@Retryable注解标注的方法抛出的异常。当重试次数耗尽后,会调用这个方法

 @Recoverpublic void recover(SomeException e) {// 处理重试失败后的逻辑System.out.println("recover from " + e.getMessage());}

注意

由于Spring Retry用到了aspect增强,所有会有aspect的坑,就是方法内部调用,会使aspect增强失效,那么retry当然也会失效

public void A(){B();
}//这里B不会执行
@Retryable(value = {SomeException.class}, maxAttempts = 2, backoff = @Backoff(delay = 2000))
public void B(){throw new SomeException("run failed");
}

  @Recover 注解来开启重试失败后调用的方法(注意,需跟重处理方法在同一个类中),此注解注释的方法参数一定要是 @Retryable 抛出的异常,否则无法识别。

六、重试当中的策略

1. @Backoff 的参数会影响我们使用哪种退避策略

  FixedBackOffPolicy:默认退避策略,每1秒重试1次

  ExponentialBackOffPolicy:指数退避策略,当设置multiplier时使用,每次重试时间间隔为 当前延迟时间 * multiplier。

  例如:默认初始1秒,系数是2,那么下次延迟2秒,再下次就是延迟4秒,如此类推,最大30秒。

  ExponentialRandomBackOffPolicy:指数随机退避策略。在指数退避策略的基础上增加了随机性。

  UniformRandomBackOffPolicy:均匀随机策略,设置maxDely但没有设置multiplier时使用,重试间隔会在maxDelay和delay间随机

2. 重试策略

  SimpleRetryPolicy:默认最多重试 3 次

  TimeoutRetryPolicy:默认在 1 秒内失败都会重试

  ExpressionRetryPolicy:符合表达式就会重试

  CircuitBreakerRetryPolicy:增加了熔断的机制,如果不在熔断状态,则允许重试

  CompositeRetryPolicy:可以组合多个重试策略

  NeverRetryPolicy:从不重试(也是一种重试策略哈)

  AlwaysRetryPolicy:总是重试

3. RetryTemplate提供了更为灵活的重试控制

  了解了重试策略,当我们使用RetryTemplate模式的时候,可以更加灵活的重试控制

@Configuration
@EnableRetry
public class RetryConfig {@Beanpublic RetryTemplate retryTemplate() {SimpleRetryPolicy retryPolicy = new SimpleRetryPolicy();retryPolicy.setMaxAttempts(3);FixedBackOffPolicy backOffPolicy = new FixedBackOffPolicy();backOffPolicy.setBackOffPeriod(1000);RetryTemplate retryTemplate = new RetryTemplate();retryTemplate.setRetryPolicy(retryPolicy);retryTemplate.setBackOffPolicy(backOffPolicy);return retryTemplate;}
}
 public Object executeWithRetry() throws Exception{return retryTemplate.execute(new RetryCallback<Object, Exception>() {@Overridepublic Object doWithRetry(RetryContext context) throws Exception {// 这里放置可能会失败的操作// 例如,调用远程服务或执行数据库操作// ...// 模拟失败if (true) {throw new RuntimeException("Operation failed");}// 如果成功,则返回结果return "success";}});}

  在Spring Boot项目中,通过集成Spring Retry模块,我们可以优雅地实现对第三方API调用的重试机制。通过@Retryable注解,我们能够很方便地在方法级别上添加重试策略。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/36917.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于 Triton Inference Server 的算法工程

如何将算法部署在 Triton Inference Server 基于Python后端的基础模型 (基础示例) 编写配置 config.pbtxt 以目标检测为例 定义输入输出: 参数名, 参数类型, 参数维度 name: "object_detect" # 模型名称, 与当前目录文件名一致 backend: "python" # 推…

基于uni-app与图鸟UI的移动应用模板构建研究

摘要 随着移动互联网技术的迅猛发展&#xff0c;移动端应用已成为企业展示形象、提供服务的重要窗口。本文基于uni-app框架和图鸟UI设计&#xff0c;深入探讨了如何高效构建覆盖多个领域的移动端应用模板。通过对商城、办公、投票、生活服务等多种类型模板的详细介绍&#xff…

Educational Codeforces Round 112 (Rated for Div. 2) C. Coin Rows(构造 + 贪心 + 前缀和)

可以知道爱丽丝的路径是拐两次弯的折线 那么我们知道鲍勃能够选择的位置只有两段黄线中的一段 所以可以求出来第二行的后缀和&#xff0c;然后求出来第一行的前缀行&#xff0c;这样鲍勃在爱丽丝分割之后的情况下就会选择这两者中最大的一段&#xff0c;然而爱丽丝也会阻碍鲍…

Open AI Stream Completion Set Variable Inside Function PHP With Openai-php SDK

题意&#xff1a;使用 OpenAI 的 PHP SDK&#xff08;例如 openai-php&#xff09;来在函数内部设置和完成一个流&#xff08;stream&#xff09;相关的变量 问题背景&#xff1a; How to set variable inside this openai-php sdk function in stream completion ? I am usi…

使用System.currentTimeMillis获取当前时间

使用System.currentTimeMillis获取当前时间 大家好&#xff0c;我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编&#xff0c;也是冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01;今天我们来探讨Java中如何使用System.currentTimeMillis()方法来获取…

保护隐私,释放智能:使用LangChain和Presidio构建安全的AI问答系统

保护隐私&#xff0c;释放智能&#xff1a;使用LangChain和Presidio构建安全的AI问答系统 在人工智能&#xff08;AI&#xff09;飞速发展的今天&#xff0c;AI问答系统已经成为企业与客户互动的重要工具。然而&#xff0c;随之而来的个人数据隐私问题也日益凸显。如何在不泄露…

华为HCIA综合实验(结合前几期所有内容)

第一章 实验目的 &#xff08;1&#xff09;配置Telnet&#xff0c;要求所有网络设备支持远程管理&#xff0c;密码为admin&#xff08;2&#xff09;配置Trunk&#xff0c;交换机之间的链路均为Trunk模式&#xff08;3&#xff09;配置VLAN&#xff0c;在SW2和SW3上创建相关…

android-aidl5

aidl类是实现Manager和Service通信的桥梁。 例如在修改Android Wifi功能的时候看到WifiManager管理WifiService&#xff1b; AIDL是一种android内部进程通信接口的描述语言,通过它我们可以定义进程间的通信接口。 比如onclick&#xff08;&#xff09;&#xff0c;用oneway修…

Qt6.6编译Qt二维图形编辑器QVGE源码

QVGE是一个开源的多平台QtC编写的图形编辑器&#xff0c;可以用来画网络节点图&#xff0c;或者其他作用。 QVGE可以轻松创建和参数设定的小型到中型图形(1000节点/边缘)&#xff0c;共同的视觉特性的节点和边缘&#xff1a;形状、尺寸、颜色、标签等。定义(用户定义)属性的图表…

深度学习Week18——学习残差网络和ResNet-50算法

文章目录 深度学习Week18——学习残差网络和ResNet-50算法 一、前言 二、我的环境 三、前期工作 1、配置环境 2、导入数据 2.1 加载数据 2.2 配置数据集 2.3 数据可视化 2.4 再次检查数据 四、构建ResNet-50网络模型 五、编译模型 六、训练模型 七、模型评估 八、指定图片预测 …

leetCode.92. 反转链表 II

leetCode.92. 反转链表 II 题目思路 代码 /*** Definition for singly-linked list.* struct ListNode {* int val;* ListNode *next;* ListNode() : val(0), next(nullptr) {}* ListNode(int x) : val(x), next(nullptr) {}* ListNode(int x, ListNode …

【Python数据分析与可视化】:使用【Matplotlib】实现销售数据的全面分析 ——【Matplotlib】数模学习

目录 安装Matplotlib 1.打开PyCharm&#xff1a; 2.打开终端&#xff1a; 3.安装Matplotlib&#xff1a; 4.确认安装&#xff1a; 导入Matplotlib 创建简单的折线图 代码解析&#xff1a; 创建子图 代码解析&#xff1a; 创建柱状图 代码解析&#xff1a; 创建散点…

Vite响应Ajax请求

Vite响应Ajax请求 陈拓 2024/06/20-2024/06/24 1. 概述 http-server、live-server 等常用于本地测试和开发的http服务器不能很好的支持 ES 模块&#xff0c;在测试ES 模块时浏览器控制台经常显示错误&#xff1a; Failed to load module script: Expected a JavaScript modu…

esp8266 GPIO

功能综述 ESP8266 的 16 个通⽤ IO 的管脚位置和名称如下表所示。 管脚功能选择 功能选择寄存器 PERIPHS_IO_MUX_MTDI_U&#xff08;不同的 GPIO&#xff0c;该寄存器不同&#xff09; PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDI_U,FUNC_GPIO12);PERIPHS_IO_MUX_为前缀。后面的…

基于SpringBoot+Vue的大药房管理系统(带1w+文档)

基于SpringBootVue的大药房管理系统(带1w文档) 本系统主要包括管理员和用户两个用户角色&#xff1b;主要包括&#xff1a;首页&#xff0c;个人中心&#xff0c;用户管理&#xff0c;保健品分类管理&#xff0c;药品分类管理&#xff0c;药品信息管理&#xff0c;疫情常识管理…

Flink入门实战详解

Flink入门实战 Flink项目构建 1)基于MavenIdea创建项目&#xff1a; 使用maven进行项目构建&#xff0c;如图1所示。 图-34 构建maven项目 输入项目中的maven的坐标和存储坐标&#xff0c;如图2所示。 图2 maven坐标和存储位置 2)Maven依赖&#xff1a; <properties>…

开源API网关-ApacheShenYu首次按照启动遇到的问题

一.背景 公司有API网关产品需求&#xff0c;希望有图形化的后台管理功能。看到了ApacheShenYu&#xff0c;作为Apache的顶级项目&#xff0c;直接认可了。首先&#xff0c;感谢各位大神的付出&#xff0c;初步看这个项目是国内大厂中的大神创立的&#xff0c;在此表示膜拜&…

Zookeeper集群安装部署

简介 ZooKeeper是一个分布式的&#xff0c;开放源码的分布式应用程序协调服务&#xff0c;是Hadoop和Hbase的重要组件。它是一个为分布式应用提供一致性服务的软件&#xff0c;提供的功能包括&#xff1a;配置维护、域名服务、分布式同步、组服务等。 除了为Hadoop和HBase提供…

区块链开发基础知识及应用

区块链开发基础知识及应用 大家好&#xff0c;我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编&#xff0c;也是冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01;在本文中&#xff0c;我们将深入探讨区块链技术的基础知识及其在应用开发中的实际应用…

阿里云服务器入门使用教程——购买及操作系统选择并进行远程连接

文章目录 一、首先选择一个你自己要买的云服务器类型二、能选的就一个地域和一个操作系统&#xff0c;其他都是固定的三、创建完实例并使用finalshell连接的效果(要在完成后续步骤后才能连接)四、购买之后进入阿里云控制台&#xff0c;开通资源中心五、然后就可以看到已经帮你创…