使用 guava-retrying 实现灵活的重试机制
Hollis
共 2662字,需浏览 6分钟
· 2020-12-16
有意思的是,这个项目最初源于 Jean-Baptiste Nizet 在 guava 仓库下的评论。
guava-retrying 入门
<dependency>
<groupId>com.github.rholdergroupId>
<artifactId>guava-retryingartifactId>
<version>2.0.0version>
dependency>
compile "com.github.rholder:guava-retrying:2.0.0"
// 调用接口
boolean result;
AtomicInteger atomicInteger = new AtomicInteger(0);
int sleepNum = 10000;
while(!result && atomicInteger.get() < 4) {
atomicInteger.incrementAndGet();
result = thirdApi.invoke();
Thread.sleep(sleepNum);
sleepNum += sleepNum * atomicInteger.get();
}
Callable<Boolean> callable = () -> {
return thirdApi.invoke(); // 业务逻辑
};
// 定义重试器
Retryer<Boolean> retryer = RetryerBuilder.<Boolean>newBuilder()
.retryIfResult(Predicates.<Boolean>isNull()) // 如果结果为空则重试
.retryIfExceptionOfType(IOException.class) // 发生IO异常则重试
.retryIfRuntimeException() // 发生运行时异常则重试
.withWaitStrategy(WaitStrategies.incrementingWait(10, TimeUnit.SECONDS, 10, TimeUnit.SECONDS)) // 等待
.withStopStrategy(StopStrategies.stopAfterAttempt(4)) // 允许执行4次(首次执行 + 最多重试3次)
.build();
try {
retryer.call(callable); // 执行
} catch (RetryException | ExecutionException e) { // 重试次数超过阈值或被强制中断
e.printStackTrace();
}
重试条件 retryIfResult、retryIfExceptionOfType、retryIfRuntimeException 重试等待策略(延迟)withWaitStrategy 重试停止策略 withStopStrategy 阻塞策略、超时限制、注册重试监听器(上述代码未使用)
RetryerBuilder<V> newBuilder()
Retryer<V> build()
重试条件
RetryerBuilder<V> retryIfResult(@Nonnull Predicate<V> resultPredicate)
// 发生任何异常都重试
retryIfException()
// 发生 Runtime 异常都重试
RetryerBuilder
retryIfRuntimeException() // 发生指定 type 异常时重试
RetryerBuilder
retryIfExceptionOfType(extends Throwable> exceptionClass) Class// 匹配到指定类型异常时重试
RetryerBuilder
retryIfException( PredicateexceptionPredicate)
RetryerBuilder<V> withWaitStrategy(@Nonnull WaitStrategy waitStrategy) throws IllegalStateException
// 参数:等待时间,时间单位
WaitStrategy fixedWait(long sleepTime, @Nonnull TimeUnit timeUnit) throws IllegalStateException
// 参数:随机上限,时间单位
WaitStrategy randomWait(long maximumTime, @Nonnull TimeUnit timeUnit)
// 参数:随机下限,下限时间单位,随机上限,上限时间单位
WaitStrategy randomWait(long minimumTime,
@Nonnull TimeUnit minimumTimeUnit,
long maximumTime,
@Nonnull TimeUnit maximumTimeUnit)
// 参数:初始等待时长,初始值时间单位,递增值,递增值时间单位
WaitStrategy incrementingWait(long initialSleepTime,
@Nonnull TimeUnit initialSleepTimeUnit,
long increment,
@Nonnull TimeUnit incrementTimeUnit)
// 无参数(默认初始值为1)
WaitStrategy exponentialWait()
// 参数:最大等待时长,最大等待时间单位(默认初始值为1)
WaitStrategy exponentialWait(long maximumTime, @Nonnull TimeUnit maximumTimeUnit)
// 参数:初始值,最大等待时长,最大等待时间单位
WaitStrategy exponentialWait(long multiplier, long maximumTime, @Nonnull TimeUnit maximumTimeUnit)
// 无参数(默认初始值为1)
WaitStrategy fibonacciWait()
// 参数:最大等待时长,最大等待时间单位(默认初始值为1)
WaitStrategy fibonacciWait(long maximumTime, @Nonnull TimeUnit maximumTimeUnit)
// 参数:最大等待时长,最大等待时间单位(默认初始值为1)
WaitStrategy fibonacciWait(long multiplier, long maximumTime, @Nonnull TimeUnit maximumTimeUnit)
// 参数:异常类型,计算等待时长的函数
extends Throwable> WaitStrategy exceptionWait( ClassexceptionClass, Function
function)
// 参数:等待策略数组
WaitStrategy join(WaitStrategy... waitStrategies)
RetryerBuilder<V> withBlockStrategy(@Nonnull BlockStrategy blockStrategy) throws IllegalStateException
private static class ThreadSleepStrategy implements BlockStrategy {
public void block(long sleepTime) throws InterruptedException {
Thread.sleep(sleepTime);
}
}
停止策略
RetryerBuilder<V> withStopStrategy(@Nonnull StopStrategy stopStrategy) throws IllegalStateException
超时限制
RetryerBuilder<V> withAttemptTimeLimiter(@Nonnull AttemptTimeLimiter<V> attemptTimeLimiter)
NoAttemptTimeLimit:不限制执行时间 FixedAttemptTimeLimit:限制执行时间为固定值
监听器
import com.github.rholder.retry.Attempt;
import com.github.rholder.retry.RetryListener;
public class MyRetryListener<T> implements RetryListener {
@Override
public <T> void onRetry(Attempt<T> attempt) {
// 第几次重试,(注意:第一次重试其实是第一次调用)
System.out.print("[retry]time=" + attempt.getAttemptNumber());
// 距离第一次重试的延迟
System.out.print(",delay=" + attempt.getDelaySinceFirstAttempt());
// 重试结果: 是异常终止, 还是正常返回
System.out.print(",hasException=" + attempt.hasException());
System.out.print(",hasResult=" + attempt.hasResult());
// 是什么原因导致异常
if (attempt.hasException()) {
System.out.print(",causeBy=" + attempt.getExceptionCause().toString());
} else {
// 正常返回时的结果
System.out.print(",result=" + attempt.getResult());
}
}
}
public V call(Callable
callable ) throws ExecutionException, RetryException {long startTime = System.nanoTime(); // 1. 记录开始时间,用于后续的时间计算
for (int attemptNumber = 1; ; attemptNumber++) {
Attempt
attempt; try {
V result = attemptTimeLimiter.call(callable); // 2. 执行callable任务,得到attempt
attempt = new ResultAttempt
(result, attemptNumber, TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startTime)); } catch (Throwable t) {
attempt = new ExceptionAttempt
(t, attemptNumber, TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startTime)); }
for (RetryListener listener : listeners) { // 3. 如果有***,通知
listener.onRetry(attempt);
}
if (!rejectionPredicate.apply(attempt)) { // 4. 如果执行callable出现异常,则返回异常的attempt
return attempt.get();
}
if (stopStrategy.shouldStop(attempt)) { // 5. 根据停止策略判断是否停止重试
throw new RetryException(attemptNumber, attempt); // 若停止,抛出异常
} else {
long sleepTime = waitStrategy.computeSleepTime(attempt); // 6. 根据等待策略计算休眠时间
try {
blockStrategy.block(sleepTime); // 7. 根据阻塞策略决定休眠行为,默认为sleep
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new RetryException(attemptNumber, attempt);
}
}
}
}
如果 attemptTimeLimiter 是 NoAttemptTimeLimit,则直接调用 callable.call 执行。 如果 attemptTimeLimiter 是 FixedAttemptTimeLimit,则调用 timeLimiter.callWithTimeout 限制执行时间。
rejectionPredicate = Predicates.or(rejectionPredicate, new ExceptionClassPredicate(RuntimeException.class));
有道无术,术可成;有术无道,止于术
欢迎大家关注Java之道公众号
好文章,我在看❤️
评论
如何画出漂亮的神经网络图?神经网络可视化工具集锦搜集
点击上方“小白学视觉”,选择加"星标"或“置顶”重磅干货,第一时间送达1. draw_convnet一个用于画卷积神经网络的Python脚本https://github.com/gwding/draw_convnet2. NNSVGhttp://alexlenail.me/NN-SVG/LeNet.
小白学视觉
0
使用 YOLO 进行自定义对象检测
点击上方“小白学视觉”,选择加"星标"或“置顶”重磅干货,第一时间送达我们知道我们可以专门检测一些对象。那么我们如何训练系统检测自定义对象呢?让我们一步一步来。1. 创建数据集机器是通过数据集学习的。数据集必须包含图像和标签。例如,让我的目标是创建一个检测坦克的系统。我准备了从网上下载的坦克图片。然
小白学视觉
0
如何看待稚晖君的时间管理水平?
点击上方“小白学视觉”,选择加"星标"或“置顶”重磅干货,第一时间送达计算机视觉life整理原文链接:https://www.zhihu.com/question/491456524/answer/2183081310稚晖君究竟是如何安排业余时间去做这么多高水平的项目?而且每个项目的用时也很少,普通
小白学视觉
2
三个优秀的PyTorch实现语义分割框架
点击上方“小白学视觉”,选择加"星标"或“置顶”重磅干货,第一时间送达转自 | 机器学习AI算法工程使用的VOC数据集链接开放在文章中,预训练模型已上传Github,环境我使用Colab pro,大家下载模型做预测即可。代码链接: https://github.com/lixiang007
小白学视觉
0
如何确定神经网络的层数和隐藏层神经元数量?
点击上方“小白学视觉”,选择加"星标"或“置顶”重磅干货,第一时间送达公众号:尤而小屋作者:呦呦鹿鸣编辑:Peter大家好,我是Peter~关于神经网络中隐藏层的层数和神经元个数充满了疑惑。刚好看到一篇文章很好地答疑了,分享给大家~https://zhuanlan.zhihu.com/p/10041
小白学视觉
0
神经网络之CNN与RNN的关系
点击上方“小白学视觉”,选择加"星标"或“置顶”重磅干货,第一时间送达1、CNN介绍CNN是一种利用卷积计算的神经网络。它可以通过卷积计算将原像素很大的图片保留主要特征变成很小的像素图片。本文以李宏毅老师ppt内容展开具体介绍。1.1 Why CNN for Image①为什么引入CNN ?图片示意
小白学视觉
0
“海优最初弄出来可并不是为了给大佬弟子开后门的, 学术界现在几乎不存在任何套利空间,不要相信有什么办法可以投机取巧”
点击上方“小白学视觉”,选择加"星标"或“置顶”重磅干货,第一时间送达知乎问题:为什么部分同学倾向土博+国外博后而不是直接国外读博?感觉身边土博越来越多,基本都是土博➕海博后,申国外phd的明显减少(相比较疫情之前几年)知乎Tianteman: 这个问题下,可以看得出一部分国内硕博信息检索能力差的离
小白学视觉
0
真高!比亚迪员工爆料比亚迪在越南的薪资水平:基本工资480万,全勤奖35万,交通补助20万,餐补110万,每周6天,每天10小时
上一篇:某大公司为逼迫员工离职,竟然把他的工位安排到厕所旁,没想到他直接开始记录领导的如厕时间,还发到公司大群...对此,你怎么看?--完--PS:欢迎在留言区留下你的观点,一起讨论提高。如果今天的文章让你有新的启发,欢迎转发分享给更多人。全文完,感谢你的耐心阅读。如果你还想看到我的文章,请一定给本
开发者全社区
0