From 9349663e1da0f39f4fe74074426acd9c1d51b871 Mon Sep 17 00:00:00 2001 From: "Shanyou Yu (Sean Yu)" Date: Mon, 8 May 2023 14:37:43 +0800 Subject: [PATCH] Feature: add AssemblyFlow to support tsf (#994) --- CHANGELOG.md | 1 + ...olarisCircuitBreakerAutoConfiguration.java | 8 +- ...olarisCircuitBreakerAutoConfiguration.java | 8 +- .../ExceptionCircuitBreakerReporter.java | 28 +-- .../SuccessCircuitBreakerReporter.java | 27 +-- .../ExceptionCircuitBreakerReporterTest.java | 4 +- .../SuccessCircuitBreakerReporterTest.java | 11 +- .../polaris/PolarisDiscoveryProperties.java | 14 ++ .../PolarisLoadBalancerAutoConfiguration.java | 29 +++ ...olarisLoadBalancerRingHashKeyProvider.java | 2 +- .../PolarisAutoServiceRegistration.java | 17 +- .../registry/PolarisServiceRegistry.java | 1 + ...larisServiceRegistryAutoConfiguration.java | 11 +- .../PolarisDiscoveryPropertiesTest.java | 5 + .../PolarisAutoServiceRegistrationTest.java | 2 +- ...arisRouterServiceInstanceListSupplier.java | 2 +- .../cloud/polaris/router/RouterUtils.java | 2 +- .../config/LoadBalancerConfiguration.java | 4 +- ...RouterServiceInstanceListSupplierTest.java | 2 +- .../cloud/polaris/router/RouterUtilsTest.java | 2 +- .../config/LoadBalancerConfigurationTest.java | 2 +- .../PolarisInstanceTransformerTest.java | 1 + .../common/metadata/MetadataContext.java | 17 +- spring-cloud-tencent-dependencies/pom.xml | 8 +- spring-cloud-tencent-plugin-starters/pom.xml | 2 + ...acosDiscoveryAdapterAutoConfiguration.java | 2 +- .../transformer/NacosInstanceTransformer.java | 2 +- ...DiscoveryAdapterAutoConfigurationTest.java | 2 +- .../pom.xml | 37 ++++ .../PolarisTsfAdapterAutoConfiguration.java | 47 +++++ .../config/PolarisTsfFlowConfigModifier.java | 46 +++++ ...olarisTsfAdapterAutoConfigurationTest.java | 48 +++++ .../tsf/adapter/config/TsfAssemblyFlow.java | 38 ++++ .../tsf/adapter/config/TsfDiscoveryFlow.java | 40 +++++ .../tsf/adapter/config/TsfRouterFlow.java | 39 ++++ ...com.tencent.polaris.api.flow.DiscoveryFlow | 1 + ...tencent.polaris.assembly.flow.AssemblyFlow | 1 + ...tencent.polaris.router.api.flow.RouterFlow | 1 + spring-cloud-tencent-polaris-context/pom.xml | 5 + .../PolarisContextAutoConfiguration.java | 7 + spring-cloud-tencent-rpc-enhancement/pom.xml | 2 +- .../RpcEnhancementAutoConfiguration.java | 127 ++++++++++++-- .../feign/EnhancedFeignClient.java | 30 ++-- .../EnhancedLoadBalancerClientAspect.java} | 20 ++- .../filter/EnhancedReactiveFilter.java | 93 ++++++++++ .../filter/EnhancedServletFilter.java | 116 ++++++++++++ .../plugin/DefaultEnhancedPluginRunner.java | 34 +++- .../plugin/EnhancedPluginContext.java | 27 ++- .../plugin/EnhancedPluginRunner.java | 5 + .../plugin/EnhancedPluginType.java | 69 +++++--- .../plugin/PluginOrderConstant.java | 67 +++++++ .../PolarisEnhancedPluginUtils.java} | 127 ++++++++------ .../assembly/AssemblyMetadataProvider.java | 56 ++++++ .../assembly/AssemblyRequestContext.java | 126 +++++++++++++ .../assembly/AssemblyResponseContext.java | 87 +++++++++ .../client/AssemblyClientExceptionHook.java | 82 +++++++++ .../client/AssemblyClientPostHook.java | 83 +++++++++ .../client/AssemblyClientPreHook.java | 73 ++++++++ .../server/AssemblyServerExceptionHook.java | 76 ++++++++ .../server/AssemblyServerPostHook.java | 75 ++++++++ .../server/AssemblyServerPreHook.java | 70 ++++++++ .../reporter/ExceptionPolarisReporter.java | 35 ++-- .../reporter/SuccessPolarisReporter.java | 35 ++-- .../EnhancedRestTemplateInterceptor.java | 32 ++-- ...olarisLoadBalancerRequestTransformer.java} | 36 ++-- .../scg/EnhancedGatewayGlobalFilter.java | 27 ++- .../transformer}/InstanceTransformer.java | 2 +- .../PolarisInstanceTransformer.java | 3 +- ...ancedWebClientExchangeFilterFunction.java} | 39 ++-- ...sLoadBalancerClientRequestTransformer.java | 11 +- .../feign/EnhancedFeignClientTest.java | 17 +- ...EnhancedLoadBalancerClientAspectTest.java} | 21 +-- .../AssemblyClientExceptionHookTest.java | 146 +++++++++++++++ .../plugin/AssemblyClientPostHookTest.java | 146 +++++++++++++++ .../plugin/AssemblyClientPreHookTest.java | 143 +++++++++++++++ .../plugin/AssemblyMetadataProviderTest.java | 57 ++++++ .../plugin/AssemblyRequestContextTest.java | 83 +++++++++ .../plugin/AssemblyResponseContextTest.java | 101 +++++++++++ .../AssemblyServerExceptionHookTest.java | 143 +++++++++++++++ .../plugin/AssemblyServerPostHookTest.java | 143 +++++++++++++++ .../plugin/AssemblyServerPreHookTest.java | 143 +++++++++++++++ .../plugin/EnhancedPluginContextTest.java | 38 +++- .../plugin/ExceptionPolarisReporterTest.java | 30 ++-- .../PolarisEnhancedPluginUtilsTest.java} | 166 ++++++++++-------- .../plugin/SuccessPolarisReporterTest.java | 29 ++- .../EnhancedRestTemplateInterceptorTest.java | 5 +- ...risLoadBalancerRequestTransformerTest.java | 89 ++++++++++ .../scg/EnhancedGatewayGlobalFilterTest.java | 5 +- ...dWebClientExchangeFilterFunctionTest.java} | 9 +- ...dBalancerClientRequestTransformerTest.java | 5 +- 90 files changed, 3271 insertions(+), 439 deletions(-) create mode 100644 spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-tsf-adapter-plugin/pom.xml create mode 100644 spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-tsf-adapter-plugin/src/main/java/com/tencent/cloud/tsf/adapter/config/PolarisTsfAdapterAutoConfiguration.java create mode 100644 spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-tsf-adapter-plugin/src/main/java/com/tencent/cloud/tsf/adapter/config/PolarisTsfFlowConfigModifier.java create mode 100644 spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-tsf-adapter-plugin/src/test/java/com/tencent/cloud/tsf/adapter/config/PolarisTsfAdapterAutoConfigurationTest.java create mode 100644 spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-tsf-adapter-plugin/src/test/java/com/tencent/cloud/tsf/adapter/config/TsfAssemblyFlow.java create mode 100644 spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-tsf-adapter-plugin/src/test/java/com/tencent/cloud/tsf/adapter/config/TsfDiscoveryFlow.java create mode 100644 spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-tsf-adapter-plugin/src/test/java/com/tencent/cloud/tsf/adapter/config/TsfRouterFlow.java create mode 100644 spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-tsf-adapter-plugin/src/test/resources/META-INF/services/com.tencent.polaris.api.flow.DiscoveryFlow create mode 100644 spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-tsf-adapter-plugin/src/test/resources/META-INF/services/com.tencent.polaris.assembly.flow.AssemblyFlow create mode 100644 spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-tsf-adapter-plugin/src/test/resources/META-INF/services/com.tencent.polaris.router.api.flow.RouterFlow rename spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/{resttemplate/BlockingLoadBalancerClientAspect.java => feign/EnhancedLoadBalancerClientAspect.java} (62%) create mode 100644 spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/filter/EnhancedReactiveFilter.java create mode 100644 spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/filter/EnhancedServletFilter.java create mode 100644 spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/plugin/PluginOrderConstant.java rename spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/{AbstractPolarisReporterAdapter.java => plugin/PolarisEnhancedPluginUtils.java} (73%) create mode 100644 spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/plugin/assembly/AssemblyMetadataProvider.java create mode 100644 spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/plugin/assembly/AssemblyRequestContext.java create mode 100644 spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/plugin/assembly/AssemblyResponseContext.java create mode 100644 spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/plugin/assembly/client/AssemblyClientExceptionHook.java create mode 100644 spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/plugin/assembly/client/AssemblyClientPostHook.java create mode 100644 spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/plugin/assembly/client/AssemblyClientPreHook.java create mode 100644 spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/plugin/assembly/server/AssemblyServerExceptionHook.java create mode 100644 spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/plugin/assembly/server/AssemblyServerPostHook.java create mode 100644 spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/plugin/assembly/server/AssemblyServerPreHook.java rename spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/resttemplate/{LoadBalancerClientAspectUtils.java => PolarisLoadBalancerRequestTransformer.java} (55%) rename {spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/spi => spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/transformer}/InstanceTransformer.java (97%) rename {spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router => spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement}/transformer/PolarisInstanceTransformer.java (93%) rename spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/webclient/{EnhancedWebClientReporter.java => EnhancedWebClientExchangeFilterFunction.java} (68%) rename spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/{resttemplate/BlockingLoadBalancerClientAspectTest.java => feign/EnhancedLoadBalancerClientAspectTest.java} (84%) create mode 100644 spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/plugin/AssemblyClientExceptionHookTest.java create mode 100644 spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/plugin/AssemblyClientPostHookTest.java create mode 100644 spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/plugin/AssemblyClientPreHookTest.java create mode 100644 spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/plugin/AssemblyMetadataProviderTest.java create mode 100644 spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/plugin/AssemblyRequestContextTest.java create mode 100644 spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/plugin/AssemblyResponseContextTest.java create mode 100644 spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/plugin/AssemblyServerExceptionHookTest.java create mode 100644 spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/plugin/AssemblyServerPostHookTest.java create mode 100644 spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/plugin/AssemblyServerPreHookTest.java rename spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/{AbstractPolarisReporterAdapterTest.java => plugin/PolarisEnhancedPluginUtilsTest.java} (55%) create mode 100644 spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/resttemplate/PolarisLoadBalancerRequestTransformerTest.java rename spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/webclient/{EnhancedWebClientReporterTest.java => EnhancedWebClientExchangeFilterFunctionTest.java} (91%) diff --git a/CHANGELOG.md b/CHANGELOG.md index acd85d867..27670c698 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,3 +3,4 @@ - [feature: support reactive discovery client health indicator.](https://github.com/Tencent/spring-cloud-tencent/pull/986) - [feature: Enhance default configuration to support `application*.yaml` and `bootstrap*.yaml`.](https://github.com/Tencent/spring-cloud-tencent/pull/986) - [feat:Remove error log from `DecodeTransferMetadataReactiveFilter`.](https://github.com/Tencent/spring-cloud-tencent/pull/990) +- [Feature: add AssemblyFlow to support tsf.](https://github.com/Tencent/spring-cloud-tencent/pull/994) diff --git a/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/config/PolarisCircuitBreakerAutoConfiguration.java b/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/config/PolarisCircuitBreakerAutoConfiguration.java index 2c1f9decb..70999eff4 100644 --- a/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/config/PolarisCircuitBreakerAutoConfiguration.java +++ b/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/config/PolarisCircuitBreakerAutoConfiguration.java @@ -66,15 +66,15 @@ public class PolarisCircuitBreakerAutoConfiguration { @Bean @ConditionalOnMissingBean(SuccessCircuitBreakerReporter.class) public SuccessCircuitBreakerReporter successCircuitBreakerReporter(RpcEnhancementReporterProperties properties, - SDKContext polarisContext, CircuitBreakAPI circuitBreakAPI) { - return new SuccessCircuitBreakerReporter(properties, polarisContext, circuitBreakAPI); + CircuitBreakAPI circuitBreakAPI) { + return new SuccessCircuitBreakerReporter(properties, circuitBreakAPI); } @Bean @ConditionalOnMissingBean(ExceptionCircuitBreakerReporter.class) public ExceptionCircuitBreakerReporter exceptionCircuitBreakerReporter(RpcEnhancementReporterProperties properties, - SDKContext polarisContext, CircuitBreakAPI circuitBreakAPI) { - return new ExceptionCircuitBreakerReporter(properties, polarisContext, circuitBreakAPI); + CircuitBreakAPI circuitBreakAPI) { + return new ExceptionCircuitBreakerReporter(properties, circuitBreakAPI); } @Bean diff --git a/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/config/ReactivePolarisCircuitBreakerAutoConfiguration.java b/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/config/ReactivePolarisCircuitBreakerAutoConfiguration.java index f2f509218..fba34d253 100644 --- a/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/config/ReactivePolarisCircuitBreakerAutoConfiguration.java +++ b/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/config/ReactivePolarisCircuitBreakerAutoConfiguration.java @@ -64,15 +64,15 @@ public class ReactivePolarisCircuitBreakerAutoConfiguration { @Bean @ConditionalOnMissingBean(SuccessCircuitBreakerReporter.class) public SuccessCircuitBreakerReporter successCircuitBreakerReporter(RpcEnhancementReporterProperties properties, - SDKContext polarisContext, CircuitBreakAPI circuitBreakAPI) { - return new SuccessCircuitBreakerReporter(properties, polarisContext, circuitBreakAPI); + CircuitBreakAPI circuitBreakAPI) { + return new SuccessCircuitBreakerReporter(properties, circuitBreakAPI); } @Bean @ConditionalOnMissingBean(ExceptionCircuitBreakerReporter.class) public ExceptionCircuitBreakerReporter exceptionCircuitBreakerReporter(RpcEnhancementReporterProperties properties, - SDKContext polarisContext, CircuitBreakAPI circuitBreakAPI) { - return new ExceptionCircuitBreakerReporter(properties, polarisContext, circuitBreakAPI); + CircuitBreakAPI circuitBreakAPI) { + return new ExceptionCircuitBreakerReporter(properties, circuitBreakAPI); } @Bean diff --git a/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/reporter/ExceptionCircuitBreakerReporter.java b/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/reporter/ExceptionCircuitBreakerReporter.java index b47c1a4a2..4ef515aa7 100644 --- a/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/reporter/ExceptionCircuitBreakerReporter.java +++ b/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/reporter/ExceptionCircuitBreakerReporter.java @@ -19,32 +19,38 @@ package com.tencent.cloud.polaris.circuitbreaker.reporter; import java.util.Optional; -import com.tencent.cloud.rpc.enhancement.AbstractPolarisReporterAdapter; import com.tencent.cloud.rpc.enhancement.config.RpcEnhancementReporterProperties; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPlugin; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginContext; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedRequestContext; +import com.tencent.cloud.rpc.enhancement.plugin.PolarisEnhancedPluginUtils; import com.tencent.polaris.api.plugin.circuitbreaker.ResourceStat; import com.tencent.polaris.circuitbreak.api.CircuitBreakAPI; -import com.tencent.polaris.client.api.SDKContext; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.cloud.client.DefaultServiceInstance; import org.springframework.cloud.client.ServiceInstance; -import org.springframework.core.Ordered; -public class ExceptionCircuitBreakerReporter extends AbstractPolarisReporterAdapter implements EnhancedPlugin { +import static com.tencent.cloud.rpc.enhancement.plugin.PluginOrderConstant.ClientPluginOrder.CIRCUIT_BREAKER_REPORTER_PLUGIN_ORDER; + +/** + * ExceptionCircuitBreakerReporter. + * + * @author sean yu + */ +public class ExceptionCircuitBreakerReporter implements EnhancedPlugin { private static final Logger LOG = LoggerFactory.getLogger(ExceptionCircuitBreakerReporter.class); private final CircuitBreakAPI circuitBreakAPI; + private final RpcEnhancementReporterProperties reportProperties; + public ExceptionCircuitBreakerReporter(RpcEnhancementReporterProperties reportProperties, - SDKContext context, CircuitBreakAPI circuitBreakAPI) { - super(reportProperties, context); + this.reportProperties = reportProperties; this.circuitBreakAPI = circuitBreakAPI; } @@ -55,19 +61,19 @@ public class ExceptionCircuitBreakerReporter extends AbstractPolarisReporterAdap @Override public EnhancedPluginType getType() { - return EnhancedPluginType.EXCEPTION; + return EnhancedPluginType.Client.EXCEPTION; } @Override public void run(EnhancedPluginContext context) throws Throwable { - if (!super.reportProperties.isEnabled()) { + if (!this.reportProperties.isEnabled()) { return; } EnhancedRequestContext request = context.getRequest(); - ServiceInstance serviceInstance = Optional.ofNullable(context.getServiceInstance()).orElse(new DefaultServiceInstance()); + ServiceInstance serviceInstance = Optional.ofNullable(context.getTargetServiceInstance()).orElse(new DefaultServiceInstance()); - ResourceStat resourceStat = createInstanceResourceStat( + ResourceStat resourceStat = PolarisEnhancedPluginUtils.createInstanceResourceStat( serviceInstance.getServiceId(), serviceInstance.getHost(), serviceInstance.getPort(), @@ -92,6 +98,6 @@ public class ExceptionCircuitBreakerReporter extends AbstractPolarisReporterAdap @Override public int getOrder() { - return Ordered.HIGHEST_PRECEDENCE + 2; + return CIRCUIT_BREAKER_REPORTER_PLUGIN_ORDER; } } diff --git a/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/reporter/SuccessCircuitBreakerReporter.java b/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/reporter/SuccessCircuitBreakerReporter.java index ce5fe2a81..8975b97ee 100644 --- a/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/reporter/SuccessCircuitBreakerReporter.java +++ b/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/reporter/SuccessCircuitBreakerReporter.java @@ -19,35 +19,40 @@ package com.tencent.cloud.polaris.circuitbreaker.reporter; import java.util.Optional; -import com.tencent.cloud.rpc.enhancement.AbstractPolarisReporterAdapter; import com.tencent.cloud.rpc.enhancement.config.RpcEnhancementReporterProperties; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPlugin; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginContext; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedRequestContext; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedResponseContext; +import com.tencent.cloud.rpc.enhancement.plugin.PolarisEnhancedPluginUtils; import com.tencent.cloud.rpc.enhancement.plugin.reporter.SuccessPolarisReporter; import com.tencent.polaris.api.plugin.circuitbreaker.ResourceStat; import com.tencent.polaris.circuitbreak.api.CircuitBreakAPI; -import com.tencent.polaris.client.api.SDKContext; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.cloud.client.DefaultServiceInstance; import org.springframework.cloud.client.ServiceInstance; -import org.springframework.core.Ordered; +import static com.tencent.cloud.rpc.enhancement.plugin.PluginOrderConstant.ClientPluginOrder.CIRCUIT_BREAKER_REPORTER_PLUGIN_ORDER; -public class SuccessCircuitBreakerReporter extends AbstractPolarisReporterAdapter implements EnhancedPlugin { +/** + * SuccessCircuitBreakerReporter. + * + * @author sean yu + */ +public class SuccessCircuitBreakerReporter implements EnhancedPlugin { private static final Logger LOG = LoggerFactory.getLogger(SuccessPolarisReporter.class); private final CircuitBreakAPI circuitBreakAPI; + private final RpcEnhancementReporterProperties reportProperties; + public SuccessCircuitBreakerReporter(RpcEnhancementReporterProperties reportProperties, - SDKContext context, CircuitBreakAPI circuitBreakAPI) { - super(reportProperties, context); + this.reportProperties = reportProperties; this.circuitBreakAPI = circuitBreakAPI; } @@ -58,19 +63,19 @@ public class SuccessCircuitBreakerReporter extends AbstractPolarisReporterAdapte @Override public EnhancedPluginType getType() { - return EnhancedPluginType.POST; + return EnhancedPluginType.Client.POST; } @Override public void run(EnhancedPluginContext context) throws Throwable { - if (!super.reportProperties.isEnabled()) { + if (!this.reportProperties.isEnabled()) { return; } EnhancedRequestContext request = context.getRequest(); EnhancedResponseContext response = context.getResponse(); - ServiceInstance serviceInstance = Optional.ofNullable(context.getServiceInstance()).orElse(new DefaultServiceInstance()); + ServiceInstance serviceInstance = Optional.ofNullable(context.getTargetServiceInstance()).orElse(new DefaultServiceInstance()); - ResourceStat resourceStat = createInstanceResourceStat( + ResourceStat resourceStat = PolarisEnhancedPluginUtils.createInstanceResourceStat( serviceInstance.getServiceId(), serviceInstance.getHost(), serviceInstance.getPort(), @@ -94,6 +99,6 @@ public class SuccessCircuitBreakerReporter extends AbstractPolarisReporterAdapte @Override public int getOrder() { - return Ordered.HIGHEST_PRECEDENCE + 2; + return CIRCUIT_BREAKER_REPORTER_PLUGIN_ORDER; } } diff --git a/spring-cloud-starter-tencent-polaris-circuitbreaker/src/test/java/com/tencent/cloud/polaris/circuitbreaker/reporter/ExceptionCircuitBreakerReporterTest.java b/spring-cloud-starter-tencent-polaris-circuitbreaker/src/test/java/com/tencent/cloud/polaris/circuitbreaker/reporter/ExceptionCircuitBreakerReporterTest.java index 53e38c9d2..7be53b2fa 100644 --- a/spring-cloud-starter-tencent-polaris-circuitbreaker/src/test/java/com/tencent/cloud/polaris/circuitbreaker/reporter/ExceptionCircuitBreakerReporterTest.java +++ b/spring-cloud-starter-tencent-polaris-circuitbreaker/src/test/java/com/tencent/cloud/polaris/circuitbreaker/reporter/ExceptionCircuitBreakerReporterTest.java @@ -95,7 +95,7 @@ public class ExceptionCircuitBreakerReporterTest { @Test public void testType() { - assertThat(exceptionCircuitBreakerReporter.getType()).isEqualTo(EnhancedPluginType.EXCEPTION); + assertThat(exceptionCircuitBreakerReporter.getType()).isEqualTo(EnhancedPluginType.Client.EXCEPTION); } @Test @@ -121,7 +121,7 @@ public class ExceptionCircuitBreakerReporterTest { pluginContext.setRequest(request); pluginContext.setResponse(response); - pluginContext.setServiceInstance(serviceInstance); + pluginContext.setTargetServiceInstance(serviceInstance); pluginContext.setThrowable(new RuntimeException()); exceptionCircuitBreakerReporter.run(pluginContext); diff --git a/spring-cloud-starter-tencent-polaris-circuitbreaker/src/test/java/com/tencent/cloud/polaris/circuitbreaker/reporter/SuccessCircuitBreakerReporterTest.java b/spring-cloud-starter-tencent-polaris-circuitbreaker/src/test/java/com/tencent/cloud/polaris/circuitbreaker/reporter/SuccessCircuitBreakerReporterTest.java index 4dcd3d19e..5d50a24c1 100644 --- a/spring-cloud-starter-tencent-polaris-circuitbreaker/src/test/java/com/tencent/cloud/polaris/circuitbreaker/reporter/SuccessCircuitBreakerReporterTest.java +++ b/spring-cloud-starter-tencent-polaris-circuitbreaker/src/test/java/com/tencent/cloud/polaris/circuitbreaker/reporter/SuccessCircuitBreakerReporterTest.java @@ -40,6 +40,7 @@ import org.mockito.Mockito; import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.cloud.client.DefaultServiceInstance; +import org.springframework.context.ApplicationContext; import org.springframework.http.HttpMethod; import static com.tencent.polaris.test.common.Consts.NAMESPACE_TEST; @@ -74,6 +75,12 @@ public class SuccessCircuitBreakerReporterTest { mockedApplicationContextAwareUtils = Mockito.mockStatic(ApplicationContextAwareUtils.class); mockedApplicationContextAwareUtils.when(() -> ApplicationContextAwareUtils.getProperties(anyString())) .thenReturn("unit-test"); + ApplicationContext applicationContext = mock(ApplicationContext.class); + RpcEnhancementReporterProperties reporterProperties = mock(RpcEnhancementReporterProperties.class); + doReturn(reporterProperties) + .when(applicationContext).getBean(RpcEnhancementReporterProperties.class); + mockedApplicationContextAwareUtils.when(ApplicationContextAwareUtils::getApplicationContext) + .thenReturn(applicationContext); } @AfterAll @@ -94,7 +101,7 @@ public class SuccessCircuitBreakerReporterTest { @Test public void testType() { - assertThat(successCircuitBreakerReporter.getType()).isEqualTo(EnhancedPluginType.POST); + assertThat(successCircuitBreakerReporter.getType()).isEqualTo(EnhancedPluginType.Client.POST); } @Test @@ -120,7 +127,7 @@ public class SuccessCircuitBreakerReporterTest { pluginContext.setRequest(request); pluginContext.setResponse(response); - pluginContext.setServiceInstance(serviceInstance); + pluginContext.setTargetServiceInstance(serviceInstance); successCircuitBreakerReporter.run(pluginContext); successCircuitBreakerReporter.getOrder(); diff --git a/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/PolarisDiscoveryProperties.java b/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/PolarisDiscoveryProperties.java index ea480d406..3f83bfd44 100644 --- a/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/PolarisDiscoveryProperties.java +++ b/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/PolarisDiscoveryProperties.java @@ -45,6 +45,11 @@ public class PolarisDiscoveryProperties { @Value("${spring.cloud.polaris.discovery.service:${spring.cloud.polaris.service:${spring.application.name:}}}") private String service; + /** + * Service instance id. + */ + private String instanceId; + /** * The polaris authentication token. */ @@ -96,6 +101,14 @@ public class PolarisDiscoveryProperties { */ private Long serviceListRefreshInterval = 60000L; + public String getInstanceId() { + return instanceId; + } + + public void setInstanceId(String instanceId) { + this.instanceId = instanceId; + } + public String getNamespace() { return namespace; } @@ -204,6 +217,7 @@ public class PolarisDiscoveryProperties { return "PolarisDiscoveryProperties{" + "namespace='" + namespace + '\'' + ", service='" + service + '\'' + + ", instanceId='" + instanceId + '\'' + ", token='" + token + '\'' + ", weight=" + weight + ", version='" + version + '\'' + diff --git a/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/loadbalancer/PolarisLoadBalancerAutoConfiguration.java b/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/loadbalancer/PolarisLoadBalancerAutoConfiguration.java index 38f1e0dfa..8ee742d6a 100644 --- a/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/loadbalancer/PolarisLoadBalancerAutoConfiguration.java +++ b/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/loadbalancer/PolarisLoadBalancerAutoConfiguration.java @@ -17,15 +17,25 @@ package com.tencent.cloud.polaris.loadbalancer; +import java.util.ArrayList; +import java.util.List; + import com.tencent.cloud.polaris.context.ConditionalOnPolarisEnabled; +import com.tencent.cloud.rpc.enhancement.resttemplate.EnhancedRestTemplateInterceptor; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.AutoConfigureAfter; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.cloud.client.ConditionalOnDiscoveryEnabled; +import org.springframework.cloud.client.loadbalancer.LoadBalancerInterceptor; +import org.springframework.cloud.client.loadbalancer.RestTemplateCustomizer; import org.springframework.cloud.loadbalancer.annotation.LoadBalancerClients; import org.springframework.cloud.loadbalancer.config.LoadBalancerAutoConfiguration; +import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.http.client.ClientHttpRequestInterceptor; /** * Auto-configuration of loadbalancer for Polaris. @@ -41,4 +51,23 @@ import org.springframework.context.annotation.Configuration; @LoadBalancerClients(defaultConfiguration = PolarisLoadBalancerClientConfiguration.class) public class PolarisLoadBalancerAutoConfiguration { + @Bean + @ConditionalOnMissingBean + public RestTemplateCustomizer restTemplateCustomizer(@Autowired(required = false) LoadBalancerInterceptor loadBalancerInterceptor) { + return restTemplate -> { + List list = new ArrayList<>(restTemplate.getInterceptors()); + // LoadBalancerInterceptor must invoke before EnhancedRestTemplateInterceptor + if (loadBalancerInterceptor != null) { + int addIndex = list.size(); + for (int i = 0; i < list.size(); i++) { + if (list.get(i) instanceof EnhancedRestTemplateInterceptor) { + addIndex = i; + } + } + list.add(addIndex, loadBalancerInterceptor); + } + restTemplate.setInterceptors(list); + }; + } + } diff --git a/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/loadbalancer/PolarisLoadBalancerRingHashKeyProvider.java b/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/loadbalancer/PolarisLoadBalancerRingHashKeyProvider.java index 8a94f799b..e07d57dcc 100644 --- a/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/loadbalancer/PolarisLoadBalancerRingHashKeyProvider.java +++ b/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/loadbalancer/PolarisLoadBalancerRingHashKeyProvider.java @@ -36,7 +36,7 @@ public final class PolarisLoadBalancerRingHashKeyProvider { } static String getHashKey() { - return MetadataContextHolder.get().getLoadbalancerMetadata().get(LOAD_BALANCER_HASH_KEY); + return (String) MetadataContextHolder.get().getLoadbalancerMetadata().get(LOAD_BALANCER_HASH_KEY); } } diff --git a/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/registry/PolarisAutoServiceRegistration.java b/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/registry/PolarisAutoServiceRegistration.java index e4e74cf31..d8c9b2f27 100644 --- a/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/registry/PolarisAutoServiceRegistration.java +++ b/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/registry/PolarisAutoServiceRegistration.java @@ -17,6 +17,9 @@ package com.tencent.cloud.polaris.registry; +import com.tencent.cloud.common.metadata.MetadataContext; +import com.tencent.polaris.api.pojo.ServiceKey; +import com.tencent.polaris.assembly.api.AssemblyAPI; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -36,10 +39,17 @@ public class PolarisAutoServiceRegistration extends AbstractAutoServiceRegistrat private final PolarisRegistration registration; - public PolarisAutoServiceRegistration(ServiceRegistry serviceRegistry, - AutoServiceRegistrationProperties autoServiceRegistrationProperties, PolarisRegistration registration) { + private final AssemblyAPI assemblyAPI; + + public PolarisAutoServiceRegistration( + ServiceRegistry serviceRegistry, + AutoServiceRegistrationProperties autoServiceRegistrationProperties, + PolarisRegistration registration, + AssemblyAPI assemblyAPI + ) { super(serviceRegistry, autoServiceRegistrationProperties); this.registration = registration; + this.assemblyAPI = assemblyAPI; } @Override @@ -58,6 +68,9 @@ public class PolarisAutoServiceRegistration extends AbstractAutoServiceRegistrat log.debug("Registration disabled."); return; } + if (assemblyAPI != null) { + assemblyAPI.initService(new ServiceKey(MetadataContext.LOCAL_NAMESPACE, MetadataContext.LOCAL_SERVICE)); + } super.register(); } diff --git a/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/registry/PolarisServiceRegistry.java b/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/registry/PolarisServiceRegistry.java index 8a4177026..63e340386 100644 --- a/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/registry/PolarisServiceRegistry.java +++ b/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/registry/PolarisServiceRegistry.java @@ -114,6 +114,7 @@ public class PolarisServiceRegistry implements ServiceRegistry> fragmentContexts; + private final Map loadbalancerMetadata; + + public MetadataContext() { this.fragmentContexts = new ConcurrentHashMap<>(); + this.loadbalancerMetadata = new ConcurrentHashMap<>(); } public Map getDisposableMetadata() { @@ -148,8 +147,8 @@ public class MetadataContext { return this.getFragmentContext(MetadataContext.FRAGMENT_RAW_TRANSHEADERS_KV); } - public Map getLoadbalancerMetadata() { - return this.getFragmentContext(FRAGMENT_LOAD_BALANCER); + public Map getLoadbalancerMetadata() { + return this.loadbalancerMetadata; } public void setTransitiveMetadata(Map transitiveMetadata) { @@ -172,8 +171,8 @@ public class MetadataContext { this.putContext(FRAGMENT_RAW_TRANSHEADERS, key, value); } - public void setLoadbalancer(String key, String value) { - this.putContext(FRAGMENT_LOAD_BALANCER, key, value); + public void setLoadbalancer(String key, Object value) { + this.loadbalancerMetadata.put(key, value); } public Map getFragmentContext(String fragment) { diff --git a/spring-cloud-tencent-dependencies/pom.xml b/spring-cloud-tencent-dependencies/pom.xml index 3098b60ae..fbb72740f 100644 --- a/spring-cloud-tencent-dependencies/pom.xml +++ b/spring-cloud-tencent-dependencies/pom.xml @@ -73,7 +73,7 @@ 1.12.0-2020.0.6-SNAPSHOT - 1.12.3 + 1.13.0-SNAPSHOT 31.0.1-jre 1.2.11 4.5.1 @@ -168,6 +168,12 @@ ${revision} + + com.tencent.cloud + spring-cloud-starter-tencent-tsf-adapter-plugin + ${revision} + + com.tencent.cloud spring-cloud-tencent-featureenv-plugin diff --git a/spring-cloud-tencent-plugin-starters/pom.xml b/spring-cloud-tencent-plugin-starters/pom.xml index bc2f153b9..3de6b8ac8 100644 --- a/spring-cloud-tencent-plugin-starters/pom.xml +++ b/spring-cloud-tencent-plugin-starters/pom.xml @@ -18,6 +18,8 @@ spring-cloud-tencent-featureenv-plugin spring-cloud-tencent-gateway-plugin spring-cloud-starter-tencent-discovery-adapter-plugin + spring-cloud-starter-tencent-tsf-adapter-plugin + diff --git a/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-discovery-adapter-plugin/src/main/java/com/tencent/cloud/plugin/discovery/adapter/config/NacosDiscoveryAdapterAutoConfiguration.java b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-discovery-adapter-plugin/src/main/java/com/tencent/cloud/plugin/discovery/adapter/config/NacosDiscoveryAdapterAutoConfiguration.java index 08aaf6651..9145d82aa 100644 --- a/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-discovery-adapter-plugin/src/main/java/com/tencent/cloud/plugin/discovery/adapter/config/NacosDiscoveryAdapterAutoConfiguration.java +++ b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-discovery-adapter-plugin/src/main/java/com/tencent/cloud/plugin/discovery/adapter/config/NacosDiscoveryAdapterAutoConfiguration.java @@ -21,7 +21,7 @@ package com.tencent.cloud.plugin.discovery.adapter.config; import com.tencent.cloud.plugin.discovery.adapter.transformer.NacosInstanceTransformer; import com.tencent.cloud.polaris.router.config.ConditionalOnPolarisRouterEnabled; import com.tencent.cloud.polaris.router.config.LoadBalancerConfiguration; -import com.tencent.cloud.polaris.router.spi.InstanceTransformer; +import com.tencent.cloud.rpc.enhancement.transformer.InstanceTransformer; import org.springframework.boot.autoconfigure.AutoConfigureBefore; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; diff --git a/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-discovery-adapter-plugin/src/main/java/com/tencent/cloud/plugin/discovery/adapter/transformer/NacosInstanceTransformer.java b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-discovery-adapter-plugin/src/main/java/com/tencent/cloud/plugin/discovery/adapter/transformer/NacosInstanceTransformer.java index 498040c04..2959e86df 100644 --- a/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-discovery-adapter-plugin/src/main/java/com/tencent/cloud/plugin/discovery/adapter/transformer/NacosInstanceTransformer.java +++ b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-discovery-adapter-plugin/src/main/java/com/tencent/cloud/plugin/discovery/adapter/transformer/NacosInstanceTransformer.java @@ -18,7 +18,7 @@ package com.tencent.cloud.plugin.discovery.adapter.transformer; -import com.tencent.cloud.polaris.router.spi.InstanceTransformer; +import com.tencent.cloud.rpc.enhancement.transformer.InstanceTransformer; import com.tencent.polaris.api.pojo.DefaultInstance; import org.apache.commons.lang.StringUtils; diff --git a/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-discovery-adapter-plugin/src/test/java/com/tencent/cloud/plugin/discovery/adapter/config/NacosDiscoveryAdapterAutoConfigurationTest.java b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-discovery-adapter-plugin/src/test/java/com/tencent/cloud/plugin/discovery/adapter/config/NacosDiscoveryAdapterAutoConfigurationTest.java index cae2a60fd..f8f4b7e95 100644 --- a/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-discovery-adapter-plugin/src/test/java/com/tencent/cloud/plugin/discovery/adapter/config/NacosDiscoveryAdapterAutoConfigurationTest.java +++ b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-discovery-adapter-plugin/src/test/java/com/tencent/cloud/plugin/discovery/adapter/config/NacosDiscoveryAdapterAutoConfigurationTest.java @@ -19,7 +19,7 @@ package com.tencent.cloud.plugin.discovery.adapter.config; import com.tencent.cloud.plugin.discovery.adapter.transformer.NacosInstanceTransformer; -import com.tencent.cloud.polaris.router.transformer.PolarisInstanceTransformer; +import com.tencent.cloud.rpc.enhancement.transformer.PolarisInstanceTransformer; import org.junit.jupiter.api.Test; import org.springframework.boot.autoconfigure.AutoConfigurations; diff --git a/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-tsf-adapter-plugin/pom.xml b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-tsf-adapter-plugin/pom.xml new file mode 100644 index 000000000..0c0deb4f1 --- /dev/null +++ b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-tsf-adapter-plugin/pom.xml @@ -0,0 +1,37 @@ + + + + spring-cloud-tencent-plugin-starters + com.tencent.cloud + ${revision} + ../pom.xml + + 4.0.0 + + spring-cloud-starter-tencent-tsf-adapter-plugin + Spring Cloud Starter Tencent TSF Plugin + + + + + + com.tencent.cloud + spring-cloud-tencent-rpc-enhancement + + + + + org.springframework.boot + spring-boot-starter-test + test + + + + org.mockito + mockito-inline + test + + + diff --git a/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-tsf-adapter-plugin/src/main/java/com/tencent/cloud/tsf/adapter/config/PolarisTsfAdapterAutoConfiguration.java b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-tsf-adapter-plugin/src/main/java/com/tencent/cloud/tsf/adapter/config/PolarisTsfAdapterAutoConfiguration.java new file mode 100644 index 000000000..d9d2b4041 --- /dev/null +++ b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-tsf-adapter-plugin/src/main/java/com/tencent/cloud/tsf/adapter/config/PolarisTsfAdapterAutoConfiguration.java @@ -0,0 +1,47 @@ +/* + * Tencent is pleased to support the open source community by making Spring Cloud Tencent available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * Unless required by applicable law or agreed to in writing, software distributed + * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package com.tencent.cloud.tsf.adapter.config; + +import com.tencent.cloud.polaris.context.ConditionalOnPolarisEnabled; +import com.tencent.cloud.rpc.enhancement.config.RpcEnhancementAutoConfiguration; +import com.tencent.polaris.api.exception.PolarisException; + +import org.springframework.boot.autoconfigure.AutoConfigureAfter; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * PolarisTsfAdapterAutoConfiguration. + * + * @author sean yu + */ +@Configuration(proxyBeanMethods = false) +@ConditionalOnPolarisEnabled +@AutoConfigureAfter(RpcEnhancementAutoConfiguration.class) +public class PolarisTsfAdapterAutoConfiguration { + + @Bean + @ConditionalOnMissingBean + public PolarisTsfFlowConfigModifier polarisFlowConfigModifier() throws PolarisException { + return new PolarisTsfFlowConfigModifier(); + } + + + +} diff --git a/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-tsf-adapter-plugin/src/main/java/com/tencent/cloud/tsf/adapter/config/PolarisTsfFlowConfigModifier.java b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-tsf-adapter-plugin/src/main/java/com/tencent/cloud/tsf/adapter/config/PolarisTsfFlowConfigModifier.java new file mode 100644 index 000000000..335e55ae3 --- /dev/null +++ b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-tsf-adapter-plugin/src/main/java/com/tencent/cloud/tsf/adapter/config/PolarisTsfFlowConfigModifier.java @@ -0,0 +1,46 @@ +/* + * Tencent is pleased to support the open source community by making Spring Cloud Tencent available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * Unless required by applicable law or agreed to in writing, software distributed + * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package com.tencent.cloud.tsf.adapter.config; + +import com.tencent.cloud.common.constant.ContextConstant; +import com.tencent.cloud.polaris.context.PolarisConfigModifier; +import com.tencent.polaris.factory.config.ConfigurationImpl; + +/** + * PolarisTsfFlowConfigModifier. + * + * @author sean yu + */ +public class PolarisTsfFlowConfigModifier implements PolarisConfigModifier { + + /** + * Polaris Tsf Flow Name. + */ + public static final String TSF_FLOW_NAME = "tsf"; + + @Override + public void modify(ConfigurationImpl configuration) { + configuration.getGlobal().getSystem().getFlow().setName(TSF_FLOW_NAME); + } + + @Override + public int getOrder() { + return ContextConstant.ModifierOrder.FIRST; + } + +} diff --git a/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-tsf-adapter-plugin/src/test/java/com/tencent/cloud/tsf/adapter/config/PolarisTsfAdapterAutoConfigurationTest.java b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-tsf-adapter-plugin/src/test/java/com/tencent/cloud/tsf/adapter/config/PolarisTsfAdapterAutoConfigurationTest.java new file mode 100644 index 000000000..fa8e4120c --- /dev/null +++ b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-tsf-adapter-plugin/src/test/java/com/tencent/cloud/tsf/adapter/config/PolarisTsfAdapterAutoConfigurationTest.java @@ -0,0 +1,48 @@ +/* + * Tencent is pleased to support the open source community by making Spring Cloud Tencent available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * Unless required by applicable law or agreed to in writing, software distributed + * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package com.tencent.cloud.tsf.adapter.config; + +import com.tencent.cloud.polaris.context.config.PolarisContextAutoConfiguration; +import org.junit.jupiter.api.Test; + +import org.springframework.boot.autoconfigure.AutoConfigurations; +import org.springframework.boot.test.context.runner.ApplicationContextRunner; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * PolarisTsfAdapterAutoConfigurationTest. + * + * @author sean yu + */ +public class PolarisTsfAdapterAutoConfigurationTest { + + private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() + .withConfiguration(AutoConfigurations.of( + PolarisContextAutoConfiguration.class, + PolarisTsfAdapterAutoConfiguration.class + )); + + @Test + public void testDefaultInitialization() { + this.contextRunner.run(context -> { + assertThat(context).hasSingleBean(PolarisTsfFlowConfigModifier.class); + }); + } + +} diff --git a/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-tsf-adapter-plugin/src/test/java/com/tencent/cloud/tsf/adapter/config/TsfAssemblyFlow.java b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-tsf-adapter-plugin/src/test/java/com/tencent/cloud/tsf/adapter/config/TsfAssemblyFlow.java new file mode 100644 index 000000000..bef51db17 --- /dev/null +++ b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-tsf-adapter-plugin/src/test/java/com/tencent/cloud/tsf/adapter/config/TsfAssemblyFlow.java @@ -0,0 +1,38 @@ +/* + * Tencent is pleased to support the open source community by making Spring Cloud Tencent available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * Unless required by applicable law or agreed to in writing, software distributed + * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package com.tencent.cloud.tsf.adapter.config; + +import com.tencent.polaris.assembly.flow.AssemblyFlow; +import com.tencent.polaris.client.api.SDKContext; + +/** + * TsfAssemblyFlow. + * + * @author sean yu + */ +public class TsfAssemblyFlow implements AssemblyFlow { + @Override + public String getName() { + return PolarisTsfFlowConfigModifier.TSF_FLOW_NAME; + } + + @Override + public void setSDKContext(SDKContext sdkContext) { + + } +} diff --git a/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-tsf-adapter-plugin/src/test/java/com/tencent/cloud/tsf/adapter/config/TsfDiscoveryFlow.java b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-tsf-adapter-plugin/src/test/java/com/tencent/cloud/tsf/adapter/config/TsfDiscoveryFlow.java new file mode 100644 index 000000000..d183d23ef --- /dev/null +++ b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-tsf-adapter-plugin/src/test/java/com/tencent/cloud/tsf/adapter/config/TsfDiscoveryFlow.java @@ -0,0 +1,40 @@ +/* + * Tencent is pleased to support the open source community by making Spring Cloud Tencent available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * Unless required by applicable law or agreed to in writing, software distributed + * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package com.tencent.cloud.tsf.adapter.config; + +import com.tencent.polaris.api.flow.DiscoveryFlow; +import com.tencent.polaris.client.api.SDKContext; + +/** + * TsfDiscoveryFlow. + * + * @author sean yu + */ +public class TsfDiscoveryFlow implements DiscoveryFlow { + + + @Override + public String getName() { + return PolarisTsfFlowConfigModifier.TSF_FLOW_NAME; + } + + @Override + public void setSDKContext(SDKContext sdkContext) { + + } +} diff --git a/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-tsf-adapter-plugin/src/test/java/com/tencent/cloud/tsf/adapter/config/TsfRouterFlow.java b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-tsf-adapter-plugin/src/test/java/com/tencent/cloud/tsf/adapter/config/TsfRouterFlow.java new file mode 100644 index 000000000..644d59bb0 --- /dev/null +++ b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-tsf-adapter-plugin/src/test/java/com/tencent/cloud/tsf/adapter/config/TsfRouterFlow.java @@ -0,0 +1,39 @@ +/* + * Tencent is pleased to support the open source community by making Spring Cloud Tencent available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * Unless required by applicable law or agreed to in writing, software distributed + * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package com.tencent.cloud.tsf.adapter.config; + +import com.tencent.polaris.client.api.SDKContext; +import com.tencent.polaris.router.api.flow.RouterFlow; + +/** + * TsfRouterFlow. + * + * @author sean yu + */ +public class TsfRouterFlow implements RouterFlow { + + @Override + public String getName() { + return PolarisTsfFlowConfigModifier.TSF_FLOW_NAME; + } + + @Override + public void setSDKContext(SDKContext sdkContext) { + + } +} diff --git a/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-tsf-adapter-plugin/src/test/resources/META-INF/services/com.tencent.polaris.api.flow.DiscoveryFlow b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-tsf-adapter-plugin/src/test/resources/META-INF/services/com.tencent.polaris.api.flow.DiscoveryFlow new file mode 100644 index 000000000..639ce8bd7 --- /dev/null +++ b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-tsf-adapter-plugin/src/test/resources/META-INF/services/com.tencent.polaris.api.flow.DiscoveryFlow @@ -0,0 +1 @@ +com.tencent.cloud.tsf.adapter.config.TsfDiscoveryFlow \ No newline at end of file diff --git a/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-tsf-adapter-plugin/src/test/resources/META-INF/services/com.tencent.polaris.assembly.flow.AssemblyFlow b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-tsf-adapter-plugin/src/test/resources/META-INF/services/com.tencent.polaris.assembly.flow.AssemblyFlow new file mode 100644 index 000000000..bd5df065c --- /dev/null +++ b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-tsf-adapter-plugin/src/test/resources/META-INF/services/com.tencent.polaris.assembly.flow.AssemblyFlow @@ -0,0 +1 @@ +com.tencent.cloud.tsf.adapter.config.TsfAssemblyFlow \ No newline at end of file diff --git a/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-tsf-adapter-plugin/src/test/resources/META-INF/services/com.tencent.polaris.router.api.flow.RouterFlow b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-tsf-adapter-plugin/src/test/resources/META-INF/services/com.tencent.polaris.router.api.flow.RouterFlow new file mode 100644 index 000000000..2ed23f638 --- /dev/null +++ b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-tsf-adapter-plugin/src/test/resources/META-INF/services/com.tencent.polaris.router.api.flow.RouterFlow @@ -0,0 +1 @@ +com.tencent.cloud.tsf.adapter.config.TsfRouterFlow \ No newline at end of file diff --git a/spring-cloud-tencent-polaris-context/pom.xml b/spring-cloud-tencent-polaris-context/pom.xml index 2507beddd..50aa9dc1b 100644 --- a/spring-cloud-tencent-polaris-context/pom.xml +++ b/spring-cloud-tencent-polaris-context/pom.xml @@ -104,6 +104,11 @@ com.tencent.polaris loadbalancer-ringhash + + + com.tencent.polaris + polaris-assembly-factory + diff --git a/spring-cloud-tencent-polaris-context/src/main/java/com/tencent/cloud/polaris/context/config/PolarisContextAutoConfiguration.java b/spring-cloud-tencent-polaris-context/src/main/java/com/tencent/cloud/polaris/context/config/PolarisContextAutoConfiguration.java index 298d89fa4..104a4e057 100644 --- a/spring-cloud-tencent-polaris-context/src/main/java/com/tencent/cloud/polaris/context/config/PolarisContextAutoConfiguration.java +++ b/spring-cloud-tencent-polaris-context/src/main/java/com/tencent/cloud/polaris/context/config/PolarisContextAutoConfiguration.java @@ -27,6 +27,8 @@ import com.tencent.cloud.polaris.context.ServiceRuleManager; import com.tencent.polaris.api.core.ConsumerAPI; import com.tencent.polaris.api.core.ProviderAPI; import com.tencent.polaris.api.exception.PolarisException; +import com.tencent.polaris.assembly.api.AssemblyAPI; +import com.tencent.polaris.assembly.factory.AssemblyAPIFactory; import com.tencent.polaris.client.api.SDKContext; import com.tencent.polaris.factory.api.DiscoveryAPIFactory; import com.tencent.polaris.factory.api.RouterAPIFactory; @@ -73,6 +75,11 @@ public class PolarisContextAutoConfiguration { return RouterAPIFactory.createRouterAPIByContext(polarisContext); } + @Bean + public AssemblyAPI assemblyAPI(SDKContext polarisContext) throws PolarisException { + return AssemblyAPIFactory.createAssemblyAPIByContext(polarisContext); + } + @Bean @ConditionalOnMissingBean public ModifyAddress polarisConfigModifier(PolarisContextProperties properties) { diff --git a/spring-cloud-tencent-rpc-enhancement/pom.xml b/spring-cloud-tencent-rpc-enhancement/pom.xml index 5d7cf2d24..1dd931227 100644 --- a/spring-cloud-tencent-rpc-enhancement/pom.xml +++ b/spring-cloud-tencent-rpc-enhancement/pom.xml @@ -71,7 +71,7 @@ org.springframework.boot spring-boot-starter-web - test + true diff --git a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/config/RpcEnhancementAutoConfiguration.java b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/config/RpcEnhancementAutoConfiguration.java index d675886ce..b81c67289 100644 --- a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/config/RpcEnhancementAutoConfiguration.java +++ b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/config/RpcEnhancementAutoConfiguration.java @@ -20,20 +20,33 @@ package com.tencent.cloud.rpc.enhancement.config; import java.util.Collections; import java.util.List; +import com.tencent.cloud.common.pojo.PolarisServiceInstance; import com.tencent.cloud.polaris.context.ConditionalOnPolarisEnabled; import com.tencent.cloud.polaris.context.config.PolarisContextAutoConfiguration; import com.tencent.cloud.rpc.enhancement.feign.EnhancedFeignBeanPostProcessor; +import com.tencent.cloud.rpc.enhancement.feign.EnhancedLoadBalancerClientAspect; +import com.tencent.cloud.rpc.enhancement.filter.EnhancedReactiveFilter; +import com.tencent.cloud.rpc.enhancement.filter.EnhancedServletFilter; import com.tencent.cloud.rpc.enhancement.plugin.DefaultEnhancedPluginRunner; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPlugin; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginRunner; +import com.tencent.cloud.rpc.enhancement.plugin.assembly.client.AssemblyClientExceptionHook; +import com.tencent.cloud.rpc.enhancement.plugin.assembly.client.AssemblyClientPostHook; +import com.tencent.cloud.rpc.enhancement.plugin.assembly.client.AssemblyClientPreHook; +import com.tencent.cloud.rpc.enhancement.plugin.assembly.server.AssemblyServerExceptionHook; +import com.tencent.cloud.rpc.enhancement.plugin.assembly.server.AssemblyServerPostHook; +import com.tencent.cloud.rpc.enhancement.plugin.assembly.server.AssemblyServerPreHook; import com.tencent.cloud.rpc.enhancement.plugin.reporter.ExceptionPolarisReporter; import com.tencent.cloud.rpc.enhancement.plugin.reporter.SuccessPolarisReporter; -import com.tencent.cloud.rpc.enhancement.resttemplate.BlockingLoadBalancerClientAspect; import com.tencent.cloud.rpc.enhancement.resttemplate.EnhancedRestTemplateInterceptor; +import com.tencent.cloud.rpc.enhancement.resttemplate.PolarisLoadBalancerRequestTransformer; import com.tencent.cloud.rpc.enhancement.scg.EnhancedGatewayGlobalFilter; -import com.tencent.cloud.rpc.enhancement.webclient.EnhancedWebClientReporter; +import com.tencent.cloud.rpc.enhancement.transformer.InstanceTransformer; +import com.tencent.cloud.rpc.enhancement.transformer.PolarisInstanceTransformer; +import com.tencent.cloud.rpc.enhancement.webclient.EnhancedWebClientExchangeFilterFunction; import com.tencent.cloud.rpc.enhancement.webclient.PolarisLoadBalancerClientRequestTransformer; import com.tencent.polaris.api.core.ConsumerAPI; +import com.tencent.polaris.assembly.api.AssemblyAPI; import com.tencent.polaris.client.api.SDKContext; import org.springframework.beans.factory.SmartInitializingSingleton; @@ -44,15 +57,25 @@ import org.springframework.boot.autoconfigure.AutoConfigureBefore; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.cloud.client.loadbalancer.LoadBalanced; +import org.springframework.cloud.client.serviceregistry.Registration; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Lazy; import org.springframework.context.annotation.Role; +import org.springframework.core.annotation.Order; import org.springframework.web.client.RestTemplate; import org.springframework.web.reactive.function.client.WebClient; +import static javax.servlet.DispatcherType.ASYNC; +import static javax.servlet.DispatcherType.ERROR; +import static javax.servlet.DispatcherType.FORWARD; +import static javax.servlet.DispatcherType.INCLUDE; +import static javax.servlet.DispatcherType.REQUEST; + /** * Auto Configuration for Polaris {@link feign.Feign} OR {@link RestTemplate} which can automatically bring in the call * results for reporting. @@ -67,23 +90,92 @@ import org.springframework.web.reactive.function.client.WebClient; public class RpcEnhancementAutoConfiguration { @Bean + @ConditionalOnMissingBean + @ConditionalOnClass(PolarisServiceInstance.class) + public InstanceTransformer instanceTransformer() { + return new PolarisInstanceTransformer(); + } + + @Bean + @Lazy public EnhancedPluginRunner enhancedFeignPluginRunner( - @Autowired(required = false) List enhancedPlugins) { - return new DefaultEnhancedPluginRunner(enhancedPlugins); + @Autowired(required = false) List enhancedPlugins, + @Autowired(required = false) Registration registration, + SDKContext sdkContext) { + return new DefaultEnhancedPluginRunner(enhancedPlugins, registration, sdkContext); } @Bean public SuccessPolarisReporter successPolarisReporter(RpcEnhancementReporterProperties properties, - SDKContext context, ConsumerAPI consumerAPI) { - return new SuccessPolarisReporter(properties, context, consumerAPI); + return new SuccessPolarisReporter(properties, consumerAPI); } @Bean public ExceptionPolarisReporter exceptionPolarisReporter(RpcEnhancementReporterProperties properties, - SDKContext context, ConsumerAPI consumerAPI) { - return new ExceptionPolarisReporter(properties, context, consumerAPI); + return new ExceptionPolarisReporter(properties, consumerAPI); + } + + @Bean + public AssemblyClientExceptionHook assemblyClientExceptionHook(AssemblyAPI assemblyAPI, InstanceTransformer instanceTransformer) { + return new AssemblyClientExceptionHook(assemblyAPI, instanceTransformer); + } + + @Bean + public AssemblyClientPostHook assemblyClientPostHook(AssemblyAPI assemblyAPI, InstanceTransformer instanceTransformer) { + return new AssemblyClientPostHook(assemblyAPI, instanceTransformer); + } + + @Bean + public AssemblyClientPreHook assemblyClientPreHook(AssemblyAPI assemblyAPI) { + return new AssemblyClientPreHook(assemblyAPI); + } + + @Bean + public AssemblyServerExceptionHook assemblyServerExceptionHook(AssemblyAPI assemblyAPI) { + return new AssemblyServerExceptionHook(assemblyAPI); + } + + @Bean + public AssemblyServerPostHook assemblyServerPostHook(AssemblyAPI assemblyAPI) { + return new AssemblyServerPostHook(assemblyAPI); + } + + @Bean + public AssemblyServerPreHook assemblyServerPreHook(AssemblyAPI assemblyAPI) { + return new AssemblyServerPreHook(assemblyAPI); + } + + @Configuration(proxyBeanMethods = false) + @ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET) + protected static class RpcEnhancementServletFilterConfig { + + @Bean + public FilterRegistrationBean enhancedServletFilterRegistrationBean( + EnhancedServletFilter enhancedServletFilter) { + FilterRegistrationBean filterRegistrationBean = + new FilterRegistrationBean<>(enhancedServletFilter); + filterRegistrationBean.setDispatcherTypes(ASYNC, ERROR, FORWARD, INCLUDE, REQUEST); + filterRegistrationBean.setOrder(enhancedServletFilter.getClass().getAnnotation(Order.class).value()); + return filterRegistrationBean; + } + + @Bean + public EnhancedServletFilter enhancedServletFilter(@Lazy EnhancedPluginRunner pluginRunner) { + return new EnhancedServletFilter(pluginRunner); + } + + } + + @Configuration(proxyBeanMethods = false) + @ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.REACTIVE) + protected static class RpcEnhancementReactiveFilterConfig { + + @Bean + public EnhancedReactiveFilter enhancedReactiveFilter(@Lazy EnhancedPluginRunner pluginRunner) { + return new EnhancedReactiveFilter(pluginRunner); + } } /** @@ -103,6 +195,13 @@ public class RpcEnhancementAutoConfiguration { return new EnhancedFeignBeanPostProcessor(pluginRunner); } + @Bean + @ConditionalOnMissingBean + @ConditionalOnClass(name = "org.springframework.cloud.client.loadbalancer.ServiceInstanceChooser") + public EnhancedLoadBalancerClientAspect enhancedLoadBalancerClientAspect() { + return new EnhancedLoadBalancerClientAspect(); + } + } /** @@ -135,9 +234,9 @@ public class RpcEnhancementAutoConfiguration { @Bean @ConditionalOnMissingBean - @ConditionalOnClass(name = {"org.springframework.cloud.loadbalancer.blocking.client.BlockingLoadBalancerClient"}) - public BlockingLoadBalancerClientAspect blockingLoadBalancerClientAspect() { - return new BlockingLoadBalancerClientAspect(); + @ConditionalOnClass(name = {"org.springframework.cloud.client.loadbalancer.LoadBalancerRequestTransformer"}) + public PolarisLoadBalancerRequestTransformer polarisLoadBalancerRequestTransformer() { + return new PolarisLoadBalancerRequestTransformer(); } } @@ -154,12 +253,12 @@ public class RpcEnhancementAutoConfiguration { private List webClientBuilder = Collections.emptyList(); @Bean - public EnhancedWebClientReporter exchangeFilterFunction(@Lazy EnhancedPluginRunner pluginRunner) { - return new EnhancedWebClientReporter(pluginRunner); + public EnhancedWebClientExchangeFilterFunction exchangeFilterFunction(@Lazy EnhancedPluginRunner pluginRunner) { + return new EnhancedWebClientExchangeFilterFunction(pluginRunner); } @Bean - public SmartInitializingSingleton addEnhancedWebClientReporterForWebClient(EnhancedWebClientReporter reporter) { + public SmartInitializingSingleton addEnhancedWebClientReporterForWebClient(EnhancedWebClientExchangeFilterFunction reporter) { return () -> webClientBuilder.forEach(webClient -> { webClient.filter(reporter); }); diff --git a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/feign/EnhancedFeignClient.java b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/feign/EnhancedFeignClient.java index e191edfde..1af26f5b6 100644 --- a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/feign/EnhancedFeignClient.java +++ b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/feign/EnhancedFeignClient.java @@ -21,8 +21,10 @@ import java.io.IOException; import java.net.URI; import java.util.ArrayList; +import com.tencent.cloud.common.metadata.MetadataContextHolder; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginContext; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginRunner; +import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedRequestContext; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedResponseContext; import feign.Client; @@ -30,14 +32,11 @@ import feign.Request; import feign.Request.Options; import feign.Response; -import org.springframework.cloud.client.DefaultServiceInstance; +import org.springframework.cloud.client.ServiceInstance; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; -import static com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType.EXCEPTION; -import static com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType.FINALLY; -import static com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType.POST; -import static com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType.PRE; +import static com.tencent.cloud.rpc.enhancement.resttemplate.PolarisLoadBalancerRequestTransformer.LOAD_BALANCER_SERVICE_INSTANCE; import static feign.Util.checkNotNull; /** @@ -66,13 +65,18 @@ public class EnhancedFeignClient implements Client { EnhancedRequestContext enhancedRequestContext = EnhancedRequestContext.builder() .httpHeaders(requestHeaders) - .httpMethod(HttpMethod.resolve(request.httpMethod().name())) + .httpMethod(HttpMethod.valueOf(request.httpMethod().name())) .url(url) .build(); enhancedPluginContext.setRequest(enhancedRequestContext); + enhancedPluginContext.setLocalServiceInstance(pluginRunner.getLocalServiceInstance()); + enhancedPluginContext.setTargetServiceInstance( + (ServiceInstance) MetadataContextHolder.get().getLoadbalancerMetadata().get(LOAD_BALANCER_SERVICE_INSTANCE)); + // Run pre enhanced plugins. - pluginRunner.run(PRE, enhancedPluginContext); + pluginRunner.run(EnhancedPluginType.Client.PRE, enhancedPluginContext); + long startMillis = System.currentTimeMillis(); try { Response response = delegate.execute(request, options); @@ -87,26 +91,20 @@ public class EnhancedFeignClient implements Client { .build(); enhancedPluginContext.setResponse(enhancedResponseContext); - DefaultServiceInstance serviceInstance = new DefaultServiceInstance(); - serviceInstance.setServiceId(request.requestTemplate().feignTarget().name()); - serviceInstance.setHost(url.getHost()); - serviceInstance.setPort(url.getPort()); - enhancedPluginContext.setServiceInstance(serviceInstance); - // Run post enhanced plugins. - pluginRunner.run(POST, enhancedPluginContext); + pluginRunner.run(EnhancedPluginType.Client.POST, enhancedPluginContext); return response; } catch (IOException origin) { enhancedPluginContext.setDelay(System.currentTimeMillis() - startMillis); enhancedPluginContext.setThrowable(origin); // Run exception enhanced feign plugins. - pluginRunner.run(EXCEPTION, enhancedPluginContext); + pluginRunner.run(EnhancedPluginType.Client.EXCEPTION, enhancedPluginContext); throw origin; } finally { // Run finally enhanced plugins. - pluginRunner.run(FINALLY, enhancedPluginContext); + pluginRunner.run(EnhancedPluginType.Client.FINALLY, enhancedPluginContext); } } } diff --git a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/resttemplate/BlockingLoadBalancerClientAspect.java b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/feign/EnhancedLoadBalancerClientAspect.java similarity index 62% rename from spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/resttemplate/BlockingLoadBalancerClientAspect.java rename to spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/feign/EnhancedLoadBalancerClientAspect.java index 418ce4846..0bab294ab 100644 --- a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/resttemplate/BlockingLoadBalancerClientAspect.java +++ b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/feign/EnhancedLoadBalancerClientAspect.java @@ -15,29 +15,35 @@ * specific language governing permissions and limitations under the License. */ -package com.tencent.cloud.rpc.enhancement.resttemplate; +package com.tencent.cloud.rpc.enhancement.feign; +import com.tencent.cloud.common.metadata.MetadataContextHolder; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut; +import static com.tencent.cloud.rpc.enhancement.resttemplate.PolarisLoadBalancerRequestTransformer.LOAD_BALANCER_SERVICE_INSTANCE; + /** - * Intercept for BlockingLoadBalancerClient, put host and port to thread local. + * EnhancedLoadBalancerClientAspect. * - * @author lepdou 2022-09-05 + * @author sean yu */ @Aspect -public class BlockingLoadBalancerClientAspect { +public class EnhancedLoadBalancerClientAspect { - @Pointcut("execution(public * org.springframework.cloud.loadbalancer.blocking.client.BlockingLoadBalancerClient.reconstructURI(..)) ") + @Pointcut("execution(public * org.springframework.cloud.client.loadbalancer.ServiceInstanceChooser.choose(..)) ") public void pointcut() { } @Around("pointcut()") public Object invoke(ProceedingJoinPoint joinPoint) throws Throwable { - LoadBalancerClientAspectUtils.extractLoadBalancerResult(joinPoint); - return joinPoint.proceed(); + Object result = joinPoint.proceed(); + if (result != null) { + MetadataContextHolder.get().setLoadbalancer(LOAD_BALANCER_SERVICE_INSTANCE, result); + } + return result; } } diff --git a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/filter/EnhancedReactiveFilter.java b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/filter/EnhancedReactiveFilter.java new file mode 100644 index 000000000..4fa6899ce --- /dev/null +++ b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/filter/EnhancedReactiveFilter.java @@ -0,0 +1,93 @@ +/* + * Tencent is pleased to support the open source community by making Spring Cloud Tencent available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * Unless required by applicable law or agreed to in writing, software distributed + * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package com.tencent.cloud.rpc.enhancement.filter; + +import com.tencent.cloud.common.constant.MetadataConstant; +import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginContext; +import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginRunner; +import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType; +import com.tencent.cloud.rpc.enhancement.plugin.EnhancedRequestContext; +import com.tencent.cloud.rpc.enhancement.plugin.EnhancedResponseContext; +import reactor.core.publisher.Mono; + +import org.springframework.core.Ordered; +import org.springframework.web.server.ServerWebExchange; +import org.springframework.web.server.WebFilter; +import org.springframework.web.server.WebFilterChain; + +/** + * EnhancedReactiveFilter. + * + * @author sean yu + */ +public class EnhancedReactiveFilter implements WebFilter, Ordered { + + private final EnhancedPluginRunner pluginRunner; + + public EnhancedReactiveFilter(EnhancedPluginRunner pluginRunner) { + this.pluginRunner = pluginRunner; + } + + @Override + public Mono filter(ServerWebExchange exchange, WebFilterChain chain) { + EnhancedPluginContext enhancedPluginContext = new EnhancedPluginContext(); + + EnhancedRequestContext enhancedRequestContext = EnhancedRequestContext.builder() + .httpHeaders(exchange.getRequest().getHeaders()) + .httpMethod(exchange.getRequest().getMethod()) + .url(exchange.getRequest().getURI()) + .build(); + enhancedPluginContext.setRequest(enhancedRequestContext); + + enhancedPluginContext.setLocalServiceInstance(pluginRunner.getLocalServiceInstance()); + + // Run pre enhanced plugins. + pluginRunner.run(EnhancedPluginType.Server.PRE, enhancedPluginContext); + + long startMillis = System.currentTimeMillis(); + return chain.filter(exchange) + .doOnSuccess(v -> { + enhancedPluginContext.setDelay(System.currentTimeMillis() - startMillis); + + EnhancedResponseContext enhancedResponseContext = EnhancedResponseContext.builder() + .httpStatus(exchange.getResponse().getRawStatusCode()) + .httpHeaders(exchange.getResponse().getHeaders()) + .build(); + enhancedPluginContext.setResponse(enhancedResponseContext); + + // Run post enhanced plugins. + pluginRunner.run(EnhancedPluginType.Server.POST, enhancedPluginContext); + }) + .doOnError(e -> { + enhancedPluginContext.setDelay(System.currentTimeMillis() - startMillis); + enhancedPluginContext.setThrowable(e); + // Run exception enhanced plugins. + pluginRunner.run(EnhancedPluginType.Server.EXCEPTION, enhancedPluginContext); + }) + .doFinally(v -> { + // Run finally enhanced plugins. + pluginRunner.run(EnhancedPluginType.Server.FINALLY, enhancedPluginContext); + }); + } + + @Override + public int getOrder() { + return MetadataConstant.OrderConstant.WEB_FILTER_ORDER + 1; + } + +} diff --git a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/filter/EnhancedServletFilter.java b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/filter/EnhancedServletFilter.java new file mode 100644 index 000000000..9d404281c --- /dev/null +++ b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/filter/EnhancedServletFilter.java @@ -0,0 +1,116 @@ +/* + * Tencent is pleased to support the open source community by making Spring Cloud Tencent available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * Unless required by applicable law or agreed to in writing, software distributed + * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package com.tencent.cloud.rpc.enhancement.filter; + +import java.io.IOException; +import java.net.URI; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Enumeration; + +import javax.servlet.FilterChain; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import com.tencent.cloud.common.constant.MetadataConstant; +import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginContext; +import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginRunner; +import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType; +import com.tencent.cloud.rpc.enhancement.plugin.EnhancedRequestContext; +import com.tencent.cloud.rpc.enhancement.plugin.EnhancedResponseContext; + +import org.springframework.core.annotation.Order; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.web.filter.OncePerRequestFilter; + +/** + * EnhancedServletFilter. + * + * @author sean yu + */ +@Order(MetadataConstant.OrderConstant.WEB_FILTER_ORDER + 1) +public class EnhancedServletFilter extends OncePerRequestFilter { + + private final EnhancedPluginRunner pluginRunner; + + public EnhancedServletFilter(EnhancedPluginRunner pluginRunner) { + this.pluginRunner = pluginRunner; + } + + @Override + protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { + EnhancedPluginContext enhancedPluginContext = new EnhancedPluginContext(); + + HttpHeaders requestHeaders = new HttpHeaders(); + Enumeration requestHeaderNames = request.getHeaderNames(); + if (requestHeaderNames != null) { + while (requestHeaderNames.hasMoreElements()) { + String requestHeaderName = requestHeaderNames.nextElement(); + requestHeaders.addAll(requestHeaderName, Collections.list(request.getHeaders(requestHeaderName))); + } + } + EnhancedRequestContext enhancedRequestContext = EnhancedRequestContext.builder() + .httpHeaders(requestHeaders) + .httpMethod(HttpMethod.valueOf(request.getMethod())) + .url(URI.create(request.getRequestURL().toString())) + .build(); + enhancedPluginContext.setRequest(enhancedRequestContext); + + enhancedPluginContext.setLocalServiceInstance(pluginRunner.getLocalServiceInstance()); + + // Run pre enhanced plugins. + pluginRunner.run(EnhancedPluginType.Server.PRE, enhancedPluginContext); + + long startMillis = System.currentTimeMillis(); + try { + filterChain.doFilter(request, response); + enhancedPluginContext.setDelay(System.currentTimeMillis() - startMillis); + + HttpHeaders responseHeaders = new HttpHeaders(); + Collection responseHeaderNames = response.getHeaderNames(); + if (responseHeaderNames != null) { + for (String responseHeaderName : responseHeaderNames) { + responseHeaders.addAll(responseHeaderName, new ArrayList<>(response.getHeaders(responseHeaderName))); + } + } + EnhancedResponseContext enhancedResponseContext = EnhancedResponseContext.builder() + .httpStatus(response.getStatus()) + .httpHeaders(responseHeaders) + .build(); + enhancedPluginContext.setResponse(enhancedResponseContext); + + // Run post enhanced plugins. + pluginRunner.run(EnhancedPluginType.Server.POST, enhancedPluginContext); + } + catch (ServletException | IOException e) { + enhancedPluginContext.setDelay(System.currentTimeMillis() - startMillis); + enhancedPluginContext.setThrowable(e); + // Run exception enhanced plugins. + pluginRunner.run(EnhancedPluginType.Server.EXCEPTION, enhancedPluginContext); + throw e; + } + finally { + // Run finally enhanced plugins. + pluginRunner.run(EnhancedPluginType.Server.FINALLY, enhancedPluginContext); + } + } + +} diff --git a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/plugin/DefaultEnhancedPluginRunner.java b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/plugin/DefaultEnhancedPluginRunner.java index ca34b2af1..fe88923f6 100644 --- a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/plugin/DefaultEnhancedPluginRunner.java +++ b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/plugin/DefaultEnhancedPluginRunner.java @@ -23,7 +23,12 @@ import java.util.List; import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.Multimap; +import com.tencent.cloud.common.metadata.MetadataContext; +import com.tencent.polaris.client.api.SDKContext; +import org.springframework.cloud.client.DefaultServiceInstance; +import org.springframework.cloud.client.ServiceInstance; +import org.springframework.cloud.client.serviceregistry.Registration; import org.springframework.util.CollectionUtils; /** @@ -33,13 +38,28 @@ import org.springframework.util.CollectionUtils; */ public class DefaultEnhancedPluginRunner implements EnhancedPluginRunner { - private final Multimap pluginMap = ArrayListMultimap.create(); + private final Multimap pluginMap = ArrayListMultimap.create(); - public DefaultEnhancedPluginRunner(List enhancedPlugins) { + private final ServiceInstance localServiceInstance; + + public DefaultEnhancedPluginRunner( + List enhancedPlugins, + Registration registration, + SDKContext sdkContext + ) { if (!CollectionUtils.isEmpty(enhancedPlugins)) { enhancedPlugins.stream() .sorted(Comparator.comparing(EnhancedPlugin::getOrder)) - .forEach(plugin -> pluginMap.put(plugin.getType().name(), plugin)); + .forEach(plugin -> pluginMap.put(plugin.getType(), plugin)); + } + if (registration != null) { + localServiceInstance = registration; + } + else { + DefaultServiceInstance defaultServiceInstance = new DefaultServiceInstance(); + defaultServiceInstance.setServiceId(MetadataContext.LOCAL_SERVICE); + defaultServiceInstance.setHost(sdkContext.getConfig().getGlobal().getAPI().getBindIP()); + localServiceInstance = defaultServiceInstance; } } @@ -51,7 +71,7 @@ public class DefaultEnhancedPluginRunner implements EnhancedPluginRunner { */ @Override public void run(EnhancedPluginType pluginType, EnhancedPluginContext context) { - for (EnhancedPlugin plugin : pluginMap.get(pluginType.name())) { + for (EnhancedPlugin plugin : pluginMap.get(pluginType)) { try { plugin.run(context); } @@ -60,4 +80,10 @@ public class DefaultEnhancedPluginRunner implements EnhancedPluginRunner { } } } + + @Override + public ServiceInstance getLocalServiceInstance() { + return this.localServiceInstance; + } + } diff --git a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/plugin/EnhancedPluginContext.java b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/plugin/EnhancedPluginContext.java index fa4e891d0..4676c51ad 100644 --- a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/plugin/EnhancedPluginContext.java +++ b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/plugin/EnhancedPluginContext.java @@ -35,7 +35,12 @@ public class EnhancedPluginContext { private long delay; - private ServiceInstance serviceInstance; + private ServiceInstance localServiceInstance; + + /** + * targetServiceInstance only exist in a client runner type. + */ + private ServiceInstance targetServiceInstance; public EnhancedRequestContext getRequest() { return request; @@ -69,12 +74,20 @@ public class EnhancedPluginContext { this.delay = delay; } - public ServiceInstance getServiceInstance() { - return serviceInstance; + public ServiceInstance getLocalServiceInstance() { + return localServiceInstance; + } + + public void setLocalServiceInstance(ServiceInstance localServiceInstance) { + this.localServiceInstance = localServiceInstance; } - public void setServiceInstance(ServiceInstance serviceInstance) { - this.serviceInstance = serviceInstance; + public ServiceInstance getTargetServiceInstance() { + return targetServiceInstance; + } + + public void setTargetServiceInstance(ServiceInstance targetServiceInstance) { + this.targetServiceInstance = targetServiceInstance; } @Override @@ -84,7 +97,9 @@ public class EnhancedPluginContext { ", response=" + response + ", throwable=" + throwable + ", delay=" + delay + - ", serviceInstance=" + serviceInstance + + ", localServiceInstance=" + localServiceInstance + + ", targetServiceInstance=" + targetServiceInstance + '}'; } + } diff --git a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/plugin/EnhancedPluginRunner.java b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/plugin/EnhancedPluginRunner.java index e15af39e5..5ff7d1bf6 100644 --- a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/plugin/EnhancedPluginRunner.java +++ b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/plugin/EnhancedPluginRunner.java @@ -18,6 +18,8 @@ package com.tencent.cloud.rpc.enhancement.plugin; +import org.springframework.cloud.client.ServiceInstance; + /** * Plugin runner. * @@ -32,4 +34,7 @@ public interface EnhancedPluginRunner { * @param context context in enhanced feign client. */ void run(EnhancedPluginType pluginType, EnhancedPluginContext context); + + ServiceInstance getLocalServiceInstance(); + } diff --git a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/plugin/EnhancedPluginType.java b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/plugin/EnhancedPluginType.java index 64dc2ecb9..996af00bb 100644 --- a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/plugin/EnhancedPluginType.java +++ b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/plugin/EnhancedPluginType.java @@ -22,25 +22,52 @@ package com.tencent.cloud.rpc.enhancement.plugin; * * @author Haotian Zhang */ -public enum EnhancedPluginType { - - /** - * Pre feign plugin. - */ - PRE, - - /** - * Post feign plugin. - */ - POST, - - /** - * Exception feign plugin. - */ - EXCEPTION, - - /** - * Finally feign plugin. - */ - FINALLY +public interface EnhancedPluginType { + + enum Client implements EnhancedPluginType { + /** + * Pre Client plugin. + */ + PRE, + + /** + * Post Client plugin. + */ + POST, + + /** + * Exception Client plugin. + */ + EXCEPTION, + + /** + * Finally Client plugin. + */ + FINALLY + + } + + enum Server implements EnhancedPluginType { + /** + * Pre Server plugin. + */ + PRE, + + /** + * Post Server plugin. + */ + POST, + + /** + * Exception Server plugin. + */ + EXCEPTION, + + /** + * Finally Server plugin. + */ + FINALLY + + } + } diff --git a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/plugin/PluginOrderConstant.java b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/plugin/PluginOrderConstant.java new file mode 100644 index 000000000..dfa4148b1 --- /dev/null +++ b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/plugin/PluginOrderConstant.java @@ -0,0 +1,67 @@ +/* + * Tencent is pleased to support the open source community by making Spring Cloud Tencent available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * Unless required by applicable law or agreed to in writing, software distributed + * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + */ + +package com.tencent.cloud.rpc.enhancement.plugin; + +import org.springframework.core.Ordered; + +/** + * PluginOrderConstant. + * + * @author sean yu + */ +public class PluginOrderConstant { + + public static class ClientPluginOrder { + /** + * order for + * {@link com.tencent.cloud.polaris.circuitbreaker.reporter.SuccessCircuitBreakerReporter} + * and + * {@link com.tencent.cloud.polaris.circuitbreaker.reporter.ExceptionCircuitBreakerReporter}. + */ + public static final int CONSUMER_REPORTER_PLUGIN_ORDER = Ordered.HIGHEST_PRECEDENCE + 1; + /** + * order for + * {@link com.tencent.cloud.rpc.enhancement.plugin.reporter.SuccessPolarisReporter} + * and + * {@link com.tencent.cloud.rpc.enhancement.plugin.reporter.ExceptionPolarisReporter}. + */ + public static final int CIRCUIT_BREAKER_REPORTER_PLUGIN_ORDER = Ordered.HIGHEST_PRECEDENCE + 2; + /** + * order for + * {@link com.tencent.cloud.rpc.enhancement.plugin.assembly.client.AssemblyClientPreHook} + * and + * {@link com.tencent.cloud.rpc.enhancement.plugin.assembly.client.AssemblyClientPostHook} + * and + * {@link com.tencent.cloud.rpc.enhancement.plugin.assembly.client.AssemblyClientExceptionHook}. + */ + public static final int ASSEMBLY_PLUGIN_ORDER = Ordered.HIGHEST_PRECEDENCE + 3; + } + + public static class ServerPluginOrder { + /** + * order for + * {@link com.tencent.cloud.rpc.enhancement.plugin.assembly.server.AssemblyServerPreHook} + * and + * {@link com.tencent.cloud.rpc.enhancement.plugin.assembly.server.AssemblyServerPostHook} + * and + * {@link com.tencent.cloud.rpc.enhancement.plugin.assembly.server.AssemblyServerExceptionHook}. + */ + public static final int ASSEMBLY_PLUGIN_ORDER = Ordered.HIGHEST_PRECEDENCE + 1; + } +} diff --git a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/AbstractPolarisReporterAdapter.java b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/plugin/PolarisEnhancedPluginUtils.java similarity index 73% rename from spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/AbstractPolarisReporterAdapter.java rename to spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/plugin/PolarisEnhancedPluginUtils.java index d177aad8b..e1556c82d 100644 --- a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/AbstractPolarisReporterAdapter.java +++ b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/plugin/PolarisEnhancedPluginUtils.java @@ -15,7 +15,7 @@ * specific language governing permissions and limitations under the License. */ -package com.tencent.cloud.rpc.enhancement; +package com.tencent.cloud.rpc.enhancement.plugin; import java.io.UnsupportedEncodingException; import java.net.SocketTimeoutException; @@ -24,12 +24,18 @@ import java.net.URLDecoder; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Objects; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; import com.tencent.cloud.common.constant.HeaderConstant; import com.tencent.cloud.common.constant.RouterConstant; import com.tencent.cloud.common.metadata.MetadataContext; +import com.tencent.cloud.common.util.ApplicationContextAwareUtils; import com.tencent.cloud.common.util.RequestLabelUtils; import com.tencent.cloud.rpc.enhancement.config.RpcEnhancementReporterProperties; import com.tencent.polaris.api.plugin.circuitbreaker.ResourceStat; @@ -39,11 +45,11 @@ import com.tencent.polaris.api.pojo.RetStatus; import com.tencent.polaris.api.pojo.ServiceKey; import com.tencent.polaris.api.rpc.ServiceCallResult; import com.tencent.polaris.api.utils.CollectionUtils; -import com.tencent.polaris.client.api.SDKContext; import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.beans.BeansException; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.lang.Nullable; @@ -63,30 +69,21 @@ import static org.springframework.http.HttpStatus.SERVICE_UNAVAILABLE; import static org.springframework.http.HttpStatus.VARIANT_ALSO_NEGOTIATES; /** - * Abstract Polaris Reporter Adapter . + * Abstract Polaris Plugin Adapter . * * @author Elve.Xu 2022-07-11 */ -public abstract class AbstractPolarisReporterAdapter { - private static final Logger LOG = LoggerFactory.getLogger(AbstractPolarisReporterAdapter.class); - private static final List HTTP_STATUSES = toList(NOT_IMPLEMENTED, BAD_GATEWAY, - SERVICE_UNAVAILABLE, GATEWAY_TIMEOUT, HTTP_VERSION_NOT_SUPPORTED, VARIANT_ALSO_NEGOTIATES, - INSUFFICIENT_STORAGE, LOOP_DETECTED, BANDWIDTH_LIMIT_EXCEEDED, NOT_EXTENDED, NETWORK_AUTHENTICATION_REQUIRED); +public final class PolarisEnhancedPluginUtils { - protected final RpcEnhancementReporterProperties reportProperties; + private PolarisEnhancedPluginUtils() { - protected final SDKContext context; - - /** - * Constructor With {@link RpcEnhancementReporterProperties} . - * - * @param reportProperties instance of {@link RpcEnhancementReporterProperties}. - */ - protected AbstractPolarisReporterAdapter(RpcEnhancementReporterProperties reportProperties, SDKContext context) { - this.reportProperties = reportProperties; - this.context = context; } + private static final Logger LOG = LoggerFactory.getLogger(PolarisEnhancedPluginUtils.class); + private static final List HTTP_STATUSES = toList(NOT_IMPLEMENTED, BAD_GATEWAY, + SERVICE_UNAVAILABLE, GATEWAY_TIMEOUT, HTTP_VERSION_NOT_SUPPORTED, VARIANT_ALSO_NEGOTIATES, + INSUFFICIENT_STORAGE, LOOP_DETECTED, BANDWIDTH_LIMIT_EXCEEDED, NOT_EXTENDED, NETWORK_AUTHENTICATION_REQUIRED); + /** * createServiceCallResult. * @param calleeServiceName will pick up url host when null @@ -100,7 +97,7 @@ public abstract class AbstractPolarisReporterAdapter { * @param exception exception * @return ServiceCallResult */ - public ServiceCallResult createServiceCallResult( + public static ServiceCallResult createServiceCallResult(String callerHost, @Nullable String calleeServiceName, @Nullable String calleeHost, @Nullable Integer calleePort, URI uri, HttpHeaders requestHeaders, @Nullable HttpHeaders responseHeaders, @Nullable Integer statusCode, long delay, @Nullable Throwable exception) { @@ -112,11 +109,11 @@ public abstract class AbstractPolarisReporterAdapter { resultRequest.setRetCode(statusCode == null ? -1 : statusCode); resultRequest.setDelay(delay); resultRequest.setCallerService(new ServiceKey(MetadataContext.LOCAL_NAMESPACE, MetadataContext.LOCAL_SERVICE)); - resultRequest.setCallerIp(this.context.getConfig().getGlobal().getAPI().getBindIP()); + resultRequest.setCallerIp(callerHost); resultRequest.setHost(StringUtils.isBlank(calleeHost) ? uri.getHost() : calleeHost); resultRequest.setPort(calleePort == null ? getPort(uri) : calleePort); resultRequest.setLabels(getLabels(requestHeaders)); - resultRequest.setRetStatus(getRetStatusFromRequest(responseHeaders, getDefaultRetStatus(statusCode, exception))); + resultRequest.setRetStatus(getRetStatusFromRequest(responseHeaders, statusCode, exception)); resultRequest.setRuleName(getActiveRuleNameFromRequest(responseHeaders)); return resultRequest; } @@ -132,7 +129,7 @@ public abstract class AbstractPolarisReporterAdapter { * @param exception exception * @return ResourceStat */ - public ResourceStat createInstanceResourceStat( + public static ResourceStat createInstanceResourceStat( @Nullable String calleeServiceName, @Nullable String calleeHost, @Nullable Integer calleePort, URI uri, @Nullable Integer statusCode, long delay, @Nullable Throwable exception) { ServiceKey calleeServiceKey = new ServiceKey(MetadataContext.LOCAL_NAMESPACE, StringUtils.isBlank(calleeServiceName) ? uri.getHost() : calleeServiceName); @@ -165,42 +162,40 @@ public abstract class AbstractPolarisReporterAdapter { * @param httpStatus request http status code * @return true , otherwise return false . */ - protected boolean apply(@Nullable HttpStatus httpStatus) { + static boolean apply(@Nullable HttpStatus httpStatus) { if (Objects.isNull(httpStatus)) { return false; } - else { - // statuses > series - List status = reportProperties.getStatuses(); - - if (status.isEmpty()) { - List series = reportProperties.getSeries(); - // Check INTERNAL_SERVER_ERROR (500) status. - if (reportProperties.isIgnoreInternalServerError() && Objects.equals(httpStatus, INTERNAL_SERVER_ERROR)) { - return false; - } - if (series.isEmpty()) { - return HTTP_STATUSES.contains(httpStatus); - } - else { - try { - return series.contains(HttpStatus.Series.valueOf(httpStatus)); - } - catch (Exception e) { - LOG.warn("Decode http status failed.", e); - } - } + RpcEnhancementReporterProperties reportProperties; + try { + reportProperties = ApplicationContextAwareUtils.getApplicationContext().getBean(RpcEnhancementReporterProperties.class); + } + catch (BeansException e) { + LOG.error("get RpcEnhancementReporterProperties bean err", e); + reportProperties = new RpcEnhancementReporterProperties(); + } + // statuses > series + List status = reportProperties.getStatuses(); + if (status.isEmpty()) { + List series = reportProperties.getSeries(); + // Check INTERNAL_SERVER_ERROR (500) status. + if (reportProperties.isIgnoreInternalServerError() && Objects.equals(httpStatus, INTERNAL_SERVER_ERROR)) { + return false; } - else { - // Use the user-specified fuse status code. - return status.contains(httpStatus); + if (series.isEmpty()) { + return HTTP_STATUSES.contains(httpStatus); } + return series.contains(httpStatus.series()); } - // DEFAULT RETURN FALSE. - return false; + // Use the user-specified fuse status code. + return status.contains(httpStatus); + } + + public static RetStatus getRetStatusFromRequest(HttpHeaders headers, Integer statusCode, Throwable exception) { + return getRetStatusFromRequest(headers, getDefaultRetStatus(statusCode, exception)); } - protected RetStatus getRetStatusFromRequest(HttpHeaders headers, RetStatus defaultVal) { + static RetStatus getRetStatusFromRequest(HttpHeaders headers, RetStatus defaultVal) { if (headers != null && headers.containsKey(HeaderConstant.INTERNAL_CALLEE_RET_STATUS)) { List values = headers.get(HeaderConstant.INTERNAL_CALLEE_RET_STATUS); if (CollectionUtils.isNotEmpty(values)) { @@ -216,7 +211,7 @@ public abstract class AbstractPolarisReporterAdapter { return defaultVal; } - protected String getActiveRuleNameFromRequest(HttpHeaders headers) { + static String getActiveRuleNameFromRequest(HttpHeaders headers) { if (headers != null && headers.containsKey(HeaderConstant.INTERNAL_ACTIVE_RULE_NAME)) { Collection values = headers.get(HeaderConstant.INTERNAL_ACTIVE_RULE_NAME); if (CollectionUtils.isNotEmpty(values)) { @@ -226,7 +221,7 @@ public abstract class AbstractPolarisReporterAdapter { return ""; } - private RetStatus getDefaultRetStatus(Integer statusCode, Throwable exception) { + private static RetStatus getDefaultRetStatus(Integer statusCode, Throwable exception) { RetStatus retStatus = RetStatus.RetSuccess; if (exception != null) { retStatus = RetStatus.RetFail; @@ -240,12 +235,12 @@ public abstract class AbstractPolarisReporterAdapter { return retStatus; } - private int getPort(URI uri) { + private static int getPort(URI uri) { // -1 means access directly by url, and use http default port number 80 return uri.getPort() == -1 ? 80 : uri.getPort(); } - private String getLabels(HttpHeaders headers) { + private static String getLabels(HttpHeaders headers) { if (headers != null) { Collection labels = headers.get(RouterConstant.ROUTER_LABEL_HEADER); if (CollectionUtils.isNotEmpty(labels) && labels.iterator().hasNext()) { @@ -262,5 +257,27 @@ public abstract class AbstractPolarisReporterAdapter { return null; } + public static Map getLabelMap(HttpHeaders headers) { + if (headers != null) { + Collection labels = headers.get(RouterConstant.ROUTER_LABEL_HEADER); + if (CollectionUtils.isNotEmpty(labels) && labels.iterator().hasNext()) { + String label = labels.iterator().next(); + try { + label = URLDecoder.decode(label, UTF_8); + } + catch (UnsupportedEncodingException e) { + LOG.error("unsupported charset exception " + UTF_8, e); + } + try { + return new ObjectMapper().readValue(label, new TypeReference>() { }); + } + catch (JsonProcessingException e) { + LOG.error("parse label map exception", e); + } + } + } + return null; + } + } diff --git a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/plugin/assembly/AssemblyMetadataProvider.java b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/plugin/assembly/AssemblyMetadataProvider.java new file mode 100644 index 000000000..e937f244b --- /dev/null +++ b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/plugin/assembly/AssemblyMetadataProvider.java @@ -0,0 +1,56 @@ +/* + * Tencent is pleased to support the open source community by making Spring Cloud Tencent available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * Unless required by applicable law or agreed to in writing, software distributed + * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package com.tencent.cloud.rpc.enhancement.plugin.assembly; + +import com.tencent.polaris.api.pojo.ServiceKey; +import com.tencent.polaris.api.rpc.MetadataProvider; + +import org.springframework.cloud.client.ServiceInstance; + +/** + * AssemblyMetadataProvider. + * + * @author sean yu + */ +public class AssemblyMetadataProvider implements MetadataProvider { + + private final ServiceInstance serviceInstance; + + private final String namespace; + + public AssemblyMetadataProvider(ServiceInstance localServiceInstance, String namespace) { + this.serviceInstance = localServiceInstance; + this.namespace = namespace; + } + + @Override + public String getMetadata(String key) { + return serviceInstance.getMetadata().get(key); + } + + @Override + public ServiceKey getLocalService() { + return new ServiceKey(namespace, serviceInstance.getServiceId()); + } + + @Override + public String getLocalIp() { + return serviceInstance.getHost(); + } + +} diff --git a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/plugin/assembly/AssemblyRequestContext.java b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/plugin/assembly/AssemblyRequestContext.java new file mode 100644 index 000000000..dfcaa2ed8 --- /dev/null +++ b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/plugin/assembly/AssemblyRequestContext.java @@ -0,0 +1,126 @@ +/* + * Tencent is pleased to support the open source community by making Spring Cloud Tencent available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * Unless required by applicable law or agreed to in writing, software distributed + * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package com.tencent.cloud.rpc.enhancement.plugin.assembly; + +import java.net.URI; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.stream.Collectors; + +import com.google.common.net.HttpHeaders; +import com.tencent.cloud.rpc.enhancement.plugin.EnhancedRequestContext; +import com.tencent.polaris.api.pojo.ServiceKey; +import com.tencent.polaris.api.rpc.RequestContext; + +import org.springframework.http.HttpMethod; + +/** + * AssemblyRequestContext. + * + * @author sean yu + */ +public class AssemblyRequestContext implements RequestContext { + + private final EnhancedRequestContext requestContext; + + private final ServiceKey callerService; + + private final String callerIp; + + private final Map cookies; + + public AssemblyRequestContext(EnhancedRequestContext requestContext, ServiceKey callerService, String callerIp) { + this.requestContext = requestContext; + this.callerService = callerService; + this.callerIp = callerIp; + this.cookies = new HashMap<>(); + List allCookies = + Optional.ofNullable(requestContext.getHttpHeaders().get(HttpHeaders.COOKIE)) + .orElse(new ArrayList<>()) + .stream() + .flatMap(it -> Arrays.stream(it.split(";"))) + .collect(Collectors.toList()); + allCookies.forEach(cookie -> { + String[] cookieKV = cookie.split("="); + if (cookieKV.length == 2) { + cookies.put(cookieKV[0], cookieKV[1]); + } + }); + } + + @Override + public String getMethod() { + return requestContext.getHttpMethod().name(); + } + + @Override + public void setMethod(String method) { + requestContext.setHttpMethod(HttpMethod.valueOf(method)); + } + + @Override + public String getHeader(String key) { + return requestContext.getHttpHeaders().getFirst(key); + } + + @Override + public void setHeader(String key, String value) { + requestContext.getHttpHeaders().set(key, value); + } + + @Override + public Collection listHeaderKeys() { + return requestContext.getHttpHeaders().keySet(); + } + + @Override + public String getCookie(String key) { + return this.cookies.get(key); + } + + @Override + public void setCookie(String key, String value) { + this.cookies.put(key, value); + } + + @Override + public Collection listCookieKeys() { + return this.cookies.keySet(); + } + + @Override + public String getCallerIp() { + return callerIp; + } + + @Override + public ServiceKey getCallerService() { + return callerService; + } + + @Override + public URI getURI() { + return requestContext.getUrl(); + } + +} diff --git a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/plugin/assembly/AssemblyResponseContext.java b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/plugin/assembly/AssemblyResponseContext.java new file mode 100644 index 000000000..4dbfa81d7 --- /dev/null +++ b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/plugin/assembly/AssemblyResponseContext.java @@ -0,0 +1,87 @@ +/* + * Tencent is pleased to support the open source community by making Spring Cloud Tencent available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * Unless required by applicable law or agreed to in writing, software distributed + * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package com.tencent.cloud.rpc.enhancement.plugin.assembly; + +import java.util.Collection; + +import com.tencent.cloud.rpc.enhancement.plugin.EnhancedResponseContext; +import com.tencent.cloud.rpc.enhancement.plugin.PolarisEnhancedPluginUtils; +import com.tencent.polaris.api.pojo.RetStatus; +import com.tencent.polaris.api.rpc.ResponseContext; + +import org.springframework.lang.Nullable; + +/** + * AssemblyResponseContext. + * + * @author sean yu + */ +public class AssemblyResponseContext implements ResponseContext { + + private final EnhancedResponseContext responseContext; + + private final Throwable throwable; + + private final RetStatus retStatus; + + public AssemblyResponseContext(@Nullable EnhancedResponseContext responseContext, @Nullable Throwable throwable) { + this.responseContext = responseContext; + this.throwable = throwable; + if (responseContext == null) { + this.retStatus = PolarisEnhancedPluginUtils.getRetStatusFromRequest(null, null, throwable); + } + else { + this.retStatus = PolarisEnhancedPluginUtils.getRetStatusFromRequest(responseContext.getHttpHeaders(), responseContext.getHttpStatus(), throwable); + } + } + + @Override + public Object getRetCode() { + if (responseContext == null) { + return null; + } + return this.responseContext.getHttpStatus(); + } + + @Override + public String getHeader(String key) { + if (responseContext == null) { + return null; + } + return this.responseContext.getHttpHeaders().getFirst(key); + } + + @Override + public Collection listHeaders() { + if (responseContext == null) { + return null; + } + return this.responseContext.getHttpHeaders().keySet(); + } + + @Override + public Throwable getThrowable() { + return this.throwable; + } + + @Override + public RetStatus getRetStatus() { + return this.retStatus; + } + +} diff --git a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/plugin/assembly/client/AssemblyClientExceptionHook.java b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/plugin/assembly/client/AssemblyClientExceptionHook.java new file mode 100644 index 000000000..398485b59 --- /dev/null +++ b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/plugin/assembly/client/AssemblyClientExceptionHook.java @@ -0,0 +1,82 @@ +/* + * Tencent is pleased to support the open source community by making Spring Cloud Tencent available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * Unless required by applicable law or agreed to in writing, software distributed + * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package com.tencent.cloud.rpc.enhancement.plugin.assembly.client; + +import com.tencent.cloud.common.metadata.MetadataContext; +import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPlugin; +import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginContext; +import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType; +import com.tencent.cloud.rpc.enhancement.plugin.PolarisEnhancedPluginUtils; +import com.tencent.cloud.rpc.enhancement.plugin.assembly.AssemblyMetadataProvider; +import com.tencent.cloud.rpc.enhancement.plugin.assembly.AssemblyRequestContext; +import com.tencent.cloud.rpc.enhancement.plugin.assembly.AssemblyResponseContext; +import com.tencent.cloud.rpc.enhancement.transformer.InstanceTransformer; +import com.tencent.polaris.api.pojo.ServiceKey; +import com.tencent.polaris.assembly.api.AssemblyAPI; +import com.tencent.polaris.assembly.api.pojo.AfterRequest; +import com.tencent.polaris.assembly.api.pojo.Capability; + +import static com.tencent.cloud.rpc.enhancement.plugin.PluginOrderConstant.ClientPluginOrder.ASSEMBLY_PLUGIN_ORDER; + +/** + * AssemblyClientExceptionHook. + * + * @author sean yu + */ +public class AssemblyClientExceptionHook implements EnhancedPlugin { + + private final AssemblyAPI assemblyAPI; + + private final InstanceTransformer instanceTransformer; + + public AssemblyClientExceptionHook(AssemblyAPI assemblyAPI, InstanceTransformer instanceTransformer) { + this.assemblyAPI = assemblyAPI; + this.instanceTransformer = instanceTransformer; + } + + @Override + public EnhancedPluginType getType() { + return EnhancedPluginType.Client.EXCEPTION; + } + + @Override + public void run(EnhancedPluginContext context) { + + AfterRequest afterRequest = new AfterRequest(); + afterRequest.setCapabilities(new Capability[]{Capability.ALL}); + afterRequest.setRequestContext(new AssemblyRequestContext( + context.getRequest(), + new ServiceKey(MetadataContext.LOCAL_NAMESPACE, context.getLocalServiceInstance().getServiceId()), + context.getLocalServiceInstance().getHost() + )); + afterRequest.setResponseContext(new AssemblyResponseContext(null, context.getThrowable())); + afterRequest.setMetadataProvider(new AssemblyMetadataProvider(context.getLocalServiceInstance(), MetadataContext.LOCAL_NAMESPACE)); + afterRequest.setDelay(context.getDelay()); + afterRequest.setRouteLabels(PolarisEnhancedPluginUtils.getLabelMap(context.getRequest().getHttpHeaders())); + // TargetService and TargetInstance only exist in client side + afterRequest.setTargetService(new ServiceKey(MetadataContext.LOCAL_NAMESPACE, context.getTargetServiceInstance().getServiceId())); + afterRequest.setTargetInstance(instanceTransformer.transform(context.getTargetServiceInstance())); + + assemblyAPI.afterCallService(afterRequest); + } + + @Override + public int getOrder() { + return ASSEMBLY_PLUGIN_ORDER; + } +} diff --git a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/plugin/assembly/client/AssemblyClientPostHook.java b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/plugin/assembly/client/AssemblyClientPostHook.java new file mode 100644 index 000000000..9148a0de9 --- /dev/null +++ b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/plugin/assembly/client/AssemblyClientPostHook.java @@ -0,0 +1,83 @@ +/* + * Tencent is pleased to support the open source community by making Spring Cloud Tencent available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * Unless required by applicable law or agreed to in writing, software distributed + * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package com.tencent.cloud.rpc.enhancement.plugin.assembly.client; + +import com.tencent.cloud.common.metadata.MetadataContext; +import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPlugin; +import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginContext; +import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType; +import com.tencent.cloud.rpc.enhancement.plugin.PolarisEnhancedPluginUtils; +import com.tencent.cloud.rpc.enhancement.plugin.assembly.AssemblyMetadataProvider; +import com.tencent.cloud.rpc.enhancement.plugin.assembly.AssemblyRequestContext; +import com.tencent.cloud.rpc.enhancement.plugin.assembly.AssemblyResponseContext; +import com.tencent.cloud.rpc.enhancement.transformer.InstanceTransformer; +import com.tencent.polaris.api.pojo.ServiceKey; +import com.tencent.polaris.assembly.api.AssemblyAPI; +import com.tencent.polaris.assembly.api.pojo.AfterRequest; +import com.tencent.polaris.assembly.api.pojo.Capability; + +import static com.tencent.cloud.rpc.enhancement.plugin.PluginOrderConstant.ClientPluginOrder.ASSEMBLY_PLUGIN_ORDER; + +/** + * AssemblyClientPostHook. + * + * @author sean yu + */ +public class AssemblyClientPostHook implements EnhancedPlugin { + + private final AssemblyAPI assemblyAPI; + + private final InstanceTransformer instanceTransformer; + + public AssemblyClientPostHook(AssemblyAPI assemblyAPI, InstanceTransformer instanceTransformer) { + this.assemblyAPI = assemblyAPI; + this.instanceTransformer = instanceTransformer; + } + + @Override + public EnhancedPluginType getType() { + return EnhancedPluginType.Client.POST; + } + + @Override + public void run(EnhancedPluginContext context) { + + AfterRequest afterRequest = new AfterRequest(); + afterRequest.setCapabilities(new Capability[]{Capability.ALL}); + afterRequest.setRequestContext(new AssemblyRequestContext( + context.getRequest(), + new ServiceKey(MetadataContext.LOCAL_NAMESPACE, context.getLocalServiceInstance().getServiceId()), + context.getLocalServiceInstance().getHost() + )); + afterRequest.setResponseContext(new AssemblyResponseContext(context.getResponse(), null)); + afterRequest.setMetadataProvider(new AssemblyMetadataProvider(context.getLocalServiceInstance(), MetadataContext.LOCAL_NAMESPACE)); + afterRequest.setDelay(context.getDelay()); + afterRequest.setRouteLabels(PolarisEnhancedPluginUtils.getLabelMap(context.getRequest().getHttpHeaders())); + // TargetService and TargetInstance only exist in client side + afterRequest.setTargetService(new ServiceKey(MetadataContext.LOCAL_NAMESPACE, context.getTargetServiceInstance().getServiceId())); + afterRequest.setTargetInstance(instanceTransformer.transform(context.getTargetServiceInstance())); + + assemblyAPI.afterCallService(afterRequest); + } + + @Override + public int getOrder() { + return ASSEMBLY_PLUGIN_ORDER; + } + +} diff --git a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/plugin/assembly/client/AssemblyClientPreHook.java b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/plugin/assembly/client/AssemblyClientPreHook.java new file mode 100644 index 000000000..fde540277 --- /dev/null +++ b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/plugin/assembly/client/AssemblyClientPreHook.java @@ -0,0 +1,73 @@ +/* + * Tencent is pleased to support the open source community by making Spring Cloud Tencent available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * Unless required by applicable law or agreed to in writing, software distributed + * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package com.tencent.cloud.rpc.enhancement.plugin.assembly.client; + +import com.tencent.cloud.common.metadata.MetadataContext; +import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPlugin; +import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginContext; +import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType; +import com.tencent.cloud.rpc.enhancement.plugin.assembly.AssemblyMetadataProvider; +import com.tencent.cloud.rpc.enhancement.plugin.assembly.AssemblyRequestContext; +import com.tencent.polaris.api.pojo.ServiceKey; +import com.tencent.polaris.assembly.api.AssemblyAPI; +import com.tencent.polaris.assembly.api.pojo.BeforeRequest; +import com.tencent.polaris.assembly.api.pojo.Capability; + +import static com.tencent.cloud.rpc.enhancement.plugin.PluginOrderConstant.ClientPluginOrder.ASSEMBLY_PLUGIN_ORDER; + +/** + * AssemblyClientPreHook. + * + * @author sean yu + */ +public class AssemblyClientPreHook implements EnhancedPlugin { + + private final AssemblyAPI assemblyAPI; + + public AssemblyClientPreHook(AssemblyAPI assemblyAPI) { + this.assemblyAPI = assemblyAPI; + } + + @Override + public EnhancedPluginType getType() { + return EnhancedPluginType.Client.PRE; + } + + @Override + public void run(EnhancedPluginContext context) { + + BeforeRequest beforeRequest = new BeforeRequest(); + beforeRequest.setCapabilities(new Capability[]{Capability.ALL}); + beforeRequest.setRequestContext(new AssemblyRequestContext( + context.getRequest(), + new ServiceKey(MetadataContext.LOCAL_NAMESPACE, context.getLocalServiceInstance().getServiceId()), + context.getLocalServiceInstance().getHost() + )); + beforeRequest.setMetadataProvider(new AssemblyMetadataProvider(context.getLocalServiceInstance(), MetadataContext.LOCAL_NAMESPACE)); + // TargetService only exist in client side + beforeRequest.setTargetService(new ServiceKey(MetadataContext.LOCAL_NAMESPACE, context.getTargetServiceInstance().getServiceId())); + + assemblyAPI.beforeCallService(beforeRequest); + } + + @Override + public int getOrder() { + return ASSEMBLY_PLUGIN_ORDER; + } + +} diff --git a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/plugin/assembly/server/AssemblyServerExceptionHook.java b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/plugin/assembly/server/AssemblyServerExceptionHook.java new file mode 100644 index 000000000..bde03d0d7 --- /dev/null +++ b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/plugin/assembly/server/AssemblyServerExceptionHook.java @@ -0,0 +1,76 @@ +/* + * Tencent is pleased to support the open source community by making Spring Cloud Tencent available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * Unless required by applicable law or agreed to in writing, software distributed + * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package com.tencent.cloud.rpc.enhancement.plugin.assembly.server; + +import com.tencent.cloud.common.metadata.MetadataContext; +import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPlugin; +import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginContext; +import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType; +import com.tencent.cloud.rpc.enhancement.plugin.PolarisEnhancedPluginUtils; +import com.tencent.cloud.rpc.enhancement.plugin.assembly.AssemblyMetadataProvider; +import com.tencent.cloud.rpc.enhancement.plugin.assembly.AssemblyRequestContext; +import com.tencent.cloud.rpc.enhancement.plugin.assembly.AssemblyResponseContext; +import com.tencent.polaris.api.pojo.ServiceKey; +import com.tencent.polaris.assembly.api.AssemblyAPI; +import com.tencent.polaris.assembly.api.pojo.AfterRequest; +import com.tencent.polaris.assembly.api.pojo.Capability; + +import static com.tencent.cloud.rpc.enhancement.plugin.PluginOrderConstant.ServerPluginOrder.ASSEMBLY_PLUGIN_ORDER; + + +/** + * AssemblyServerExceptionHook. + * + * @author sean yu + */ +public class AssemblyServerExceptionHook implements EnhancedPlugin { + + private final AssemblyAPI assemblyAPI; + + public AssemblyServerExceptionHook(AssemblyAPI assemblyAPI) { + this.assemblyAPI = assemblyAPI; + } + + @Override + public EnhancedPluginType getType() { + return EnhancedPluginType.Server.EXCEPTION; + } + + @Override + public void run(EnhancedPluginContext context) { + AfterRequest afterRequest = new AfterRequest(); + afterRequest.setCapabilities(new Capability[]{Capability.ALL}); + afterRequest.setRequestContext(new AssemblyRequestContext( + context.getRequest(), + new ServiceKey(MetadataContext.LOCAL_NAMESPACE, context.getLocalServiceInstance().getServiceId()), + context.getLocalServiceInstance().getHost() + )); + afterRequest.setResponseContext(new AssemblyResponseContext(null, context.getThrowable())); + afterRequest.setMetadataProvider(new AssemblyMetadataProvider(context.getLocalServiceInstance(), MetadataContext.LOCAL_NAMESPACE)); + afterRequest.setDelay(context.getDelay()); + afterRequest.setRouteLabels(PolarisEnhancedPluginUtils.getLabelMap(context.getRequest().getHttpHeaders())); + + assemblyAPI.afterProcess(afterRequest); + } + + @Override + public int getOrder() { + return ASSEMBLY_PLUGIN_ORDER; + } + +} diff --git a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/plugin/assembly/server/AssemblyServerPostHook.java b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/plugin/assembly/server/AssemblyServerPostHook.java new file mode 100644 index 000000000..855994eb1 --- /dev/null +++ b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/plugin/assembly/server/AssemblyServerPostHook.java @@ -0,0 +1,75 @@ +/* + * Tencent is pleased to support the open source community by making Spring Cloud Tencent available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * Unless required by applicable law or agreed to in writing, software distributed + * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package com.tencent.cloud.rpc.enhancement.plugin.assembly.server; + +import com.tencent.cloud.common.metadata.MetadataContext; +import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPlugin; +import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginContext; +import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType; +import com.tencent.cloud.rpc.enhancement.plugin.PolarisEnhancedPluginUtils; +import com.tencent.cloud.rpc.enhancement.plugin.assembly.AssemblyMetadataProvider; +import com.tencent.cloud.rpc.enhancement.plugin.assembly.AssemblyRequestContext; +import com.tencent.cloud.rpc.enhancement.plugin.assembly.AssemblyResponseContext; +import com.tencent.polaris.api.pojo.ServiceKey; +import com.tencent.polaris.assembly.api.AssemblyAPI; +import com.tencent.polaris.assembly.api.pojo.AfterRequest; +import com.tencent.polaris.assembly.api.pojo.Capability; + +import static com.tencent.cloud.rpc.enhancement.plugin.PluginOrderConstant.ServerPluginOrder.ASSEMBLY_PLUGIN_ORDER; + +/** + * AssemblyServerPostHook. + * + * @author sean yu + */ +public class AssemblyServerPostHook implements EnhancedPlugin { + + private final AssemblyAPI assemblyAPI; + + public AssemblyServerPostHook(AssemblyAPI assemblyAPI) { + this.assemblyAPI = assemblyAPI; + } + + @Override + public EnhancedPluginType getType() { + return EnhancedPluginType.Server.POST; + } + + @Override + public void run(EnhancedPluginContext context) { + AfterRequest afterRequest = new AfterRequest(); + afterRequest.setCapabilities(new Capability[]{Capability.ALL}); + afterRequest.setRequestContext(new AssemblyRequestContext( + context.getRequest(), + new ServiceKey(MetadataContext.LOCAL_NAMESPACE, context.getLocalServiceInstance().getServiceId()), + context.getLocalServiceInstance().getHost() + )); + afterRequest.setResponseContext(new AssemblyResponseContext(context.getResponse(), null)); + afterRequest.setMetadataProvider(new AssemblyMetadataProvider(context.getLocalServiceInstance(), MetadataContext.LOCAL_NAMESPACE)); + afterRequest.setDelay(context.getDelay()); + afterRequest.setRouteLabels(PolarisEnhancedPluginUtils.getLabelMap(context.getRequest().getHttpHeaders())); + + assemblyAPI.afterProcess(afterRequest); + } + + @Override + public int getOrder() { + return ASSEMBLY_PLUGIN_ORDER; + } + +} diff --git a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/plugin/assembly/server/AssemblyServerPreHook.java b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/plugin/assembly/server/AssemblyServerPreHook.java new file mode 100644 index 000000000..5b279b80d --- /dev/null +++ b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/plugin/assembly/server/AssemblyServerPreHook.java @@ -0,0 +1,70 @@ +/* + * Tencent is pleased to support the open source community by making Spring Cloud Tencent available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * Unless required by applicable law or agreed to in writing, software distributed + * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package com.tencent.cloud.rpc.enhancement.plugin.assembly.server; + +import com.tencent.cloud.common.metadata.MetadataContext; +import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPlugin; +import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginContext; +import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType; +import com.tencent.cloud.rpc.enhancement.plugin.assembly.AssemblyMetadataProvider; +import com.tencent.cloud.rpc.enhancement.plugin.assembly.AssemblyRequestContext; +import com.tencent.polaris.api.pojo.ServiceKey; +import com.tencent.polaris.assembly.api.AssemblyAPI; +import com.tencent.polaris.assembly.api.pojo.BeforeRequest; +import com.tencent.polaris.assembly.api.pojo.Capability; + +import static com.tencent.cloud.rpc.enhancement.plugin.PluginOrderConstant.ServerPluginOrder.ASSEMBLY_PLUGIN_ORDER; + +/** + * AssemblyServerPreHook. + * + * @author sean yu + */ +public class AssemblyServerPreHook implements EnhancedPlugin { + + private final AssemblyAPI assemblyAPI; + + public AssemblyServerPreHook(AssemblyAPI assemblyAPI) { + this.assemblyAPI = assemblyAPI; + } + + @Override + public EnhancedPluginType getType() { + return EnhancedPluginType.Server.PRE; + } + + @Override + public void run(EnhancedPluginContext context) { + BeforeRequest beforeRequest = new BeforeRequest(); + beforeRequest.setCapabilities(new Capability[]{Capability.ALL}); + beforeRequest.setRequestContext(new AssemblyRequestContext( + context.getRequest(), + new ServiceKey(MetadataContext.LOCAL_NAMESPACE, context.getLocalServiceInstance().getServiceId()), + context.getLocalServiceInstance().getHost() + )); + beforeRequest.setMetadataProvider(new AssemblyMetadataProvider(context.getLocalServiceInstance(), MetadataContext.LOCAL_NAMESPACE)); + + assemblyAPI.beforeProcess(beforeRequest); + } + + @Override + public int getOrder() { + return ASSEMBLY_PLUGIN_ORDER; + } + +} diff --git a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/plugin/reporter/ExceptionPolarisReporter.java b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/plugin/reporter/ExceptionPolarisReporter.java index 76c4250b3..471c9a179 100644 --- a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/plugin/reporter/ExceptionPolarisReporter.java +++ b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/plugin/reporter/ExceptionPolarisReporter.java @@ -20,37 +20,38 @@ package com.tencent.cloud.rpc.enhancement.plugin.reporter; import java.util.Optional; -import com.tencent.cloud.rpc.enhancement.AbstractPolarisReporterAdapter; import com.tencent.cloud.rpc.enhancement.config.RpcEnhancementReporterProperties; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPlugin; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginContext; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedRequestContext; +import com.tencent.cloud.rpc.enhancement.plugin.PolarisEnhancedPluginUtils; import com.tencent.polaris.api.core.ConsumerAPI; import com.tencent.polaris.api.rpc.ServiceCallResult; -import com.tencent.polaris.client.api.SDKContext; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.cloud.client.DefaultServiceInstance; import org.springframework.cloud.client.ServiceInstance; -import org.springframework.core.Ordered; + +import static com.tencent.cloud.rpc.enhancement.plugin.PluginOrderConstant.ClientPluginOrder.CONSUMER_REPORTER_PLUGIN_ORDER; /** * Polaris reporter when feign call fails. * * @author Haotian Zhang */ -public class ExceptionPolarisReporter extends AbstractPolarisReporterAdapter implements EnhancedPlugin { +public class ExceptionPolarisReporter implements EnhancedPlugin { private static final Logger LOG = LoggerFactory.getLogger(ExceptionPolarisReporter.class); private final ConsumerAPI consumerAPI; - public ExceptionPolarisReporter(RpcEnhancementReporterProperties reporterProperties, - SDKContext context, + private final RpcEnhancementReporterProperties reportProperties; + + public ExceptionPolarisReporter(RpcEnhancementReporterProperties reportProperties, ConsumerAPI consumerAPI) { - super(reporterProperties, context); + this.reportProperties = reportProperties; this.consumerAPI = consumerAPI; } @@ -61,22 +62,24 @@ public class ExceptionPolarisReporter extends AbstractPolarisReporterAdapter imp @Override public EnhancedPluginType getType() { - return EnhancedPluginType.EXCEPTION; + return EnhancedPluginType.Client.EXCEPTION; } @Override public void run(EnhancedPluginContext context) { - if (!super.reportProperties.isEnabled()) { + if (!this.reportProperties.isEnabled()) { return; } EnhancedRequestContext request = context.getRequest(); - ServiceInstance serviceInstance = Optional.ofNullable(context.getServiceInstance()).orElse(new DefaultServiceInstance()); - - ServiceCallResult resultRequest = createServiceCallResult( - serviceInstance.getServiceId(), - serviceInstance.getHost(), - serviceInstance.getPort(), + ServiceInstance callerServiceInstance = Optional.ofNullable(context.getLocalServiceInstance()).orElse(new DefaultServiceInstance()); + ServiceInstance calleeServiceInstance = Optional.ofNullable(context.getTargetServiceInstance()).orElse(new DefaultServiceInstance()); + + ServiceCallResult resultRequest = PolarisEnhancedPluginUtils.createServiceCallResult( + callerServiceInstance.getHost(), + calleeServiceInstance.getServiceId(), + calleeServiceInstance.getHost(), + calleeServiceInstance.getPort(), request.getUrl(), request.getHttpHeaders(), null, @@ -100,7 +103,7 @@ public class ExceptionPolarisReporter extends AbstractPolarisReporterAdapter imp @Override public int getOrder() { - return Ordered.HIGHEST_PRECEDENCE + 1; + return CONSUMER_REPORTER_PLUGIN_ORDER; } } diff --git a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/plugin/reporter/SuccessPolarisReporter.java b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/plugin/reporter/SuccessPolarisReporter.java index 4b35396da..d4c7d6a1e 100644 --- a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/plugin/reporter/SuccessPolarisReporter.java +++ b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/plugin/reporter/SuccessPolarisReporter.java @@ -19,38 +19,39 @@ package com.tencent.cloud.rpc.enhancement.plugin.reporter; import java.util.Optional; -import com.tencent.cloud.rpc.enhancement.AbstractPolarisReporterAdapter; import com.tencent.cloud.rpc.enhancement.config.RpcEnhancementReporterProperties; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPlugin; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginContext; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedRequestContext; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedResponseContext; +import com.tencent.cloud.rpc.enhancement.plugin.PolarisEnhancedPluginUtils; import com.tencent.polaris.api.core.ConsumerAPI; import com.tencent.polaris.api.rpc.ServiceCallResult; -import com.tencent.polaris.client.api.SDKContext; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.cloud.client.DefaultServiceInstance; import org.springframework.cloud.client.ServiceInstance; -import org.springframework.core.Ordered; + +import static com.tencent.cloud.rpc.enhancement.plugin.PluginOrderConstant.ClientPluginOrder.CONSUMER_REPORTER_PLUGIN_ORDER; /** * Polaris reporter when feign call is successful. * * @author Haotian Zhang */ -public class SuccessPolarisReporter extends AbstractPolarisReporterAdapter implements EnhancedPlugin { +public class SuccessPolarisReporter implements EnhancedPlugin { private static final Logger LOG = LoggerFactory.getLogger(SuccessPolarisReporter.class); private final ConsumerAPI consumerAPI; - public SuccessPolarisReporter(RpcEnhancementReporterProperties properties, - SDKContext context, + private final RpcEnhancementReporterProperties reportProperties; + + public SuccessPolarisReporter(RpcEnhancementReporterProperties reportProperties, ConsumerAPI consumerAPI) { - super(properties, context); + this.reportProperties = reportProperties; this.consumerAPI = consumerAPI; } @@ -61,23 +62,25 @@ public class SuccessPolarisReporter extends AbstractPolarisReporterAdapter imple @Override public EnhancedPluginType getType() { - return EnhancedPluginType.POST; + return EnhancedPluginType.Client.POST; } @Override public void run(EnhancedPluginContext context) { - if (!super.reportProperties.isEnabled()) { + if (!this.reportProperties.isEnabled()) { return; } EnhancedRequestContext request = context.getRequest(); EnhancedResponseContext response = context.getResponse(); - ServiceInstance serviceInstance = Optional.ofNullable(context.getServiceInstance()).orElse(new DefaultServiceInstance()); - - ServiceCallResult resultRequest = createServiceCallResult( - serviceInstance.getServiceId(), - serviceInstance.getHost(), - serviceInstance.getPort(), + ServiceInstance callerServiceInstance = Optional.ofNullable(context.getLocalServiceInstance()).orElse(new DefaultServiceInstance()); + ServiceInstance calleeServiceInstance = Optional.ofNullable(context.getTargetServiceInstance()).orElse(new DefaultServiceInstance()); + + ServiceCallResult resultRequest = PolarisEnhancedPluginUtils.createServiceCallResult( + callerServiceInstance.getHost(), + calleeServiceInstance.getServiceId(), + calleeServiceInstance.getHost(), + calleeServiceInstance.getPort(), request.getUrl(), request.getHttpHeaders(), response.getHttpHeaders(), @@ -101,6 +104,6 @@ public class SuccessPolarisReporter extends AbstractPolarisReporterAdapter imple @Override public int getOrder() { - return Ordered.HIGHEST_PRECEDENCE + 1; + return CONSUMER_REPORTER_PLUGIN_ORDER; } } diff --git a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/resttemplate/EnhancedRestTemplateInterceptor.java b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/resttemplate/EnhancedRestTemplateInterceptor.java index e67e241f2..2a4e0f6fc 100644 --- a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/resttemplate/EnhancedRestTemplateInterceptor.java +++ b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/resttemplate/EnhancedRestTemplateInterceptor.java @@ -18,25 +18,21 @@ package com.tencent.cloud.rpc.enhancement.resttemplate; import java.io.IOException; -import java.util.Map; -import com.tencent.cloud.common.constant.HeaderConstant; import com.tencent.cloud.common.metadata.MetadataContextHolder; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginContext; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginRunner; +import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedRequestContext; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedResponseContext; -import org.springframework.cloud.client.DefaultServiceInstance; +import org.springframework.cloud.client.ServiceInstance; import org.springframework.http.HttpRequest; import org.springframework.http.client.ClientHttpRequestExecution; import org.springframework.http.client.ClientHttpRequestInterceptor; import org.springframework.http.client.ClientHttpResponse; -import static com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType.EXCEPTION; -import static com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType.FINALLY; -import static com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType.POST; -import static com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType.PRE; +import static com.tencent.cloud.rpc.enhancement.resttemplate.PolarisLoadBalancerRequestTransformer.LOAD_BALANCER_SERVICE_INSTANCE; /** * EnhancedRestTemplateInterceptor. @@ -63,8 +59,13 @@ public class EnhancedRestTemplateInterceptor implements ClientHttpRequestInterce .build(); enhancedPluginContext.setRequest(enhancedRequestContext); + enhancedPluginContext.setLocalServiceInstance(pluginRunner.getLocalServiceInstance()); + enhancedPluginContext.setTargetServiceInstance( + (ServiceInstance) MetadataContextHolder.get().getLoadbalancerMetadata().get(LOAD_BALANCER_SERVICE_INSTANCE)); + // Run pre enhanced plugins. - pluginRunner.run(PRE, enhancedPluginContext); + pluginRunner.run(EnhancedPluginType.Client.PRE, enhancedPluginContext); + long startMillis = System.currentTimeMillis(); try { ClientHttpResponse response = execution.execute(request, body); @@ -76,29 +77,20 @@ public class EnhancedRestTemplateInterceptor implements ClientHttpRequestInterce .build(); enhancedPluginContext.setResponse(enhancedResponseContext); - Map loadBalancerContext = MetadataContextHolder.get().getLoadbalancerMetadata(); - DefaultServiceInstance serviceInstance = new DefaultServiceInstance(); - serviceInstance.setServiceId(request.getURI().getHost()); - serviceInstance.setHost(loadBalancerContext.get(HeaderConstant.INTERNAL_CALLEE_INSTANCE_HOST)); - if (loadBalancerContext.get(HeaderConstant.INTERNAL_CALLEE_INSTANCE_PORT) != null) { - serviceInstance.setPort(Integer.parseInt(loadBalancerContext.get(HeaderConstant.INTERNAL_CALLEE_INSTANCE_PORT))); - } - enhancedPluginContext.setServiceInstance(serviceInstance); - // Run post enhanced plugins. - pluginRunner.run(POST, enhancedPluginContext); + pluginRunner.run(EnhancedPluginType.Client.POST, enhancedPluginContext); return response; } catch (IOException e) { enhancedPluginContext.setDelay(System.currentTimeMillis() - startMillis); enhancedPluginContext.setThrowable(e); // Run exception enhanced plugins. - pluginRunner.run(EXCEPTION, enhancedPluginContext); + pluginRunner.run(EnhancedPluginType.Client.EXCEPTION, enhancedPluginContext); throw e; } finally { // Run finally enhanced plugins. - pluginRunner.run(FINALLY, enhancedPluginContext); + pluginRunner.run(EnhancedPluginType.Client.FINALLY, enhancedPluginContext); } } diff --git a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/resttemplate/LoadBalancerClientAspectUtils.java b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/resttemplate/PolarisLoadBalancerRequestTransformer.java similarity index 55% rename from spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/resttemplate/LoadBalancerClientAspectUtils.java rename to spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/resttemplate/PolarisLoadBalancerRequestTransformer.java index 04ffac0cf..961633cfa 100644 --- a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/resttemplate/LoadBalancerClientAspectUtils.java +++ b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/resttemplate/PolarisLoadBalancerRequestTransformer.java @@ -17,28 +17,36 @@ package com.tencent.cloud.rpc.enhancement.resttemplate; -import com.tencent.cloud.common.constant.HeaderConstant; import com.tencent.cloud.common.metadata.MetadataContextHolder; -import org.aspectj.lang.ProceedingJoinPoint; import org.springframework.cloud.client.ServiceInstance; -import org.springframework.cloud.client.loadbalancer.LoadBalancerClient; +import org.springframework.cloud.client.loadbalancer.LoadBalancerRequestTransformer; +import org.springframework.http.HttpRequest; /** - * Extract load balancer result from {@link LoadBalancerClient} and put to MetadataContext. - * @author lepdou 2022-09-06 + * PolarisLoadBalancerRequestTransformer. + * + * @author sean yu */ -public final class LoadBalancerClientAspectUtils { +public class PolarisLoadBalancerRequestTransformer implements LoadBalancerRequestTransformer { - private LoadBalancerClientAspectUtils() { - } + /** + * LOAD_BALANCER_SERVICE_INSTANCE MetadataContext key. + */ + public static final String LOAD_BALANCER_SERVICE_INSTANCE = "LOAD_BALANCER_SERVICE_INSTANCE"; - public static void extractLoadBalancerResult(ProceedingJoinPoint joinPoint) { - Object server = joinPoint.getArgs()[0]; - if (server instanceof ServiceInstance) { - ServiceInstance instance = (ServiceInstance) server; - MetadataContextHolder.get().setLoadbalancer(HeaderConstant.INTERNAL_CALLEE_INSTANCE_HOST, instance.getHost()); - MetadataContextHolder.get().setLoadbalancer(HeaderConstant.INTERNAL_CALLEE_INSTANCE_PORT, String.valueOf(instance.getPort())); + /** + * Transform Request, add Loadbalancer ServiceInstance to MetadataContext. + * @param request request + * @param instance instance + * @return HttpRequest + */ + @Override + public HttpRequest transformRequest(HttpRequest request, ServiceInstance instance) { + if (instance != null) { + MetadataContextHolder.get().setLoadbalancer(LOAD_BALANCER_SERVICE_INSTANCE, instance); } + return request; } + } diff --git a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/scg/EnhancedGatewayGlobalFilter.java b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/scg/EnhancedGatewayGlobalFilter.java index bfe816f32..39cd0a608 100644 --- a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/scg/EnhancedGatewayGlobalFilter.java +++ b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/scg/EnhancedGatewayGlobalFilter.java @@ -19,6 +19,7 @@ package com.tencent.cloud.rpc.enhancement.scg; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginContext; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginRunner; +import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedRequestContext; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedResponseContext; import reactor.core.publisher.Mono; @@ -30,10 +31,6 @@ import org.springframework.cloud.gateway.filter.GlobalFilter; import org.springframework.core.Ordered; import org.springframework.web.server.ServerWebExchange; -import static com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType.EXCEPTION; -import static com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType.FINALLY; -import static com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType.POST; -import static com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType.PRE; import static org.springframework.cloud.gateway.filter.ReactiveLoadBalancerClientFilter.LOAD_BALANCER_CLIENT_FILTER_ORDER; import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_LOADBALANCER_RESPONSE_ATTR; @@ -61,18 +58,18 @@ public class EnhancedGatewayGlobalFilter implements GlobalFilter, Ordered { .build(); enhancedPluginContext.setRequest(enhancedRequestContext); + enhancedPluginContext.setLocalServiceInstance(pluginRunner.getLocalServiceInstance()); + Response serviceInstanceResponse = exchange.getAttribute(GATEWAY_LOADBALANCER_RESPONSE_ATTR); + if (serviceInstanceResponse != null && serviceInstanceResponse.hasServer()) { + ServiceInstance instance = serviceInstanceResponse.getServer(); + enhancedPluginContext.setTargetServiceInstance(instance); + } + // Run pre enhanced plugins. - pluginRunner.run(PRE, enhancedPluginContext); + pluginRunner.run(EnhancedPluginType.Client.PRE, enhancedPluginContext); long startTime = System.currentTimeMillis(); return chain.filter(exchange) - .doOnSubscribe(v -> { - Response serviceInstanceResponse = exchange.getAttribute(GATEWAY_LOADBALANCER_RESPONSE_ATTR); - if (serviceInstanceResponse != null && serviceInstanceResponse.hasServer()) { - ServiceInstance instance = serviceInstanceResponse.getServer(); - enhancedPluginContext.setServiceInstance(instance); - } - }) .doOnSuccess(v -> { enhancedPluginContext.setDelay(System.currentTimeMillis() - startTime); EnhancedResponseContext enhancedResponseContext = EnhancedResponseContext.builder() @@ -82,18 +79,18 @@ public class EnhancedGatewayGlobalFilter implements GlobalFilter, Ordered { enhancedPluginContext.setResponse(enhancedResponseContext); // Run post enhanced plugins. - pluginRunner.run(POST, enhancedPluginContext); + pluginRunner.run(EnhancedPluginType.Client.POST, enhancedPluginContext); }) .doOnError(t -> { enhancedPluginContext.setDelay(System.currentTimeMillis() - startTime); enhancedPluginContext.setThrowable(t); // Run exception enhanced plugins. - pluginRunner.run(EXCEPTION, enhancedPluginContext); + pluginRunner.run(EnhancedPluginType.Client.EXCEPTION, enhancedPluginContext); }) .doFinally(v -> { // Run finally enhanced plugins. - pluginRunner.run(FINALLY, enhancedPluginContext); + pluginRunner.run(EnhancedPluginType.Client.FINALLY, enhancedPluginContext); }); } diff --git a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/spi/InstanceTransformer.java b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/transformer/InstanceTransformer.java similarity index 97% rename from spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/spi/InstanceTransformer.java rename to spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/transformer/InstanceTransformer.java index f5684299e..13c19dfb0 100644 --- a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/spi/InstanceTransformer.java +++ b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/transformer/InstanceTransformer.java @@ -16,7 +16,7 @@ * */ -package com.tencent.cloud.polaris.router.spi; +package com.tencent.cloud.rpc.enhancement.transformer; import com.tencent.cloud.common.metadata.MetadataContext; import com.tencent.polaris.api.pojo.DefaultInstance; diff --git a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/transformer/PolarisInstanceTransformer.java b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/transformer/PolarisInstanceTransformer.java similarity index 93% rename from spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/transformer/PolarisInstanceTransformer.java rename to spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/transformer/PolarisInstanceTransformer.java index 183090362..a44ef3a56 100644 --- a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/transformer/PolarisInstanceTransformer.java +++ b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/transformer/PolarisInstanceTransformer.java @@ -16,10 +16,9 @@ * */ -package com.tencent.cloud.polaris.router.transformer; +package com.tencent.cloud.rpc.enhancement.transformer; import com.tencent.cloud.common.pojo.PolarisServiceInstance; -import com.tencent.cloud.polaris.router.spi.InstanceTransformer; import com.tencent.polaris.api.pojo.DefaultInstance; import org.springframework.cloud.client.ServiceInstance; diff --git a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/webclient/EnhancedWebClientReporter.java b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/webclient/EnhancedWebClientExchangeFilterFunction.java similarity index 68% rename from spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/webclient/EnhancedWebClientReporter.java rename to spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/webclient/EnhancedWebClientExchangeFilterFunction.java index 2b62fc5d0..2d5577fc2 100644 --- a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/webclient/EnhancedWebClientReporter.java +++ b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/webclient/EnhancedWebClientExchangeFilterFunction.java @@ -17,35 +17,31 @@ package com.tencent.cloud.rpc.enhancement.webclient; -import java.util.Map; - -import com.tencent.cloud.common.constant.HeaderConstant; import com.tencent.cloud.common.metadata.MetadataContextHolder; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginContext; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginRunner; +import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedRequestContext; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedResponseContext; import reactor.core.publisher.Mono; -import org.springframework.cloud.client.DefaultServiceInstance; +import org.springframework.cloud.client.ServiceInstance; import org.springframework.web.reactive.function.client.ClientRequest; import org.springframework.web.reactive.function.client.ClientResponse; import org.springframework.web.reactive.function.client.ExchangeFilterFunction; import org.springframework.web.reactive.function.client.ExchangeFunction; -import static com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType.EXCEPTION; -import static com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType.FINALLY; -import static com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType.POST; +import static com.tencent.cloud.rpc.enhancement.resttemplate.PolarisLoadBalancerRequestTransformer.LOAD_BALANCER_SERVICE_INSTANCE; /** - * EnhancedWebClientReporter. + * EnhancedWebClientExchangeFilterFunction. * * @author sean yu */ -public class EnhancedWebClientReporter implements ExchangeFilterFunction { +public class EnhancedWebClientExchangeFilterFunction implements ExchangeFilterFunction { private final EnhancedPluginRunner pluginRunner; - public EnhancedWebClientReporter(EnhancedPluginRunner pluginRunner) { + public EnhancedWebClientExchangeFilterFunction(EnhancedPluginRunner pluginRunner) { this.pluginRunner = pluginRunner; } @@ -60,38 +56,37 @@ public class EnhancedWebClientReporter implements ExchangeFilterFunction { .build(); enhancedPluginContext.setRequest(enhancedRequestContext); + enhancedPluginContext.setLocalServiceInstance(pluginRunner.getLocalServiceInstance()); + enhancedPluginContext.setTargetServiceInstance( + (ServiceInstance) MetadataContextHolder.get().getLoadbalancerMetadata().get(LOAD_BALANCER_SERVICE_INSTANCE)); + + // Run post enhanced plugins. + pluginRunner.run(EnhancedPluginType.Client.PRE, enhancedPluginContext); + long startTime = System.currentTimeMillis(); return next.exchange(request) - .doOnSubscribe(subscription -> { - Map loadBalancerContext = MetadataContextHolder.get().getLoadbalancerMetadata(); - DefaultServiceInstance serviceInstance = new DefaultServiceInstance(); - serviceInstance.setServiceId(loadBalancerContext.get(HeaderConstant.INTERNAL_CALLEE_SERVICE_ID)); - serviceInstance.setHost(request.url().getHost()); - serviceInstance.setPort(request.url().getPort()); - enhancedPluginContext.setServiceInstance(serviceInstance); - }) .doOnSuccess(response -> { enhancedPluginContext.setDelay(System.currentTimeMillis() - startTime); EnhancedResponseContext enhancedResponseContext = EnhancedResponseContext.builder() - .httpStatus(response.rawStatusCode()) + .httpStatus(response.statusCode().value()) .httpHeaders(response.headers().asHttpHeaders()) .build(); enhancedPluginContext.setResponse(enhancedResponseContext); // Run post enhanced plugins. - pluginRunner.run(POST, enhancedPluginContext); + pluginRunner.run(EnhancedPluginType.Client.POST, enhancedPluginContext); }) .doOnError(t -> { enhancedPluginContext.setDelay(System.currentTimeMillis() - startTime); enhancedPluginContext.setThrowable(t); // Run exception enhanced plugins. - pluginRunner.run(EXCEPTION, enhancedPluginContext); + pluginRunner.run(EnhancedPluginType.Client.EXCEPTION, enhancedPluginContext); }) .doFinally(v -> { // Run finally enhanced plugins. - pluginRunner.run(FINALLY, enhancedPluginContext); + pluginRunner.run(EnhancedPluginType.Client.FINALLY, enhancedPluginContext); }); } } diff --git a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/webclient/PolarisLoadBalancerClientRequestTransformer.java b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/webclient/PolarisLoadBalancerClientRequestTransformer.java index 4e6913164..be1807ff0 100644 --- a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/webclient/PolarisLoadBalancerClientRequestTransformer.java +++ b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/webclient/PolarisLoadBalancerClientRequestTransformer.java @@ -17,13 +17,14 @@ package com.tencent.cloud.rpc.enhancement.webclient; -import com.tencent.cloud.common.constant.HeaderConstant; import com.tencent.cloud.common.metadata.MetadataContextHolder; import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.client.loadbalancer.reactive.LoadBalancerClientRequestTransformer; import org.springframework.web.reactive.function.client.ClientRequest; +import static com.tencent.cloud.rpc.enhancement.resttemplate.PolarisLoadBalancerRequestTransformer.LOAD_BALANCER_SERVICE_INSTANCE; + /** * PolarisLoadBalancerClientRequestTransformer. * @@ -31,10 +32,16 @@ import org.springframework.web.reactive.function.client.ClientRequest; */ public class PolarisLoadBalancerClientRequestTransformer implements LoadBalancerClientRequestTransformer { + /** + * Transform Request, add Loadbalancer ServiceInstance to MetadataContext. + * @param request request + * @param instance instance + * @return HttpRequest + */ @Override public ClientRequest transformRequest(ClientRequest request, ServiceInstance instance) { if (instance != null) { - MetadataContextHolder.get().setLoadbalancer(HeaderConstant.INTERNAL_CALLEE_SERVICE_ID, instance.getServiceId()); + MetadataContextHolder.get().setLoadbalancer(LOAD_BALANCER_SERVICE_INSTANCE, instance); } return request; } diff --git a/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/feign/EnhancedFeignClientTest.java b/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/feign/EnhancedFeignClientTest.java index 2ff9ff909..faa02de8a 100644 --- a/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/feign/EnhancedFeignClientTest.java +++ b/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/feign/EnhancedFeignClientTest.java @@ -26,6 +26,7 @@ import com.tencent.cloud.rpc.enhancement.plugin.DefaultEnhancedPluginRunner; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPlugin; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginContext; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType; +import com.tencent.polaris.client.api.SDKContext; import feign.Client; import feign.Request; import feign.RequestTemplate; @@ -34,6 +35,7 @@ import feign.Target; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit.jupiter.SpringExtension; @@ -55,6 +57,9 @@ import static org.mockito.Mockito.mock; properties = {"spring.cloud.polaris.namespace=Test", "spring.cloud.polaris.service=TestApp", "spring.cloud.gateway.enabled=false"}) public class EnhancedFeignClientTest { + @Autowired + private SDKContext sdkContext; + @Test public void testConstructor() { try { @@ -75,7 +80,7 @@ public class EnhancedFeignClientTest { List enhancedPlugins = getMockEnhancedFeignPlugins(); try { - new EnhancedFeignClient(mock(Client.class), new DefaultEnhancedPluginRunner(enhancedPlugins)); + new EnhancedFeignClient(mock(Client.class), new DefaultEnhancedPluginRunner(enhancedPlugins, null, sdkContext)); } catch (Throwable e) { fail("Exception encountered.", e); @@ -104,7 +109,7 @@ public class EnhancedFeignClientTest { RequestTemplate requestTemplate = new RequestTemplate(); requestTemplate.feignTarget(target); - EnhancedFeignClient polarisFeignClient = new EnhancedFeignClient(delegate, new DefaultEnhancedPluginRunner(getMockEnhancedFeignPlugins())); + EnhancedFeignClient polarisFeignClient = new EnhancedFeignClient(delegate, new DefaultEnhancedPluginRunner(getMockEnhancedFeignPlugins(), null, sdkContext)); // 200 Response response = polarisFeignClient.execute(Request.create(Request.HttpMethod.GET, "http://localhost:8080/test", @@ -134,7 +139,7 @@ public class EnhancedFeignClientTest { enhancedPlugins.add(new EnhancedPlugin() { @Override public EnhancedPluginType getType() { - return EnhancedPluginType.PRE; + return EnhancedPluginType.Client.PRE; } @Override @@ -156,7 +161,7 @@ public class EnhancedFeignClientTest { enhancedPlugins.add(new EnhancedPlugin() { @Override public EnhancedPluginType getType() { - return EnhancedPluginType.POST; + return EnhancedPluginType.Client.POST; } @Override @@ -178,7 +183,7 @@ public class EnhancedFeignClientTest { enhancedPlugins.add(new EnhancedPlugin() { @Override public EnhancedPluginType getType() { - return EnhancedPluginType.EXCEPTION; + return EnhancedPluginType.Client.EXCEPTION; } @Override @@ -200,7 +205,7 @@ public class EnhancedFeignClientTest { enhancedPlugins.add(new EnhancedPlugin() { @Override public EnhancedPluginType getType() { - return EnhancedPluginType.FINALLY; + return EnhancedPluginType.Client.FINALLY; } @Override diff --git a/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/resttemplate/BlockingLoadBalancerClientAspectTest.java b/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/feign/EnhancedLoadBalancerClientAspectTest.java similarity index 84% rename from spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/resttemplate/BlockingLoadBalancerClientAspectTest.java rename to spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/feign/EnhancedLoadBalancerClientAspectTest.java index 82bf173ba..74839fef7 100644 --- a/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/resttemplate/BlockingLoadBalancerClientAspectTest.java +++ b/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/feign/EnhancedLoadBalancerClientAspectTest.java @@ -15,9 +15,8 @@ * specific language governing permissions and limitations under the License. */ -package com.tencent.cloud.rpc.enhancement.resttemplate; +package com.tencent.cloud.rpc.enhancement.feign; -import com.tencent.cloud.common.constant.HeaderConstant; import com.tencent.cloud.common.metadata.MetadataContext; import com.tencent.cloud.common.metadata.MetadataContextHolder; import com.tencent.cloud.common.metadata.StaticMetadataManager; @@ -37,6 +36,7 @@ import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.cloud.client.ServiceInstance; import org.springframework.context.ApplicationContext; +import static com.tencent.cloud.rpc.enhancement.resttemplate.PolarisLoadBalancerRequestTransformer.LOAD_BALANCER_SERVICE_INSTANCE; import static com.tencent.polaris.test.common.Consts.NAMESPACE_TEST; import static com.tencent.polaris.test.common.Consts.SERVICE_PROVIDER; import static org.assertj.core.api.Assertions.assertThat; @@ -44,14 +44,19 @@ import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; +/** + * EnhancedLoadBalancerClientAspectTest. + * + * @author sean yu + */ @ExtendWith(MockitoExtension.class) -public class BlockingLoadBalancerClientAspectTest { +public class EnhancedLoadBalancerClientAspectTest { private static MockedStatic mockedApplicationContextAwareUtils; @Mock private ProceedingJoinPoint proceedingJoinPoint; - private BlockingLoadBalancerClientAspect aspect = new BlockingLoadBalancerClientAspect(); + private EnhancedLoadBalancerClientAspect aspect = new EnhancedLoadBalancerClientAspect(); @BeforeAll static void beforeAll() { @@ -80,13 +85,9 @@ public class BlockingLoadBalancerClientAspectTest { @Test public void test() throws Throwable { ServiceInstance serviceInstance = mock(ServiceInstance.class); - doReturn("0.0.0.0").when(serviceInstance).getHost(); - doReturn(80).when(serviceInstance).getPort(); - doReturn(new Object[]{ serviceInstance }).when(proceedingJoinPoint).getArgs(); + doReturn(serviceInstance).when(proceedingJoinPoint).proceed(); aspect.invoke(proceedingJoinPoint); aspect.pointcut(); - assertThat(MetadataContextHolder.get().getLoadbalancerMetadata().get(HeaderConstant.INTERNAL_CALLEE_INSTANCE_HOST)).isEqualTo("0.0.0.0"); - assertThat(MetadataContextHolder.get().getLoadbalancerMetadata().get(HeaderConstant.INTERNAL_CALLEE_INSTANCE_PORT)).isEqualTo("80"); + assertThat(MetadataContextHolder.get().getLoadbalancerMetadata().get(LOAD_BALANCER_SERVICE_INSTANCE)).isEqualTo(serviceInstance); } - } diff --git a/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/plugin/AssemblyClientExceptionHookTest.java b/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/plugin/AssemblyClientExceptionHookTest.java new file mode 100644 index 000000000..a3f959c69 --- /dev/null +++ b/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/plugin/AssemblyClientExceptionHookTest.java @@ -0,0 +1,146 @@ +/* + * Tencent is pleased to support the open source community by making Spring Cloud Tencent available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * Unless required by applicable law or agreed to in writing, software distributed + * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package com.tencent.cloud.rpc.enhancement.plugin; + +import java.net.URI; + +import com.tencent.cloud.common.metadata.MetadataContext; +import com.tencent.cloud.common.util.ApplicationContextAwareUtils; +import com.tencent.cloud.rpc.enhancement.config.RpcEnhancementReporterProperties; +import com.tencent.cloud.rpc.enhancement.plugin.assembly.client.AssemblyClientExceptionHook; +import com.tencent.cloud.rpc.enhancement.transformer.InstanceTransformer; +import com.tencent.polaris.assembly.api.AssemblyAPI; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockedStatic; +import org.mockito.Mockito; +import org.mockito.junit.jupiter.MockitoExtension; + +import org.springframework.cloud.client.DefaultServiceInstance; +import org.springframework.context.ApplicationContext; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; + +import static com.tencent.polaris.test.common.Consts.NAMESPACE_TEST; +import static com.tencent.polaris.test.common.Consts.SERVICE_PROVIDER; +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; + +/** + * AssemblyClientExceptionHookTest. + * + * @author sean yu + */ +@ExtendWith(MockitoExtension.class) +public class AssemblyClientExceptionHookTest { + + private static MockedStatic mockedApplicationContextAwareUtils; + @InjectMocks + private AssemblyClientExceptionHook assemblyClientExceptionHook; + @Mock + private AssemblyAPI assemblyAPI; + @Mock + private InstanceTransformer instanceTransformer; + + @BeforeAll + static void beforeAll() { + mockedApplicationContextAwareUtils = Mockito.mockStatic(ApplicationContextAwareUtils.class); + mockedApplicationContextAwareUtils.when(() -> ApplicationContextAwareUtils.getProperties(anyString())) + .thenReturn("unit-test"); + ApplicationContext applicationContext = mock(ApplicationContext.class); + RpcEnhancementReporterProperties reporterProperties = mock(RpcEnhancementReporterProperties.class); + doReturn(reporterProperties) + .when(applicationContext).getBean(RpcEnhancementReporterProperties.class); + mockedApplicationContextAwareUtils.when(ApplicationContextAwareUtils::getApplicationContext) + .thenReturn(applicationContext); + } + + @AfterAll + static void afterAll() { + mockedApplicationContextAwareUtils.close(); + } + + @BeforeEach + void setUp() { + MetadataContext.LOCAL_NAMESPACE = NAMESPACE_TEST; + MetadataContext.LOCAL_SERVICE = SERVICE_PROVIDER; + } + + @Test + public void testGetName() { + assertThat(assemblyClientExceptionHook.getName()).isEqualTo(AssemblyClientExceptionHook.class.getName()); + } + + @Test + public void testType() { + assertThat(assemblyClientExceptionHook.getType()).isEqualTo(EnhancedPluginType.Client.EXCEPTION); + } + + @Test + public void testRun() { + EnhancedPluginContext pluginContext = new EnhancedPluginContext(); + EnhancedRequestContext request = EnhancedRequestContext.builder() + .httpMethod(HttpMethod.GET) + .url(URI.create("http://0.0.0.0/")) + .httpHeaders(new HttpHeaders()) + .build(); + request.toString(); + EnhancedResponseContext response = EnhancedResponseContext.builder() + .httpStatus(200) + .build(); + response.toString(); + + DefaultServiceInstance targetServiceInstance = new DefaultServiceInstance(); + targetServiceInstance.setServiceId(SERVICE_PROVIDER); + + DefaultServiceInstance localServiceInstance = new DefaultServiceInstance(); + localServiceInstance.setServiceId(SERVICE_PROVIDER); + + pluginContext.setRequest(request); + pluginContext.setResponse(response); + pluginContext.setTargetServiceInstance(targetServiceInstance); + pluginContext.setLocalServiceInstance(localServiceInstance); + pluginContext.setThrowable(new RuntimeException()); + + assemblyClientExceptionHook.run(pluginContext); + assemblyClientExceptionHook.getOrder(); + assemblyClientExceptionHook.getName(); + assemblyClientExceptionHook.getType(); + } + + @Test + public void testHandlerThrowable() { + // mock request + EnhancedRequestContext request = mock(EnhancedRequestContext.class); + // mock response + EnhancedResponseContext response = mock(EnhancedResponseContext.class); + + EnhancedPluginContext context = new EnhancedPluginContext(); + context.setRequest(request); + context.setResponse(response); + assemblyClientExceptionHook.handlerThrowable(context, new RuntimeException("Mock exception.")); + } + +} diff --git a/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/plugin/AssemblyClientPostHookTest.java b/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/plugin/AssemblyClientPostHookTest.java new file mode 100644 index 000000000..22b11cc32 --- /dev/null +++ b/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/plugin/AssemblyClientPostHookTest.java @@ -0,0 +1,146 @@ +/* + * Tencent is pleased to support the open source community by making Spring Cloud Tencent available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * Unless required by applicable law or agreed to in writing, software distributed + * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package com.tencent.cloud.rpc.enhancement.plugin; + +import java.net.URI; + +import com.tencent.cloud.common.metadata.MetadataContext; +import com.tencent.cloud.common.util.ApplicationContextAwareUtils; +import com.tencent.cloud.rpc.enhancement.config.RpcEnhancementReporterProperties; +import com.tencent.cloud.rpc.enhancement.plugin.assembly.client.AssemblyClientPostHook; +import com.tencent.cloud.rpc.enhancement.transformer.InstanceTransformer; +import com.tencent.polaris.assembly.api.AssemblyAPI; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockedStatic; +import org.mockito.Mockito; +import org.mockito.junit.jupiter.MockitoExtension; + +import org.springframework.cloud.client.DefaultServiceInstance; +import org.springframework.context.ApplicationContext; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; + +import static com.tencent.polaris.test.common.Consts.NAMESPACE_TEST; +import static com.tencent.polaris.test.common.Consts.SERVICE_PROVIDER; +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; + +/** + * AssemblyClientPostHookTest. + * + * @author sean yu + */ +@ExtendWith(MockitoExtension.class) +public class AssemblyClientPostHookTest { + + private static MockedStatic mockedApplicationContextAwareUtils; + @InjectMocks + private AssemblyClientPostHook assemblyClientPostHook; + @Mock + private AssemblyAPI assemblyAPI; + @Mock + private InstanceTransformer instanceTransformer; + + @BeforeAll + static void beforeAll() { + mockedApplicationContextAwareUtils = Mockito.mockStatic(ApplicationContextAwareUtils.class); + mockedApplicationContextAwareUtils.when(() -> ApplicationContextAwareUtils.getProperties(anyString())) + .thenReturn("unit-test"); + ApplicationContext applicationContext = mock(ApplicationContext.class); + RpcEnhancementReporterProperties reporterProperties = mock(RpcEnhancementReporterProperties.class); + doReturn(reporterProperties) + .when(applicationContext).getBean(RpcEnhancementReporterProperties.class); + mockedApplicationContextAwareUtils.when(ApplicationContextAwareUtils::getApplicationContext) + .thenReturn(applicationContext); + } + + @AfterAll + static void afterAll() { + mockedApplicationContextAwareUtils.close(); + } + + @BeforeEach + void setUp() { + MetadataContext.LOCAL_NAMESPACE = NAMESPACE_TEST; + MetadataContext.LOCAL_SERVICE = SERVICE_PROVIDER; + } + + @Test + public void testGetName() { + assertThat(assemblyClientPostHook.getName()).isEqualTo(AssemblyClientPostHook.class.getName()); + } + + @Test + public void testType() { + assertThat(assemblyClientPostHook.getType()).isEqualTo(EnhancedPluginType.Client.POST); + } + + @Test + public void testRun() { + EnhancedPluginContext pluginContext = new EnhancedPluginContext(); + EnhancedRequestContext request = EnhancedRequestContext.builder() + .httpMethod(HttpMethod.GET) + .url(URI.create("http://0.0.0.0/")) + .httpHeaders(new HttpHeaders()) + .build(); + request.toString(); + EnhancedResponseContext response = EnhancedResponseContext.builder() + .httpStatus(200) + .build(); + response.toString(); + + DefaultServiceInstance targetServiceInstance = new DefaultServiceInstance(); + targetServiceInstance.setServiceId(SERVICE_PROVIDER); + + DefaultServiceInstance localServiceInstance = new DefaultServiceInstance(); + localServiceInstance.setServiceId(SERVICE_PROVIDER); + + pluginContext.setRequest(request); + pluginContext.setResponse(response); + pluginContext.setTargetServiceInstance(targetServiceInstance); + pluginContext.setLocalServiceInstance(localServiceInstance); + pluginContext.setThrowable(new RuntimeException()); + + assemblyClientPostHook.run(pluginContext); + assemblyClientPostHook.getOrder(); + assemblyClientPostHook.getName(); + assemblyClientPostHook.getType(); + } + + @Test + public void testHandlerThrowable() { + // mock request + EnhancedRequestContext request = mock(EnhancedRequestContext.class); + // mock response + EnhancedResponseContext response = mock(EnhancedResponseContext.class); + + EnhancedPluginContext context = new EnhancedPluginContext(); + context.setRequest(request); + context.setResponse(response); + assemblyClientPostHook.handlerThrowable(context, new RuntimeException("Mock exception.")); + } + +} diff --git a/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/plugin/AssemblyClientPreHookTest.java b/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/plugin/AssemblyClientPreHookTest.java new file mode 100644 index 000000000..08d8d7a2b --- /dev/null +++ b/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/plugin/AssemblyClientPreHookTest.java @@ -0,0 +1,143 @@ +/* + * Tencent is pleased to support the open source community by making Spring Cloud Tencent available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * Unless required by applicable law or agreed to in writing, software distributed + * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package com.tencent.cloud.rpc.enhancement.plugin; + +import java.net.URI; + +import com.tencent.cloud.common.metadata.MetadataContext; +import com.tencent.cloud.common.util.ApplicationContextAwareUtils; +import com.tencent.cloud.rpc.enhancement.config.RpcEnhancementReporterProperties; +import com.tencent.cloud.rpc.enhancement.plugin.assembly.client.AssemblyClientPreHook; +import com.tencent.polaris.assembly.api.AssemblyAPI; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockedStatic; +import org.mockito.Mockito; +import org.mockito.junit.jupiter.MockitoExtension; + +import org.springframework.cloud.client.DefaultServiceInstance; +import org.springframework.context.ApplicationContext; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; + +import static com.tencent.polaris.test.common.Consts.NAMESPACE_TEST; +import static com.tencent.polaris.test.common.Consts.SERVICE_PROVIDER; +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; + +/** + * AssemblyClientPreHookTest. + * + * @author sean yu + */ +@ExtendWith(MockitoExtension.class) +public class AssemblyClientPreHookTest { + + private static MockedStatic mockedApplicationContextAwareUtils; + @InjectMocks + private AssemblyClientPreHook assemblyClientPreHook; + @Mock + private AssemblyAPI assemblyAPI; + + @BeforeAll + static void beforeAll() { + mockedApplicationContextAwareUtils = Mockito.mockStatic(ApplicationContextAwareUtils.class); + mockedApplicationContextAwareUtils.when(() -> ApplicationContextAwareUtils.getProperties(anyString())) + .thenReturn("unit-test"); + ApplicationContext applicationContext = mock(ApplicationContext.class); + RpcEnhancementReporterProperties reporterProperties = mock(RpcEnhancementReporterProperties.class); + doReturn(reporterProperties) + .when(applicationContext).getBean(RpcEnhancementReporterProperties.class); + mockedApplicationContextAwareUtils.when(ApplicationContextAwareUtils::getApplicationContext) + .thenReturn(applicationContext); + } + + @AfterAll + static void afterAll() { + mockedApplicationContextAwareUtils.close(); + } + + @BeforeEach + void setUp() { + MetadataContext.LOCAL_NAMESPACE = NAMESPACE_TEST; + MetadataContext.LOCAL_SERVICE = SERVICE_PROVIDER; + } + + @Test + public void testGetName() { + assertThat(assemblyClientPreHook.getName()).isEqualTo(AssemblyClientPreHook.class.getName()); + } + + @Test + public void testType() { + assertThat(assemblyClientPreHook.getType()).isEqualTo(EnhancedPluginType.Client.PRE); + } + + @Test + public void testRun() { + EnhancedPluginContext pluginContext = new EnhancedPluginContext(); + EnhancedRequestContext request = EnhancedRequestContext.builder() + .httpMethod(HttpMethod.GET) + .url(URI.create("http://0.0.0.0/")) + .httpHeaders(new HttpHeaders()) + .build(); + request.toString(); + EnhancedResponseContext response = EnhancedResponseContext.builder() + .httpStatus(200) + .build(); + response.toString(); + + DefaultServiceInstance targetServiceInstance = new DefaultServiceInstance(); + targetServiceInstance.setServiceId(SERVICE_PROVIDER); + + DefaultServiceInstance localServiceInstance = new DefaultServiceInstance(); + localServiceInstance.setServiceId(SERVICE_PROVIDER); + + pluginContext.setRequest(request); + pluginContext.setResponse(response); + pluginContext.setTargetServiceInstance(targetServiceInstance); + pluginContext.setLocalServiceInstance(localServiceInstance); + pluginContext.setThrowable(new RuntimeException()); + + assemblyClientPreHook.run(pluginContext); + assemblyClientPreHook.getOrder(); + assemblyClientPreHook.getName(); + assemblyClientPreHook.getType(); + } + + @Test + public void testHandlerThrowable() { + // mock request + EnhancedRequestContext request = mock(EnhancedRequestContext.class); + // mock response + EnhancedResponseContext response = mock(EnhancedResponseContext.class); + + EnhancedPluginContext context = new EnhancedPluginContext(); + context.setRequest(request); + context.setResponse(response); + assemblyClientPreHook.handlerThrowable(context, new RuntimeException("Mock exception.")); + } + +} diff --git a/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/plugin/AssemblyMetadataProviderTest.java b/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/plugin/AssemblyMetadataProviderTest.java new file mode 100644 index 000000000..8a216977e --- /dev/null +++ b/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/plugin/AssemblyMetadataProviderTest.java @@ -0,0 +1,57 @@ +/* + * Tencent is pleased to support the open source community by making Spring Cloud Tencent available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * Unless required by applicable law or agreed to in writing, software distributed + * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package com.tencent.cloud.rpc.enhancement.plugin; + +import java.util.HashMap; +import java.util.Map; + +import com.tencent.cloud.rpc.enhancement.plugin.assembly.AssemblyMetadataProvider; +import com.tencent.polaris.api.pojo.ServiceKey; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mockito; +import org.mockito.junit.jupiter.MockitoExtension; + +import org.springframework.cloud.client.ServiceInstance; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.doReturn; + +/** + * AssemblyMetadataProviderTest. + * + * @author sean yu + */ +@ExtendWith(MockitoExtension.class) +public class AssemblyMetadataProviderTest { + + @Test + public void testAssemblyMetadataProvider() { + ServiceInstance serviceInstance = Mockito.mock(ServiceInstance.class); + Map metadata = new HashMap() {{ + put("k", "v"); + }}; + doReturn(metadata).when(serviceInstance).getMetadata(); + doReturn("0.0.0.0").when(serviceInstance).getHost(); + doReturn("test").when(serviceInstance).getServiceId(); + AssemblyMetadataProvider assemblyMetadataProvider = new AssemblyMetadataProvider(serviceInstance, "test"); + assertThat(assemblyMetadataProvider.getMetadata("k")).isEqualTo("v"); + assertThat(assemblyMetadataProvider.getLocalIp()).isEqualTo("0.0.0.0"); + assertThat(assemblyMetadataProvider.getLocalService()).isEqualTo(new ServiceKey("test", "test")); + } +} diff --git a/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/plugin/AssemblyRequestContextTest.java b/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/plugin/AssemblyRequestContextTest.java new file mode 100644 index 000000000..de8f7f17f --- /dev/null +++ b/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/plugin/AssemblyRequestContextTest.java @@ -0,0 +1,83 @@ +/* + * Tencent is pleased to support the open source community by making Spring Cloud Tencent available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * Unless required by applicable law or agreed to in writing, software distributed + * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package com.tencent.cloud.rpc.enhancement.plugin; + +import java.net.URI; +import java.util.Arrays; +import java.util.HashSet; + +import com.tencent.cloud.rpc.enhancement.plugin.assembly.AssemblyRequestContext; +import com.tencent.polaris.api.pojo.ServiceKey; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.junit.jupiter.MockitoExtension; + +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * AssemblyRequestContextTest. + * + * @author sean yu + */ +@ExtendWith(MockitoExtension.class) +public class AssemblyRequestContextTest { + + @Test + public void testAssemblyRequestContext() { + URI uri = URI.create("http://0.0.0.0/"); + + HttpHeaders httpHeaders = new HttpHeaders(); + httpHeaders.add("a", "a"); + httpHeaders.add(HttpHeaders.COOKIE, "cookies-k1=cookies-v1;cookies-k2=cookies-v2"); + + EnhancedRequestContext enhancedRequestContext = EnhancedRequestContext.builder() + .httpMethod(HttpMethod.GET) + .url(uri) + .httpHeaders(httpHeaders) + .build(); + + ServiceKey callerService = new ServiceKey("test", "test"); + AssemblyRequestContext assemblyRequestContext = new AssemblyRequestContext( + enhancedRequestContext, + callerService, + "0.0.0.0" + ); + + assertThat(assemblyRequestContext.getURI()).isEqualTo(uri); + + assertThat(assemblyRequestContext.getHeader("a")).isEqualTo("a"); + assemblyRequestContext.setHeader("b", "b"); + assertThat(assemblyRequestContext.listHeaderKeys()).isEqualTo(new HashSet<>(Arrays.asList(HttpHeaders.COOKIE, "a", "b"))); + + assertThat(assemblyRequestContext.getMethod()).isEqualTo(HttpMethod.GET.toString()); + assemblyRequestContext.setMethod(HttpMethod.OPTIONS.name()); + assertThat(assemblyRequestContext.getMethod()).isEqualTo(HttpMethod.OPTIONS.toString()); + + assertThat(assemblyRequestContext.getCookie("cookies-k1")).isEqualTo("cookies-v1"); + assertThat(assemblyRequestContext.getCookie("cookies-k2")).isEqualTo("cookies-v2"); + assemblyRequestContext.setCookie("cookies-k3", "cookies-v3"); + assertThat(assemblyRequestContext.listCookieKeys()).isEqualTo(new HashSet<>(Arrays.asList("cookies-k1", "cookies-k2", "cookies-k3"))); + + assertThat(assemblyRequestContext.getCallerService()).isEqualTo(callerService); + assertThat(assemblyRequestContext.getCallerIp()).isEqualTo("0.0.0.0"); + } + +} diff --git a/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/plugin/AssemblyResponseContextTest.java b/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/plugin/AssemblyResponseContextTest.java new file mode 100644 index 000000000..d3c96e899 --- /dev/null +++ b/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/plugin/AssemblyResponseContextTest.java @@ -0,0 +1,101 @@ +/* + * Tencent is pleased to support the open source community by making Spring Cloud Tencent available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * Unless required by applicable law or agreed to in writing, software distributed + * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package com.tencent.cloud.rpc.enhancement.plugin; + +import java.net.SocketTimeoutException; +import java.util.Arrays; +import java.util.HashSet; + +import com.tencent.cloud.common.util.ApplicationContextAwareUtils; +import com.tencent.cloud.rpc.enhancement.config.RpcEnhancementReporterProperties; +import com.tencent.cloud.rpc.enhancement.plugin.assembly.AssemblyResponseContext; +import com.tencent.polaris.api.pojo.RetStatus; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.MockedStatic; +import org.mockito.Mockito; +import org.mockito.junit.jupiter.MockitoExtension; + +import org.springframework.context.ApplicationContext; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; + +/** + * AssemblyResponseContextTest. + * + * @author sean yu + */ +@ExtendWith(MockitoExtension.class) +public class AssemblyResponseContextTest { + + private static MockedStatic mockedApplicationContextAwareUtils; + + @BeforeAll + static void beforeAll() { + mockedApplicationContextAwareUtils = Mockito.mockStatic(ApplicationContextAwareUtils.class); + mockedApplicationContextAwareUtils.when(() -> ApplicationContextAwareUtils.getProperties(anyString())) + .thenReturn("unit-test"); + ApplicationContext applicationContext = mock(ApplicationContext.class); + RpcEnhancementReporterProperties reporterProperties = mock(RpcEnhancementReporterProperties.class); + doReturn(reporterProperties) + .when(applicationContext).getBean(RpcEnhancementReporterProperties.class); + mockedApplicationContextAwareUtils.when(ApplicationContextAwareUtils::getApplicationContext) + .thenReturn(applicationContext); + } + + @AfterAll + static void afterAll() { + mockedApplicationContextAwareUtils.close(); + } + + @Test + public void testAssemblyResponseContext() { + + HttpHeaders httpHeaders = new HttpHeaders(); + httpHeaders.add("a", "a"); + + EnhancedResponseContext enhancedResponseContext = EnhancedResponseContext.builder() + .httpHeaders(httpHeaders) + .httpStatus(HttpStatus.OK.value()) + .build(); + + AssemblyResponseContext assemblyResponseContext = new AssemblyResponseContext(enhancedResponseContext, null); + assertThat(assemblyResponseContext.getHeader("a")).isEqualTo("a"); + assertThat(assemblyResponseContext.getRetCode()).isEqualTo(HttpStatus.OK.value()); + assertThat(assemblyResponseContext.getThrowable()).isEqualTo(null); + assertThat(assemblyResponseContext.getRetStatus()).isEqualTo(RetStatus.RetSuccess); + assertThat(assemblyResponseContext.listHeaders()).isEqualTo(new HashSet<>(Arrays.asList("a"))); + + Throwable e = new SocketTimeoutException(); + assemblyResponseContext = new AssemblyResponseContext(null, e); + assertThat(assemblyResponseContext.getHeader("a")).isEqualTo(null); + assertThat(assemblyResponseContext.getRetCode()).isEqualTo(null); + assertThat(assemblyResponseContext.getThrowable()).isEqualTo(e); + assertThat(assemblyResponseContext.getRetStatus()).isEqualTo(RetStatus.RetTimeout); + assertThat(assemblyResponseContext.listHeaders()).isEqualTo(null); + + } + +} diff --git a/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/plugin/AssemblyServerExceptionHookTest.java b/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/plugin/AssemblyServerExceptionHookTest.java new file mode 100644 index 000000000..644e82bb2 --- /dev/null +++ b/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/plugin/AssemblyServerExceptionHookTest.java @@ -0,0 +1,143 @@ +/* + * Tencent is pleased to support the open source community by making Spring Cloud Tencent available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * Unless required by applicable law or agreed to in writing, software distributed + * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package com.tencent.cloud.rpc.enhancement.plugin; + +import java.net.URI; + +import com.tencent.cloud.common.metadata.MetadataContext; +import com.tencent.cloud.common.util.ApplicationContextAwareUtils; +import com.tencent.cloud.rpc.enhancement.config.RpcEnhancementReporterProperties; +import com.tencent.cloud.rpc.enhancement.plugin.assembly.server.AssemblyServerExceptionHook; +import com.tencent.polaris.assembly.api.AssemblyAPI; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockedStatic; +import org.mockito.Mockito; +import org.mockito.junit.jupiter.MockitoExtension; + +import org.springframework.cloud.client.DefaultServiceInstance; +import org.springframework.context.ApplicationContext; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; + +import static com.tencent.polaris.test.common.Consts.NAMESPACE_TEST; +import static com.tencent.polaris.test.common.Consts.SERVICE_PROVIDER; +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; + +/** + * AssemblyServerExceptionHookTest. + * + * @author sean yu + */ +@ExtendWith(MockitoExtension.class) +public class AssemblyServerExceptionHookTest { + + private static MockedStatic mockedApplicationContextAwareUtils; + @InjectMocks + private AssemblyServerExceptionHook assemblyServerExceptionHook; + @Mock + private AssemblyAPI assemblyAPI; + + @BeforeAll + static void beforeAll() { + mockedApplicationContextAwareUtils = Mockito.mockStatic(ApplicationContextAwareUtils.class); + mockedApplicationContextAwareUtils.when(() -> ApplicationContextAwareUtils.getProperties(anyString())) + .thenReturn("unit-test"); + ApplicationContext applicationContext = mock(ApplicationContext.class); + RpcEnhancementReporterProperties reporterProperties = mock(RpcEnhancementReporterProperties.class); + doReturn(reporterProperties) + .when(applicationContext).getBean(RpcEnhancementReporterProperties.class); + mockedApplicationContextAwareUtils.when(ApplicationContextAwareUtils::getApplicationContext) + .thenReturn(applicationContext); + } + + @AfterAll + static void afterAll() { + mockedApplicationContextAwareUtils.close(); + } + + @BeforeEach + void setUp() { + MetadataContext.LOCAL_NAMESPACE = NAMESPACE_TEST; + MetadataContext.LOCAL_SERVICE = SERVICE_PROVIDER; + } + + @Test + public void testGetName() { + assertThat(assemblyServerExceptionHook.getName()).isEqualTo(AssemblyServerExceptionHook.class.getName()); + } + + @Test + public void testType() { + assertThat(assemblyServerExceptionHook.getType()).isEqualTo(EnhancedPluginType.Server.EXCEPTION); + } + + @Test + public void testRun() { + EnhancedPluginContext pluginContext = new EnhancedPluginContext(); + EnhancedRequestContext request = EnhancedRequestContext.builder() + .httpMethod(HttpMethod.GET) + .url(URI.create("http://0.0.0.0/")) + .httpHeaders(new HttpHeaders()) + .build(); + request.toString(); + EnhancedResponseContext response = EnhancedResponseContext.builder() + .httpStatus(200) + .build(); + response.toString(); + + DefaultServiceInstance targetServiceInstance = new DefaultServiceInstance(); + targetServiceInstance.setServiceId(SERVICE_PROVIDER); + + DefaultServiceInstance localServiceInstance = new DefaultServiceInstance(); + localServiceInstance.setServiceId(SERVICE_PROVIDER); + + pluginContext.setRequest(request); + pluginContext.setResponse(response); + pluginContext.setTargetServiceInstance(targetServiceInstance); + pluginContext.setLocalServiceInstance(localServiceInstance); + pluginContext.setThrowable(new RuntimeException()); + + assemblyServerExceptionHook.run(pluginContext); + assemblyServerExceptionHook.getOrder(); + assemblyServerExceptionHook.getName(); + assemblyServerExceptionHook.getType(); + } + + @Test + public void testHandlerThrowable() { + // mock request + EnhancedRequestContext request = mock(EnhancedRequestContext.class); + // mock response + EnhancedResponseContext response = mock(EnhancedResponseContext.class); + + EnhancedPluginContext context = new EnhancedPluginContext(); + context.setRequest(request); + context.setResponse(response); + assemblyServerExceptionHook.handlerThrowable(context, new RuntimeException("Mock exception.")); + } + +} diff --git a/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/plugin/AssemblyServerPostHookTest.java b/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/plugin/AssemblyServerPostHookTest.java new file mode 100644 index 000000000..2cf1f0400 --- /dev/null +++ b/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/plugin/AssemblyServerPostHookTest.java @@ -0,0 +1,143 @@ +/* + * Tencent is pleased to support the open source community by making Spring Cloud Tencent available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * Unless required by applicable law or agreed to in writing, software distributed + * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package com.tencent.cloud.rpc.enhancement.plugin; + +import java.net.URI; + +import com.tencent.cloud.common.metadata.MetadataContext; +import com.tencent.cloud.common.util.ApplicationContextAwareUtils; +import com.tencent.cloud.rpc.enhancement.config.RpcEnhancementReporterProperties; +import com.tencent.cloud.rpc.enhancement.plugin.assembly.server.AssemblyServerPostHook; +import com.tencent.polaris.assembly.api.AssemblyAPI; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockedStatic; +import org.mockito.Mockito; +import org.mockito.junit.jupiter.MockitoExtension; + +import org.springframework.cloud.client.DefaultServiceInstance; +import org.springframework.context.ApplicationContext; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; + +import static com.tencent.polaris.test.common.Consts.NAMESPACE_TEST; +import static com.tencent.polaris.test.common.Consts.SERVICE_PROVIDER; +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; + +/** + * AssemblyServerPostHookTest. + * + * @author sean yu + */ +@ExtendWith(MockitoExtension.class) +public class AssemblyServerPostHookTest { + + private static MockedStatic mockedApplicationContextAwareUtils; + @InjectMocks + private AssemblyServerPostHook assemblyServerPostHook; + @Mock + private AssemblyAPI assemblyAPI; + + @BeforeAll + static void beforeAll() { + mockedApplicationContextAwareUtils = Mockito.mockStatic(ApplicationContextAwareUtils.class); + mockedApplicationContextAwareUtils.when(() -> ApplicationContextAwareUtils.getProperties(anyString())) + .thenReturn("unit-test"); + ApplicationContext applicationContext = mock(ApplicationContext.class); + RpcEnhancementReporterProperties reporterProperties = mock(RpcEnhancementReporterProperties.class); + doReturn(reporterProperties) + .when(applicationContext).getBean(RpcEnhancementReporterProperties.class); + mockedApplicationContextAwareUtils.when(ApplicationContextAwareUtils::getApplicationContext) + .thenReturn(applicationContext); + } + + @AfterAll + static void afterAll() { + mockedApplicationContextAwareUtils.close(); + } + + @BeforeEach + void setUp() { + MetadataContext.LOCAL_NAMESPACE = NAMESPACE_TEST; + MetadataContext.LOCAL_SERVICE = SERVICE_PROVIDER; + } + + @Test + public void testGetName() { + assertThat(assemblyServerPostHook.getName()).isEqualTo(AssemblyServerPostHook.class.getName()); + } + + @Test + public void testType() { + assertThat(assemblyServerPostHook.getType()).isEqualTo(EnhancedPluginType.Server.POST); + } + + @Test + public void testRun() { + EnhancedPluginContext pluginContext = new EnhancedPluginContext(); + EnhancedRequestContext request = EnhancedRequestContext.builder() + .httpMethod(HttpMethod.GET) + .url(URI.create("http://0.0.0.0/")) + .httpHeaders(new HttpHeaders()) + .build(); + request.toString(); + EnhancedResponseContext response = EnhancedResponseContext.builder() + .httpStatus(200) + .build(); + response.toString(); + + DefaultServiceInstance targetServiceInstance = new DefaultServiceInstance(); + targetServiceInstance.setServiceId(SERVICE_PROVIDER); + + DefaultServiceInstance localServiceInstance = new DefaultServiceInstance(); + localServiceInstance.setServiceId(SERVICE_PROVIDER); + + pluginContext.setRequest(request); + pluginContext.setResponse(response); + pluginContext.setTargetServiceInstance(targetServiceInstance); + pluginContext.setLocalServiceInstance(localServiceInstance); + pluginContext.setThrowable(new RuntimeException()); + + assemblyServerPostHook.run(pluginContext); + assemblyServerPostHook.getOrder(); + assemblyServerPostHook.getName(); + assemblyServerPostHook.getType(); + } + + @Test + public void testHandlerThrowable() { + // mock request + EnhancedRequestContext request = mock(EnhancedRequestContext.class); + // mock response + EnhancedResponseContext response = mock(EnhancedResponseContext.class); + + EnhancedPluginContext context = new EnhancedPluginContext(); + context.setRequest(request); + context.setResponse(response); + assemblyServerPostHook.handlerThrowable(context, new RuntimeException("Mock exception.")); + } + +} diff --git a/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/plugin/AssemblyServerPreHookTest.java b/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/plugin/AssemblyServerPreHookTest.java new file mode 100644 index 000000000..d3d324806 --- /dev/null +++ b/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/plugin/AssemblyServerPreHookTest.java @@ -0,0 +1,143 @@ +/* + * Tencent is pleased to support the open source community by making Spring Cloud Tencent available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * Unless required by applicable law or agreed to in writing, software distributed + * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package com.tencent.cloud.rpc.enhancement.plugin; + +import java.net.URI; + +import com.tencent.cloud.common.metadata.MetadataContext; +import com.tencent.cloud.common.util.ApplicationContextAwareUtils; +import com.tencent.cloud.rpc.enhancement.config.RpcEnhancementReporterProperties; +import com.tencent.cloud.rpc.enhancement.plugin.assembly.server.AssemblyServerPreHook; +import com.tencent.polaris.assembly.api.AssemblyAPI; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockedStatic; +import org.mockito.Mockito; +import org.mockito.junit.jupiter.MockitoExtension; + +import org.springframework.cloud.client.DefaultServiceInstance; +import org.springframework.context.ApplicationContext; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; + +import static com.tencent.polaris.test.common.Consts.NAMESPACE_TEST; +import static com.tencent.polaris.test.common.Consts.SERVICE_PROVIDER; +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; + +/** + * AssemblyServerPreHookTest. + * + * @author sean yu + */ +@ExtendWith(MockitoExtension.class) +public class AssemblyServerPreHookTest { + + private static MockedStatic mockedApplicationContextAwareUtils; + @InjectMocks + private AssemblyServerPreHook assemblyServerPreHook; + @Mock + private AssemblyAPI assemblyAPI; + + @BeforeAll + static void beforeAll() { + mockedApplicationContextAwareUtils = Mockito.mockStatic(ApplicationContextAwareUtils.class); + mockedApplicationContextAwareUtils.when(() -> ApplicationContextAwareUtils.getProperties(anyString())) + .thenReturn("unit-test"); + ApplicationContext applicationContext = mock(ApplicationContext.class); + RpcEnhancementReporterProperties reporterProperties = mock(RpcEnhancementReporterProperties.class); + doReturn(reporterProperties) + .when(applicationContext).getBean(RpcEnhancementReporterProperties.class); + mockedApplicationContextAwareUtils.when(ApplicationContextAwareUtils::getApplicationContext) + .thenReturn(applicationContext); + } + + @AfterAll + static void afterAll() { + mockedApplicationContextAwareUtils.close(); + } + + @BeforeEach + void setUp() { + MetadataContext.LOCAL_NAMESPACE = NAMESPACE_TEST; + MetadataContext.LOCAL_SERVICE = SERVICE_PROVIDER; + } + + @Test + public void testGetName() { + assertThat(assemblyServerPreHook.getName()).isEqualTo(AssemblyServerPreHook.class.getName()); + } + + @Test + public void testType() { + assertThat(assemblyServerPreHook.getType()).isEqualTo(EnhancedPluginType.Server.PRE); + } + + @Test + public void testRun() { + EnhancedPluginContext pluginContext = new EnhancedPluginContext(); + EnhancedRequestContext request = EnhancedRequestContext.builder() + .httpMethod(HttpMethod.GET) + .url(URI.create("http://0.0.0.0/")) + .httpHeaders(new HttpHeaders()) + .build(); + request.toString(); + EnhancedResponseContext response = EnhancedResponseContext.builder() + .httpStatus(200) + .build(); + response.toString(); + + DefaultServiceInstance targetServiceInstance = new DefaultServiceInstance(); + targetServiceInstance.setServiceId(SERVICE_PROVIDER); + + DefaultServiceInstance localServiceInstance = new DefaultServiceInstance(); + localServiceInstance.setServiceId(SERVICE_PROVIDER); + + pluginContext.setRequest(request); + pluginContext.setResponse(response); + pluginContext.setTargetServiceInstance(targetServiceInstance); + pluginContext.setLocalServiceInstance(localServiceInstance); + pluginContext.setThrowable(new RuntimeException()); + + assemblyServerPreHook.run(pluginContext); + assemblyServerPreHook.getOrder(); + assemblyServerPreHook.getName(); + assemblyServerPreHook.getType(); + } + + @Test + public void testHandlerThrowable() { + // mock request + EnhancedRequestContext request = mock(EnhancedRequestContext.class); + // mock response + EnhancedResponseContext response = mock(EnhancedResponseContext.class); + + EnhancedPluginContext context = new EnhancedPluginContext(); + context.setRequest(request); + context.setResponse(response); + assemblyServerPreHook.handlerThrowable(context, new RuntimeException("Mock exception.")); + } + +} diff --git a/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/plugin/EnhancedPluginContextTest.java b/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/plugin/EnhancedPluginContextTest.java index a516483f1..0e9824911 100644 --- a/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/plugin/EnhancedPluginContextTest.java +++ b/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/plugin/EnhancedPluginContextTest.java @@ -25,6 +25,9 @@ import com.tencent.cloud.common.util.ApplicationContextAwareUtils; import com.tencent.cloud.rpc.enhancement.config.RpcEnhancementReporterProperties; import com.tencent.cloud.rpc.enhancement.plugin.reporter.ExceptionPolarisReporter; import com.tencent.cloud.rpc.enhancement.plugin.reporter.SuccessPolarisReporter; +import com.tencent.polaris.api.config.Configuration; +import com.tencent.polaris.api.config.global.APIConfig; +import com.tencent.polaris.api.config.global.GlobalConfig; import com.tencent.polaris.api.core.ConsumerAPI; import com.tencent.polaris.client.api.SDKContext; import org.junit.jupiter.api.AfterAll; @@ -38,6 +41,7 @@ import org.mockito.Mockito; import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.cloud.client.DefaultServiceInstance; +import org.springframework.cloud.client.serviceregistry.Registration; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; @@ -65,6 +69,8 @@ public class EnhancedPluginContextTest { private SDKContext sdkContext; @Mock private ConsumerAPI consumerAPI; + @Mock + private Registration registration; @BeforeAll static void beforeAll() { @@ -111,24 +117,38 @@ public class EnhancedPluginContextTest { EnhancedPluginContext enhancedPluginContext = new EnhancedPluginContext(); enhancedPluginContext.setRequest(requestContext); enhancedPluginContext.setResponse(responseContext); - enhancedPluginContext.setServiceInstance(new DefaultServiceInstance()); + enhancedPluginContext.setTargetServiceInstance(new DefaultServiceInstance()); enhancedPluginContext.setThrowable(mock(Exception.class)); enhancedPluginContext.setDelay(0); assertThat(enhancedPluginContext.getRequest()).isNotNull(); assertThat(enhancedPluginContext.getResponse()).isNotNull(); - assertThat(enhancedPluginContext.getServiceInstance()).isNotNull(); + assertThat(enhancedPluginContext.getTargetServiceInstance()).isNotNull(); assertThat(enhancedPluginContext.getThrowable()).isNotNull(); assertThat(enhancedPluginContext.getDelay()).isNotNull(); - EnhancedPlugin enhancedPlugin = new SuccessPolarisReporter(reporterProperties, sdkContext, consumerAPI); - EnhancedPlugin enhancedPlugin1 = new ExceptionPolarisReporter(reporterProperties, sdkContext, consumerAPI); - EnhancedPluginRunner enhancedPluginRunner = new DefaultEnhancedPluginRunner(Arrays.asList(enhancedPlugin, enhancedPlugin1)); - enhancedPluginRunner.run(EnhancedPluginType.POST, enhancedPluginContext); + EnhancedPlugin enhancedPlugin = new SuccessPolarisReporter(reporterProperties, consumerAPI); + EnhancedPlugin enhancedPlugin1 = new ExceptionPolarisReporter(reporterProperties, consumerAPI); + EnhancedPluginRunner enhancedPluginRunner = new DefaultEnhancedPluginRunner(Arrays.asList(enhancedPlugin, enhancedPlugin1), registration, sdkContext); + enhancedPluginRunner.run(EnhancedPluginType.Client.POST, enhancedPluginContext); + + assertThat(enhancedPluginRunner.getLocalServiceInstance()).isEqualTo(registration); EnhancedPlugin enhancedPlugin2 = mock(EnhancedPlugin.class); doThrow(new RuntimeException()).when(enhancedPlugin2).run(any()); - doReturn(EnhancedPluginType.POST).when(enhancedPlugin2).getType(); - enhancedPluginRunner = new DefaultEnhancedPluginRunner(Arrays.asList(enhancedPlugin2)); - enhancedPluginRunner.run(EnhancedPluginType.POST, enhancedPluginContext); + doReturn(EnhancedPluginType.Client.POST).when(enhancedPlugin2).getType(); + + APIConfig apiConfig = mock(APIConfig.class); + doReturn("0.0.0.0").when(apiConfig).getBindIP(); + + GlobalConfig globalConfig = mock(GlobalConfig.class); + doReturn(apiConfig).when(globalConfig).getAPI(); + + Configuration configuration = mock(Configuration.class); + doReturn(globalConfig).when(configuration).getGlobal(); + + doReturn(configuration).when(sdkContext).getConfig(); + + enhancedPluginRunner = new DefaultEnhancedPluginRunner(Arrays.asList(enhancedPlugin2), null, sdkContext); + enhancedPluginRunner.run(EnhancedPluginType.Client.POST, enhancedPluginContext); } } diff --git a/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/plugin/ExceptionPolarisReporterTest.java b/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/plugin/ExceptionPolarisReporterTest.java index 21c61ef92..840c5d498 100644 --- a/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/plugin/ExceptionPolarisReporterTest.java +++ b/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/plugin/ExceptionPolarisReporterTest.java @@ -23,11 +23,7 @@ import com.tencent.cloud.common.metadata.MetadataContext; import com.tencent.cloud.common.util.ApplicationContextAwareUtils; import com.tencent.cloud.rpc.enhancement.config.RpcEnhancementReporterProperties; import com.tencent.cloud.rpc.enhancement.plugin.reporter.ExceptionPolarisReporter; -import com.tencent.polaris.api.config.Configuration; -import com.tencent.polaris.api.config.global.APIConfig; -import com.tencent.polaris.api.config.global.GlobalConfig; import com.tencent.polaris.api.core.ConsumerAPI; -import com.tencent.polaris.client.api.SDKContext; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; @@ -40,6 +36,7 @@ import org.mockito.Mockito; import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.cloud.client.DefaultServiceInstance; +import org.springframework.context.ApplicationContext; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; @@ -63,8 +60,6 @@ public class ExceptionPolarisReporterTest { private static MockedStatic mockedApplicationContextAwareUtils; @Mock private RpcEnhancementReporterProperties reporterProperties; - @Mock - private SDKContext sdkContext; @InjectMocks private ExceptionPolarisReporter exceptionPolarisReporter; @Mock @@ -75,6 +70,12 @@ public class ExceptionPolarisReporterTest { mockedApplicationContextAwareUtils = Mockito.mockStatic(ApplicationContextAwareUtils.class); mockedApplicationContextAwareUtils.when(() -> ApplicationContextAwareUtils.getProperties(anyString())) .thenReturn("unit-test"); + ApplicationContext applicationContext = mock(ApplicationContext.class); + RpcEnhancementReporterProperties reporterProperties = mock(RpcEnhancementReporterProperties.class); + doReturn(reporterProperties) + .when(applicationContext).getBean(RpcEnhancementReporterProperties.class); + mockedApplicationContextAwareUtils.when(ApplicationContextAwareUtils::getApplicationContext) + .thenReturn(applicationContext); } @AfterAll @@ -95,7 +96,7 @@ public class ExceptionPolarisReporterTest { @Test public void testType() { - assertThat(exceptionPolarisReporter.getType()).isEqualTo(EnhancedPluginType.EXCEPTION); + assertThat(exceptionPolarisReporter.getType()).isEqualTo(EnhancedPluginType.Client.EXCEPTION); } @Test @@ -107,32 +108,23 @@ public class ExceptionPolarisReporterTest { doReturn(true).when(reporterProperties).isEnabled(); - APIConfig apiConfig = mock(APIConfig.class); - doReturn("0.0.0.0").when(apiConfig).getBindIP(); - - GlobalConfig globalConfig = mock(GlobalConfig.class); - doReturn(apiConfig).when(globalConfig).getAPI(); - - Configuration configuration = mock(Configuration.class); - doReturn(globalConfig).when(configuration).getGlobal(); - - doReturn(configuration).when(sdkContext).getConfig(); - EnhancedPluginContext pluginContext = new EnhancedPluginContext(); EnhancedRequestContext request = EnhancedRequestContext.builder() .httpMethod(HttpMethod.GET) .url(URI.create("http://0.0.0.0/")) .httpHeaders(new HttpHeaders()) .build(); + request.toString(); EnhancedResponseContext response = EnhancedResponseContext.builder() .httpStatus(200) .build(); + response.toString(); DefaultServiceInstance serviceInstance = new DefaultServiceInstance(); serviceInstance.setServiceId(SERVICE_PROVIDER); pluginContext.setRequest(request); pluginContext.setResponse(response); - pluginContext.setServiceInstance(serviceInstance); + pluginContext.setTargetServiceInstance(serviceInstance); pluginContext.setThrowable(new RuntimeException()); exceptionPolarisReporter.run(pluginContext); diff --git a/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/AbstractPolarisReporterAdapterTest.java b/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/plugin/PolarisEnhancedPluginUtilsTest.java similarity index 55% rename from spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/AbstractPolarisReporterAdapterTest.java rename to spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/plugin/PolarisEnhancedPluginUtilsTest.java index 825da246f..6b0006da6 100644 --- a/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/AbstractPolarisReporterAdapterTest.java +++ b/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/plugin/PolarisEnhancedPluginUtilsTest.java @@ -15,20 +15,19 @@ * specific language governing permissions and limitations under the License. */ -package com.tencent.cloud.rpc.enhancement; +package com.tencent.cloud.rpc.enhancement.plugin; import java.net.SocketTimeoutException; import java.net.URI; import java.net.URISyntaxException; +import java.util.Arrays; +import java.util.HashMap; import com.tencent.cloud.common.constant.HeaderConstant; import com.tencent.cloud.common.constant.RouterConstant; import com.tencent.cloud.common.metadata.MetadataContext; import com.tencent.cloud.common.util.ApplicationContextAwareUtils; import com.tencent.cloud.rpc.enhancement.config.RpcEnhancementReporterProperties; -import com.tencent.polaris.api.config.Configuration; -import com.tencent.polaris.api.config.global.APIConfig; -import com.tencent.polaris.api.config.global.GlobalConfig; import com.tencent.polaris.api.plugin.circuitbreaker.ResourceStat; import com.tencent.polaris.api.pojo.RetStatus; import com.tencent.polaris.api.rpc.ServiceCallResult; @@ -43,6 +42,7 @@ import org.mockito.MockedStatic; import org.mockito.Mockito; import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.context.ApplicationContext; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; @@ -54,12 +54,12 @@ import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; /** - * Test For {@link AbstractPolarisReporterAdapter}. + * Test For {@link PolarisEnhancedPluginUtils}. * * @author Elve.Xu 2022/7/11 */ @ExtendWith(MockitoExtension.class) -public class AbstractPolarisReporterAdapterTest { +public class PolarisEnhancedPluginUtilsTest { private static MockedStatic mockedApplicationContextAwareUtils; private final RpcEnhancementReporterProperties reporterProperties = new RpcEnhancementReporterProperties(); @@ -71,6 +71,12 @@ public class AbstractPolarisReporterAdapterTest { mockedApplicationContextAwareUtils = Mockito.mockStatic(ApplicationContextAwareUtils.class); mockedApplicationContextAwareUtils.when(() -> ApplicationContextAwareUtils.getProperties(anyString())) .thenReturn("unit-test"); + ApplicationContext applicationContext = mock(ApplicationContext.class); + RpcEnhancementReporterProperties reporterProperties = mock(RpcEnhancementReporterProperties.class); + doReturn(reporterProperties) + .when(applicationContext).getBean(RpcEnhancementReporterProperties.class); + mockedApplicationContextAwareUtils.when(ApplicationContextAwareUtils::getApplicationContext) + .thenReturn(applicationContext); } @AfterAll @@ -86,25 +92,18 @@ public class AbstractPolarisReporterAdapterTest { @Test public void testServiceCallResult() throws URISyntaxException { - APIConfig apiConfig = mock(APIConfig.class); - doReturn("0.0.0.0").when(apiConfig).getBindIP(); - - GlobalConfig globalConfig = mock(GlobalConfig.class); - doReturn(apiConfig).when(globalConfig).getAPI(); - - Configuration configuration = mock(Configuration.class); - doReturn(globalConfig).when(configuration).getGlobal(); - - doReturn(configuration).when(sdkContext).getConfig(); - - SimplePolarisReporterAdapter adapter = new SimplePolarisReporterAdapter(reporterProperties, sdkContext); ServiceCallResult serviceCallResult; HttpHeaders requestHeaders = new HttpHeaders(); requestHeaders.add(RouterConstant.ROUTER_LABEL_HEADER, "{\"k1\":\"v1\"}"); - serviceCallResult = adapter.createServiceCallResult( + assertThat(PolarisEnhancedPluginUtils.getLabelMap(requestHeaders)).isEqualTo(new HashMap() {{ + put("k1", "v1"); + }}); + + serviceCallResult = PolarisEnhancedPluginUtils.createServiceCallResult( + "0.0.0.0", "test", null, null, @@ -117,7 +116,8 @@ public class AbstractPolarisReporterAdapterTest { ); assertThat(serviceCallResult.getRetStatus()).isEqualTo(RetStatus.RetSuccess); - serviceCallResult = adapter.createServiceCallResult( + serviceCallResult = PolarisEnhancedPluginUtils.createServiceCallResult( + "0.0.0.0", "test", null, null, @@ -130,7 +130,8 @@ public class AbstractPolarisReporterAdapterTest { ); assertThat(serviceCallResult.getRetStatus()).isEqualTo(RetStatus.RetFail); - serviceCallResult = adapter.createServiceCallResult( + serviceCallResult = PolarisEnhancedPluginUtils.createServiceCallResult( + "0.0.0.0", "test", null, null, @@ -143,7 +144,8 @@ public class AbstractPolarisReporterAdapterTest { ); assertThat(serviceCallResult.getRetStatus()).isEqualTo(RetStatus.RetTimeout); - serviceCallResult = adapter.createServiceCallResult( + serviceCallResult = PolarisEnhancedPluginUtils.createServiceCallResult( + "0.0.0.0", "test", "0.0.0.0", 8080, @@ -162,11 +164,9 @@ public class AbstractPolarisReporterAdapterTest { @Test public void testResourceStat() throws URISyntaxException { - SimplePolarisReporterAdapter adapter = new SimplePolarisReporterAdapter(reporterProperties, sdkContext); - ResourceStat resourceStat; - resourceStat = adapter.createInstanceResourceStat("test", + resourceStat = PolarisEnhancedPluginUtils.createInstanceResourceStat("test", null, null, new URI("http://0.0.0.0/"), @@ -176,7 +176,7 @@ public class AbstractPolarisReporterAdapterTest { ); assertThat(resourceStat.getRetStatus()).isEqualTo(RetStatus.RetSuccess); - resourceStat = adapter.createInstanceResourceStat("test", + resourceStat = PolarisEnhancedPluginUtils.createInstanceResourceStat("test", null, null, new URI("http://0.0.0.0/"), @@ -186,7 +186,7 @@ public class AbstractPolarisReporterAdapterTest { ); assertThat(resourceStat.getRetStatus()).isEqualTo(RetStatus.RetTimeout); - resourceStat = adapter.createInstanceResourceStat("test", + resourceStat = PolarisEnhancedPluginUtils.createInstanceResourceStat("test", null, null, new URI("http://0.0.0.0/"), @@ -200,13 +200,32 @@ public class AbstractPolarisReporterAdapterTest { @Test public void testApplyWithDefaultConfig() { RpcEnhancementReporterProperties properties = new RpcEnhancementReporterProperties(); - // Mock Condition - SimplePolarisReporterAdapter adapter = new SimplePolarisReporterAdapter(properties, sdkContext); + ApplicationContext applicationContext = mock(ApplicationContext.class); + doReturn(properties) + .when(applicationContext).getBean(RpcEnhancementReporterProperties.class); + mockedApplicationContextAwareUtils.when(ApplicationContextAwareUtils::getApplicationContext) + .thenReturn(applicationContext); + // Assert + assertThat(PolarisEnhancedPluginUtils.apply(HttpStatus.OK)).isEqualTo(false); + assertThat(PolarisEnhancedPluginUtils.apply(HttpStatus.INTERNAL_SERVER_ERROR)).isEqualTo(false); + assertThat(PolarisEnhancedPluginUtils.apply(HttpStatus.BAD_GATEWAY)).isEqualTo(true); + } + + @Test + public void testApplyWithHttpStatus() { + RpcEnhancementReporterProperties properties = new RpcEnhancementReporterProperties(); + properties.setStatuses(Arrays.asList(HttpStatus.BAD_GATEWAY, HttpStatus.INTERNAL_SERVER_ERROR)); + ApplicationContext applicationContext = mock(ApplicationContext.class); + doReturn(properties) + .when(applicationContext).getBean(RpcEnhancementReporterProperties.class); + mockedApplicationContextAwareUtils.when(ApplicationContextAwareUtils::getApplicationContext) + .thenReturn(applicationContext); // Assert - assertThat(adapter.apply(HttpStatus.OK)).isEqualTo(false); - assertThat(adapter.apply(HttpStatus.INTERNAL_SERVER_ERROR)).isEqualTo(false); - assertThat(adapter.apply(HttpStatus.BAD_GATEWAY)).isEqualTo(true); + assertThat(PolarisEnhancedPluginUtils.apply(null)).isEqualTo(false); + assertThat(PolarisEnhancedPluginUtils.apply(HttpStatus.OK)).isEqualTo(false); + assertThat(PolarisEnhancedPluginUtils.apply(HttpStatus.INTERNAL_SERVER_ERROR)).isEqualTo(true); + assertThat(PolarisEnhancedPluginUtils.apply(HttpStatus.BAD_GATEWAY)).isEqualTo(true); } @Test @@ -216,12 +235,16 @@ public class AbstractPolarisReporterAdapterTest { properties.getStatuses().clear(); properties.setIgnoreInternalServerError(false); - SimplePolarisReporterAdapter adapter = new SimplePolarisReporterAdapter(properties, sdkContext); + ApplicationContext applicationContext = mock(ApplicationContext.class); + doReturn(properties) + .when(applicationContext).getBean(RpcEnhancementReporterProperties.class); + mockedApplicationContextAwareUtils.when(ApplicationContextAwareUtils::getApplicationContext) + .thenReturn(applicationContext); // Assert - assertThat(adapter.apply(HttpStatus.OK)).isEqualTo(false); - assertThat(adapter.apply(HttpStatus.INTERNAL_SERVER_ERROR)).isEqualTo(true); - assertThat(adapter.apply(HttpStatus.BAD_GATEWAY)).isEqualTo(true); + assertThat(PolarisEnhancedPluginUtils.apply(HttpStatus.OK)).isEqualTo(false); + assertThat(PolarisEnhancedPluginUtils.apply(HttpStatus.INTERNAL_SERVER_ERROR)).isEqualTo(true); + assertThat(PolarisEnhancedPluginUtils.apply(HttpStatus.BAD_GATEWAY)).isEqualTo(true); } @Test @@ -231,12 +254,16 @@ public class AbstractPolarisReporterAdapterTest { properties.getStatuses().clear(); properties.setIgnoreInternalServerError(true); - SimplePolarisReporterAdapter adapter = new SimplePolarisReporterAdapter(properties, sdkContext); + ApplicationContext applicationContext = mock(ApplicationContext.class); + doReturn(properties) + .when(applicationContext).getBean(RpcEnhancementReporterProperties.class); + mockedApplicationContextAwareUtils.when(ApplicationContextAwareUtils::getApplicationContext) + .thenReturn(applicationContext); // Assert - assertThat(adapter.apply(HttpStatus.OK)).isEqualTo(false); - assertThat(adapter.apply(HttpStatus.INTERNAL_SERVER_ERROR)).isEqualTo(false); - assertThat(adapter.apply(HttpStatus.BAD_GATEWAY)).isEqualTo(true); + assertThat(PolarisEnhancedPluginUtils.apply(HttpStatus.OK)).isEqualTo(false); + assertThat(PolarisEnhancedPluginUtils.apply(HttpStatus.INTERNAL_SERVER_ERROR)).isEqualTo(false); + assertThat(PolarisEnhancedPluginUtils.apply(HttpStatus.BAD_GATEWAY)).isEqualTo(true); } @Test @@ -246,12 +273,16 @@ public class AbstractPolarisReporterAdapterTest { properties.getStatuses().clear(); properties.getSeries().clear(); - SimplePolarisReporterAdapter adapter = new SimplePolarisReporterAdapter(properties, sdkContext); + ApplicationContext applicationContext = mock(ApplicationContext.class); + doReturn(properties) + .when(applicationContext).getBean(RpcEnhancementReporterProperties.class); + mockedApplicationContextAwareUtils.when(ApplicationContextAwareUtils::getApplicationContext) + .thenReturn(applicationContext); // Assert - assertThat(adapter.apply(HttpStatus.OK)).isEqualTo(false); - assertThat(adapter.apply(HttpStatus.INTERNAL_SERVER_ERROR)).isEqualTo(false); - assertThat(adapter.apply(HttpStatus.BAD_GATEWAY)).isEqualTo(true); + assertThat(PolarisEnhancedPluginUtils.apply(HttpStatus.OK)).isEqualTo(false); + assertThat(PolarisEnhancedPluginUtils.apply(HttpStatus.INTERNAL_SERVER_ERROR)).isEqualTo(false); + assertThat(PolarisEnhancedPluginUtils.apply(HttpStatus.BAD_GATEWAY)).isEqualTo(true); } @Test @@ -262,65 +293,46 @@ public class AbstractPolarisReporterAdapterTest { properties.getSeries().clear(); properties.getSeries().add(HttpStatus.Series.CLIENT_ERROR); - SimplePolarisReporterAdapter adapter = new SimplePolarisReporterAdapter(properties, sdkContext); + ApplicationContext applicationContext = mock(ApplicationContext.class); + doReturn(properties) + .when(applicationContext).getBean(RpcEnhancementReporterProperties.class); + mockedApplicationContextAwareUtils.when(ApplicationContextAwareUtils::getApplicationContext) + .thenReturn(applicationContext); // Assert - assertThat(adapter.apply(HttpStatus.OK)).isEqualTo(false); - assertThat(adapter.apply(HttpStatus.INTERNAL_SERVER_ERROR)).isEqualTo(false); - assertThat(adapter.apply(HttpStatus.BAD_GATEWAY)).isEqualTo(false); - assertThat(adapter.apply(HttpStatus.FORBIDDEN)).isEqualTo(true); + assertThat(PolarisEnhancedPluginUtils.apply(HttpStatus.OK)).isEqualTo(false); + assertThat(PolarisEnhancedPluginUtils.apply(HttpStatus.INTERNAL_SERVER_ERROR)).isEqualTo(false); + assertThat(PolarisEnhancedPluginUtils.apply(HttpStatus.BAD_GATEWAY)).isEqualTo(false); + assertThat(PolarisEnhancedPluginUtils.apply(HttpStatus.FORBIDDEN)).isEqualTo(true); } @Test public void testGetRetStatusFromRequest() { - RpcEnhancementReporterProperties properties = new RpcEnhancementReporterProperties(); - // Mock Condition - properties.getStatuses().clear(); - properties.getSeries().clear(); - properties.getSeries().add(HttpStatus.Series.CLIENT_ERROR); - - SimplePolarisReporterAdapter adapter = new SimplePolarisReporterAdapter(properties, sdkContext); HttpHeaders headers = new HttpHeaders(); - RetStatus ret = adapter.getRetStatusFromRequest(headers, RetStatus.RetFail); + RetStatus ret = PolarisEnhancedPluginUtils.getRetStatusFromRequest(headers, RetStatus.RetFail); assertThat(ret).isEqualTo(RetStatus.RetFail); headers.set(HeaderConstant.INTERNAL_CALLEE_RET_STATUS, RetStatus.RetFlowControl.getDesc()); - ret = adapter.getRetStatusFromRequest(headers, RetStatus.RetFail); + ret = PolarisEnhancedPluginUtils.getRetStatusFromRequest(headers, RetStatus.RetFail); assertThat(ret).isEqualTo(RetStatus.RetFlowControl); headers.set(HeaderConstant.INTERNAL_CALLEE_RET_STATUS, RetStatus.RetReject.getDesc()); - ret = adapter.getRetStatusFromRequest(headers, RetStatus.RetFail); + ret = PolarisEnhancedPluginUtils.getRetStatusFromRequest(headers, RetStatus.RetFail); assertThat(ret).isEqualTo(RetStatus.RetReject); } @Test public void testGetActiveRuleNameFromRequest() { - RpcEnhancementReporterProperties properties = new RpcEnhancementReporterProperties(); - // Mock Condition - properties.getStatuses().clear(); - properties.getSeries().clear(); - properties.getSeries().add(HttpStatus.Series.CLIENT_ERROR); - - SimplePolarisReporterAdapter adapter = new SimplePolarisReporterAdapter(properties, sdkContext); HttpHeaders headers = new HttpHeaders(); - String ruleName = adapter.getActiveRuleNameFromRequest(headers); + String ruleName = PolarisEnhancedPluginUtils.getActiveRuleNameFromRequest(headers); assertThat(ruleName).isEqualTo(""); headers.set(HeaderConstant.INTERNAL_ACTIVE_RULE_NAME, "mock_rule"); - ruleName = adapter.getActiveRuleNameFromRequest(headers); + ruleName = PolarisEnhancedPluginUtils.getActiveRuleNameFromRequest(headers); assertThat(ruleName).isEqualTo("mock_rule"); } - /** - * Simple Polaris CircuitBreak Adapter Implements . - */ - public static class SimplePolarisReporterAdapter extends AbstractPolarisReporterAdapter { - - protected SimplePolarisReporterAdapter(RpcEnhancementReporterProperties reportProperties, SDKContext context) { - super(reportProperties, context); - } - } } diff --git a/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/plugin/SuccessPolarisReporterTest.java b/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/plugin/SuccessPolarisReporterTest.java index 9af4ca019..5af25a89b 100644 --- a/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/plugin/SuccessPolarisReporterTest.java +++ b/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/plugin/SuccessPolarisReporterTest.java @@ -23,11 +23,7 @@ import com.tencent.cloud.common.metadata.MetadataContext; import com.tencent.cloud.common.util.ApplicationContextAwareUtils; import com.tencent.cloud.rpc.enhancement.config.RpcEnhancementReporterProperties; import com.tencent.cloud.rpc.enhancement.plugin.reporter.SuccessPolarisReporter; -import com.tencent.polaris.api.config.Configuration; -import com.tencent.polaris.api.config.global.APIConfig; -import com.tencent.polaris.api.config.global.GlobalConfig; import com.tencent.polaris.api.core.ConsumerAPI; -import com.tencent.polaris.client.api.SDKContext; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; @@ -40,6 +36,7 @@ import org.mockito.Mockito; import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.cloud.client.DefaultServiceInstance; +import org.springframework.context.ApplicationContext; import org.springframework.http.HttpMethod; import static com.tencent.polaris.test.common.Consts.NAMESPACE_TEST; @@ -60,8 +57,6 @@ import static org.mockito.Mockito.verify; public class SuccessPolarisReporterTest { private static MockedStatic mockedApplicationContextAwareUtils; @Mock - private SDKContext sdkContext; - @Mock private RpcEnhancementReporterProperties reporterProperties; @InjectMocks private SuccessPolarisReporter successPolarisReporter; @@ -73,6 +68,12 @@ public class SuccessPolarisReporterTest { mockedApplicationContextAwareUtils = Mockito.mockStatic(ApplicationContextAwareUtils.class); mockedApplicationContextAwareUtils.when(() -> ApplicationContextAwareUtils.getProperties(anyString())) .thenReturn("unit-test"); + ApplicationContext applicationContext = mock(ApplicationContext.class); + RpcEnhancementReporterProperties reporterProperties = mock(RpcEnhancementReporterProperties.class); + doReturn(reporterProperties) + .when(applicationContext).getBean(RpcEnhancementReporterProperties.class); + mockedApplicationContextAwareUtils.when(ApplicationContextAwareUtils::getApplicationContext) + .thenReturn(applicationContext); } @AfterAll @@ -93,7 +94,7 @@ public class SuccessPolarisReporterTest { @Test public void testType() { - assertThat(successPolarisReporter.getType()).isEqualTo(EnhancedPluginType.POST); + assertThat(successPolarisReporter.getType()).isEqualTo(EnhancedPluginType.Client.POST); } @Test @@ -105,31 +106,23 @@ public class SuccessPolarisReporterTest { verify(context, times(0)).getRequest(); doReturn(true).when(reporterProperties).isEnabled(); - APIConfig apiConfig = mock(APIConfig.class); - doReturn("0.0.0.0").when(apiConfig).getBindIP(); - - GlobalConfig globalConfig = mock(GlobalConfig.class); - doReturn(apiConfig).when(globalConfig).getAPI(); - - Configuration configuration = mock(Configuration.class); - doReturn(globalConfig).when(configuration).getGlobal(); - - doReturn(configuration).when(sdkContext).getConfig(); EnhancedPluginContext pluginContext = new EnhancedPluginContext(); EnhancedRequestContext request = EnhancedRequestContext.builder() .httpMethod(HttpMethod.GET) .url(URI.create("http://0.0.0.0/")) .build(); + request.toString(); EnhancedResponseContext response = EnhancedResponseContext.builder() .httpStatus(200) .build(); + response.toString(); DefaultServiceInstance serviceInstance = new DefaultServiceInstance(); serviceInstance.setServiceId(SERVICE_PROVIDER); pluginContext.setRequest(request); pluginContext.setResponse(response); - pluginContext.setServiceInstance(serviceInstance); + pluginContext.setTargetServiceInstance(serviceInstance); successPolarisReporter.run(pluginContext); successPolarisReporter.getOrder(); diff --git a/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/resttemplate/EnhancedRestTemplateInterceptorTest.java b/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/resttemplate/EnhancedRestTemplateInterceptorTest.java index 6b256f014..10bcbab69 100644 --- a/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/resttemplate/EnhancedRestTemplateInterceptorTest.java +++ b/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/resttemplate/EnhancedRestTemplateInterceptorTest.java @@ -40,6 +40,7 @@ import org.mockito.MockedStatic; import org.mockito.Mockito; import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.cloud.client.serviceregistry.Registration; import org.springframework.context.ApplicationContext; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; @@ -65,6 +66,8 @@ public class EnhancedRestTemplateInterceptorTest { @Mock private SDKContext sdkContext; @Mock + Registration registration; + @Mock private ClientHttpRequestExecution mockClientHttpRequestExecution; @Mock private ClientHttpResponse mockClientHttpResponse; @@ -109,7 +112,7 @@ public class EnhancedRestTemplateInterceptorTest { doReturn(mockHttpHeaders).when(mockHttpRequest).getHeaders(); doReturn(mockClientHttpResponse).when(mockClientHttpRequestExecution).execute(mockHttpRequest, inputBody); - EnhancedRestTemplateInterceptor reporter = new EnhancedRestTemplateInterceptor(new DefaultEnhancedPluginRunner(new ArrayList<>())); + EnhancedRestTemplateInterceptor reporter = new EnhancedRestTemplateInterceptor(new DefaultEnhancedPluginRunner(new ArrayList<>(), registration, null)); actualResult = reporter.intercept(mockHttpRequest, inputBody, mockClientHttpRequestExecution); assertThat(actualResult).isEqualTo(mockClientHttpResponse); diff --git a/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/resttemplate/PolarisLoadBalancerRequestTransformerTest.java b/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/resttemplate/PolarisLoadBalancerRequestTransformerTest.java new file mode 100644 index 000000000..4ae6084ad --- /dev/null +++ b/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/resttemplate/PolarisLoadBalancerRequestTransformerTest.java @@ -0,0 +1,89 @@ +/* + * Tencent is pleased to support the open source community by making Spring Cloud Tencent available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * Unless required by applicable law or agreed to in writing, software distributed + * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package com.tencent.cloud.rpc.enhancement.resttemplate; + +import com.tencent.cloud.common.metadata.MetadataContext; +import com.tencent.cloud.common.metadata.MetadataContextHolder; +import com.tencent.cloud.common.metadata.StaticMetadataManager; +import com.tencent.cloud.common.metadata.config.MetadataLocalProperties; +import com.tencent.cloud.common.util.ApplicationContextAwareUtils; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.MockedStatic; +import org.mockito.Mockito; +import org.mockito.junit.jupiter.MockitoExtension; + +import org.springframework.cloud.client.ServiceInstance; +import org.springframework.context.ApplicationContext; +import org.springframework.http.HttpRequest; + +import static com.tencent.cloud.rpc.enhancement.resttemplate.PolarisLoadBalancerRequestTransformer.LOAD_BALANCER_SERVICE_INSTANCE; +import static com.tencent.polaris.test.common.Consts.NAMESPACE_TEST; +import static com.tencent.polaris.test.common.Consts.SERVICE_PROVIDER; +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; + +@ExtendWith(MockitoExtension.class) +public class PolarisLoadBalancerRequestTransformerTest { + private static MockedStatic mockedApplicationContextAwareUtils; + + private PolarisLoadBalancerRequestTransformer transformer = new PolarisLoadBalancerRequestTransformer(); + + @Mock + private HttpRequest clientRequest; + + @Mock + private ServiceInstance serviceInstance; + + @BeforeAll + static void beforeAll() { + mockedApplicationContextAwareUtils = Mockito.mockStatic(ApplicationContextAwareUtils.class); + mockedApplicationContextAwareUtils.when(() -> ApplicationContextAwareUtils.getProperties(anyString())) + .thenReturn("unit-test"); + ApplicationContext applicationContext = mock(ApplicationContext.class); + MetadataLocalProperties metadataLocalProperties = mock(MetadataLocalProperties.class); + StaticMetadataManager staticMetadataManager = mock(StaticMetadataManager.class); + doReturn(metadataLocalProperties).when(applicationContext).getBean(MetadataLocalProperties.class); + doReturn(staticMetadataManager).when(applicationContext).getBean(StaticMetadataManager.class); + mockedApplicationContextAwareUtils.when(ApplicationContextAwareUtils::getApplicationContext).thenReturn(applicationContext); + } + + @AfterAll + static void afterAll() { + mockedApplicationContextAwareUtils.close(); + } + + @BeforeEach + void setUp() { + MetadataContext.LOCAL_NAMESPACE = NAMESPACE_TEST; + MetadataContext.LOCAL_SERVICE = SERVICE_PROVIDER; + } + + @Test + public void test() throws Throwable { + transformer.transformRequest(clientRequest, serviceInstance); + assertThat(MetadataContextHolder.get().getLoadbalancerMetadata().get(LOAD_BALANCER_SERVICE_INSTANCE)).isEqualTo(serviceInstance); + } +} + diff --git a/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/scg/EnhancedGatewayGlobalFilterTest.java b/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/scg/EnhancedGatewayGlobalFilterTest.java index 6d5e8816d..d50adce6f 100644 --- a/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/scg/EnhancedGatewayGlobalFilterTest.java +++ b/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/scg/EnhancedGatewayGlobalFilterTest.java @@ -41,6 +41,7 @@ import reactor.core.publisher.Mono; import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.client.loadbalancer.Response; +import org.springframework.cloud.client.serviceregistry.Registration; import org.springframework.cloud.gateway.filter.GatewayFilterChain; import org.springframework.context.ApplicationContext; import org.springframework.http.HttpHeaders; @@ -66,6 +67,8 @@ public class EnhancedGatewayGlobalFilterTest { @Mock private SDKContext sdkContext; @Mock + Registration registration; + @Mock ServerWebExchange exchange; @Mock GatewayFilterChain chain; @@ -123,7 +126,7 @@ public class EnhancedGatewayGlobalFilterTest { doReturn(request).when(exchange).getRequest(); doReturn(response).when(exchange).getResponse(); - EnhancedGatewayGlobalFilter reporter = new EnhancedGatewayGlobalFilter(new DefaultEnhancedPluginRunner(new ArrayList<>())); + EnhancedGatewayGlobalFilter reporter = new EnhancedGatewayGlobalFilter(new DefaultEnhancedPluginRunner(new ArrayList<>(), registration, null)); reporter.getOrder(); reporter.filter(exchange, chain).block(); diff --git a/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/webclient/EnhancedWebClientReporterTest.java b/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/webclient/EnhancedWebClientExchangeFilterFunctionTest.java similarity index 91% rename from spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/webclient/EnhancedWebClientReporterTest.java rename to spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/webclient/EnhancedWebClientExchangeFilterFunctionTest.java index f8a4a673a..4801e4cb2 100644 --- a/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/webclient/EnhancedWebClientReporterTest.java +++ b/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/webclient/EnhancedWebClientExchangeFilterFunctionTest.java @@ -39,9 +39,11 @@ import org.mockito.Mockito; import org.mockito.junit.jupiter.MockitoExtension; import reactor.core.publisher.Mono; +import org.springframework.cloud.client.serviceregistry.Registration; import org.springframework.context.ApplicationContext; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatus; import org.springframework.web.reactive.function.client.ClientRequest; import org.springframework.web.reactive.function.client.ClientResponse; import org.springframework.web.reactive.function.client.ExchangeFunction; @@ -56,7 +58,7 @@ import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; @ExtendWith(MockitoExtension.class) -public class EnhancedWebClientReporterTest { +public class EnhancedWebClientExchangeFilterFunctionTest { private static MockedStatic mockedApplicationContextAwareUtils; @Mock @@ -64,6 +66,8 @@ public class EnhancedWebClientReporterTest { @Mock private SDKContext sdkContext; @Mock + private Registration registration; + @Mock private ClientRequest clientRequest; @Mock private ExchangeFunction exchangeFunction; @@ -101,9 +105,10 @@ public class EnhancedWebClientReporterTest { doReturn(HttpMethod.GET).when(clientRequest).method(); ClientResponse.Headers headers = mock(ClientResponse.Headers.class); doReturn(headers).when(clientResponse).headers(); + doReturn(HttpStatus.valueOf(200)).when(clientResponse).statusCode(); doReturn(Mono.just(clientResponse)).when(exchangeFunction).exchange(any()); - EnhancedWebClientReporter reporter = new EnhancedWebClientReporter(new DefaultEnhancedPluginRunner(new ArrayList<>())); + EnhancedWebClientExchangeFilterFunction reporter = new EnhancedWebClientExchangeFilterFunction(new DefaultEnhancedPluginRunner(new ArrayList<>(), registration, null)); ClientResponse clientResponse1 = reporter.filter(clientRequest, exchangeFunction).block(); assertThat(clientResponse1).isEqualTo(clientResponse); diff --git a/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/webclient/PolarisLoadBalancerClientRequestTransformerTest.java b/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/webclient/PolarisLoadBalancerClientRequestTransformerTest.java index 811b7c5eb..7b7c4e0d5 100644 --- a/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/webclient/PolarisLoadBalancerClientRequestTransformerTest.java +++ b/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/webclient/PolarisLoadBalancerClientRequestTransformerTest.java @@ -17,7 +17,6 @@ package com.tencent.cloud.rpc.enhancement.webclient; -import com.tencent.cloud.common.constant.HeaderConstant; import com.tencent.cloud.common.metadata.MetadataContext; import com.tencent.cloud.common.metadata.MetadataContextHolder; import com.tencent.cloud.common.metadata.StaticMetadataManager; @@ -37,6 +36,7 @@ import org.springframework.cloud.client.ServiceInstance; import org.springframework.context.ApplicationContext; import org.springframework.web.reactive.function.client.ClientRequest; +import static com.tencent.cloud.rpc.enhancement.resttemplate.PolarisLoadBalancerRequestTransformer.LOAD_BALANCER_SERVICE_INSTANCE; import static com.tencent.polaris.test.common.Consts.NAMESPACE_TEST; import static com.tencent.polaris.test.common.Consts.SERVICE_PROVIDER; import static org.assertj.core.api.Assertions.assertThat; @@ -83,8 +83,7 @@ public class PolarisLoadBalancerClientRequestTransformerTest { @Test public void test() throws Throwable { - doReturn("test").when(serviceInstance).getServiceId(); transformer.transformRequest(clientRequest, serviceInstance); - assertThat(MetadataContextHolder.get().getLoadbalancerMetadata().get(HeaderConstant.INTERNAL_CALLEE_SERVICE_ID)).isEqualTo("test"); + assertThat(MetadataContextHolder.get().getLoadbalancerMetadata().get(LOAD_BALANCER_SERVICE_INSTANCE)).isEqualTo(serviceInstance); } }