/**
* for循环 失败处理后,延迟重试
*
* @throws InterruptedException
*/
@Test
void test28() throws InterruptedException {
ExecutorService executorService = Executors.newFixedThreadPool(3);
executorService.execute(() -> {
// 最大重试次数
int maxTryCount = 3;
// 最大重试时间(秒)
int maxWaitTime = 1;
for (int tryCount = 0; tryCount < maxTryCount; tryCount++) {
try {
log.info("处理任务:" + (tryCount + 1));
int a = 1 / 0;
break;
} catch (Exception e) {
log.error("处理任务失败,原因是:{}", e.toString());
if (tryCount == maxTryCount - 1) {
// 1.记录日志
log.error("超过最大尝试次数,记录日志:{}", e.toString());
// 2.发送邮件
break;
}
// 延迟重试
try {
TimeUnit.SECONDS.sleep(maxWaitTime);
} catch (InterruptedException ex) {
throw new RuntimeException(ex);
}
}
}
});
TimeUnit.SECONDS.sleep(5);
}
/**
* while循环 失败处理后,延迟重试(指数重试)
*
* @throws InterruptedException
*/
@Test
public void test29() throws InterruptedException {
ExecutorService executorService = Executors.newFixedThreadPool(3);
executorService.execute(() -> {
int tryCount = 0;
int maxTryCount = 3;
while (tryCount < maxTryCount) {
try {
log.info("执行任务");
int a = 1 / 0;
break;
} catch (Exception e) {
log.error("处理任务失败,原因是:{}", e.toString());
tryCount++;
if (tryCount == maxTryCount) {
// 1.记录日志
log.error("超过最大尝试次数,记录日志:{}", e.toString());
// 2.发送邮件
break;
}
try {
// 指数重试
long sleepTime = (long) Math.pow(2, tryCount);
TimeUnit.SECONDS.sleep(sleepTime);
} catch (InterruptedException ex) {
throw new RuntimeException(ex);
}
}
}
});
TimeUnit.SECONDS.sleep(10);
}
/**
* while循环 失败处理后,延迟重试(固定间隔)
*
* @throws InterruptedException
*/
@Test
void test30() throws InterruptedException {
InheritableThreadLocal<String> data = new InheritableThreadLocal<>();
data.set("李四");
ExecutorService executorService = Executors.newFixedThreadPool(3);
executorService.execute(() -> {
int tryCount = 0;
int maxTryCount = 3;
while (tryCount < maxTryCount) {
try {
log.info("执行任务");
int a = 1 / 0;
break;
} catch (Exception e) {
log.error("处理任务失败,原因是:{}", e.toString());
tryCount++;
if (tryCount == maxTryCount) {
// 1.记录日志
log.error("超过最大尝试次数,记录日志:{}", e.toString());
// 2.发送邮件
break;
}
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException ex) {
throw new RuntimeException(ex);
}
}
}
});
TimeUnit.SECONDS.sleep(5);
}
建议:
1. Retry会加速雪崩,需谨慎重试
2. 要求被调用的接口是幂等的,不然扣款重试会导致用户资损,退款重试会导致平台资损
3. 不再最上游进行重试,在单节点进行重试
4. 推荐使用指数重试,避免导致系统瞬间压力过大
参考:
https://mp.weixin.qq.com/s/8_NJiy2dtFpJgIWbbYUGbQ
https://mp.weixin.qq.com/s/fBHl2XShpBpvHofYK2i6JQ