Fork me on GitHub

失败重试策略与思考

简介

自己封装的失败重试策略,比较适合访问网络或者蓝牙通信的时候任务失败重试,当失败次数达到预定的次数之后,就会提示本次任务失败。
以下是代码的结构:
《失败重试策略》

RetryPolicyI是失败重试接口;
AbstractRetryPolicy继承了接口,并实现了任务执行重试的逻辑;
FixedRetryPlicy固定时间的重试;
LinearRetryPlicy线性增加时间的重试;
RandomRetryPolicy随机时间的重试;

重试接口和抽象类

RetryPolicyI

public interface RetryPolicyI {
    void tryCall(Callable<Void> callable,Class<? extends Throwable> exception) throws Exception; }

AbstractRetryPolicy

当请求失败,如果请求次数小于最多尝试的次数,则先等待一段时间再继续执行;如果已经超过了最多尝试次数,则直接抛出异常,执行失败。

public abstract class AbstractRetryPolicy implements RetryPolicyI {

    private String tag = "AbstractRetryPolicy";

    private int maxAttempts;//最多尝试次数

    public AbstractRetryPolicy(int maxAttempts) {
        this.maxAttempts = maxAttempts;
    }

    @Override
    public void tryCall(Callable<Void> callable, Condition condition, Class<? extends Throwable> exception) throws Exception {
        int attempts = 0;
        while (attempts <= maxAttempts) {

            try {
                LogUtil.getInstance().ilog(tag,"第"+attempts+"次call");
                callable.call();
                break;
            } catch (Exception e) {
                LogUtil.getInstance().elog(tag,"retry请求出现异常"+e);
                attempts++;
                if ((exception != null) && (exception.isAssignableFrom(e.getClass()))
                        && !(attempts >= maxAttempts)) {
                    Thread.sleep(getDelay(attempts));
                    LogUtil.getInstance().ilog(tag,"retry异常,重新请求");
                } else {
                    LogUtil.getInstance().elog(tag,"请求失败,抛出异常 "+e);
                    throw e;
                }
            }
        }
    }

    protected abstract long getDelay(int attempts);
}

具体重试实现

等待固定时间重试

根据传入的initialDelay参数来确定等待时间。

public class FixedRetryPolicy extends AbstractRetryPolicy{

    private long initialDelay;

    public FixedRetryPolicy(int maxAttempts,long initialDelay) {
        super(maxAttempts);
        this.initialDelay = initialDelay;
    }

    @Override
    protected long getDelay(int attempts) {
        return initialDelay;
    }
}

等待时间线性增加

等待的时间为:固定等待时间*尝试次数,尝试越多次,等待时间越久。

public class LinearRetryPolicy extends AbstractRetryPolicy {
    private long initialDelay;

    public LinearRetryPolicy(long initialDelay, int maxAttempts) {
        super(maxAttempts);
        this.initialDelay = initialDelay;
    }

    @Override
    protected long getDelay(int attempts) {
        return attempts * initialDelay;
    }
}

随机等待时间

每次等待时间是最长等待时间和最短等待时间中间的一个值。

public class RandomRetryPolicy extends AbstractRetryPolicy{

    private long min;
    private long max;

    public RandomRetryPolicy(int maxAttempts,long min,long max){
        super(maxAttempts);
        this.min = min;
        this.max = max;
    }

    @Override
    protected long getDelay(int attempts) {
        long delay = (long)(Math.random()*(max - min)) + min;
        return delay;
    }
}

总结

非常简单又好用的一个失败重试策略框架,还可以在此基础上增加超时的功能,当任务执行超过预定的时间之后,可以抛出异常,表示本次任务执行失败,继续下一个任务的执行。

posted @ 2020-08-28 16:06  思考的大腿  阅读(335)  评论(0编辑  收藏  举报