美文网首页
非常非常地重试重试组件,使用杠铃的

非常非常地重试重试组件,使用杠铃的

作者: 欧子有话说_ | 来源:发表于2022-09-20 10:35 被阅读0次

前言

小伙伴是不是经常遇到接口调用异常的情况?

很多小伙伴的实现方式是写个循环调用;

for(int i= 1 ;i<= 3 ;i++){
try {
if (doExec()){
break ;
}
}抓{
}
}
方式是比较简单的,但是非常不灵活,今天出门不能很顾虑,但是这种情况很顾虑。实现给大家带来一个重试重试的组件,流行度很明亮,即是番石榴重试组件。功能强大,是平日旅行的必备工具。

引用

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

<! -- <exclusions>-->



<!- - </exclusions>-->
</依赖>
guava-retrying包中应用有相关的guava版本依赖,如果和自身项目突破可以解决。

示例

执行方法

@Service public class RetryService {
private static Logger logger = LoggerFactory.getLogger ( RetryService.class )
; _
私有AtomicInteger计数= 新AtomicInteger ( 0 );
公共int doExec(){
logger.info( "调用了{}次" , count .incrementAndGet());
if ( count . get () % 2 == 0 ){
throw new Exception ( "----->异常了哦" );
}
返回 计数。得到();
}
}
其中定义了doExec方法,每次调用计数加1,如果是的倍数就抛。

调用方法

公共字符串 test01(){
Retryer<Integer> retryer = RetryerBuilder.<Integer>newBuilder()
.retryIfRuntimeException()
//retryIfResult 表达式返回true,则重试
.retryIfResult(结果 -> {
如果(结果 % 3 == 0){
logger.info( "----->应该试重了" );
返回 真;
}
返回 假;
})
.withStopStrategy(StopStrategies.stopAfterAttempt( 3 ))
。建造();
试试{
retryer.call(() -> retryService.doExec());
}捕捉(ExecutionException e){
logger.error( "异常1:{}" ,e.getMessage());
}捕捉(重试异常 e){
logger.error( "异常:{}" ,e.getMessage());
}
返回 “确定”;
}
从上面代码中,我们就可以实现条件重试。

番石榴的重试思想可分为重试重条件、停试策略、重试间歇策略

一、试重条件

表示在什么情况下,重试。重试组件中的RetryerBuilder的retryIfXXX()方法使用设置在什么情况下进行重试,用户可以在什么情况下根据执行异常进行重试和根据方法执行结果进行重试三个。

可知异常重试

1、retryIfException() 当执行方法抛出异常时重试

2、retryIfRuntimeException()当方法执行抛出异常RuntimeException时重试

3、retryIfExceptionOfType(exceptionClass)当方法执行抛出异常具体哪个异常时重试

4、retryIfException(Predicate p)自定义异常什么情况下重试

可知返回结果重试

retryIfResult(@Nonnull Predicate<V> resultPredicate)根据返回值判断是否重试。

//返回真时,重试
.retryIfResult(结果 -> {
如果(结果 % 3 == 0){
logger.info( "----->应该试重了" );
返回 真;
}
返回 假;
})
上面的结果代表的是返回值,判断返回值对3取余,返回真实时则进行重试。

二、停止重试策略

重试需要提供停止重试的策略withStopStrategy,简单的方式就是重试次数最多

1、StopAfterAttempt策略

从面字上面就知道什么英文,即在执行次数指定次数之后停止重试。

.withStopStrategy ( StopStrategies .stopAfterAttempt (3))
2、永不停止策略

永远重试,一直重试

.withStopStrategy ( StopStrategies .neverStop ())
3、StopAfterDelay策略

设定一个最长的时间;只要设定一次执行最多执行10s,不计次数,试试的时间与第一次的时间差,最长时间,执行则执行,返回执行重试重试异常

.withStopStrategy ( StopStrategies .stopAfterDelay (10, TimeUnit .SECONDS ))
三、重试间隔策略

在重试场景中,我们最好的试试重试的间隔,如果没有间隔,可能有连续的重试失败。

等待策略

1、固定等待策略

固定时长重试间歇。

.withWaitStrategy ( WaitStrategies .fixedWait (1, TimeUnit .SECONDS ))
那就是重试间隔为1秒。

2、随机等待策略

随时的间隔时长

.withWaitStrategy ( WaitStrategies .randomWait (1, TimeUnit .SECONDS ,5, TimeUnit .SECONDS ))
第1个间隔时间长,最小个间隔时间长的时间;每次间隔时间是第二个参数。

3、增量等待策略

递增的间隔时间长,即每次任务重试的时间递增,越来越长

.withWaitStrategy ( WaitStrategies .incrementingWait (3, TimeUnit .SECONDS ,1, TimeUnit .SECONDS ))
该策略输入一个每隔一段时间的等待时间增加一个步长,然后每次值和时间的长都递增。

4、异常等待策略

根据不同的不同,决定不同的间隔时长。

.withWaitStrategy (WaitStrategies.exceptionWait(Exception.class, new Function<Exception, Long>() {
@Override
public @Nullable Long apply( @Nullable异常输入) {
if (input instanceof NullPointerException){
返回 1 * 1000升;
}else if (input instanceof IndexOutOfBoundsException){
返回 2 * 1000升;
}else if (input instanceof IllegalStateException){
返回 3 * 1000升;
}
返回0升;
}
}))
这个的代码一看就知道了。

是一些常见的策略,不常用的策略,小伙伴们先等待。

我们需要记录一个非常重要的试试机会关注系统的产品。

我们来介绍一下重试监听器。

重试监听器RetryListener

当重试时,会调用RetryListener的onRetry方法,这样我们就可以做一些自定义的重试的额外任务。

定义一个类,继承RetryListener接口

公共 类 MyRetryListener 实现 RetryListener {

私有 静态Logger logger = LoggerFactory.getLogger(MyRetryListener.class);

@Override 
public <Integer> void  onRetry (Attempt<Integer> 尝试)  {
     if (attempt.hasResult()){
        logger.info( "===> 方法返回的结果:{}" ,attempt.getResult());
    }

    if (attempt.hasException()){
        logger.info( "===>第{}次执行, 异常:{}" ,attempt.getAttemptNumber(),attempt.getExceptionCause()== null ? "" : attempt.getExceptionCause().getMessage());
        返回;
    }
    logger.info( "===>第{}次执行" ,attempt.getAttemptNumber());
}

}
在RetryerBuilder中加入;

.withRetryListener (new MyRetryListener())
这样就实现了监听业务

重试原理

guava-retrying的组件功能还是比较强大的,我们可以看看内核的代码

public V call (Callable<V> callable) throws ExecutionException, RetryException {
long startTime = System.nanoTime();

// 执行次数从
1Startfor ( int attemptNumber = 1 ; ; attemptNumber++) {
尝试<V>尝试;
try {
//尝试执行
V result = attemptTimeLimiter. 调用(可调用);

  // 执行成功则将结果封装为ResultAttempt 
  attempt = Retryer.ResultAttempt <V>(result, tryNumberlis(System.nanoTime() - startTime));
} catch 
  ( Thrable t) { // 执行异常则将封装结果为ExceptionAttempt
  
}

// 这里将执行结果传给RetryListener 做一些额外的事情
for (RetryListener listener : listeners) {
  listener.onRetry(尝试);
}
//这个就是决定是否要进行重试的地方,如果不进行重试直接返回结果,执行成功就返回结果,执行失败就返回异常
if (!rejectionPredicate.apply(attempt)) {
   return attempt.get() ;
}

// 到这里,说明需要重试,此时先决定是否达到异常则停止重试的时机,如果了则直接返回
if (stopStrategy.shouldStop(attempt)) {
   throw  new RetryException(attemptNumber, attempt) ;
} else {
   // 决定重试间隔
  long sleepTime = waitStrategy.computeSleepTime(attempt);
  尝试{
     // 进行阻尼
    blockStrategy.block(sleepTime);
  }捕捉(InterruptedException e){
    Thread.currentThread().interrupt();
    抛出 新的重试异常(尝试编号,尝试);
  }
}

}

}

相关文章

  • 非常非常地重试重试组件,使用杠铃的

    前言 小伙伴是不是经常遇到接口调用异常的情况? 很多小伙伴的实现方式是写个循环调用; for(int i= 1 ;...

  • 重试利器之Guava Retrying

    目录 重试的使用场景 如何优雅地设计重试实现 guava-retrying基础用法 guava-retrying实...

  • 分布式弹力设计之重试机制

    重试机制的使用场景 重试的前提是认为故障是暂时的,不是永久的,所以重试才有意义。 使用重试机制是必须要明确哪些错误...

  • 一文详解Spring Cloud Feign重试机制

    前言 Feign组件默认使用Ribbon的重试机制并增加了根据状态码判断重试机制,默认情况下是不启用的。Feign...

  • Python重试的多重方法

    没人能保证自己的的程序没BUG,所以重试非常有必要。 下面说下我知道的几种Python重试方法。 装饰器 这是最最...

  • RocketMQ(九)高级特性-消息重试机制

    rocketMq具有消息重试的机制,重试也分为两种重试:producer重试和consumer重试。 produc...

  • Spring提供的重试模板Spring Retry的使用

    使用场景:有些业务有调用失败的情况,可以 设置多次重试,当重试达到一定次数后取消重试。 使用步骤:1、首先要添加依...

  • 牢骚打油

    题记:最近简书问题不少,经常打不开文章,老是提示重试,重试多了,就非常考验我的耐心。好吧,我投降,我试不了,也不想...

  • Spring Retry 详细教程

    什么时候用可以重试 远程调用失败的可以重试 参校失败不应该重试 只读操作可以重试 幂等写操作可以重试 非幂等写操作...

  • Dubbo-Retry超时重试导致数据重复问题

    使用dubbo的重试机制造成了不小的困恼,就希望dubbo能在数据写入操作不进行重试,读取操作进行重试,是否可有相...

网友评论

      本文标题:非常非常地重试重试组件,使用杠铃的

      本文链接:https://www.haomeiwen.com/subject/krnmortx.html