`
raymond.chen
  • 浏览: 1414311 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

Spring BackOff退避算法

阅读更多

Spring的util包提供了退避算法的实现,BackOff接口和BackOffExecution接口,还有两种具体的策略实现,ExponentialBackOff和FixedBackOff。

 

FixedBackOff 固定时间间隔重试

       每次的间隔时间一样,累计间隔次数达到设定值时,下次BackOff返回-1

long interval = 1000;  //重试间隔
long maxAttempts = 10;  //最大重试次数
BackOff backOff = new FixedBackOff(interval, maxAttempts);  
BackOffExecution execution = backOff.start();  

while(true){
	long value = execution.nextBackOff();
	if(value == BackOffExecution.STOP){
		break;
	}else{
		System.out.println(value);  
	}
}

 

ExponentialBackOff 指数时间间隔重试

       间隔时间每次倍数递增,达到最大的间隔时间后就不再递增。累计的间隔时间达到设定值时,下次BackOff返回-1

long initialInterval = 100;  //初始间隔
double multiplier = 1.5; //递增倍数
long maxInterval = 5 * 1000L;  //最大间隔
long maxElapsedTime = 50 * 1000L;  //累计最大的时间间隔

ExponentialBackOff backOff = new ExponentialBackOff(initialInterval, multiplier);
backOff.setMaxInterval(maxInterval);
backOff.setMaxElapsedTime(maxElapsedTime); 

BackOffExecution execution = backOff.start();

while(true){
	long value = execution.nextBackOff();
	if(value == BackOffExecution.STOP){
		break;
	}else{
		System.out.println(value);  
	}
}

 

自定义退避算法:

     LoopExponentialBackOff: 可循环的指数时间间隔重试:间隔时间每次倍数递增,达到最大的间隔时间后,从初始的间隔时间重新倍数递增,无穷循环。

public class LoopExponentialBackOff implements BackOff {
	public static final long DEFAULT_INITIAL_INTERVAL = 2000L;
	public static final double DEFAULT_MULTIPLIER = 1.5;
	public static final long DEFAULT_MAX_INTERVAL = 30000L;

	private long initialInterval = DEFAULT_INITIAL_INTERVAL;
	private double multiplier = DEFAULT_MULTIPLIER;
	private long maxInterval = DEFAULT_MAX_INTERVAL;
	
	public LoopExponentialBackOff(){
		
	}
	
	public LoopExponentialBackOff(long initialInterval, double multiplier){
		checkMultiplier(multiplier);
		this.initialInterval = initialInterval;
		this.multiplier = multiplier;
	}
	
	public long getInitialInterval() {
		return initialInterval;
	}

	public void setInitialInterval(long initialInterval) {
		this.initialInterval = initialInterval;
	}

	public double getMultiplier() {
		return multiplier;
	}

	public void setMultiplier(double multiplier) {
		checkMultiplier(multiplier);
		this.multiplier = multiplier;
	}

	public long getMaxInterval() {
		return maxInterval;
	}

	public void setMaxInterval(long maxInterval) {
		this.maxInterval = maxInterval;
	}

	private void checkMultiplier(double multiplier) {
		if (multiplier < 1) {
			throw new IllegalArgumentException("Invalid multiplier '" + multiplier + "'. Should be equal" +
					"or higher than 1. A multiplier of 1 is equivalent to a fixed interval");
		}
	}
	
	@Override
	public BackOffExecution start() {
		return new LoopExponentialBackOffExecution();
	}
	
	private class LoopExponentialBackOffExecution implements BackOffExecution {
		private long currentInterval = -1;

		@Override
		public long nextBackOff() {
			long nextInterval = computeNextInterval();
			return nextInterval;
		}

		private long computeNextInterval() {
			long maxInterval = getMaxInterval();
			
			if(this.currentInterval < 0 || this.currentInterval >= maxInterval){
				long initialInterval = getInitialInterval();
				this.currentInterval = (initialInterval < maxInterval ? initialInterval : maxInterval);
			}else {
				this.currentInterval = multiplyInterval(maxInterval);
			}
			return this.currentInterval;
		}

		private long multiplyInterval(long maxInterval) {
			long i = this.currentInterval;
			i *= getMultiplier();
			return (i > maxInterval ? maxInterval : i);
		}

		@Override
		public String toString() {
			StringBuilder sb = new StringBuilder("LoopExponentialBackOff{");
			sb.append("currentInterval=").append(this.currentInterval < 0 ? "n/a" : this.currentInterval + "ms");
			sb.append(", multiplier=").append(getMultiplier());
			sb.append('}');
			return sb.toString();
		}
	}
}

 

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics