乐趣区

关于spring:阿里P7大佬首次分享Spring-Retry不为人知的技巧

今日分享开始啦,请大家多多指教~

内部服务对于调用者来说个别都是不牢靠的,尤其是在网络环境比拟差的状况下,网络抖动很容易导致申请超时等异常情况,这时候就须要应用失败重试策略从新调用 API 接口来获取。重试策略在服务治理方面也有很宽泛的应用,通过定时检测,来查看服务是否存活。

Spring 异样重试框架 Spring Retry

Spring Retry 反对集成到 Spring 或者 Spring Boot 我的项目中,而它反对 AOP 的切面注入写法,所以在引入时必须引入 aspectjweaver.jar 包。

1. 引入 maven 依赖

2. 增加 @Retryable 和 @Recover 注解

@Retryable 注解,被注解的办法产生异样时会重试

  • value:指定产生的异样进行重试
  • include:和 value 一样,默认空,当 exclude 也为空时,所有异样都重试
  • exclude:指定异样不重试,默认空,当 include 也为空时,所有异样都重试
  • maxAttemps:重试次数,默认 3
  • backoff:重试弥补机制,默认没有

@Backoff 注解

  • delay: 指定提早后重试
  • multiplier: 指定提早的倍数,比方 delay=5000l,multiplier=2 时,第一次重试为 5 秒后,第二次为 10 秒,第三次为 20 秒

@Recover 注解: 当重试达到指定次数时,被注解的办法将被回调,能够在该办法中进行日志解决。须要留神的是产生的异样和入参类型统一时才会回调。

3. 启用重试性能

启动类下面增加 @EnableRetry 注解,启用重试性能,或者在应用 retry 的 service 下面增加也能够,或者 Configuration 配置类下面。倡议所有的 Enable 配置加在启动类上,能够清晰地对立治理应用的性能。

4. 启动服务,运行测试

基于 guava 的重试组件 Guava-Retryer

间接看组件作者对此组件的介绍:

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.(这是对 Google 的 guava 库的一个小扩大,容许为任意函数调用创立可配置的重试策略,例如与运行工夫不稳固的近程服务对话的策略。)

第一步引入 maven 坐标:

1. 其次要接口及策略介绍

  • 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:复合时长期待策略;

2. 依据后果判断是否重试

应用场景:如果返回值决定是否要重试。重试接口:

测试:

输入:

3. 依据异样判断是否重试

应用场景:依据抛出异样类型判断是否执行重试。重试接口:

测试:

输入:

4. 重试策略——设定有限重试

应用场景:在有异常情况下,有限重试(默认执行策略),直到返回失常无效后果;

5. 重试策略——设定最大的重试次数

应用场景:在有异常情况下,最多重试次数,如果超过次数则会抛出异样;

测试:

输入:

6. 期待策略——设定重试期待固定时长策略

应用场景:设定每次重试期待距离固定为 10s;

测试输入,能够看出调用距离是 10S:

7. 期待策略——设定重试期待时长固定增长策略

场景:设定初始期待时长值,并设定固定增长步长,但不设定最大期待时长;

测试输入,能够看出调用间隔时间递增 1 秒:

8. 期待策略——设定重试期待时长按指数增长策略

应用场景:依据 multiplier 值依照指数级增长期待时长,并设定最大期待时长;

这个重试策略和入参不是很懂,好吧,查看源码:

通过源码看出 ExponentialWaitStrategy 是一个不可变的外部类,结构器中校验入参,最重要的延迟时间计算方法 computeSleepTime(),能够看出延迟时间计算形式

计算以 2 为底失败次数为指数的值

第一步的值结构器第一个入参相乘,而后四舍五入失去延迟时间(毫秒)

通过以上剖析可知入参为 1000 工夫隔是应该为 2,4,8s

测试输入,能够看出调用间隔时间 2×1000,4×1000,8×1000:

9. 期待策略——设定重试期待时长按斐波那契数列策略

应用场景:依据 multiplier 值依照斐波那契数列增长期待时长,并设定最大期待时长,斐波那契数列:1、1、2、3、5、8、13、21、34、……

同样,看源码可知计算可知延迟时间为斐波那契数列和第一入参的乘积(毫秒)

测试输入,可看出距离调用为 1×1000,1×1000,2×1000:

10. 期待策略——组合重试期待时长策略

应用场景:当现有策略不满足应用场景时,能够对多个策略进行组合应用。

同样,看源码能力了解组合策略是什么意思:

可看出组合策略其实依照多个策略的延迟时间相加失去组合策略的延迟时间。exponentialWait 的延迟时间为 2,4,8,16,32…,fixedWait 提早为 2,2,2,2,2…, 所以总的延迟时间为 4,6,10,18,34…

测试输入:

11. 监听器——RetryListener 实现重试过程细节解决

应用场景:自定义监听器,别离打印重试过程中的细节,将来可更多的用于异步日志记录,亦或是非凡解决。

测试:

输入:

总结

两种形式都是比拟优雅的重试策略,Spring-retry 配置更简略,实现的性能也绝对简略,Guava 自身就是谷歌推出的精品 java 类库,guava-retry 也是性能十分弱小,相比拟于 Spring-Retry 在是否重试的判断条件上有更多的选择性,能够作为 Spring-retry 的补充。

退出移动版