guava-retrying重试工具库: 什么时候终止

本文介绍了在使用重试机制时如何设定合理的停止策略,包括按尝试次数、延迟时间和自定义策略来终止重试,并通过示例代码展示了不同策略的应用。

当我们重试到一定阶段的时候,需要终止重试过程,比如重试了n次或者重试了n秒等。


StopStrategies.stopAfterAttempt(n):在重试了n次后终止,这个实际中最常用。

import com.github.rholder.retry.Retryer;
import com.github.rholder.retry.RetryerBuilder;
import com.github.rholder.retry.StopStrategies;
import com.github.rholder.retry.WaitStrategies;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit;

public class TestStop {

    private static final SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss,SSS");

    private static Callable<Void> task = new Callable<Void>() {
        @Override
        public Void call() throws Exception {
            System.out.println(df.format(new Date()));
            throw new RuntimeException();
        }
    };

    public static void main(String[] args) throws Exception {
        // 每次间隔1s后重试
        Retryer<Void> retryer = RetryerBuilder.<Void>newBuilder()
                .retryIfException()
                .withWaitStrategy(WaitStrategies.fixedWait(1, TimeUnit.SECONDS))
                .withStopStrategy(StopStrategies.stopAfterAttempt(3))
                //.withStopStrategy(StopStrategies.neverStop())
                //.withStopStrategy(StopStrategies.stopAfterDelay(10, TimeUnit.SECONDS))
                .build();

        System.out.println("begin..." + df.format(new Date()));

        try {
            retryer.call(task);
        } catch (Exception e) {
            System.err.println("still failed after retry." + e.getCause().toString());
        }

        System.out.println("end..." + df.format(new Date()));
    }
}


StopStrategies.neverStop():从不终止,一直重试,没有什么实际用处。


StopStrategies.stopAfterDelay(10, TimeUnit.SECONDS):一直重试,指定时间过后终止。


guava-retrying提供了StopStrategy接口,我们可以实现自己想要的终止逻辑。


import com.github.rholder.retry.Attempt;
import com.github.rholder.retry.StopStrategy;

public class MyStopStrategy implements StopStrategy {

    private int attemptCount;

    public MyStopStrategy() {
        this.attemptCount = (int) Math.floor(Math.random() * 10) + 1;
        System.out.println("重试" + attemptCount + "后终止");
    }


    @Override
    public boolean shouldStop(Attempt failedAttempt) {
        return failedAttempt.getAttemptNumber() == attemptCount;
    }
}


下面我们使用自己实现的终止策略,重试1~11间的随机次数后终止。
Retryer<Void> retryer = RetryerBuilder.<Void>newBuilder()
		.retryIfException()
		.withWaitStrategy(WaitStrategies.fixedWait(1, TimeUnit.SECONDS))
		.withStopStrategy(new MyStopStrategy())
		.build();
try {
	retryer.call(task);
} catch (Exception e) {
	System.err.println("still failed after retry." + e.getCause().toString());
}



<think>我们正在参考用户提供的引用内容,特别是引用[1]和引用[2]关于guava-retrying库的信息。用户的需求是获取使用GuavaRetrying库实现Java重试机制的简单示例或教程。根据引用[1],我们知道guava-retrying是GoogleGuava库的一个扩展,用于为任意函数调用创建可配置的重试策略。引用[2]则提到了传统手写重试逻辑的缺点,并暗示了使用注解或库来更优雅地实现重试。我们将按照以下步骤提供帮助:1.引入依赖(因为用户可能需要知道如何开始)2.构建一个简单的重试器示例3.解释重试策略的常见配置选项由于引用中并没有直接给出代码示例,但根据引用[1]的项目地址,我们可以参考其文档。然而,用户要求我们使用站内引用,因此我们只能基于已有引用和我们的知识来编写。注意:引用[3]是关于Git工作区的,与当前问题无关,可以忽略。根据引用[2]中提到的传统重试逻辑的缺点,我们可以展示如何使用guava-retrying来替代手写逻辑。示例代码将包括:-定义重试条件(如何情况下重试-配置重试策略(重试次数、间隔等)-执行带有重试的操作下面开始逐步构建答案。</think> ### 使用 Guava Retrying 实现 Java 重试机制 Guava Retrying 是一个基于 Google Guava 的轻量级重试库,可优雅处理远程服务调用等不稳定操作。以下是完整实现示例: #### 1. 添加 Maven 依赖 ```xml <dependency> <groupId>com.github.rholder</groupId> <artifactId>guava-retrying</artifactId> <version>2.0.0</version> </dependency> ``` #### 2. 基础重试示例 ```java import com.github.rholder.retry.*; import java.util.concurrent.TimeUnit; public class RetryDemo { // 模拟不稳定的远程服务调用 public static boolean callRemoteService() throws Exception { double rand = Math.random(); if (rand > 0.3) throw new Exception("服务超时"); return true; } public static void main(String[] args) { // 配置重试策略 Retryer<Boolean> retryer = RetryerBuilder.<Boolean>newBuilder() .retryIfException() // 异常时重试 .withWaitStrategy(WaitStrategies.fixedWait(1, TimeUnit.SECONDS)) // 每次间隔1秒 .withStopStrategy(StopStrategies.stopAfterAttempt(3)) // 最多重试3次 .build(); try { retryer.call(() -> callRemoteService()); System.out.println("服务调用成功!"); } catch (Exception e) { System.err.println("所有重试失败: " + e.getMessage()); } } } ``` #### 3. 高级配置选项 | **配置项** | **说明** | **示例** | |-------------------|-------------------------------------------------------------------------|-----------------------------------------------------------------------| | 重试条件 | 根据异常类型或返回结果触发重试 | `.retryIfResult(res -> res == null)` | | 等待策略 | 控制重试间隔(固定/随机/指数) | `WaitStrategies.exponentialWait()` | | 停止策略 | 控制最大重试次数/时间 | `StopStrategies.stopAfterDelay(10, TimeUnit.SECONDS)` | | 监听器 | 重试事件监听 | `.withRetryListener(new RetryListener() {...})` | #### 4. 完整企业级示例 ```java Retryer<Response> retryer = RetryerBuilder.<Response>newBuilder() .retryIfExceptionOfType(ServiceTimeoutException.class) .retryIfResult(res -> !res.isSuccess()) .withWaitStrategy(WaitStrategies.exponentialWait(100, 5, TimeUnit.SECONDS)) .withStopStrategy(StopStrategies.stopAfterDelay(30, TimeUnit.SECONDS)) .withRetryListener(new RetryListener() { @Override public <V> void onRetry(Attempt<V> attempt) { if (attempt.hasException()) { log.error("第{}次重试失败: {}", attempt.getAttemptNumber(), attempt.getExceptionCause().getMessage()); } } }) .build(); // 在业务代码中使用 Response result = retryer.call(() -> paymentService.confirm(orderId)); ``` #### 适用场景推荐: 1. 支付回调验证(避免因网络波动导致支付状态丢失) 2. 第三方 API 调用(地图服务/短信服务等不稳定接口)[^2] 3. 数据库连接恢复(瞬时连接失败自动重连) 4. 分布式服务调用(处理临时性节点故障) 相比于传统手动重试(如引用[2]所示),Guava Retrying 通过策略模式提供更强的灵活性和可观测性,同时避免代码重复。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值