guava-retrying延迟重试使用

星期三, 2020-09-30 | Author: Lee | JAVA-and-J2EE | 2,715 views

0.很好用,但还是放弃使用了,主要guava依赖的版本原因,在guava-29和28版本中无法使用

项目git地址:https://github.com/rholder/guava-retrying

1.用法的几个类 列出如下:

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

    import com.github.rholder.retry.Attempt;
import com.github.rholder.retry.RetryListener;
import lombok.extern.slf4j.Slf4j;
 
/**
 * @author pomelo.lee
 * @date 2020-09-28 16:07:31
 */
@Slf4j
public class RetryLogListener implements RetryListener {
 
	@Override
	public <V> void onRetry(Attempt<V> attempt) {
 
		// 第几次重试,(注意:第一次重试其实是第一次调用)
		log.info("retry time : [{}]", attempt.getAttemptNumber());
 
		// 距离第一次重试的延迟
		log.info("retry delay : [{}]", attempt.getDelaySinceFirstAttempt());
 
		// 重试结果: 是异常终止, 还是正常返回
		log.info("hasException={}", attempt.hasException());
		log.info("hasResult={}", attempt.hasResult());
 
		// 是什么原因导致异常
		if (attempt.hasException()) {
			log.info("causeBy={}", attempt.getExceptionCause().toString());
		} else {
			// 正常返回时的结果
			log.info("result={}", attempt.getResult());
		}
 
		log.info("log listen over.");
 
	}
}
    import com.github.rholder.retry.Attempt;
import com.github.rholder.retry.WaitStrategy;
 
/**
 * 自定义等待策略:根据重试次数动态调节等待时间,第一次请求间隔1s,第二次间隔10s,第三次及以后都是20s。
 * 
 * 
 * 在创建Retryer的时候通过withWaitStrategy将该等待策略生效即可。
 * 
 * RetryerBuilder.<Boolean>newBuilder() .withWaitStrategy(new
 * AlipayWaitStrategy())
 * 
 * 类似的效果也可以通过自定义 BlockStrategy 来实现
 * 
 * @author pomelo.lee
 * @date 2020-09-28 11:29:20
 */
public class CntWaitStrategy implements WaitStrategy {
 
	@Override
	public long computeSleepTime(@SuppressWarnings("rawtypes") Attempt failedAttempt) {
		long number = failedAttempt.getAttemptNumber();
		if (number == 1) {
			return 1 * 1000;
		}
		if (number == 2) {
			return 10 * 1000;
		}
		return 20 * 1000;
	}
 
}
    import java.util.concurrent.TimeUnit;
 
import org.springframework.stereotype.Component;
 
import com.github.rholder.retry.AttemptTimeLimiters;
import com.github.rholder.retry.Retryer;
import com.github.rholder.retry.RetryerBuilder;
import com.github.rholder.retry.StopStrategies;
import com.github.rholder.retry.WaitStrategies;
import com.google.common.base.Predicates;
 
@Component
public class IaRetryerBuilder {
 
	public Retryer<Boolean> build() {
		// 定义重试机制
		Retryer<Boolean> retryer = RetryerBuilder.<Boolean>newBuilder()
				// retryIf 重试条件
				// .retryIfException()
				// .retryIfRuntimeException()
				// .retryIfExceptionOfType(Exception.class)
				// .retryIfException(Predicates.equalTo(new Exception()))
				.retryIfResult(Predicates.equalTo(false))
				.retryIfExceptionOfType(NeedRetryException.class)
				// 等待策略:每次请求间隔1s
				.withWaitStrategy(WaitStrategies.fixedWait(2, TimeUnit.SECONDS))
				// 停止策略 : 尝试请求3次
				.withStopStrategy(StopStrategies.stopAfterAttempt(3))
				// 时间限制 : 某次请求不得超过2s , 类似: TimeLimiter timeLimiter = new SimpleTimeLimiter();
				.withAttemptTimeLimiter(AttemptTimeLimiters.fixedTimeLimit(1, TimeUnit.SECONDS))
				// 默认的阻塞策略:线程睡眠
				// .withBlockStrategy(BlockStrategies.threadSleepStrategy())
				// 自定义阻塞策略:自旋锁
				.withBlockStrategy(new SpinBlockStrategy())
				// 自定义重试监听器
				.withRetryListener(new RetryLogListener()).build();
		return retryer;
 
	}
 
}
    /**
 * 当抛出这个异常的时候,表示需要重试
 */
public class NeedRetryException extends Exception {
 
	private static final long serialVersionUID = 5757167596140601453L;
 
	public NeedRetryException(String message) {
        super("NeedRetryException can retry."+message);
    }
}
    import com.github.rholder.retry.BlockStrategy;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
 
import java.time.Duration;
import java.time.LocalDateTime;
 
/**
 * 自旋锁的实现, 不响应线程中断
 */
@Slf4j
@NoArgsConstructor
public class SpinBlockStrategy implements BlockStrategy {
 
	@Override
	public void block(long sleepTime) throws InterruptedException {
 
		LocalDateTime startTime = LocalDateTime.now();
 
		long start = System.currentTimeMillis();
		long end = start;
		log.info("[SpinBlockStrategy]...begin wait.");
 
		while (end - start <= sleepTime) {
			end = System.currentTimeMillis();
		}
 
		// 使用Java8新增的Duration计算时间间隔
		Duration duration = Duration.between(startTime, LocalDateTime.now());
 
		log.info("[SpinBlockStrategy]...end wait.duration={}", duration.toMillis());
 
	}
}
    import lombok.extern.slf4j.Slf4j;
 
@Slf4j
public class InfoHander implements Callable<Boolean> {
 
 
	@Override
	public Boolean call() throws Exception {
		log.info("start ....");
		log.info("over  ....");
		return true;
	}
}

使用即可

    Retryer<Boolean> retryer = builder.build();
	InfoHander hander = new InfoHander(bean);
	retryer.call(hander);

Tags:

文章作者: Lee

本文地址: https://www.pomelolee.com/2108.html

除非注明,Pomelo Lee文章均为原创,转载请以链接形式标明本文地址

No comments yet.

Leave a comment

Search

文章分类

Links

Meta