【Java技巧】深入浅出 Guava Retry 框架:业务兜底重试方案示例

为什么要重试

重试常用于三方的对接的过程中,比如调第三方的接口,可能因为网络抖动等不可预知的问题而出现错误,这个时候只需要重新一下就好了。Guava Retry 是一个基于 Java 的开源重试库,可以帮助开发者在面对不可预期的失败(如网络异常或服务超时)时实现逻辑重试功能。本文将详细讲解如何使用 Guava Retry,包括示例代码和方法参数的详细说明。

guava-retrying的使用

1. 引入依赖

maven:

xml 复制代码
<dependency>
    <groupId>com.github.rholder</groupId>
    <artifactId>guava-retrying</artifactId>
    <version>2.0.0</version>
</dependency>

gradle:

xml 复制代码
implementation 'com.github.rholder:guava-retrying:2.0.0'

2. 基本概念

Guava Retry 的核心概念包括以下几部分:

  • Retryer:重试执行逻辑的主类。
  • RetryerBuilder:用于构建 Retryer 实例。
  • StopStrategy:定义何时停止重试。
  • WaitStrategy:定义两次重试之间的等待时间。
  • RetryListener:重试时的回调监听器。

3. 示例

下面是一个典型的使用场景:尝试调用一个可能失败的 HTTP 接口,重试 3 次,每次等待 2 秒。

java 复制代码
import com.github.rholder.retry.*;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.ExecutionException;

public class GuavaRetryExample {
    public static void main(String[] args) {
        // 构建 Retryer
        Retryer<HttpResponse> retryer = RetryerBuilder.<HttpResponse>newBuilder()
                // 设置重试条件
                .retryIfException()
                .retryIfResult(httpResponse -> !httpResponse.isOk())
                // 设置停止策略:最多重试3次
                .withStopStrategy(StopStrategies.stopAfterAttempt(3))
                // 设置等待策略:每次重试间隔2秒
                .withWaitStrategy(WaitStrategies.fixedWait(2, TimeUnit.SECONDS))
                // 添加重试监听器
                .withRetryListener(attempt -> System.out.println("重试次数: " + attempt.getAttemptNumber()))
                .build();

        // 定义需要重试的逻辑
        HttpRequest postRequest = HttpUtil.createPost(url);
        Callable<HttpResponse> httpRequestCallable = () -> {
            HttpResponse httpResponse = httpRequest.execute();
            log.info("[LLM] call Response:{}", JSON.toJSONString(httpResponse.body()));
            return httpResponse;
        };
        try {
            return retryer.call(httpRequestCallable);
        } catch (ExecutionException | RetryException e) {
            log.error("[LLM] call failed, Exception:", e);
            throw new RuntimeException(e);
        }
    }
}

4. 常用的几个参数

4.1 retryIfException() 和 retryIfExceptionOfType(Class<? extends Throwable> exceptionClass)

作用:设置重试的条件。如果执行中抛出异常,则触发重试。

参数:exceptionClass:指定需要触发重试的异常类型。

4.2 retryIfResult(Predicate<? super T> resultPredicate)

作用:基于结果判断是否需要重试。

参数:resultPredicate:一个 Lambda 表达式或匿名类,定义结果是否符合重试条件。

4.3 withStopStrategy(StopStrategy stopStrategy)

作用:设置停止策略,决定何时停止重试。

停止策略:

  • StopStrategies.stopAfterAttempt(int maxAttemptNumber):指定最大重试次数。
  • StopStrategies.neverStop():永不停止。
4.4 withWaitStrategy(WaitStrategy waitStrategy)

作用:设置等待策略,定义每次重试之间的等待时间。

等待策略:

  • WaitStrategies.fixedWait(long time, TimeUnit timeUnit):固定等待时间。
  • WaitStrategies.randomWait(long maximumTime, @Nonnull TimeUnit timeUnit): 随机等待时间
  • WaitStrategies.incrementingWait 递增等待时间
  • WaitStrategies.exponentialWait(long multiplier, long maximumTime, TimeUnit timeUnit):指数递增等待时间。
    一定要设置一个等待策略,这样业务不可以用时,等待一下,或许就可以用了,而不是不停的去调三方接口。
4.5 withRetryListener(RetryListener listener)

作用:添加监听器,记录每次重试的行为。

参数:listener:一个实现了 RetryListener 接口的实例。

5. 更多自定义使用场景

  1. 指数退避策略
java 复制代码
.withWaitStrategy(WaitStrategies.exponentialWait(500, 10_000, TimeUnit.MILLISECONDS))
  1. 仅对特定异常类型重试
java 复制代码
.retryIfExceptionOfType(IOException.class)
  1. 结合自定义逻辑
java 复制代码
.retryIfException(e -> e instanceof CustomException && ((CustomException) e).isRetryable())

6. 注意事项

  1. 线程安全性:Retryer 是线程安全的,可以在多线程环境中安全使用。
  2. 重试逻辑中的副作用:确保重试逻辑是幂等的,避免副作用导致错误数据。
  3. 合理设置策略:避免设置不合理的停止策略或等待策略,导致系统资源浪费。

总结

以上,介绍了业务中常见的重试策略,可以解决绝大多数场景。还有些情况需要保证数据的一致性,如果重试还是失败该如何处理呢?这里留个思考题,大家可以考虑下如何做到严谨的业务兜底方案。

相关推荐
老王爱玩车12 分钟前
深入理解指针2
c语言·开发语言·学习
quantdash_cc16 分钟前
股票历史数据为什么比实时行情更重要?回测结果失真的根源可能就在 K 线数据
开发语言·python·数据分析·量化交易·股票数据·quantdash
光电的一只菜鸡28 分钟前
为什么调整LSC会对AF产生影响
android·开发语言·kotlin
zhangjw3431 分钟前
第47篇:Java综合实战:电商秒杀系统(高并发场景)
java·开发语言
土司大王40 分钟前
LeetCode hot100 回溯专题总结:Java 通用模板、决策树模型
java·算法·leetcode·决策树
FOAF-lambda1 小时前
uiautomation-new 控件方位的使用
开发语言·python
OKkankan1 小时前
LangChain能力详解!:从工具调用到 LangSmith——让聊天模型具备实时交互能力!
开发语言·python·langchain
richard_yuu1 小时前
AOI 实战第五篇:c_broken 漏检严重,V4 迭代背后的权衡
开发语言·深度学习·yolo
Wang's Blog1 小时前
Java框架快速入门:Spring Security+OAuth2之用户注册与唯一性校验实现
java·数据库·spring
Wang's Blog1 小时前
Java框架快速入门: Spring Security+OAuth2之多因子认证与TOTP实战
java·spring·ui