一、使用场景

在日常开发中,我们经常会遇到需要调用外部服务和接口的场景。外部服务对于调用者来说一般都是不可靠的,尤其是在网络环境比较差的情况下,网络抖动很容易导致请求超时等异常情况,这时候就需要使用失败重试策略重新调用 API 接口来获取。重试策略在服务治理方面也有很广泛的使用,通过定时检测,来查看服务是否存活(
Active)。

Guava Retrying 是一个灵活方便的重试组件,包含了多种的重试策略,而且扩展起来非常容易。

用作者的话来说:

This is a small extension to Google’s Guava library to allow for the creation of configurable retrying strategies for an arbitrary function call, such as something that talks to a remote service with flaky uptime.

使用 Guava-retrying 你可以自定义来执行重试,同时也可以监控每次重试的结果和行为,最重要的基于 Guava 风格的重试方式真的很方便。

二、代码示例

以下会简单列出 guava-retrying 的使用方式:

  • 如果抛出 IOException 则重试,如果返回结果为 null 或者等于 2 则重试,固定等待时长为 300 ms,最多尝试 3 次;
Callable<Integer> task = new Callable<Integer>() {@Overridepublic Integer call() throws Exception {return 2;}
};Retryer<Integer> retryer = RetryerBuilder.<Integer>newBuilder().retryIfResult(Predicates.<Integer>isNull()).retryIfResult(Predicates.equalTo(2)).retryIfExceptionOfType(IOException.class).withStopStrategy(StopStrategies.stopAfterAttempt(3)).withWaitStrategy(WaitStrategies.fixedWait(300, TimeUnit.MILLISECONDS)).build();
try {retryer.call(task);
} catch (ExecutionException e) {e.printStackTrace();
} catch (RetryException e) {e.printStackTrace();
}
  • 出现异常则执行重试,每次任务执行最长执行时间限定为 3 s,重试间隔时间初始为 3 s,最多重试 1 分钟,随着重试次数的增加每次递增 1 s,每次重试失败,打印日志;
@Overridepublic Integer call() throws Exception {return 2;}
};Retryer<Integer> retryer = RetryerBuilder.<Integer>newBuilder().retryIfException().withStopStrategy(StopStrategies.stopAfterDelay(30,TimeUnit.SECONDS)).withWaitStrategy(WaitStrategies.incrementingWait(3, TimeUnit.SECONDS,1,TimeUnit.SECONDS)).withAttemptTimeLimiter(AttemptTimeLimiters.<Integer>fixedTimeLimit(3,TimeUnit.SECONDS)).withRetryListener(new RetryListener() {@Overridepublic <V> void onRetry(Attempt<V> attempt) {if (attempt.hasException()){attempt.getExceptionCause().printStackTrace();}}}).build();
try {retryer.call(task);
} catch (ExecutionException e) {e.printStackTrace();
} catch (RetryException e) {e.printStackTrace();
}

三、核心执行逻辑

long startTime = System.nanoTime();
for (int attemptNumber = 1; ; attemptNumber++) {Attempt<V> attempt;try {// 执行成功V result = attemptTimeLimiter.call(callable);attempt = new ResultAttempt<V>(result, attemptNumber, TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startTime));} catch (Throwable t) {// 执行失败attempt = new ExceptionAttempt<V>(t, attemptNumber, TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startTime));}// 监听器处理for (RetryListener listener : listeners) {listener.onRetry(attempt);}// 是否符合终止策略if (!rejectionPredicate.apply(attempt)) {return attempt.get();}// 是否符合停止策略if (stopStrategy.shouldStop(attempt)) {throw new RetryException(attemptNumber, attempt);} else {// 计算下次重试间隔时间long sleepTime = waitStrategy.computeSleepTime(attempt);try {blockStrategy.block(sleepTime);} catch (InterruptedException e) {Thread.currentThread().interrupt();throw new RetryException(attemptNumber, attempt);}}
}

四、依赖引入

<dependency><groupId>com.github.rholder</groupId><artifactId>guava-retrying</artifactId><version>2.0.0</version>
</dependency>

默认的guava中也有包含。

五、主要接口介绍:

  • Attempt:一次执行任务;

  • AttemptTimeLimiter:单次任务执行时间限制(如果单次任务执行超时,则终止执行当前任务);

  • BlockStrategies:任务阻塞策略(通俗的讲就是当前任务执行完,下次任务还没开始这段时间做什么……),默认策略为:BlockStrategies.THREAD_SLEEP_STRATEGY 也就是调用 Thread.sleep(sleepTime);

  • RetryException:重试异常;

  • RetryListener:自定义重试监听器,可以用于异步记录错误日志;

  • StopStrategy:停止重试策略,提供三种:

    • StopAfterDelayStrategy :设定一个最长允许的执行时间;比如设定最长执行10s,无论任务执行次数,只要重试的时候超出了最长时间,则任务终止,并返回重试异常RetryException;
    • NeverStopStrategy :不停止,用于需要一直轮训知道返回期望结果的情况;
    • StopAfterAttemptStrategy :设定最大重试次数,如果超出最大重试次数则停止重试,并返回重试异常;
  • WaitStrategy:等待时长策略(控制时间间隔),返回结果为下次执行时长:

    • FixedWaitStrategy:固定等待时长策略;
    • RandomWaitStrategy:随机等待时长策略(可以提供一个最小和最大时长,等待时长为其区间随机值)
    • IncrementingWaitStrategy:递增等待时长策略(提供一个初始值和步长,等待时间随重试次数增加而增加)
    • ExponentialWaitStrategy:指数等待时长策略;
    • FibonacciWaitStrategy :Fibonacci 等待时长策略;
    • ExceptionWaitStrategy :异常时长等待策略;
    • CompositeWaitStrategy :复合时长等待策略;

基于guava的重试组件Guava-Retryer相关推荐

  1. Spring-retry重试组件

    # 一.简介 Spring-retry 前面我们了解到了,Guava的重试组件,我们可以基于Guava的能力,来封装我们需要的能力来满足我们的业务.今天来分享Spring-Retry重试组件.当然Sp ...

  2. 第04篇:Guava-retry重试组件

    作者: 西魏陶渊明 博客: https://blog.springlearn.cn/ 西魏陶渊明 天下代码一大抄, 抄来抄去有提高, 看你会抄不会抄! 一.简介 Guava-retry Guava 是 ...

  3. Google guava第一讲:guava缓存实战/使用场景/缓存清理/最佳实践/caffeine实战

    Guava缓存实战及使用场景 摘要:本文是Google guava 第一件,本文先介绍了为什么使用Guava Cache缓存,然后讲解了使用方法及底层数据结构,结合实际业务,讲解使用guava过程中踩 ...

  4. 从0到1带你手撸一个请求重试组件,不信你学不会!

    点击关注公众号,实用技术文章及时了解 背景介绍 在实际的项目应用场景中,经常会需要遇到远程服务接口的调用,时不时会出现一些接口调用超时,或者函数执行失败需要重试的情况,例如下边的这种场景: 某些不太稳 ...

  5. Error:Could not download guava.jar (com.google.guava:guava:19.0): No cached version available for of

    今天从git导入demo 报错 Error:Could not download guava.jar (com.google.guava:guava:19.0): No cached version ...

  6. Visifire Silverlight Charts (基于SilverLight的Chart组件)

    偶然发现了这个东东,一个基于SilverLight的Chart组件,遵循GPL v3,支持的Chart类型挺多的(支持饼图,柱状图,圈图,区图等等). Visifire 有比较完善的文档, 而且还有一 ...

  7. guava 并发同步_Google Guava –与Monitor同步

    guava 并发同步 Google Guava项目是每个Java开发人员都应该熟悉的库的集合. Guava库涵盖了I / O,集合,字符串操作和并发性. 在这篇文章中,我将介绍Monitor类. Mo ...

  8. 如何开发一个基于 Vue 的 ui 组件库

    如何开发一个基于 Vue 的 ui 组件库 开发模式 预览 demo 在开发一个 ui 组件库时,肯定需要一边预览 demo,一边修改代码. 常见的解决方案是像开发一般项目一样使用 webpack-d ...

  9. 基于Java Swing JFream 组件的趣味推箱子小游戏

    一 需求分析 设计一个经典的推箱子小游戏,在窗体里有墙,箱子,胜利的标志,和工人,用户可以通过键盘上的"上"."下"."左"."右 ...

  10. [源码和文档分享]基于Java Swing JFream 组件的趣味推箱子小游戏

    一 需求分析 设计一个经典的推箱子小游戏,在窗体里有墙,箱子,胜利的标志,和工人,用户可以通过键盘上的"上"."下"."左"."右 ...

最新文章

  1. Android-----View绘制流程以及invalidate()等相关方法分析 .
  2. linux安装.net core3.0,树莓派4安装net core3.0环境
  3. SQL的多种JOIN
  4. 如何玩转跨库Join?跨数据库实例查询应用实践
  5. 浙江大学计算机保研条件_看了就想录取的简历长啥样?保研简历千万别踩这些坑!...
  6. halcon学习笔记——(1)单摄像机标定
  7. selenium自动化测试、Python单元测试unittest框架以及测试报告和日志输出
  8. CH - 0601 Genius ACM(倍增+归并排序)
  9. java中使用tika_Tika基本使用
  10. UI自动化测试篇 :ReportNG替代TestNG自带html版测试报告初探
  11. 3dMax模型尺寸更改与模型均匀缩放
  12. 论计算机应用技术对企业信息化的影响
  13. WinRAR5.01注册码附注册机
  14. 【读书笔记】《华为工作法》
  15. 安装教程之postman下载及安装
  16. linux系统管理员用户名为admin,Linux创建系统管理员用户
  17. MAC10.11 Python3.6 安装Scrapy
  18. java 中的连接超时_【java中处理http连接超时的方法】
  19. 二分查找的左右逼近法
  20. html 图片自动滚动播放,小卖弄:纯CSS实现图片滚动播放效果

热门文章

  1. 33. PHP Sessions
  2. 5. 什么是命名空间
  3. php中的字符串可以当做数组调用
  4. codeforces 679B
  5. python报错Nonetype object is not iterable
  6. Ural 1043 Cover the Arc
  7. Linux下编译android源码的步骤
  8. 如何实现BootStrapTable的动态表格
  9. Lack of free swap space on zabbix,增加swap空间
  10. Linux下启动/关闭Oracle