diff --git a/easy-retry-client-core/src/main/java/com/aizuda/easy/retry/client/core/intercepter/HeaderAspect.java b/easy-retry-client-core/src/main/java/com/aizuda/easy/retry/client/core/intercepter/HeaderAspect.java index d6492aed..43997731 100644 --- a/easy-retry-client-core/src/main/java/com/aizuda/easy/retry/client/core/intercepter/HeaderAspect.java +++ b/easy-retry-client-core/src/main/java/com/aizuda/easy/retry/client/core/intercepter/HeaderAspect.java @@ -1,5 +1,6 @@ package com.aizuda.easy.retry.client.core.intercepter; +import com.aizuda.easy.retry.client.core.intercepter.RetrySiteSnapshot.EnumStage; import com.aizuda.easy.retry.common.core.constant.SystemConstants; import com.aizuda.easy.retry.common.core.log.LogUtils; import com.aizuda.easy.retry.common.core.model.EasyRetryHeaders; @@ -16,24 +17,29 @@ import javax.servlet.http.HttpServletResponse; import java.util.Objects; /** - * 请求头和响应头传递 + * 服务间调用传递请求头和响应头 * * @author: www.byteblogs.com * @date : 2022-04-18 09:19 + * @since 1.0.0 */ @Aspect @Component @Slf4j public class HeaderAspect { - public void before(){ + public void before() { + if (skip()) { + return; + } + ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); String xRetry = attributes.getRequest().getHeader(SystemConstants.EASY_RETRY_HEAD_KEY); if (Objects.nonNull(xRetry)) { // 标记进入方法的时间 RetrySiteSnapshot.setEntryMethodTime(System.currentTimeMillis()); - LogUtils.info(log, "easy-retry 拦截器 xRetry:[{}]", xRetry); + LogUtils.info(log, "easy-retry request header :[{}]", xRetry); RetrySiteSnapshot.setRetryHeader(JsonUtil.parseObject(xRetry, EasyRetryHeaders.class)); } } @@ -66,7 +72,11 @@ public class HeaderAspect { HttpServletResponse response = attributes.getResponse(); response.addHeader(SystemConstants.EASY_RETRY_STATUS_CODE_KEY, RetrySiteSnapshot.getRetryStatusCode()); - // 服务端重试的在com.x.retry.client.core.client.RetryEndPoint 中进行清除threadLocal + if (skip()) { + return; + } + + // 服务端重试的在com.aizuda.easy.retry.client.core.client.RetryEndPoint.dispatch 中进行清除threadLocal if (Objects.nonNull(RetrySiteSnapshot.getStage()) && RetrySiteSnapshot.EnumStage.REMOTE.getStage() == RetrySiteSnapshot.getStage()) { return; } @@ -77,4 +87,19 @@ public class HeaderAspect { RetrySiteSnapshot.removeEntryMethodTime(); } + + /** + * 本地重试不执行afterReturning和before方法,避免header传递失效 + * + * @return + */ + private boolean skip() { + + Integer stage = RetrySiteSnapshot.getStage(); + if (Objects.nonNull(stage) && EnumStage.LOCAL.getStage() == RetrySiteSnapshot.getStage()) { + return true; + } + + return false; + } } diff --git a/easy-retry-client-core/src/main/java/com/aizuda/easy/retry/client/core/plugin/RequestHeaderPlugins.java b/easy-retry-client-core/src/main/java/com/aizuda/easy/retry/client/core/plugin/RequestHeaderPlugins.java index c6328de2..5d09d025 100644 --- a/easy-retry-client-core/src/main/java/com/aizuda/easy/retry/client/core/plugin/RequestHeaderPlugins.java +++ b/easy-retry-client-core/src/main/java/com/aizuda/easy/retry/client/core/plugin/RequestHeaderPlugins.java @@ -35,13 +35,17 @@ public class RequestHeaderPlugins { // 传递请求头 if (Objects.nonNull(retryHeader)) { long callRemoteTime = System.currentTimeMillis(); - long entryMethodTime = RetrySiteSnapshot.getEntryMethodTime(); - long transmitTime = retryHeader.getDdl() - (callRemoteTime - entryMethodTime); - LogUtils.info(log, "RPC传递header头 entryMethodTime:[{}] - callRemoteTime:[{}] = transmitTime:[{}]", entryMethodTime, callRemoteTime, transmitTime); - if (transmitTime > 0) { - retryHeader.setDdl(transmitTime); + Long entryMethodTime = RetrySiteSnapshot.getEntryMethodTime(); + if (Objects.isNull(entryMethodTime)) { + LogUtils.warn(log, "entry method time is null. easyRetryId:[{}]", retryHeader.getEasyRetryId()); } else { - throw new EasyRetryClientException("调用链超时, 不在继续调用后面请求"); + long transmitTime = retryHeader.getDdl() - (callRemoteTime - entryMethodTime); + LogUtils.info(log, "RPC传递header头 callRemoteTime:[{}] - entryMethodTime:[{}] = transmitTime:[{}]", entryMethodTime, callRemoteTime, transmitTime); + if (transmitTime > 0) { + retryHeader.setDdl(transmitTime); + } else { + throw new EasyRetryClientException("调用链超时, 不在继续调用后面请求"); + } } header.put(SystemConstants.EASY_RETRY_HEAD_KEY, JsonUtil.toJsonString(retryHeader)); diff --git a/easy-retry-client-core/src/main/java/com/aizuda/easy/retry/client/core/strategy/LocalRetryStrategies.java b/easy-retry-client-core/src/main/java/com/aizuda/easy/retry/client/core/strategy/LocalRetryStrategies.java index 86e65894..89a563db 100644 --- a/easy-retry-client-core/src/main/java/com/aizuda/easy/retry/client/core/strategy/LocalRetryStrategies.java +++ b/easy-retry-client-core/src/main/java/com/aizuda/easy/retry/client/core/strategy/LocalRetryStrategies.java @@ -1,7 +1,10 @@ package com.aizuda.easy.retry.client.core.strategy; +import cn.hutool.core.util.IdUtil; import com.aizuda.easy.retry.client.core.RetryExecutor; import com.aizuda.easy.retry.client.core.RetryExecutorParameter; +import com.aizuda.easy.retry.client.core.annotation.Retryable; +import com.aizuda.easy.retry.client.core.cache.GroupVersionCache; import com.aizuda.easy.retry.client.core.exception.EasyRetryClientException; import com.aizuda.easy.retry.client.core.intercepter.RetrySiteSnapshot; import com.aizuda.easy.retry.client.core.retryer.RetryType; @@ -9,6 +12,7 @@ import com.aizuda.easy.retry.client.core.retryer.RetryerInfo; import com.aizuda.easy.retry.client.core.retryer.RetryerResultContext; import com.aizuda.easy.retry.common.core.enums.RetryResultStatusEnum; import com.aizuda.easy.retry.common.core.log.LogUtils; +import com.aizuda.easy.retry.common.core.model.EasyRetryHeaders; import com.github.rholder.retry.Attempt; import com.github.rholder.retry.RetryListener; import com.github.rholder.retry.StopStrategies; @@ -108,6 +112,10 @@ public class LocalRetryStrategies extends AbstractRetryStrategies { // 如果是仅仅本地重试或本地_远程模式则先支持重试 case ONLY_LOCAL: case LOCAL_REMOTE: + + // 标记进入方法的时间 + RetrySiteSnapshot.setEntryMethodTime(System.currentTimeMillis()); + return () -> retryExecutor.execute(params); case ONLY_REMOTE: // 仅仅是远程重试则直接上报 diff --git a/easy-retry-server/pom.xml b/easy-retry-server/pom.xml index 7ce99d75..4529376d 100644 --- a/easy-retry-server/pom.xml +++ b/easy-retry-server/pom.xml @@ -127,6 +127,10 @@ perf4j 0.9.16 + + org.hibernate + hibernate-validator + diff --git a/example/src/main/java/com/example/controller/TestDdlController.java b/example/src/main/java/com/example/controller/TestDdlController.java index 350651de..4554a812 100644 --- a/example/src/main/java/com/example/controller/TestDdlController.java +++ b/example/src/main/java/com/example/controller/TestDdlController.java @@ -1,5 +1,7 @@ package com.example.controller; +import com.aizuda.easy.retry.client.core.annotation.Retryable; +import com.aizuda.easy.retry.client.core.retryer.RetryType; import com.aizuda.easy.retry.common.core.model.Result; import com.example.client.DemoClient; import org.springframework.beans.factory.annotation.Autowired; @@ -41,4 +43,15 @@ public class TestDdlController { return result; } + + @GetMapping("test-retry-header-controller-transfer") + @Retryable(scene = "testRetryHeaderControllerTransfer", retryStrategy = RetryType.ONLY_LOCAL) + public Result testRetryHeaderTransfer() { + Result result = demoClient.get(); + if (result.getStatus() == 0) { + throw new UnsupportedOperationException(result.getMessage()); + } + return result; + + } } diff --git a/example/src/main/java/com/example/demo/TestRetryMethodService.java b/example/src/main/java/com/example/demo/TestRetryMethodService.java index d0a95f85..c53f4a5f 100644 --- a/example/src/main/java/com/example/demo/TestRetryMethodService.java +++ b/example/src/main/java/com/example/demo/TestRetryMethodService.java @@ -2,6 +2,8 @@ package com.example.demo; import com.aizuda.easy.retry.client.core.annotation.Retryable; import com.aizuda.easy.retry.client.core.retryer.RetryType; +import com.example.client.DemoClient; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; /** @@ -11,10 +13,19 @@ import org.springframework.stereotype.Component; @Component public class TestRetryMethodService { + @Autowired + private DemoClient demoClient; + @Retryable(scene = "testRetryMethod", retryMethod = MyExecutorMethod.class, retryStrategy = RetryType.ONLY_REMOTE) public String testRetryMethod(String p) { double i = 1 / 0; return "测试自定义重试方法"; } + @Retryable(scene = "testRetryHeaderTransfer", retryStrategy = RetryType.ONLY_LOCAL) + public String testRetryHeaderTransfer(String p) { + demoClient.get(); + double i = 1 / 0; + return "测试重试流量标识服务间传递"; + } } diff --git a/example/src/test/java/com/example/TestRetryMethodServiceTest.java b/example/src/test/java/com/example/TestRetryMethodServiceTest.java index 51ce5671..f39d43bf 100644 --- a/example/src/test/java/com/example/TestRetryMethodServiceTest.java +++ b/example/src/test/java/com/example/TestRetryMethodServiceTest.java @@ -27,4 +27,14 @@ public class TestRetryMethodServiceTest { Thread.sleep(90000); } + @Test + public void testRetryHeaderTransfer() throws InterruptedException { + try { + retryMethodService.testRetryHeaderTransfer(UUID.randomUUID().toString()); + }catch (Exception e) { + + } + Thread.sleep(90000); + } + }