Java开发利器之重试器
代码中存在依赖不稳定的场景,需要使用重试获取预期结果或者尝试重新执行逻辑不立即结束,比如远程接口访问,数据加载访问,数据上传校验等 对于异常需要重试的场景,同时希望把正常逻辑和重试逻辑解耦 对方接口不支持异步回调
int time = 0;do {time++;result = testRedo(); // 调用接口} while (null == result && time < 5);
调用方需要不仅需要考虑多次调用的次数,还要考虑每次调用的间隔时间,尽量在最少调用情况下获取到最终结果(多一次请求意味着多一次网络开销,不方便实时调整) 多次调用过程中偶尔有一次调用出现异常(接口报错,网络异常),如果没有异常处理就会影响剩下次数的调用,无法保证高可用 多线程情况下上面的代码会出现并发问题,因为第一次调用的结果不一定是最早返回的,有可能后面调用的先返回,导致结果不是预期的 性能问题,如果使用多线程要考虑线程创建销毁和切换问题
支持设置重试次数和间隔时间,支持多种复杂场景的重试策略,延迟策略 而且支持多个异常或者自定义实体对象的重试源,让重试功能有更多的灵活性 线程安全,我们只需要关注我们的业务逻辑实现即可 内部使用线程池管理线程 基于命令模式使用链式调用,使用方便
pom依赖:
<dependency><groupId>com.github.rholdergroupId><artifactId>guava-retryingartifactId><version>2.0.0version>dependency>
// 重试条件Predicate<String> condition = response -> Objects.nonNull(response)&& "处理中".equals(response.getReturnCode());Optional<String> response = RetryUtil.retry(condition, // 重试条件() -> invoke(request), // 重试任务(比如调用接口)500, // 500ms重试一次, 可以做成配置化3); // 一共重试3次, 可以做成配置化return response.orElse(null);
/*** 根据输入的condition重复做task,在规定的次数内达到condition则返回,* 如果超过retryTimes则返回null, 重试次数,整个重试时间以及retry exception都会记录log** @param condition 重试条件,比如接口返回errorCode为处理中,或不是最终需要的结果* @param task 重试做的任务* @param sleepTime 重试间隔时间,单位毫秒* @param retryTimes 重试次数* @return targetBean*/public staticOptional retry(Predicate {condition, Callable task, int sleepTime, int retryTimes) Optionalresult = Optional.empty(); StopWatch stopWatch = new StopWatch();try {stopWatch.start();Retryerretry = RetryerBuilder. newBuilder() // 默认任务执行过程中发生异常自动重试.retryIfException()// 重试条件(按照业务场景).retryIfResult(condition)// 等待策略.withWaitStrategy(WaitStrategies.fixedWait(sleepTime, TimeUnit.MILLISECONDS))// 重试策略.withStopStrategy(StopStrategies.stopAfterAttempt(retryTimes))// 重试监听器.withRetryListener(new RetryListener() {publicvoid onRetry(Attempt attempt) {// 记录重试次数和异常信息log.info(MessageFormat.format("{0}th retry", attempt.getAttemptNumber()));if (attempt.hasException()) {log.error(MessageFormat.format("retry exception:{0}", attempt.getExceptionCause()));}}}).build();// 开始执行重试任务result = Optional.ofNullable(retry.call(task));} catch (Exception e) {log.error("retry fail:", e.getMessage());} finally {stopWatch.stop();log.info("retry execute time", stopWatch.getTime());}return result;}
AttemptTimeLimiter:单次任务执行时间限制(如果单次任务执行超时,则终止执行当前任务) BlockStrategies:任务阻塞策略,默认策略为:BlockStrategies.THREAD_SLEEP_STRATEGY,也就是调用Thread.sleep () StopStrategy:停止重试策略,提供三种: StopAfterDelayStrategy:设定一个最长允许的执行时间,比如设定最长执行10s,无论任务执行次数,只要重试的时候超出了最长时间,则任务终止,并返回重试异常RetryException NeverStopStrategy:不停止,用于需要一直轮询直到返回期望结果的情况
WaitStrategy:等待时长策略(控制时间间隔),返回结果为下次执行时长:

评论
