本文研究的主要是Java编程Retry重试机制实例详解,分享了相关代码示例,小编觉得还是挺不错的,具有一定借鉴价值,需要的朋友可以参考下
成都创新互联公司专注于太仆寺网站建设服务及定制,我们拥有丰富的企业做网站经验。 热诚为您提供太仆寺营销型网站建设,太仆寺网站制作、太仆寺网页设计、太仆寺网站官网定制、微信小程序开发服务,打造太仆寺网络公司原创品牌,更为您提供太仆寺网站排名全网营销落地服务。
1、业务场景
应用中需要实现一个功能: 需要将数据上传到远程存储服务,同时在返回处理成功情况下做其他操作。这个功能不复杂,分为两个步骤:第一步调用远程的Rest服务逻辑包装给处理方法返回处理结果;第二步拿到第一步结果或者捕捉异常,如果出现错误或异常实现重试上传逻辑,否则继续逻辑操作。
2、常规解决方案演化
1)try-catch-redo简单重试模式:
包装正常上传逻辑基础上,通过判断返回结果或监听异常决策是否重试,同时为了解决立即重试的无效执行(假设异常是有外部执行不稳定导致的),休眠一定延迟时间重新执行功能逻辑。
public void commonRetry(Map dataMap) throws InterruptedException {
Map paramMap = Maps.newHashMap();
paramMap.put("tableName", "creativeTable");
paramMap.put("ds", "20160220");
paramMap.put("dataMap", dataMap);
boolean result = false;
try {
result = uploadToOdps(paramMap);
if (!result) {
Thread.sleep(1000);
uploadToOdps(paramMap); //一次重试
}
} catch (Exception e) {
Thread.sleep(1000);
uploadToOdps(paramMap);//一次重试
}
}
2)try-catch-redo-retry strategy策略重试模式:
上述方案还是有可能重试无效,解决这个问题尝试增加重试次数retrycount以及重试间隔周期interval,达到增加重试有效的可能性。
public void commonRetry(Map dataMap) throws InterruptedException {
Map paramMap = Maps.newHashMap();
paramMap.put("tableName", "creativeTable");
paramMap.put("ds", "20160220");
paramMap.put("dataMap", dataMap);
boolean result = false;
try {
result = uploadToOdps(paramMap);
if (!result) {
reuploadToOdps(paramMap,1000L,10);//延迟多次重试
}
} catch (Exception e) {
reuploadToOdps(paramMap,1000L,10);//延迟多次重试
}
}
方案一和方案二存在一个问题:正常逻辑和重试逻辑强耦合,重试逻辑非常依赖正常逻辑的执行结果,对正常逻辑预期结果被动重试触发,对于重试根源往往由于逻辑复杂被淹没,可能导致后续运维对于重试逻辑要解决什么问题产生不一致理解。重试正确性难保证而且不利于运维,原因是重试设计依赖正常逻辑异常或重试根源的臆测。
3、优雅重试方案尝试:
那有没有可以参考的方案实现正常逻辑和重试逻辑解耦,同时能够让重试逻辑有一个标准化的解决思路?答案是有:那就是基于代理设计模式的重试工具,我们尝试使用相应工具来重构上述场景。
1)应用命令设计模式解耦正常和重试逻辑:
命令设计模式具体定义不展开阐述,主要该方案看中命令模式能够通过执行对象完成接口操作逻辑,同时内部封装处理重试逻辑,不暴露实现细节,对于调用者来看就是执行了正常逻辑,达到解耦的目标,具体看下功能实现。(类图结构)

IRetry约定了上传和重试接口,其实现类OdpsRetry封装ODPS上传逻辑,同时封装重试机制和重试策略。与此同时使用recover方法在结束执行做恢复操作。
而我们的调用者LogicClient无需关注重试,通过重试者Retryer实现约定接口功能,同时 Retryer需要对重试逻辑做出响应和处理, Retryer具体重试处理又交给真正的IRtry接口的实现类OdpsRetry完成。通过采用命令模式,优雅实现正常逻辑和重试逻辑分离,同时通过构建重试者角色,实现正常逻辑和重试逻辑的分离,让重试有更好的扩展性。
2)spring-retry 规范正常和重试逻辑
spring-retry是一个开源工具包,目前可用的版本为1.1.2.RELEASE,该工具把重试操作模板定制化,可以设置重试策略和回退策略。同时重试执行实例保证线程安全,具体场景操作实例如下:
public void upload(final Map map) throws Exception {
// 构建重试模板实例
RetryTemplate retryTemplate = new RetryTemplate();
// 设置重试策略,主要设置重试次数
SimpleRetryPolicy policy = new SimpleRetryPolicy(3, Collections., Boolean> singletonMap(Exception.class, true));
// 设置重试回退操作策略,主要设置重试间隔时间
FixedBackOffPolicy fixedBackOffPolicy = new FixedBackOffPolicy();
fixedBackOffPolicy.setBackOffPeriod(100);
retryTemplate.setRetryPolicy(policy);
retryTemplate.setBackOffPolicy(fixedBackOffPolicy);
// 通过RetryCallback 重试回调实例包装正常逻辑逻辑,第一次执行和重试执行执行的都是这段逻辑
final RetryCallback