当前位置:首页 > 科技  > 软件

聊聊接口重试机制的几种解决方案

来源: 责编: 时间:2023-11-06 08:53:25 356观看
导读1.前言接口请求重试机制是保证系统稳定性和容错能力的重要手段之一。当接口请求发生失败或暂时性错误时,通过重试机制可以提高请求的成功率。本文将详细介绍接口请求重试机制的几种常见方法。2.几种方法2.1循环重试它

1.前言

接口请求重试机制是保证系统稳定性和容错能力的重要手段之一。当接口请求发生失败或暂时性错误时,通过重试机制可以提高请求的成功率。本文将详细介绍接口请求重试机制的几种常见方法。Z2k28资讯网——每日最新资讯28at.com

2.几种方法

图片Z2k28资讯网——每日最新资讯28at.com

2.1循环重试

它的基本思路是:Z2k28资讯网——每日最新资讯28at.com

  1. 定义重试次数,如最大重试5次
  2. 发送请求,如果失败则进入重试逻辑
  3. 在循环内部,记录当前已重试次数,如当前已重试2次
  4. 判断当前重试次数是否达到最大次数,如果达到则终止循环,否则进行重试
  5. 在循环内部,可以添加定时重试间隔,也可以使用指数退避算法
  6. 发送重试请求,重复判断是否成功,直到成功、达到最大次数或其他终止条件

Z2k28资讯网——每日最新资讯28at.com

示例Z2k28资讯网——每日最新资讯28at.com

public class Retry {private static final int MAX_RETRIES = 5;public static Response request() throws Exception {  int retries = 0;  while (true) {    try {      // 发送请求,返回响应      Response response = HttpClient.sendRequest();      // 请求成功则返回响应      if (response.isSuccess()) {        return response;      }    } catch (Exception e) {      // 请求失败进行重试    }    // 判断是否超过最大重试次数    if (++retries >= MAX_RETRIES) {      throw new Exception("Exceeded max retries");    }    // 增加间隔后重试    int interval = (int) (Math.random() * 1000);    Thread.sleep(interval);  }}public static void main(String[] args) throws Exception {  Response response = request();  // ...}}

Z2k28资讯网——每日最新资讯28at.com

2.2 使用Spring Retry库

使用 Spring Retry 库可以很方便地实现接口请求的重试机制。Z2k28资讯网——每日最新资讯28at.com

Z2k28资讯网——每日最新资讯28at.com

2.2.1 添加 Maven 依赖
<dependency>  <groupId>org.springframework.retry</groupId>  <artifactId>spring-retry</artifactId>  <version>1.3.1</version></dependency>

Z2k28资讯网——每日最新资讯28at.com

2.2.2 添加 @EnableRetry 注解启用重试功能

Z2k28资讯网——每日最新资讯28at.com

2.2.3 在需要重试的方法上添加 @Retryable 注解
@Retryable(value = Exception.class, maxAttempts = 3, backoff = @Backoff(delay = 5000))public User getUser(String id) {// 远程调用接口}

@Retryable 定义了重试规则:- value - 重试的异常类型- maxAttempts - 最大重试次数- backoff - 重试等待策略Z2k28资讯网——每日最新资讯28at.com

Z2k28资讯网——每日最新资讯28at.com

2.2.4. 还可以自定义 RetryTemplate 进行更复杂的重试控制
RetryTemplate template = new RetryTemplate();template.execute(context -> {// 可在此处自定义重试逻辑 return remoteClient.invoke();});

Spring Retry 为接口请求重试提供了完善和易用的解决方案,可以灵活控制各种重试参数,适用于复杂系统的容错要求。Z2k28资讯网——每日最新资讯28at.com

Z2k28资讯网——每日最新资讯28at.com

2.3 并发框架异步重试

使用并发框架的异步请求方式可以较简单地实现接口请求的重试机制。以CompletableFuture为例:Z2k28资讯网——每日最新资讯28at.com

Z2k28资讯网——每日最新资讯28at.com

2.3.1 发送请求使用CompletableFuture封装:Z2k28资讯网——每日最新资讯28at.com

CompletableFuture<Response> future = CompletableFuture.supplyAsync(() -> {return service.call();});

Z2k28资讯网——每日最新资讯28at.com

2.3.2 当请求失败时,使用retryAsync自动完成重试:Z2k28资讯网——每日最新资讯28at.com

future = future.exceptionally(e -> {return service.retryAsync();});

Z2k28资讯网——每日最新资讯28at.com

2.3.3 可以链式调用,自定义重试逻辑:Z2k28资讯网——每日最新资讯28at.com

future.exceptionally(e -> {    // 处理异常}).thenApplyAsync(resp -> {    // 处理响应}).retryAsync(retryCount, delay);

主要优点是:Z2k28资讯网——每日最新资讯28at.com

  • 线程安全的异步请求
  • 自动重试失败任务
  • 简洁的链式编程方式
  • 避免阻塞主线程

Z2k28资讯网——每日最新资讯28at.com

使用并发框架可以便捷地实现异步重试机制,提高系统容错性。其他框架如RxJava也有类似的重试机制。Z2k28资讯网——每日最新资讯28at.com

Z2k28资讯网——每日最新资讯28at.com

2.4 消息队列重试

使用消息队列可以实现接口请求的异步重试机制。Z2k28资讯网——每日最新资讯28at.com

基本思路是:Z2k28资讯网——每日最新资讯28at.com

  • 接口请求发送失败后,将请求信息封装为消息,发送到请求重试的队列中。
  • 消息消费者从队列中获取失败的请求,根据策略进行重试。
  • 重复重试直到成功、重试次数用尽或其他终止条件。
  • 成功后将消息移除队列,失败则保留消息供再次重试。

主要步骤:Z2k28资讯网——每日最新资讯28at.com

  • 创建请求重试队列,如“request.retry.queue”
  • 接口请求失败后,生成重试消息,发送到队列
  • 消费者启动线程从队列中取消息重试
  • 根据重试策略进行定时重试或最大重试数
  • 成功则确认消息,失败则重新入队

使用消息队列进行重试有利于:Z2k28资讯网——每日最新资讯28at.com

  • 异步重试,不阻塞主线程
  • 可靠地完成重试任务
  • 灵活控制重试策略

Z2k28资讯网——每日最新资讯28at.com

示例Z2k28资讯网——每日最新资讯28at.com

// 1. 创建队列Queue retryQueue = new Queue("request.retry.queue");// 2. 请求失败,发送重试消息  public void request() {try {  // 调用接口  httpClient.post(url, payload);} catch (Exception e) {  // 发送重试消息  Message msg = new Message(url, payload, maxRetries);  retryQueue.send(msg);}}// 3. 消费者线程进行重试class RetryConsumer implements Runnable {public void run() {  while (true) {    Message msg = retryQueue.take();         for (int i = 0; i < msg.getMaxRetries(); i++) {      try {        // 重试请求        httpClient.post(msg.getUrl(), msg.getPayload());        // 请求成功,结束循环        break;      } catch (Exception e) {        // 等待后继续重试      }      }         // 重试完成后,确认消息    retryQueue.confirm(msg);  }}}

这就是使用消息队列实现接口重试的基本流程,可以根据需求扩展重试策略、异常处理等逻辑。Z2k28资讯网——每日最新资讯28at.com

Z2k28资讯网——每日最新资讯28at.com

2.5 自定义重试工具类

使用自定义的重试工具类来实现接口请求的重试机制,提高代码的复用性和可维护性。Z2k28资讯网——每日最新资讯28at.com

Z2k28资讯网——每日最新资讯28at.com

重试工具类的实现思路:Z2k28资讯网——每日最新资讯28at.com

  • 提供重试方法,参数包括请求函数、重试策略等
  • 在重试方法内部执行循环请求
  • 每次请求失败时,根据策略等待一段时间
  • 记录当前重试次数,与最大次数比较
  • 请求成功或者达到最大重试次数则结束循环

Z2k28资讯网——每日最新资讯28at.com

示例:Z2k28资讯网——每日最新资讯28at.com

public class RetryUtil {public static <T> T retry(RetryCallable<T> callable, RetryPolicy policy) {  int retries = 0;  while(true) {    try {      return callable.call();      } catch(Exception e) {      if (retries >= policy.maxRetries) {        throw e;      }      // 等待      policy.delay();      // 重试次数加1      retries++;    }  }}}// 执行请求的函数接口interface RetryCallable<T> {T call();}// 重试策略class RetryPolicy {int maxRetries;int delay;}// 使用示例RetryUtil.retry(() -> {// 接口请求return httpClient.get(url);}, policy);

这样可以提高重试相关逻辑的复用性,避免写重复代码。Z2k28资讯网——每日最新资讯28at.com

Z2k28资讯网——每日最新资讯28at.com

2.6 使用递归结构

使用递归结构也可以实现接口请求的重试机制。Z2k28资讯网——每日最新资讯28at.com

Z2k28资讯网——每日最新资讯28at.com

基本思路是设计一个递归函数,在函数内部发送请求,如果失败则继续递归调用自身再次重试。Z2k28资讯网——每日最新资讯28at.com

示例:Z2k28资讯网——每日最新资讯28at.com

public class RetryRequest {private static final int MAX_RETRIES = 3; public static Response request(int retries) {     try {    // 发送请求    Response response = HttpClient.get("http://example.com");    return response;       } catch (Exception e) {         // 处理异常         // 判断是否需要重试    if (retries < MAX_RETRIES) {      // 增加重试次数      retries++;      // 延迟1秒钟      Thread.sleep(1000);      // 递归调用自身进行重试      return request(retries);    }         // 重试失败    throw new RuntimeException("Request failed after " + MAX_RETRIES + " retries!");       }} public static void main(String[] args) {    Response response = request(0);  // 处理响应}}

Z2k28资讯网——每日最新资讯28at.com

主要逻辑是通过递归不断调用自身来实现重试。优点是逻辑较简单清晰,缺点是递归层次过深时可能会导致堆栈溢出。需要合理设置最大递归深度,也可以通过循环改写递归来避免深层递归。Z2k28资讯网——每日最新资讯28at.com

Z2k28资讯网——每日最新资讯28at.com

2.7 使用Resilience4j

Resilience4j是一个很好的Java重试库,可以用它来实现接口请求的重试机制。Z2k28资讯网——每日最新资讯28at.com

Z2k28资讯网——每日最新资讯28at.com

主要步骤:Z2k28资讯网——每日最新资讯28at.com

2.7.1添加Resilience4j依赖Z2k28资讯网——每日最新资讯28at.com

<dependency><groupId>io.github.resilience4j</groupId><artifactId>resilience4j-retry</artifactId></dependency>

2.7.2 定义重试逻辑Z2k28资讯网——每日最新资讯28at.com

RetryConfig config = RetryConfig.custom().maxAttempts(3).waitDuration(Duration.ofMillis(500)).build();Retry retry = Retry.of("backend", config);

2.7.3 使用重试逻辑调用接口Z2k28资讯网——每日最新资讯28at.com

String result = retry.executeSupplier(() -> {// 发送请求return backendService.callAPI();});

2.7.4 自定义重试异常predicateZ2k28资讯网——每日最新资讯28at.com

RetryConfig config = RetryConfig.custom().retryOnException(e -> isRetryable(e)).build();

Resilience4j提供了线程安全的重试 decorator,可以通过配置灵活控制重试策略,很好地支持了接口请求重试。Z2k28资讯网——每日最新资讯28at.com

Z2k28资讯网——每日最新资讯28at.com

2.8 使用网络工具重试

我们常用的一些网络工具来做重试Z2k28资讯网——每日最新资讯28at.com

Z2k28资讯网——每日最新资讯28at.com

示例Z2k28资讯网——每日最新资讯28at.com

public class RetryExample {private static final int MAX_RETRIES = 3;public static String request(String url) throws Exception {  int retries = 0;     while (true) {         try {      // 使用HttpClient发送请求      return HttpClientUtils.get(url);           } catch (Exception e) {      if (retries >= MAX_RETRIES) {        throw e;      }             // 增加重试次数      retries++;      // 延迟1秒钟      TimeUnit.SECONDS.sleep(1);    }  }}   public static void main(String[] args) throws Exception {  String result = request("http://example.com/api");  System.out.println(result);}}// 网络工具类class HttpClientUtils {public static String get(String url) throws IOException {  // 发送GET请求并返回结果}}

Z2k28资讯网——每日最新资讯28at.com

主要通过循环和网络工具类来实现重试逻辑,延时控制也可以用Random来实现指数退避。这种 utilities + 循环 的组合可以实现灵活可复用的重试机制。Z2k28资讯网——每日最新资讯28at.com

3.注意事项

图片图片Z2k28资讯网——每日最新资讯28at.com

接口请求重试时需要注意以下几点:Z2k28资讯网——每日最新资讯28at.com

3.1 幂等性接口需要是幂等的,多次调用结果相同,避免重复执行带来副作用。Z2k28资讯网——每日最新资讯28at.com

3.2 资源竞争重试可能对服务端造成更大压力,需要考虑限流等措施。Z2k28资讯网——每日最新资讯28at.com

3.3 超时设置合理设置重试最大次数和总超时时间,避免长时间等待。Z2k28资讯网——每日最新资讯28at.com

3.4 重试条件明确哪些异常情况下需要重试,不能无脑重试所有错误。Z2k28资讯网——每日最新资讯28at.com

3.5 数据一致性请求成功后要幂等更新状态,避免重复数据。Z2k28资讯网——每日最新资讯28at.com

3.6 异步机制重试过程不要阻塞主业务线程。Z2k28资讯网——每日最新资讯28at.com

3.7 退避策略失败后延迟一段时间再重试,可选避免集群重试。Z2k28资讯网——每日最新资讯28at.com

3.8 日志记录记录重试的次数、错误原因等信息,方便排查问题。Z2k28资讯网——每日最新资讯28at.com

3.9 容错机制重试失败后的降级处理,避免级联失败。Z2k28资讯网——每日最新资讯28at.com

Z2k28资讯网——每日最新资讯28at.com

总结

接口请求重试机制对保证系统高可用非常关键,需要根据业务需求选择合适的重试策略。常用的组合策略包括带最大次数的定时/指数退避重试、故障转移重试等。重试机制需要综合设置以达到容错效果 又避免产生过大的系统负载。Z2k28资讯网——每日最新资讯28at.com

本文链接:http://www.28at.com/showinfo-26-17165-0.html聊聊接口重试机制的几种解决方案

声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com

上一篇: 提升应用性能:Go中的同步与异步处理

下一篇: 如何释放React Hooks的力量

标签:
  • 热门焦点
  • 卢伟冰长文解析K60至尊版 对Redmi有着里程碑式的意义

    在今天的Redmi后性能时代战略发布会结束之后,Redmi总经理卢伟冰又带来了一篇长文,详解了为什么 Redmi 要开启后性能时代?为什么选择和 MediaTek、Pixelworks 深度合作?以及后性
  • Java NIO内存映射文件:提高文件读写效率的优秀实践!

    Java的NIO库提供了内存映射文件的支持,它可以将文件映射到内存中,从而可以更快地读取和写入文件数据。本文将对Java内存映射文件进行详细的介绍和演示。内存映射文件概述内存
  • 使用AIGC工具提升安全工作效率

    在日常工作中,安全人员可能会涉及各种各样的安全任务,包括但不限于:开发某些安全工具的插件,满足自己特定的安全需求;自定义github搜索工具,快速查找所需的安全资料、漏洞poc、exp
  • 2023年,我眼中的字节跳动

    此时此刻(2023年7月),字节跳动从未上市,也从未公布过任何官方的上市计划;但是这并不妨碍它成为中国最受关注的互联网公司之一。从2016-17年的抖音强势崛起,到2018年的&ldquo;头腾
  • 消费结构调整丨巨头低价博弈,拼多多还卷得动吗?

    来源:征探财经作者:陈香羽随着流量红利的退潮,电商的存量博弈越来越明显。曾经主攻中高端与品质的淘宝天猫、京东重拾&ldquo;低价&rdquo;口号。而过去与他们错位竞争的拼多多,靠
  • 当家的盒马,加速谋生

    来源 | 价值星球Planet作者 | 归去来自己&ldquo;当家&rdquo;的盒马,开始加速谋生了。据盒马官微消息,盒马计划今年开放生鲜供应链,将其生鲜商品送往食堂。目前,盒马在上海已经与
  • 认真聊聊东方甄选:如何告别低垂的果实

    来源:山核桃作者:财经无忌爆火一年后,俞敏洪和他的东方甄选依旧是颇受外界关心的&ldquo;网红&rdquo;。7月5日至9日,为期5天的东方甄选&ldquo;甘肃行&rdquo;首次在自有App内直播,
  • 最薄的14英寸游戏笔记本电脑 Alienware X14已可以购买

    2022年1月份在国际消费电子展(CES2022)上首次亮相的Alienware新品——Alienware X14现在已经可以购买了,这款笔记本电脑被誉为世界上最薄的 14 英寸游戏笔
  • 电博会与软博会实现"线下+云端"的双线融合

    在本次“电博会”与“软博会”双展会利好条件的加持下,既可以发挥展会拉动人流、信息流、资金流实现快速交互流动的作用,继而推动区域经济良性发展;又可以聚
Top