From d68bf433a32494d8db9062581de89ab537c7dfff Mon Sep 17 00:00:00 2001 From: "Shanyou Yu (Sean Yu)" Date: Mon, 8 May 2023 14:35:58 +0800 Subject: [PATCH] Feature: add AssemblyFlow to support tsf (#992) --- 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 | 33 ++-- ...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/EnhancedFeignBeanPostProcessor.java | 5 +- ...hancedFeignBlockingLoadBalancerClient.java | 7 +- .../feign/EnhancedFeignClient.java | 30 ++-- ...isLoadBalancerFeignRequestTransformer.java | 49 ++++++ .../filter/EnhancedReactiveFilter.java | 93 ++++++++++ .../filter/EnhancedServletFilter.java | 115 ++++++++++++ .../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 | 125 +++++++++++++ .../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 +- .../EnhancedFeignBeanPostProcessorTest.java | 5 + ...edFeignBlockingLoadBalancerClientTest.java | 2 +- .../feign/EnhancedFeignClientTest.java | 17 +- ...adBalancerFeignRequestTransformerTest.java | 94 ++++++++++ .../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 +- ...isLoadBalancerRequestTransformerTest.java} | 27 ++- .../scg/EnhancedGatewayGlobalFilterTest.java | 5 +- ...dWebClientExchangeFilterFunctionTest.java} | 9 +- ...dBalancerClientRequestTransformerTest.java | 5 +- 94 files changed, 3298 insertions(+), 456 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 rename spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/resttemplate/BlockingLoadBalancerClientAspect.java => spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-tsf-adapter-plugin/src/main/java/com/tencent/cloud/tsf/adapter/config/PolarisTsfFlowConfigModifier.java (50%) 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 create mode 100644 spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/feign/PolarisLoadBalancerFeignRequestTransformer.java 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%) create mode 100644 spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/feign/PolarisLoadBalancerFeignRequestTransformerTest.java 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%) rename spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/resttemplate/{BlockingLoadBalancerClientAspectTest.java => PolarisLoadBalancerRequestTransformerTest.java} (79%) 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 1039307e..ae98fc3b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,3 +4,4 @@ - [feature: support reactive discovery client health indicator.](https://github.com/Tencent/spring-cloud-tencent/pull/988) - [feature: Enhance default configuration to support `application*.yaml` and `bootstrap*.yaml`.](https://github.com/Tencent/spring-cloud-tencent/pull/988) - [feat:Remove error log from `DecodeTransferMetadataReactiveFilter`.](https://github.com/Tencent/spring-cloud-tencent/pull/991) +- [Feature: add AssemblyFlow to support tsf.](https://github.com/Tencent/spring-cloud-tencent/pull/992) 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 2c1f9dec..70999eff 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 f2f50921..fba34d25 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 b47c1a4a..4ef515aa 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 ce5fe2a8..8975b97e 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 53e38c9d..7be53b2f 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 4dcd3d19..5d50a24c 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 ea480d40..3f83bfd4 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 38f1e0df..8ee742d6 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 8a94f799..e07d57dc 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 4bbf3d92..3ff96086 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 LOGGER.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 8a417702..63e34038 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 493d7b61..4b4c47e6 100644 --- a/spring-cloud-tencent-dependencies/pom.xml +++ b/spring-cloud-tencent-dependencies/pom.xml @@ -73,7 +73,7 @@ 1.12.0-2022.0.1-SNAPSHOT - 1.12.3 + 1.13.0-SNAPSHOT 31.1-jre 4.9.0 1.12.19 @@ -164,6 +164,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 bc2f153b..3de6b8ac 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 08aaf665..9145d82a 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 498040c0..2959e86d 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 cae2a60f..f8f4b7e9 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 00000000..0c0deb4f --- /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 00000000..d9d2b404 --- /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-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/resttemplate/BlockingLoadBalancerClientAspect.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 similarity index 50% rename from spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/resttemplate/BlockingLoadBalancerClientAspect.java rename to spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-tsf-adapter-plugin/src/main/java/com/tencent/cloud/tsf/adapter/config/PolarisTsfFlowConfigModifier.java index 418ce484..335e55ae 100644 --- a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/resttemplate/BlockingLoadBalancerClientAspect.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 @@ -15,29 +15,32 @@ * specific language governing permissions and limitations under the License. */ -package com.tencent.cloud.rpc.enhancement.resttemplate; +package com.tencent.cloud.tsf.adapter.config; -import org.aspectj.lang.ProceedingJoinPoint; -import org.aspectj.lang.annotation.Around; -import org.aspectj.lang.annotation.Aspect; -import org.aspectj.lang.annotation.Pointcut; +import com.tencent.cloud.common.constant.ContextConstant; +import com.tencent.cloud.polaris.context.PolarisConfigModifier; +import com.tencent.polaris.factory.config.ConfigurationImpl; /** - * Intercept for BlockingLoadBalancerClient, put host and port to thread local. + * PolarisTsfFlowConfigModifier. * - * @author lepdou 2022-09-05 + * @author sean yu */ -@Aspect -public class BlockingLoadBalancerClientAspect { +public class PolarisTsfFlowConfigModifier implements PolarisConfigModifier { - @Pointcut("execution(public * org.springframework.cloud.loadbalancer.blocking.client.BlockingLoadBalancerClient.reconstructURI(..)) ") - public void pointcut() { + /** + * 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); } - @Around("pointcut()") - public Object invoke(ProceedingJoinPoint joinPoint) throws Throwable { - LoadBalancerClientAspectUtils.extractLoadBalancerResult(joinPoint); - return joinPoint.proceed(); + @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 00000000..fa8e4120 --- /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 00000000..bef51db1 --- /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 00000000..d183d23e --- /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 00000000..644d59bb --- /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 00000000..639ce8bd --- /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 00000000..bd5df065 --- /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 00000000..2ed23f63 --- /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 5b6c5cca..0ae40202 100644 --- a/spring-cloud-tencent-polaris-context/pom.xml +++ b/spring-cloud-tencent-polaris-context/pom.xml @@ -99,6 +99,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 a0256ae1..0ae6f412 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 5d7cf2d2..1dd93122 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 aadd0b0b..035c2a86 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.PolarisLoadBalancerFeignRequestTransformer; +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 jakarta.servlet.DispatcherType.ASYNC; +import static jakarta.servlet.DispatcherType.ERROR; +import static jakarta.servlet.DispatcherType.FORWARD; +import static jakarta.servlet.DispatcherType.INCLUDE; +import static jakarta.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.openfeign.loadbalancer.LoadBalancerFeignRequestTransformer"}) + public PolarisLoadBalancerFeignRequestTransformer polarisLoadBalancerFeignRequestTransformer() { + return new PolarisLoadBalancerFeignRequestTransformer(); + } + } /** @@ -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(); } } @@ -155,12 +254,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/EnhancedFeignBeanPostProcessor.java b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/feign/EnhancedFeignBeanPostProcessor.java index 1aa0abe2..99c5f6f2 100644 --- a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/feign/EnhancedFeignBeanPostProcessor.java +++ b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/feign/EnhancedFeignBeanPostProcessor.java @@ -27,6 +27,7 @@ import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.cloud.loadbalancer.blocking.client.BlockingLoadBalancerClient; import org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory; import org.springframework.cloud.openfeign.loadbalancer.FeignBlockingLoadBalancerClient; +import org.springframework.cloud.openfeign.loadbalancer.LoadBalancerFeignRequestTransformer; import org.springframework.cloud.openfeign.loadbalancer.RetryableFeignBlockingLoadBalancerClient; /** @@ -63,7 +64,9 @@ public class EnhancedFeignBeanPostProcessor implements BeanPostProcessor, BeanFa if (delegate != null) { return new EnhancedFeignBlockingLoadBalancerClient(createPolarisFeignClient(delegate), factory.getBean(BlockingLoadBalancerClient.class), - factory.getBean(LoadBalancerClientFactory.class)); + factory.getBean(LoadBalancerClientFactory.class), + factory.getBeanProvider(LoadBalancerFeignRequestTransformer.class).stream().toList() + ); } } return createPolarisFeignClient((Client) bean); diff --git a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/feign/EnhancedFeignBlockingLoadBalancerClient.java b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/feign/EnhancedFeignBlockingLoadBalancerClient.java index fa545706..9040d098 100644 --- a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/feign/EnhancedFeignBlockingLoadBalancerClient.java +++ b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/feign/EnhancedFeignBlockingLoadBalancerClient.java @@ -17,11 +17,14 @@ package com.tencent.cloud.rpc.enhancement.feign; +import java.util.List; + import feign.Client; import org.springframework.cloud.client.loadbalancer.LoadBalancerClient; import org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory; import org.springframework.cloud.openfeign.loadbalancer.FeignBlockingLoadBalancerClient; +import org.springframework.cloud.openfeign.loadbalancer.LoadBalancerFeignRequestTransformer; /** * Wrap for {@link FeignBlockingLoadBalancerClient}. @@ -31,7 +34,7 @@ import org.springframework.cloud.openfeign.loadbalancer.FeignBlockingLoadBalance public class EnhancedFeignBlockingLoadBalancerClient extends FeignBlockingLoadBalancerClient { public EnhancedFeignBlockingLoadBalancerClient(Client delegate, LoadBalancerClient loadBalancerClient, - LoadBalancerClientFactory loadBalancerClientFactory) { - super(delegate, loadBalancerClient, loadBalancerClientFactory); + LoadBalancerClientFactory loadBalancerClientFactory, List transformers) { + super(delegate, loadBalancerClient, loadBalancerClientFactory, transformers); } } 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 e191edfd..1af26f5b 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/feign/PolarisLoadBalancerFeignRequestTransformer.java b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/feign/PolarisLoadBalancerFeignRequestTransformer.java new file mode 100644 index 00000000..65b16da8 --- /dev/null +++ b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/feign/PolarisLoadBalancerFeignRequestTransformer.java @@ -0,0 +1,49 @@ +/* + * 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.feign; + +import com.tencent.cloud.common.metadata.MetadataContextHolder; +import feign.Request; + +import org.springframework.cloud.client.ServiceInstance; +import org.springframework.cloud.openfeign.loadbalancer.LoadBalancerFeignRequestTransformer; + +import static com.tencent.cloud.rpc.enhancement.resttemplate.PolarisLoadBalancerRequestTransformer.LOAD_BALANCER_SERVICE_INSTANCE; + +/** + * PolarisLoadBalancerFeignRequestTransformer. + * + * @author sean yu + */ +public class PolarisLoadBalancerFeignRequestTransformer implements LoadBalancerFeignRequestTransformer { + + /** + * Transform Request, add Loadbalancer ServiceInstance to MetadataContext. + * @param request request + * @param instance instance + * @return HttpRequest + */ + @Override + public Request transformRequest(Request 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/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 00000000..4fa6899c --- /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 00000000..894e8944 --- /dev/null +++ b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/filter/EnhancedServletFilter.java @@ -0,0 +1,115 @@ +/* + * 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 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 jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; + +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 ca34b2af..fe88923f 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 fa4e891d..4676c51a 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 e15af39e..5ff7d1bf 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 64dc2ecb..996af00b 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 00000000..dfa4148b --- /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 d177aad8..e1556c82 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 00000000..e937f244 --- /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 00000000..c5a8befa --- /dev/null +++ b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/plugin/assembly/AssemblyRequestContext.java @@ -0,0 +1,125 @@ +/* + * 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 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(";"))) + .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 00000000..4dbfa81d --- /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 00000000..398485b5 --- /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 00000000..9148a0de --- /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 00000000..fde54027 --- /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 00000000..bde03d0d --- /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 00000000..855994eb --- /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 00000000..5b279b80 --- /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 76c4250b..471c9a17 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 4b35396d..d4c7d6a1 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 e67e241f..2a4e0f6f 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 04ffac0c..961633cf 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 bfe816f3..39cd0a60 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 f5684299..13c19dfb 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 18309036..a44ef3a5 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 2b62fc5d..2d5577fc 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 4e691316..be1807ff 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/EnhancedFeignBeanPostProcessorTest.java b/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/feign/EnhancedFeignBeanPostProcessorTest.java index 40e09a94..6481518b 100644 --- a/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/feign/EnhancedFeignBeanPostProcessorTest.java +++ b/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/feign/EnhancedFeignBeanPostProcessorTest.java @@ -22,10 +22,12 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.BeanFactory; +import org.springframework.beans.factory.ObjectProvider; import org.springframework.cloud.client.loadbalancer.LoadBalancerProperties; import org.springframework.cloud.loadbalancer.blocking.client.BlockingLoadBalancerClient; import org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory; import org.springframework.cloud.openfeign.loadbalancer.FeignBlockingLoadBalancerClient; +import org.springframework.cloud.openfeign.loadbalancer.LoadBalancerFeignRequestTransformer; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.any; @@ -63,6 +65,9 @@ public class EnhancedFeignBeanPostProcessorTest { } return null; }).when(beanFactory).getBean(any(Class.class)); + ObjectProvider objectProvider = mock(ObjectProvider.class); + doReturn(new PolarisLoadBalancerFeignRequestTransformer()).when(objectProvider).getObject(); + doReturn(objectProvider).when(beanFactory).getBeanProvider(LoadBalancerFeignRequestTransformer.class); enhancedFeignBeanPostProcessor.setBeanFactory(beanFactory); // isNeedWrap(bean) == false diff --git a/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/feign/EnhancedFeignBlockingLoadBalancerClientTest.java b/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/feign/EnhancedFeignBlockingLoadBalancerClientTest.java index bcca3df8..d22e255b 100644 --- a/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/feign/EnhancedFeignBlockingLoadBalancerClientTest.java +++ b/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/feign/EnhancedFeignBlockingLoadBalancerClientTest.java @@ -30,6 +30,6 @@ public class EnhancedFeignBlockingLoadBalancerClientTest { @Test public void testConstructor() { - assertThatCode(() -> new EnhancedFeignBlockingLoadBalancerClient(null, null, null)).doesNotThrowAnyException(); + assertThatCode(() -> new EnhancedFeignBlockingLoadBalancerClient(null, null, null, null)).doesNotThrowAnyException(); } } 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 2ff9ff90..faa02de8 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/feign/PolarisLoadBalancerFeignRequestTransformerTest.java b/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/feign/PolarisLoadBalancerFeignRequestTransformerTest.java new file mode 100644 index 00000000..44e23c95 --- /dev/null +++ b/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/feign/PolarisLoadBalancerFeignRequestTransformerTest.java @@ -0,0 +1,94 @@ +/* + * 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.feign; + +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 feign.Request; +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 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; + +/** + * PolarisLoadBalancerFeignRequestTransformerTest. + * + * @author sean yu + */ +@ExtendWith(MockitoExtension.class) +public class PolarisLoadBalancerFeignRequestTransformerTest { + + private static MockedStatic mockedApplicationContextAwareUtils; + + private PolarisLoadBalancerFeignRequestTransformer transformer = new PolarisLoadBalancerFeignRequestTransformer(); + + @Mock + private Request 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/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 00000000..a3f959c6 --- /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 00000000..22b11cc3 --- /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 00000000..08d8d7a2 --- /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 00000000..ed94bb3c --- /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 00000000..de8f7f17 --- /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 00000000..c428e3a2 --- /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.HashSet; +import java.util.List; + +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<>(List.of("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 00000000..644e82bb --- /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 00000000..2cf1f040 --- /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 00000000..d3d32480 --- /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 a516483f..0e982491 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 21c61ef9..840c5d49 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 825da246..6b0006da 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 9af4ca01..5af25a89 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 6b256f01..10bcbab6 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/BlockingLoadBalancerClientAspectTest.java b/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/resttemplate/PolarisLoadBalancerRequestTransformerTest.java similarity index 79% 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/resttemplate/PolarisLoadBalancerRequestTransformerTest.java index 82bf173b..4ae6084a 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/resttemplate/PolarisLoadBalancerRequestTransformerTest.java @@ -17,13 +17,11 @@ package com.tencent.cloud.rpc.enhancement.resttemplate; -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; import com.tencent.cloud.common.metadata.config.MetadataLocalProperties; import com.tencent.cloud.common.util.ApplicationContextAwareUtils; -import org.aspectj.lang.ProceedingJoinPoint; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; @@ -36,7 +34,9 @@ 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; @@ -45,13 +45,16 @@ import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; @ExtendWith(MockitoExtension.class) -public class BlockingLoadBalancerClientAspectTest { - +public class PolarisLoadBalancerRequestTransformerTest { private static MockedStatic mockedApplicationContextAwareUtils; + + private PolarisLoadBalancerRequestTransformer transformer = new PolarisLoadBalancerRequestTransformer(); + @Mock - private ProceedingJoinPoint proceedingJoinPoint; + private HttpRequest clientRequest; - private BlockingLoadBalancerClientAspect aspect = new BlockingLoadBalancerClientAspect(); + @Mock + private ServiceInstance serviceInstance; @BeforeAll static void beforeAll() { @@ -79,14 +82,8 @@ 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(); - 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"); + 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 6d5e8816..d50adce6 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 f8a4a673..eb00afd3 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.HttpStatusCode; 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(HttpStatusCode.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 811b7c5e..7b7c4e0d 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); } }