参考资料:
- https://segmentfault.com/a/1190000014482325
- https://www.programcreek.com/java-api-examples/?api=com.github.rholder.retry.RetryerBuilder
- https://github.com/rholder/guava-retrying
本文主要介绍本人使用场景的写法。
1. 针对业务异常某个错误码
Retryer<List<T>> retryer = RetryerBuilder.<List<T>>newBuilder()
.retryIfException(throwable -> {
// 提前判断是否是指定重启异常
boolean isTrue = throwable instanceof ApiException;
if(isTrue) {
ApiException apiException = (ApiException) throwable;
// 获取错误码
int code = apiException.getCode();
return code == 429;
}
// false: 代表不发起重调
return false;
})
.withStopStrategy(StopStrategies.stopAfterAttempt(10))// 1.3尝试执行三次(也就是重试2次)
.withWaitStrategy(WaitStrategies.fibonacciWait(1, 50, TimeUnit.SECONDS))//1.4重试间隔
.build();
2. 针对单位时间内业务请求次数限制
Retryer<List<T>> retryer = RetryerBuilder.<List<T>>newBuilder()
.retryIfResult(Predicates.<List<T>>isNull())// 1.1当重试的方法返回null时候进行重试
.retryIfExceptionOfType(ApiException.class)// 1.2当重试方法抛出IOException类型异常时候进行重试
.withStopStrategy(StopStrategies.stopAfterAttempt(3))// 1.3尝试执行三次(也就是重试2次)
.withWaitStrategy(getExceptionWait())//1.4重试间隔
.build();
private static WaitStrategy getExceptionWait() {
return WaitStrategies.exceptionWait(ApiException.class, (e) -> {
// 获取请求速率限制
RateLimit rateLimit = e.getRateLimit();
// 获取超时时间
Long reset = rateLimit.getReset();
long milli = reset * 1000;
// 获取当前时间(业务中超时返回时间是UTC时区)
LocalDateTime now = LocalDateTime.now(ZoneOffset.UTC);
long currentMilli = now.toInstant(ZoneOffset.UTC).toEpochMilli();
// 返回等待毫秒数
return milli - currentMilli;
});
}
网友评论