java优雅的重试

java优雅的重试

一、概述

在项目开发中,我们经常会遇到多服务直接互相调用之类的场景,而由于网络的不稳定性,请求可能偶尔失败,如何优雅的进行失败重试,也是我们开发中不得不去考虑的一个问题。

一个基本的重试流程,需要我们去解决最基础的重试要求:
1、在什么条件下进行重试
2、在什么条件下停止重试

然而对于一个设计优良的重试程序,更要去我们去进一步完善实现
1、重试次数设置
2、重试时间间隔
3、重试超时时间

二、java重试框架之guava-retrying

guava-retrying是基于谷歌的核心类库guava的重试实现机制,可以方便快速的解决我们开发场景中常见的重试问题。

1、jar包maven引用

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

2、构建一个重试器,对重试条件,等待策略,停止策略等进行设置

Retryer myRetryer = 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(3, TimeUnit.SECONDS))
                    .build();

3、定义重试的业务

Callable<Boolean> myServiceCallable = new Callable<Boolean>() {
    int times = 1;
    @Override
    public Boolean call() {
        log.info("myService重试第{}次", times);
        try {
            // 处理业务
            handleService();
            return true;
        } catch (Exception e) {
            times++;
            return false;
        }
    }
};

4、执行重试

myRetryer.call(myServiceCallable);

在java8中也可以使用函数式编程,直接调用call方法,更加简明直接

mailRetryer.call(() -> {
    try {
        // 处理业务
        handleService();
        return true;
    } catch (Exception e) {
        return false;
    }
});

5、在spring中优雅的定义全局Retryer

在一个大型的项目中,我们不可能去对每一处的业务处理都实现一个重试器,这对资源和内存也是一种浪费,这时候就需要我们对某一组重试机制相同的业务,只创建一各重试器就可以。
在spring中,我们可以利用bean的单例性质,来创建一组全局的重试器。根据业务需要,选择使用不同类型的重试器

@Slf4j
@Component
public class CustomizeRetryer {

    //定义发送邮件的重试器
    private Retryer<Boolean> mailRetryer;

    //定义发送短信的重试器
    private Retryer<Boolean> msgRetryer;

    @Bean(value = "mailRetryer")
    public Retryer mailRetryer(){
        log.info("===========init mailRetryer==========");
        mailRetryer = 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))
                .build();
        return mailRetryer;
    }

    @Bean(value = "msgRetryer")
    public Retryer msgRetryer(){
        log.info("=========init msgRetryer===========");
        msgRetryer = RetryerBuilder.<Boolean>newBuilder()
                //retryIf 重试条件
                .retryIfException()
                .retryIfRuntimeException()
                .retryIfExceptionOfType(Exception.class)
                .retryIfException(Predicates.equalTo(new Exception()))
                .retryIfResult(Predicates.equalTo(false))
                //等待策略:每次请求间隔0.2秒
                .withWaitStrategy(WaitStrategies.fixedWait(200, TimeUnit.MILLISECONDS))
                //停止策略 : 尝试请求9次
                .withStopStrategy(StopStrategies.stopAfterAttempt(9))
                .build();
        return msgRetryer;
    }
}

在其他类中引用重试器时可直接通过spring注解的方式来引用

@Autowired
private Retryer mailRetryer;

@Autowired
private Retryer msgRetryer;
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值