失败重试策略与思考
简介
自己封装的失败重试策略,比较适合访问网络或者蓝牙通信的时候任务失败重试,当失败次数达到预定的次数之后,就会提示本次任务失败。
以下是代码的结构:
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;
}
}
总结
非常简单又好用的一个失败重试策略框架,还可以在此基础上增加超时的功能,当任务执行超过预定的时间之后,可以抛出异常,表示本次任务执行失败,继续下一个任务的执行。
用心写代码,不辜负程序员之名。