一:引入guava依赖
com.github.rholder -> guava-retrying 2.0.0-AONE-SNAPSHOT
二:封装调用工具类
package common.utils.guava;
import com.github.rholder.retry.*;
import com.google.common.base.Predicates;
import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit;
/**
* @mhh
* guava重试工具
* @param <T>
*/
public class GuavaRetryer<T> {
private Retryer<T> retryer;
public GuavaRetryer(){
}
/**
* 初始化重试实例
* @param sleepTime 重试间隔时间,单位:秒
* @param retryTimes 失败重试次数
* @param callerName 调用接口名称
*/
public GuavaRetryer(Integer sleepTime, Integer retryTimes,String callerName,String dingTalkToken){
retryer = RetryerBuilder.<T>newBuilder()
.retryIfException() //抛出runtime异常、checked异常时都会重试,但是抛出error不会重试。
.retryIfResult(Predicates.equalTo(null)) //返回null也需要重试
.withWaitStrategy(WaitStrategies.fixedWait(sleepTime, TimeUnit.SECONDS)) //重调策略
.withStopStrategy(StopStrategies.stopAfterAttempt(retryTimes)) //尝试次数
.withRetryListener(new MyRetryListener(callerName,dingTalkToken))
.build();
}
/**
* 初始化重试实例
* @param sleepTime 重试间隔时间,单位:秒
* @param retryTimes 失败重试次数
* @param retryListener 重试监听实例
*/
public GuavaRetryer(Integer sleepTime, Integer retryTimes, RetryListener retryListener){
retryer = RetryerBuilder.<T>newBuilder()
.retryIfException() //抛出runtime异常、checked异常时都会重试,但是抛出error不会重试。
.retryIfResult(Predicates.equalTo(null)) //返回null也需要重试
.withWaitStrategy(WaitStrategies.fixedWait(sleepTime, TimeUnit.SECONDS)) //重调策略
.withStopStrategy(StopStrategies.stopAfterAttempt(retryTimes)) //尝试次数
.withRetryListener(retryListener)
.build();
}
/**
* 执行可重试方法
* @param callable
* @return
* @throws Exception
*/
public T executeWithRetry(Callable<T> callable) throws Exception {
if(retryer == null){
throw new Exception("未初始化重试参数!");
}
T result= retryer.call(callable);
return result;
}
/**
* 执行可重试方法
* @param callable
* @return
* @throws Exception
*/
public T executeWithRetry(Integer sleepTime, Integer retryTimes,Callable<T> callable,
String callerName,String dingTalkToken) throws Exception {
retryer = RetryerBuilder.<T>newBuilder()
.retryIfException() //抛出runtime异常、checked异常时都会重试,但是抛出error不会重试。
.retryIfResult(Predicates.equalTo(null)) //返回null也需要重试
.withWaitStrategy(WaitStrategies.fixedWait(sleepTime, TimeUnit.SECONDS)) //重调策略
.withStopStrategy(StopStrategies.stopAfterAttempt(retryTimes)) //尝试次数
.withRetryListener(new MyRetryListener(callerName,dingTalkToken))
.build();
T result= retryer.call(callable);
return result;
}
/**
* 执行可重试方法
* @param callable
* @return
* @throws Exception
*/
public T executeWithRetry(Integer sleepTime, Integer retryTimes,Callable<T> callable,
MyRetryListener myRetryListener) throws Exception {
retryer = RetryerBuilder.<T>newBuilder()
.retryIfException() //抛出runtime异常、checked异常时都会重试,但是抛出error不会重试。
.retryIfResult(Predicates.equalTo(null)) //返回null也需要重试
.withWaitStrategy(WaitStrategies.fixedWait(sleepTime, TimeUnit.SECONDS)) //重调策略
.withStopStrategy(StopStrategies.stopAfterAttempt(retryTimes)) //尝试次数
.withRetryListener(myRetryListener)
.build();
T result= retryer.call(callable);
return result;
}
}
三:封装回调监听器
package common.utils.guava;
import com.github.rholder.retry.Attempt;
import com.github.rholder.retry.RetryListener;
import common.helper.DingTalkHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class MyRetryListener implements RetryListener {
private final static Logger LOGGER = LoggerFactory.getLogger(MyRetryListener.class);
private String callerName;
private String dingTalkToken;
public MyRetryListener(){
}
public MyRetryListener(String callerName,String dingTalkToken){
this.callerName = callerName;
this.dingTalkToken = dingTalkToken;
}
@Override
public <T> void onRetry(Attempt<T> attempt) {
Long attempNumber = attempt.getAttemptNumber();
Long delay = attempt.getDelaySinceFirstAttempt();
Boolean hasException = attempt.hasException();
Boolean hasResult = attempt.hasResult();
String msg = String.format("重试接口:%s,重试次数=%s,距离第一次重试的延迟=%s,是否有异常=%s,是否有返回结果=%s",
callerName,attempNumber,delay,hasException,hasResult);
LOGGER.info(msg);
if (attempt.hasException()) {
String causeBy = attempt.getExceptionCause().toString();
String errorMsg = String.format("重试接口:%s,异常原因=%s",callerName,causeBy);
String title = "外部接口重试调用监控";
String sendMsg = msg + "\n" + errorMsg;
LOGGER.error(errorMsg);
DingTalkHelper.sendMarkdownMsg(dingTalkToken, title, sendMsg);
}
}
}
四:使用例子
package common.utils.guava;
import com.github.rholder.retry.Attempt;
public class RetryTester {
public static void main(String[] arg) throws Exception {
/*GuavaRetryer<String> guavaRetryer = new GuavaRetryer(3,3,"测试接口");
String result1 = guavaRetryer.executeWithRetry(() -> {
String obj = "测试调用重试接口失败";
throw new Exception(obj);
//return obj;
});*/
GuavaRetryer<String> guavaRetryer = new GuavaRetryer();
/*String result2 = guavaRetryer.executeWithRetry(3,3,"测试接口",() -> {
Thread.sleep(2000);
String obj = "测试调用重试接口失败";
throw new Exception(obj);
//return obj;
});*/
String result3 = guavaRetryer.executeWithRetry(3,3,() -> {
Thread.sleep(2000);
String obj = "测试调用重试接口失败";
throw new Exception(obj);
//return obj;
},new MyRetryListener(){
@Override
public <T> void onRetry(Attempt<T> attempt) {
Long attempNumber = attempt.getAttemptNumber();
Long delay = attempt.getDelaySinceFirstAttempt();
Boolean hasException = attempt.hasException();
Boolean hasResult = attempt.hasResult();
System.out.println("重试结果:"+attempNumber+","+delay+","+hasException+","+hasResult);
}
});
}
}