前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >SpringBoot 实现Guava Retry重试机制

SpringBoot 实现Guava Retry重试机制

原创
作者头像
HLee
修改2021-11-08 14:53:04
1.4K0
修改2021-11-08 14:53:04
举报
文章被收录于专栏:房东的猫房东的猫

简介

一般在各种业务场景中,为了保持系统稳定,我们都会有相应的重试机制,因为比如说,某个接口某个数据库链接由于网络抖动或者其他因素导致响应失败,这时候直接判定失败或者Mock数据未必是一种优雅的方式,因为这种情况下未必是接口挂掉了或者数据库连不上了,有可能是网络一时的抖动导致的,所以这时候一个优雅的重试机制或许能帮上我们。

Guava Retry

Guava Retry模块提供了一种通用方法, 可以使用Guava谓词匹配增强的特定停止、重试和异常处理功能来重试任意Java代码。

代码语言:javascript
复制
https://github.com/rholder/guava-retrying

Guava Retry优点

Guava retryer工具与spring-retry类似,都是通过定义重试者角色来包装正常逻辑重试,但是Guava retryer有更优的策略定义,在支持重试次数和重试频度控制基础上,能够兼容支持多个异常或者自定义实体对象的重试源定义,让重试功能有更多的灵活性。

Guava Retryer也是线程安全的,入口调用逻辑采用的是 java.util.concurrent.Callable 的 call() 方法

maven 引入

代码语言:javascript
复制
<dependency>
  <groupId>com.github.rholder</groupId>
  <artifactId>guava-retrying</artifactId>
  <version>2.0.0</version>
</dependency>

永远重试的 Retryer

创建一个可以永远重试的 Retryer,在每次失败的重试之后,以递增指数的间隔等待直到最多5分钟。5分钟后,每隔5分钟重试一次。

代码语言:javascript
复制
Retryer<Boolean> retryer = RetryerBuilder.<Boolean>newBuilder()
        .retryIfExceptionOfType(IOException.class)
        .retryIfRuntimeException()
        .withWaitStrategy(WaitStrategies.exponentialWait(100, 5, TimeUnit.MINUTES))
        .withStopStrategy(StopStrategies.neverStop())
        .build();

创建一个可以永远重试的 Retryer,在每次失败的重试之后,增加斐波那契回退间隔,直到最多2分钟。2分钟后,每隔2分钟重试一次。

代码语言:javascript
复制
Retryer<Boolean> retryer = RetryerBuilder.<Boolean>newBuilder()
        .retryIfExceptionOfType(IOException.class)
        .retryIfRuntimeException()
        .withWaitStrategy(WaitStrategies.fibonacciWait(100, 2, TimeUnit.MINUTES))
        .withStopStrategy(StopStrategies.neverStop())
        .build();
代码语言:javascript
复制
//定义重试机制
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))

      //时间限制 : 某次请求不得超过2s , 类似: TimeLimiter timeLimiter = new SimpleTimeLimiter();
      .withAttemptTimeLimiter(AttemptTimeLimiters.fixedTimeLimit(2, TimeUnit.SECONDS))

       .build();

实现用例

代码语言:javascript
复制
import com.github.rholder.retry.*;
import com.google.common.base.Predicates;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;

@Slf4j
public class RetryerDemo {

    public static void main(String[] args) {
        //定义请求实现
        Callable<Boolean> callable = new Callable<Boolean>() {
            @Override
            public Boolean call() throws Exception {
                // do something useful here
                log.info("call...");
                throw new RuntimeException();
            }
        };

        //定义重试机制
        Retryer<Boolean> retryer = RetryerBuilder.<Boolean>newBuilder()
                // retryIf 重试条件
                .retryIfResult(Predicates.isNull())
                .retryIfExceptionOfType(IOException.class)
                .retryIfRuntimeException()
                .withStopStrategy(StopStrategies.stopAfterAttempt(3))
                .build();
        try {
            retryer.call(callable);
        } catch (RetryException | ExecutionException e) {
            e.printStackTrace();
        }

    }
}

输出:
com.github.rholder.retry.RetryException: Retrying failed to complete successfully after 3 attempts.
	at com.github.rholder.retry.Retryer.call(Retryer.java:174)
	at com.spring.master.spring.guava.retryer.RetryerDemo.main(RetryerDemo.java:39)
Caused by: java.lang.RuntimeException
	at com.spring.master.spring.guava.retryer.RetryerDemo$1.call(RetryerDemo.java:27)
	at com.spring.master.spring.guava.retryer.RetryerDemo$1.call(RetryerDemo.java:22)
	at com.github.rholder.retry.AttemptTimeLimiters$NoAttemptTimeLimit.call(AttemptTimeLimiters.java:78)
	at com.github.rholder.retry.Retryer.call(Retryer.java:160)
	... 1 more

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 简介
    • Guava Retry
      • Guava Retry优点
        • maven 引入
          • 永远重试的 Retryer
          • 实现用例
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档