在很多业务场景中,为了排除系统中的各种不稳定因素,以及逻辑上的错误,并最大概率保证获得预期的结果,重试机制都是必不可少的。
尤其是调用远程服务,在高并发场景下,很可能因为服务器响应延迟或者网络原因,造成我们得不到想要的结果,或者根本得不到响应。这个时候,一个优雅的重试调用机制,可以让我们更大概率保证得到预期的响应。
一个完备的重试实现,要很好地解决如下问题: 1. 什么条件下重试 2. 什么条件下停止 3. 如何停止重试 4. 停止重试等待多久 5. 如何等待 6. 请求时间限制 7. 如何结束 8. 如何监听整个重试过程
<dependency>
<groupId>com.github.rholder</groupId>
<artifactId>guava-retrying</artifactId>
<version>2.0.0</version>
</dependency>
完整的参考实现
public Boolean test() throws Exception {
//定义重试机制
Retryer<Boolean> retryer = RetryerBuilder.<Boolean>newBuilder()
//retryIf 重试条件
.retryIfException()
.retryIfRuntimeException()
.retryIfExceptionOfType(Exception.class)
.retryIfException(Predicates.equalTo(new Exception()))
.retryIfResult(Predicates.equalTo(false))
//等待策略:每次请求间隔1s
.withWaitStrategy(WaitStrategies.fixedWait(1, TimeUnit.SECONDS))
//停止策略 : 尝试请求6次
.withStopStrategy(StopStrategies.stopAfterAttempt(6))
//时间限制 : 某次请求不得超过3s 否则重试
.withAttemptTimeLimiter(AttemptTimeLimiters.fixedTimeLimit(3, TimeUnit.SECONDS))
.build();
//定义请求实现
Callable<Boolean> callable = new Callable<Boolean>() {
int times = 1;
@Override
public Boolean call() throws Exception {
log.info("call times={}", times);
times++;
if (times == 2) {
throw new NullPointerException();
} else if (times == 3) {
throw new Exception();
} else if (times == 4) {
throw new RuntimeException();
} else if (times == 5) {
return false;
} else {
return true;
}
}
};
//利用重试器调用请求
return retryer.call(callable);
}
具体相关质料可自行百度,因为比较简单这里就不啰嗦了
1.POM依赖
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
</dependency>
2.启用@Retryable
@EnableRetry
@SpringBootApplication
public class HelloApplication {
public static void main(String[] args) {
SpringApplication.run(HelloApplication.class, args);
}
}
3.演示
@Service
public class TestRetryServiceImpl implements TestRetryService {
// 需要重试的方法 注意: 方法必须为 public
@Override
@Retryable(value = Exception.class,maxAttempts = 3,backoff = @Backoff(delay = 2000,multiplier = 1.5))
public int test(int code,String mess,String name) throws Exception{
System.out.println("test被调用,时间:"+ LocalTime.now());
if (code==400){
throw new Exception("情况不对头!");
}
System.out.println("test被调用,情况对头了!");
return 200;
}
// 回调方法 注意: 方法必须为 public
@Recover
public int recover(Exception e, int code,String name){
System.out.println("回调方法执行!!!!");
System.out.println("code: "+code);
System.out.println("name: "+name);
//记日志到数据库 或者调用其余的方法
return 500;
}
}
来简单解释一下 @Retryable注解中几个参数的含义:
当重试耗尽时还是失败,会出现什么情况呢?
当重试耗尽时,RetryOperations可以将控制传递给另一个回调,即RecoveryCallback。Spring-Retry还提供了@Recover注解,用于@Retryable重试失败后处理方法。如果不需要回调方法,可以直接不写回调方法,那么实现的效果是,重试次数完了后,如果还是没成功没符合业务判断,就抛出异常。
对于@Recover注解的方法,需要特别注意的是:
点赞 -收藏-关注-便于以后复习和收到最新内容有其他问题在评论区讨论-或者私信我-收到会在第一时间回复在本博客学习的技术不得以任何方式直接或者间接的从事违反中华人民共和国法律,内容仅供学习、交流与参考免责声明:本文部分素材来源于网络,版权归原创者所有,如存在文章/图片/音视频等使用不当的情况,请随时私信联系我、以迅速采取适当措施,避免给双方造成不必要的经济损失。感谢,配合,希望我的努力对你有帮助^_^
版权说明 : 本文为转载文章, 版权归原作者所有 版权申明
原文链接 : https://huanmin.blog.csdn.net/article/details/126265780
内容来源于网络,如有侵权,请联系作者删除!