重试作用:

对于重试是有场景限制的,不是什么场景都适合重试,比如参数校验不合法、写操作等(要考虑写是否幂等)都不适合重试。

远程调用超时、网络突然中断可以重试。在微服务治理框架中,通常都有自己的重试与超时配置,比如dubbo可以设置retries=1,timeout=500调用失败只重试1次,超过500ms调用仍未返回则调用失败。

比如外部 RPC 调用,或者数据入库等操作,如果一次操作失败,可以进行多次重试,提高调用成功的可能性

优雅的重试机制要具备几点:

  • 无侵入:这个好理解,不改动当前的业务逻辑,对于需要重试的地方,可以很简单的实现
  • 可配置:包括重试次数,重试的间隔时间,是否使用异步方式等
  • 通用性:最好是无改动(或者很小改动)的支持绝大部分的场景,拿过来直接可用

优雅重试共性和原理:

  • 正常和重试优雅解耦,重试断言条件实例或逻辑异常实例是两者沟通的媒介。
  • 约定重试间隔,差异性重试策略,设置重试超时时间,进一步保证重试有效性以及重试流程稳定性。
  • 都使用了命令设计模式,通过委托重试对象完成相应的逻辑操作,同时内部封装实现重试逻辑。
  • Spring-tryer和guava-tryer工具都是线程安全的重试,能够支持并发业务场景的重试逻辑正确性。

优雅重试适用场景:

  • 功能逻辑中存在不稳定依赖场景,需要使用重试获取预期结果或者尝试重新执行逻辑不立即结束。比如远程接口访问,数据加载访问,数据上传校验等等。
  • 对于异常场景存在需要重试场景,同时希望把正常逻辑和重试逻辑解耦。
  • 对于需要基于数据媒介交互,希望通过重试轮询检测执行逻辑场景也可以考虑重试方案。

优雅重试解决思路:

切面方式

这个思路比较清晰,在需要添加重试的方法上添加一个用于重试的自定义注解,然后在切面中实现重试的逻辑,主要的配置参数则根据注解中的选项来初始化

优点:

    • 真正的无侵入

缺点:

    • 某些方法无法被切面拦截的场景无法覆盖(如spring-aop无法切私有方法,final方法)
    • 直接使用aspecj则有些小复杂;如果用spring-aop,则只能切被spring容器管理的bean

消息总线方式

这个也比较容易理解,在需要重试的方法中,发送一个消息,并将业务逻辑作为回调方法传入;由一个订阅了重试消息的consumer来执行重试的业务逻辑

优点:

    • 重试机制不受任何限制,即在任何地方你都可以使用
    • 利用EventBus框架,可以非常容易把框架搭起来

缺点:

    • 业务侵入,需要在重试的业务处,主动发起一条重试消息
    • 调试理解复杂(消息总线方式的最大优点和缺点,就是过于灵活了,你可能都不知道什么地方处理这个消息,特别是新的童鞋来维护这段代码时)
    • 如果要获取返回结果,不太好处理, 上下文参数不好处理

模板方式

优点:

    • 简单(依赖简单:引入一个类就可以了; 使用简单:实现抽象类,讲业务逻辑填充即可;)
    • 灵活(这个是真正的灵活了,你想怎么干都可以,完全由你控制)

缺点:

    • 强侵入
    • 代码臃肿

把这个单独捞出来,主要是某些时候我就一两个地方要用到重试,简单的实现下就好了,也没有必用用到上面这么重的方式;而且我希望可以针对代码快进行重试

这个的设计还是非常简单的,基本上代码都可以直接贴出来,一目了然:

public abstract class RetryTemplate {

    private static final int DEFAULT_RETRY_TIME = 1;
private int retryTime = DEFAULT_RETRY_TIME;
private int sleepTime = 0;// 重试的睡眠时间 public int getSleepTime() {
return sleepTime;
} public RetryTemplate setSleepTime(int sleepTime) {
if(sleepTime < 0) {
throw new IllegalArgumentException("sleepTime should equal or bigger than 0");
}
this.sleepTime = sleepTime;
return this;
} public int getRetryTime() {
return retryTime;
} public RetryTemplate setRetryTime(int retryTime) {
if (retryTime <= 0) {
throw new IllegalArgumentException("retryTime should bigger than 0");
}
this.retryTime = retryTime;
return this;
} /**
* 重试的业务执行代码
* 失败时请抛出一个异常
*
* todo 确定返回的封装类,根据返回结果的状态来判定是否需要重试
*
* @return
*/
protected abstract Object doBiz() throws Exception; //预留一个doBiz方法由业务方来实现,在其中书写需要重试的业务代码,然后执行即可 public Object execute() throws InterruptedException {
for (int i = 0; i < retryTime; i++) {
try {
return doBiz();
} catch (Exception e) {
log.error("业务执行出现异常,e: {}", e);
Thread.sleep(sleepTime);
}
}
return null;
} public Object submit(ExecutorService executorService) {
if (executorService == null) {
throw new IllegalArgumentException("please choose executorService!");
}
return executorService.submit((Callable) () -> execute());
}
}

使用示例:

public void retryDemo() throws InterruptedException {
Object ans = new RetryTemplate() {
@Override
protected Object doBiz() throws Exception {
int temp = (int) (Math.random() * 10);
System.out.println(temp);
if (temp > 3) {
throw new Exception("generate value bigger then 3! need retry");
}
return temp;
}
}.setRetryTime(10).setSleepTime(10).execute();
System.out.println(ans);
}

Java重试机制的更多相关文章

  1. Java之Retry重试机制详解

    应用中需要实现一个功能: 需要将数据上传到远程存储服务,同时在返回处理成功情况下做其他操作.这个功能不复杂,分为两个步骤:第一步调用远程的Rest服务上传数据后对返回的结果进行处理:第二步拿到第一步结 ...

  2. 转 : 深入解析Java锁机制

    深入解析Java锁机制 https://mp.weixin.qq.com/s?__biz=MzU0OTE4MzYzMw%3D%3D&mid=2247485524&idx=1&s ...

  3. Volley超时重试机制

    基础用法 Volley为开发者提供了可配置的超时重试机制,我们在使用时只需要为我们的Request设置自定义的RetryPolicy即可. 参考设置代码如下: int DEFAULT_TIMEOUT_ ...

  4. Rocket重试机制,消息模式,刷盘方式

    一.Consumer 批量消费(推模式) 可以通过 consumer.setConsumeMessageBatchMaxSize(10);//每次拉取10条 这里需要分为2种情况 Consumer端先 ...

  5. Spring Cloud重试机制与各组件的重试总结

    SpringCloud重试机制配置 首先声明一点,这里的重试并不是报错以后的重试,而是负载均衡客户端发现远程请求实例不可到达后,去重试其他实例. ? 1 2 3 4 5 6 7 8 @Bean @Lo ...

  6. spring-retry 重试机制

    业务场景 应用中需要实现一个功能: 需要将数据上传到远程存储服务,同时在返回处理成功情况下做其他操作.这个功能不复杂,分为两个步骤:第一步调用远程的Rest服务逻辑包装给处理方法返回处理结果:第二步拿 ...

  7. Spring Cloud Gateway重试机制

    前言 重试,我相信大家并不陌生.在我们调用Http接口的时候,总会因为某种原因调用失败,这个时候我们可以通过重试的方式,来重新请求接口. 生活中这样的事例很多,比如打电话,对方正在通话中啊,信号不好啊 ...

  8. spring-retry 重试机制的使用

    场景:由于网络抖动原因,或者其他原因,需要对代码重新执行,这个就需要重试了. import org.springframework.context.annotation.Configuration; ...

  9. RocketMQ重试机制和消息幂等

    一.重试机制 由于MQ经常处于复杂的分布式系统中,考虑网络波动,服务宕机,程序异常因素,很有可能出现消息发送或者消费失败的问题.因此,消息的重试就是所有MQ中间件必须考虑到的一个关键点.如果没有消息重 ...

随机推荐

  1. LeetCode_415. Add Strings

    415. Add Strings Easy Given two non-negative integers num1 and num2 represented as string, return th ...

  2. 取消Windows server 2008关机提示备注的方法

    打开“开始”-“运行”,在“打开”一栏中输入“gpedit.msc”命令打开组策略编辑器,依次展开“计算机配置”→“管理模板”→“系统”,双击右侧窗口出现的“显示‘关闭事件跟踪程序’”,将“未配置”改 ...

  3. [LeetCode] 86. Partition List 划分链表

    Given a linked list and a value x, partition it such that all nodes less than x come before nodes gr ...

  4. bugclose使用—bug管理工具

    1.前言 bugclose管理的是BUG,而不仅仅是bug.BUG概念是bugclose的创造,代表团队工作的对象,包括缺陷,任务和需求. 2.bugclose访问地址 访问地址:https://ww ...

  5. linux : 各个发行版中修改python27默认编码为utf-8

    该方法可解决robot报错:'ascii' codec can't encode character u'\xf1' in position 16: ordinal not in  range(128 ...

  6. TortoiseGit,git 未能顺利结束 (退出码 1)

    其中一个原因是不能把Git下所有文件全部删除,一个都没有,就会报这个错误. 注:空文件夹git定义为空,不是文件.所以只有空文件夹也会报这个错误.

  7. 机器学习技法总结(四)(aggregation,vote,bootstrap...)

    研究的动机是:我们采用了不同的模型得到T个不同的g,那么我们是不是可以通过这些不同的g的融合得到更加出色的G呢?因此,便有了以上四种不同的方法:1)(select)直接选择最好的一个作为融合的结果:2 ...

  8. [转] ABP框架Web API跨域问题的解决方案

    原文地址:​https://www.cnblogs.com/farb/p/ABPWebAPICrossDomain.html 1.在Web Api 项目下安装 Microsoft.AspNet.Web ...

  9. .net webapi跨域 web.config配置

    <system.webServer> <httpProtocol> <customHeaders> <add name="Access-Contro ...

  10. 重回ubutntu12.04小记(装完ubuntu做的几件事)

    原来一直是在windows下用虚拟机跑redhat 和debian 做实验和一些工程,以前也装过ubuntu和windows双系统,但是换电脑后,就一直懒得捣鼓了. 现在,由于长期需要在linux上做 ...