使用Retryer优雅地实现对Callable各种各样的重试调用
Runnable和Callable都是多线程编程中常用的接口,通常是通过实现该接口编写业务逻辑后,再由new Thread去发起线程调用。
主要区别在于Runnable没有返回值,而Callable有返回值。下面就来看一个重试框架Retryer,针对Callable做的各种重试策略方法。
API 接口调用异常, 网络异常在我们日常开发中经常会遇到,这种情况下我们需要先重试几次调用才能将其标识为错误并在确认错误之后发送异常提醒。guava-retry可以灵活的实现这一功能。Guava retryer在支持重试次数和重试频度控制基础上,能够兼容支持多个异常或者自定义实体对象的重试源定义,让重试功能有更多的灵活性。Guava Retryer也是线程安全的,入口调用逻辑采用的是Java.util.concurrent.Callable的call方法。
使用Guava retryer 很简单,我们只要做以下几步:
Step1、引入Guava-retry
<guava-retry.version>2.0.0</guava-retry.version>
<dependency><groupId>com.github.rholder</groupId><artifactId>guava-retrying</artifactId><version>${guava-retry.version}</version>
</dependency>
Step2、定义实现Callable接口的方法,以便Guava retryer能够调用
/*** @desc 更新可代理报销人接口* @author jianzhang11* @date 2017/3/31 15:17*/private static Callable<Boolean> updateReimAgentsCall = new Callable<Boolean>() {@Overridepublic Boolean call() throws Exception {String url = ConfigureUtil.get(OaConstants.OA_REIM_AGENT);String result = HttpMethod.post(url, new ArrayList<BasicNameValuePair>());if(StringUtils.isEmpty(result)){throw new RemoteException("获取OA可报销代理人接口异常");}List<OAReimAgents> oaReimAgents = JSON.parseArray(result, OAReimAgents.class);if(CollectionUtils.isNotEmpty(oaReimAgents)){CacheUtil.put(Constants.REIM_AGENT_KEY,oaReimAgents);return true;}return false;}};
Step3、定义Retry对象并设置相关策略
Retryer<Boolean> retryer = RetryerBuilder.<Boolean>newBuilder()//抛出runtime异常、checked异常时都会重试,但是抛出error不会重试。.retryIfException()//返回false也需要重试.retryIfResult(Predicates.equalTo(false))//重调策略.withWaitStrategy(WaitStrategies.fixedWait(10, TimeUnit.SECONDS))//尝试次数.withStopStrategy(StopStrategies.stopAfterAttempt(3)).build();try {retryer.call(updateReimAgentsCall);} catch (ExecutionException e) {
// e.printStackTrace();} catch (RetryException e) {logger.error("更新可代理报销人异常,需要发送提醒邮件");}
简单三步就能使用Guava Retryer优雅的实现重调方法。
接下来对其进行详细说明:
RetryerBuilder是一个factory创建者,可以定制设置重试源且可以支持多个重试源,可以配置重试次数或重试超时时间,以及可以配置等待时间间隔,创建重试者Retryer实例。
RetryerBuilder的重试源支持Exception异常对象 和自定义断言对象,通过retryIfException 和retryIfResult设置,同时支持多个且能兼容。
retryIfException,抛出runtime异常、checked异常时都会重试,但是抛出error不会重试。
retryIfRuntimeException只会在抛runtime异常的时候才重试,checked异常和error都不重试。
retryIfExceptionOfType允许我们只在发生特定异常的时候才重试,比如NullPointerException和IllegalStateException都属于runtime异常,也包括自定义的error
如:
.retryIfExceptionOfType(Error.class)// 只在抛出error重试
当然我们还可以在只有出现指定的异常的时候才重试,如:
.retryIfExceptionOfType(IllegalStateException.class)
.retryIfExceptionOfType(NullPointerException.class)
或者通过Predicate实现
.retryIfException(Predicates.or(Predicates.instanceOf(NullPointerException.class), Predicates.instanceOf(IllegalStateException.class)))
retryIfResult可以指定你的Callable方法在返回值的时候进行重试,如
// 返回false重试
.retryIfResult(Predicates.equalTo(false))
//以_error结尾才重试
.retryIfResult(Predicates.containsPattern("_error$"))
当发生重试之后,假如我们需要做一些额外的处理动作,比如发个告警邮件啥的,那么可以使用RetryListener。每次重试之后,guava-retrying会自动回调我们注册的监听。可以注册多个RetryListener,会按照注册顺序依次调用。
import com.github.rholder.retry.Attempt;
import com.github.rholder.retry.RetryListener; import java.util.concurrent.ExecutionException; public class MyRetryListener<Boolean> implements RetryListener { @Override public <Boolean> void onRetry(Attempt<Boolean> 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()); } // bad practice: 增加了额外的异常处理代码 try { Boolean result = attempt.get(); System.out.print(",rude get=" + result); } catch (ExecutionException e) { System.err.println("this attempt produce exception." + e.getCause().toString()); } System.out.println(); }
}
接下来在Retry对象中指定监听:
.withRetryListener(new MyRetryListener<>())
效果如下:
使用Retryer优雅地实现对Callable各种各样的重试调用相关推荐
- 基于Python的高校勤工俭学工资管理系统——实现对excel表格的数据操作(xwlings库)
基于Python的高校勤工俭学工资管理系统 1 需求概述 1.1 需求分析 勤工俭学是指学校组织的或学生个人从事的有酬劳动,用以助学.在我国,许多高校借以对学生进行劳动技术教育,培养正确的劳动观点和态 ...
- java iris_利用K-Means聚类算法实现对iris.data.ulab
该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 利用K-Means聚类算法实现对iris.data.ulabel数据的聚类,这是在网上找到如果要换成我的iris.date iris.date.ulabl ...
- C#代码实现对Windows凭据的管理
今天有个任务,那就是使用C#代码实现对windows凭据管理的操作. 例如:向windows凭据管理中添加凭据.删除凭据以及查询凭据等功能. 于是乎,就开始在网上查找.经过漫长的查询路,终于在一片英文 ...
- 51单片机实现对24C02进行页写、顺序读取并显示验证
源:51单片机实现对24C02进行页写.顺序读取并显示验证 //******************************************************************** ...
- 通过memcached来实现对tomcat集群中Session的共享策略 .
近期在做一套集群的实现,实现的方案是在Linux下完成对Apache + Tomcat 负载均衡的功能. 但是实现了该集群后,发现登陆系统后,每次都会被拦截回登录页面,造成该现象的原因是Session ...
- maven mybatis mysql_Java Web学习系列——Maven Web项目中集成使用Spring、MyBatis实现对MySQL的数据访问...
标签: 本篇内容还是建立在上一篇Java Web学习系列--Maven Web项目中集成使用Spring基础之上,对之前的Maven Web项目进行升级改造,实现对MySQL的数据访问. 添加依赖Ja ...
- Note:HTTP服务器是如何实现对PHP支持的
目前各种服务器HTTP Server对PHP的支持一共有三种: 通过HTTP Server内置的模块来实现,例如Apache的mod_php5,类似的Apache内置的mod_perl可以对perl支 ...
- java实现对HDFS增删改查(CRUD)等操作
实现对HDFS增删改查CRUD等操作 1 查找 列出某个目录下的文件名称,hdfs命令如下所示: hdfs dfs –ls/usr/app java代码片段: [plain] view plain c ...
- 修改html时webpack热更新,利用webpack实现对html文件的热更新
webpack中webpack-dev-server是一个简单的web服务器,能够帮助咱们实现代码的热更新,即在实际开发中只需保存修改完后的代码,不用手动刷新页面就能够看到效果.在使用webpack- ...
- php xml 增删改查,PHP实现对xml进行简单的增删改查(CRUD)操作示例
本文实例讲述了PHP实现对xml进行简单的增删改查(CRUD)操作.分享给大家供大家参考,具体如下: 假如有下面xml文件: 55.8 56 40 339 如何使用php对它进行CRUD?其实像这种简 ...
最新文章
- python二级考试试题4答案_第4卷讲解Python语言计算机等级考试二级操作题
- 【工具软件】webstorm的实用快捷操作(持续积累)
- 有了这篇 Shell 脚本实践指南,同事对我“刮目相看”!
- 过早扩张、未经检验的技术,创业公司最易跳入哪些致命陷阱?
- python与数据思维基础笔记_Python小课笔记--Python基础:数据和函数(二)
- 数据库记录的添加、修改、删除(DataAdapter、DataTable 、DataRow )
- (转)Linux内核参数之arp_ignore和arp_announce
- js中的数据类型分为两大类分别是什么_数据类型有这么重要吗?
- iOS开发:几种静态扫描工具的使用与对比
- 对于NAS,IP SAN以及iSCSCI SAN存储的一些认识和理解
- 欠采样临界采样matlab,信号临界采样、过采样、欠采样实验报告
- SPSS中的均值比较—假设检验
- 将Origin Pro设置成中文显示
- 2020年的5种常见骇客行为,你的电脑安全吗?
- 系统提供人民币(CNY)美元(USD)英镑(GBP)价值转换
- P和NP以及NPC、NP-Hard问题
- 电脑和打印机怎么连接
- 建立图书馆书目索引表
- 福州古刹梅林尽染 林阳赏梅成闽都新俗
- java 加法计算器
热门文章
- Docker 占用磁盘空间清理
- 团队管理之—— 大项目:把握关键点,谋定而后动
- TF之saved-model踩坑,多次保存模型必看
- 由二叉树前序序列、中序序列输出相应后续序列
- EBS R12中SLA子分类帐与子模块的关联关系
- php设计鸡兔同笼问题解法,鸡兔同笼问题口诀及解题方法(含经典应用题及答案)...
- 【数据结构】以不完整拼音搜索通讯录算法设计
- ptcms自动采集小说系统源码 电脑版+手机版
- SpringBoot 动态设置响应头的content-type
- 2021年中国钢铁行业发展现状分析,“双碳”背景下行业转型步伐加快「图」