From c7aee3538efd80c8828caf5aa66b4002f07fee41 Mon Sep 17 00:00:00 2001 From: byteblogs168 <598092184@qq.com> Date: Fri, 30 Sep 2022 16:27:50 +0800 Subject: [PATCH] =?UTF-8?q?feat:=200.0.4.2=201=E3=80=81=E6=B3=A8=E8=A7=A3?= =?UTF-8?q?=E6=96=B0=E5=A2=9E=E6=98=AF=E5=90=A6=E9=87=8D=E8=AF=95=E5=AE=8C?= =?UTF-8?q?=E6=88=90=E6=8A=9B=E5=87=BA=E5=BC=82=E5=B8=B8=202=E3=80=81?= =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E9=87=8D=E8=AF=95=E5=AE=8C=E6=88=90=E4=BB=8D?= =?UTF-8?q?=E7=84=B6=E6=8A=9B=E5=87=BA=E5=BC=82=E5=B8=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: byteblogs168 <598092184@qq.com> --- .../TestExistsTransactionalRetryService.java | 4 +- .../ExistsTransactionalRetryServiceTest.java | 4 +- .../client/core/annotation/Retryable.java | 11 +++++ .../client/core/intercepter/RetryAspect.java | 49 +++++++++++++------ .../core/register/scan/RetryableScanner.java | 4 +- .../client/core/retryer/RetryerInfo.java | 1 + 6 files changed, 53 insertions(+), 20 deletions(-) diff --git a/example/src/main/java/com/example/demo/TestExistsTransactionalRetryService.java b/example/src/main/java/com/example/demo/TestExistsTransactionalRetryService.java index 72e1c9829..3099d70ce 100644 --- a/example/src/main/java/com/example/demo/TestExistsTransactionalRetryService.java +++ b/example/src/main/java/com/example/demo/TestExistsTransactionalRetryService.java @@ -29,7 +29,7 @@ public class TestExistsTransactionalRetryService { @Autowired private RemoteService remoteService; - @Retryable(scene = "testSimpleInsert", bizNo = "#name", localTimes = 3) + @Retryable(scene = "testSimpleInsert", bizNo = "#name", localTimes = 3, isThrowException = false) @Transactional public String testSimpleInsert(String name) { @@ -50,7 +50,7 @@ public class TestExistsTransactionalRetryService { Result call = remoteService.call(); System.out.println("-------------->"+call.getMessage()); if (call.getStatus() == 0) { - throw new UnsupportedOperationException("调用远程失败"); + throw new UnsupportedOperationException("调用远程失败" + school.getAddress()); } return "testSimpleInsert"+school.getAddress(); diff --git a/example/src/test/java/com/example/ExistsTransactionalRetryServiceTest.java b/example/src/test/java/com/example/ExistsTransactionalRetryServiceTest.java index ebca44a3f..6d91466e7 100644 --- a/example/src/test/java/com/example/ExistsTransactionalRetryServiceTest.java +++ b/example/src/test/java/com/example/ExistsTransactionalRetryServiceTest.java @@ -39,7 +39,7 @@ public class ExistsTransactionalRetryServiceTest { Mockito.when(remoteService.call()) .thenReturn(new Result(0, "1")) .thenReturn(new Result(0, "2")) - .thenReturn(new Result(0, "3")) + .thenReturn(new Result(1, "3")) .thenReturn(new Result(0, "4")) .thenReturn(new Result(0, "5")) ; @@ -47,7 +47,7 @@ public class ExistsTransactionalRetryServiceTest { String s = testExistsTransactionalRetryService.testSimpleInsert(UUID.randomUUID().toString()); System.out.println(s); } catch (Exception e) { - log.error("", e); + log.error("重试未成功", e); } Thread.sleep(90000); diff --git a/x-retry-client-core/src/main/java/com/x/retry/client/core/annotation/Retryable.java b/x-retry-client-core/src/main/java/com/x/retry/client/core/annotation/Retryable.java index e803842dc..79ce1c89a 100644 --- a/x-retry-client-core/src/main/java/com/x/retry/client/core/annotation/Retryable.java +++ b/x-retry-client-core/src/main/java/com/x/retry/client/core/annotation/Retryable.java @@ -68,5 +68,16 @@ public @interface Retryable { */ int localInterval() default 2; + /** + * 本地重试完成后是否抛出异常 + * 如果不抛出异常,则调用需要重试方法的方法则感知不到异常信息 + * + * 比如: A->B->C->D->E + * D需要重试 若配置D不抛异常,则A->B->C无法感知,若有事物则无法回滚 + * + * @return true-抛出 false-不抛出 + */ + boolean isThrowException() default true; + } diff --git a/x-retry-client-core/src/main/java/com/x/retry/client/core/intercepter/RetryAspect.java b/x-retry-client-core/src/main/java/com/x/retry/client/core/intercepter/RetryAspect.java index cb7fa2796..3ce83db6f 100644 --- a/x-retry-client-core/src/main/java/com/x/retry/client/core/intercepter/RetryAspect.java +++ b/x-retry-client-core/src/main/java/com/x/retry/client/core/intercepter/RetryAspect.java @@ -22,8 +22,9 @@ import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.reflect.MethodSignature; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.core.PriorityOrdered; +import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; -import org.springframework.transaction.support.TransactionSynchronization; import org.springframework.transaction.support.TransactionSynchronizationManager; import java.lang.reflect.Method; @@ -39,6 +40,7 @@ import java.util.UUID; @Aspect @Component @Slf4j +@Order(PriorityOrdered.HIGHEST_PRECEDENCE + 2) public class RetryAspect { private static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); @@ -69,6 +71,7 @@ public class RetryAspect { Throwable throwable = null; Object result = null; + RetryerResultContext retryerResultContext; try { result = point.proceed(); } catch (Throwable t) { @@ -77,10 +80,20 @@ public class RetryAspect { LogUtils.debug("开始进行重试 aop [{}]", traceId); // 入口则开始处理重试 - doHandlerRetry(point, traceId, retryable, executorClassName, methodEntrance, throwable); + retryerResultContext = doHandlerRetry(point, traceId, retryable, executorClassName, methodEntrance, throwable); } LogUtils.debug("aop 结果处理 traceId:[{}] result:[{}] ", traceId, result, throwable); + + // 若是重试完成了, 则判断是否返回重试完成后的数据 + if (Objects.nonNull(retryerResultContext)) { + // 重试成功直接返回结果 若注解配置了isThrowException=false 则不抛出异常 + if (retryerResultContext.getRetryResultStatusEnum().getStatus().equals(RetryResultStatusEnum.SUCCESS.getStatus()) + || !retryable.isThrowException()) { + return retryerResultContext.getResult(); + } + } + if (throwable != null) { throw throwable; } else { @@ -89,7 +102,7 @@ public class RetryAspect { } - private void doHandlerRetry(ProceedingJoinPoint point, String traceId, Retryable retryable, String executorClassName, String methodEntrance, Throwable throwable) { + private RetryerResultContext doHandlerRetry(ProceedingJoinPoint point, String traceId, Retryable retryable, String executorClassName, String methodEntrance, Throwable throwable) { if (!RetrySiteSnapshot.isMethodEntrance(methodEntrance) || RetrySiteSnapshot.isRunning() @@ -106,27 +119,30 @@ public class RetryAspect { RetrySiteSnapshot.isRetryFlow(), RetrySiteSnapshot.isRetryForStatusCode() ); - return; + return null; } if (!TransactionSynchronizationManager.isActualTransactionActive()) { // 无事务, 开启重试 - openRetry(point, traceId, retryable, executorClassName, throwable); - return; + return openRetry(point, traceId, retryable, executorClassName, throwable); } - // 存在事物 - TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() { +// final RetryerResultContext[] retryerResultContext = {null}; - @Override - public void afterCompletion(int status) { - // 有事务开启重试 - openRetry(point, traceId, retryable, executorClassName, throwable); - } - }); + // 存在事物 +// TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() { +// +// @Override +// public void afterCompletion(int status) { +// // 有事务开启重试 +// retryerResultContext[0] = openRetry(point, traceId, retryable, executorClassName, throwable); +// } +// }); + + return null; } - private void openRetry(ProceedingJoinPoint point, String traceId, Retryable retryable, String executorClassName, Throwable throwable) { + private RetryerResultContext openRetry(ProceedingJoinPoint point, String traceId, Retryable retryable, String executorClassName, Throwable throwable) { try { @@ -136,6 +152,7 @@ public class RetryAspect { LogUtils.debug("aop 结果成功 traceId:[{}] result:[{}]", traceId, context.getResult()); } + return context; } catch (Exception e) { LogUtils.error("重试组件处理异常,{}", e); @@ -145,6 +162,8 @@ public class RetryAspect { } finally { RetrySiteSnapshot.removeAll(); } + + return null; } private void sendMessage(Exception e) { diff --git a/x-retry-client-core/src/main/java/com/x/retry/client/core/register/scan/RetryableScanner.java b/x-retry-client-core/src/main/java/com/x/retry/client/core/register/scan/RetryableScanner.java index 2829e008a..7b3f1521b 100644 --- a/x-retry-client-core/src/main/java/com/x/retry/client/core/register/scan/RetryableScanner.java +++ b/x-retry-client-core/src/main/java/com/x/retry/client/core/register/scan/RetryableScanner.java @@ -76,6 +76,7 @@ public class RetryableScanner implements Scanner, ApplicationContextAware { int localTimes = retryable.localTimes(); int localInterval = retryable.localInterval(); Class retryMethod = retryable.retryMethod(); + boolean throwException = retryable.isThrowException(); return new RetryerInfo(retryable.scene(), executorClassName, @@ -88,7 +89,8 @@ public class RetryableScanner implements Scanner, ApplicationContextAware { localInterval, bizIdGenerate, bizNo, - retryMethod + retryMethod, + throwException ); } diff --git a/x-retry-client-core/src/main/java/com/x/retry/client/core/retryer/RetryerInfo.java b/x-retry-client-core/src/main/java/com/x/retry/client/core/retryer/RetryerInfo.java index d63d9e2d3..b137e3677 100644 --- a/x-retry-client-core/src/main/java/com/x/retry/client/core/retryer/RetryerInfo.java +++ b/x-retry-client-core/src/main/java/com/x/retry/client/core/retryer/RetryerInfo.java @@ -28,4 +28,5 @@ public class RetryerInfo { private final Class bizIdGenerate; private final String bizNo; private final Class retryMethod; + private final boolean isThrowException; }