From 7e6c55e35f698dc719f83ebbcbdf401bc54c5072 Mon Sep 17 00:00:00 2001
From: Fishtail <49390359+fuyuwei01@users.noreply.github.com>
Date: Sat, 10 May 2025 13:27:46 +0800
Subject: [PATCH] feat:support smooth upgrade from tsf. (#1542)
Co-authored-by: Haotian Zhang
---
CHANGELOG.md | 1 +
spring-cloud-starter-tencent-all/pom.xml | 11 +
.../pom.xml | 5 -
.../EncodeTransferMedataScgFilterTest.java | 2 +-
.../tsf/auth/annotation/EnableTsfAuth.java | 42 +++
.../main/resources/META-INF/spring.factories | 3 +
...ot.autoconfigure.AutoConfiguration.imports | 2 -
.../config/PolarisAuthPropertiesTest.java | 45 ++++
...itBreakerFeignClientAutoConfiguration.java | 4 +-
.../PolarisCircuitBreakerFallbackFactory.java | 2 +-
.../PolarisCircuitBreakerNameResolver.java | 2 +-
.../feign/PolarisFeignCircuitBreaker.java | 2 +-
...sFeignCircuitBreakerInvocationHandler.java | 2 +-
.../PolarisCircuitBreakerFluxOperator.java | 2 +-
.../PolarisCircuitBreakerMonoOperator.java | 2 +-
...olarisCircuitBreakerReactorSubscriber.java | 2 +-
...larisCircuitBreakerReactorTransformer.java | 2 +-
.../resttemplate/PolarisCircuitBreaker.java | 5 +-
.../PolarisCircuitBreakerFallback.java | 5 +-
.../PolarisCircuitBreakerHttpResponse.java | 2 +-
.../reporter/CircuitBreakerPlugin.java | 2 +-
.../PolarisFeignCircuitBreakerTargeter.java | 2 +-
.../annotation/EnableTsfCircuitBreaker.java | 40 +++
.../common/PolarisResultToErrorCodeTest.java | 95 +++++++
...isCircuitBreakerAutoConfigurationTest.java | 2 +-
...PolarisCircuitBreakerNameResolverTest.java | 2 +-
...gnCircuitBreakerInvocationHandlerTest.java | 216 +++++++++++++++
...olarisFeignCircuitBreakerTargeterTest.java | 2 +-
.../feign/PolarisFeignCircuitBreakerTest.java | 133 ++++++++++
...arisRefreshEntireContextRefresherTest.java | 209 +++++++++++++++
.../contract/PolarisContractReporter.java | 5 +-
.../contract/filter/FilterConstant.java | 2 +-
.../contract/tsf/TsfApiMetadataGrapher.java | 6 +-
.../pom.xml | 6 +
.../refresh/PolarisRefreshConfiguration.java | 14 +-
.../PolarisServiceStatusChangeListener.java | 30 ++-
.../ServiceInstanceChangeCallback.java | 32 +++
.../ServiceInstanceChangeCallbackManager.java | 145 ++++++++++
.../ServiceInstanceChangeListener.java | 35 ++-
.../PolarisEagerLoadAutoConfiguration.java | 44 ++++
.../feign/FeignEagerLoadSmartLifecycle.java | 94 +++++++
.../registry/PolarisServiceRegistry.java | 4 +-
.../TsfApiPolarisRegistrationCustomizer.java | 2 +-
...TsfDiscoveryRegistryAutoConfiguration.java | 2 +-
.../TsfPortPolarisRegistrationCustomizer.java | 2 +-
.../TsfServletRegistrationCustomizer.java | 2 +-
.../watch/ConsulServiceChangeCallback.java | 40 +++
.../watch/ConsulServiceChangeListener.java | 53 ++++
.../watch/LocalServiceChangeListener.java | 47 ++++
...itional-spring-configuration-metadata.json | 12 +
.../main/resources/META-INF/spring.factories | 3 +-
...olarisServiceStatusChangeListenerTest.java | 2 +-
.../filter/QuotaCheckReactiveFilter.java | 1 +
.../filter/QuotaCheckServletFilter.java | 1 +
.../annotation/EnableTsfRateLimit.java | 40 +++
...BalancerClientFilterBeanPostProcessor.java | 2 +-
...dBalancerInterceptorBeanPostProcessor.java | 4 +-
...dBalancerInterceptorBeanPostProcessor.java | 4 +-
.../router/config/FeignAutoConfiguration.java | 4 +-
.../FeignLoadBalancerConfiguration.java | 2 +-
.../config/RouterAutoConfiguration.java | 8 +-
...olarisCachingSpringLoadBalanceFactory.java | 2 +-
.../feign/PolarisFeignLoadBalancer.java | 2 +-
.../feign/RouterLabelFeignInterceptor.java | 2 +-
.../PolarisInterceptorRetryPolicy.java | 2 +-
.../PolarisLoadBalancerInterceptor.java | 4 +-
.../PolarisRetryLoadBalancerInterceptor.java | 4 +-
.../resttemplate/RouterContextFactory.java | 2 +-
.../resttemplate/RouterContextHelper.java | 2 +-
.../RouterLabelRestTemplateInterceptor.java | 2 +-
.../scg/PolarisLoadBalancerClientFilter.java | 2 +-
.../scg/RouterLabelGlobalFilter.java | 2 +-
.../zuul/PolarisRibbonRoutingFilter.java | 2 +-
.../tsf/lane/annotation/EnableTsfLane.java | 41 +++
.../zonefilter/EnableTsfZoneFilter.java | 41 +++
.../tsf/unit/annotation/EnableTsfUnit.java | 41 +++
.../tsf/unit/annotation/TsfUnitCall.java | 46 ++++
.../annotation/TsfUnitCustomerIdentifier.java | 40 +++
.../tsf/unit/annotation/TsfUnitLocalCall.java | 44 ++++
.../tsf/route/annotation/EnableTsfRoute.java | 41 +++
...isCachingSpringLoadBalanceFactoryTest.java | 2 +-
.../feign/PolarisFeignLoadBalancerTest.java | 2 +-
.../RouterLabelFeignInterceptorTest.java | 2 +-
.../feign/SimpleLoadBalancer.java | 2 +-
.../PolarisLoadBalancerInterceptorTest.java | 2 +-
.../RouterContextFactoryTest.java | 2 +-
...outerLabelRestTemplateInterceptorTest.java | 2 +-
.../PolarisLoadBalancerClientFilterTest.java | 2 +-
.../scg/RouterLabelGlobalFilterTest.java | 2 +-
.../zuul/PolarisRibbonRoutingFilterTest.java | 2 +-
.../async/PolarisAsyncConfiguration.java | 83 ++++++
.../metadata/CrossThreadMetadataContext.java | 68 +++++
.../common/metadata/MetadataContext.java | 4 +-
.../metadata/MetadataContextHolder.java | 13 +-
.../util/ApplicationContextAwareUtils.java | 14 +
.../tencent/cloud/common/util/FeignUtil.java | 83 ++++++
.../util/PolarisCompletableFutureUtils.java | 45 ++++
.../tsf/core/{context => }/TsfContext.java | 19 +-
.../tsf/core/util/TsfSpringContextAware.java | 69 +++++
...itional-spring-configuration-metadata.json | 6 +
spring-cloud-tencent-dependencies/pom.xml | 16 +-
.../callee/QuickstartCalleeController.java | 21 +-
.../service/CalleeServiceChangeCallback.java | 60 +++++
.../callee/service/FaultToleranceService.java | 62 +++++
.../caller/QuickstartCallerApplication.java | 25 +-
.../CircuitBreakerController.java | 42 +--
.../tsf-example/consumer-demo/pom.xml | 32 +--
.../demo/consumer/ConsumerApplication.java | 3 -
.../controller/ConsumerController.java | 28 +-
.../demo/consumer/controller/SdkBaseTest.java | 54 ++++
.../tsf-example/provider-demo/pom.xml | 31 +--
spring-cloud-tencent-plugin-starters/pom.xml | 2 +
.../pom.xml | 34 +++
.../annotation/FaultTolerance.java | 95 +++++++
.../faulttolerance/common/FallbackMethod.java | 43 +++
.../FaultToleranceAutoConfiguration.java | 42 +++
.../instrument/FaultToleranceAspect.java | 248 ++++++++++++++++++
.../model/FaultToleranceStrategy.java | 37 +++
.../annotation/EnableTsfFaultTolerance.java | 40 +++
.../annotation/TsfFaultTolerance.java | 95 +++++++
.../annotation/TsfFaultToleranceProperty.java | 54 ++++
.../model/TsfFaultToleranceStragety.java | 41 +++
.../main/resources/META-INF/spring.factories | 3 +
.../integration/FaultToleranceService.java | 73 ++++++
.../integration/FaultToleranceTest.java | 74 ++++++
.../monitor/annotation/EnableTsfMonitor.java | 41 +++
.../sleuth/annotation/EnableTsfSleuth.java | 41 +++
.../main/resources/META-INF/spring.factories | 4 +-
.../pom.xml | 59 +++++
.../cloud/plugin/protection/ExitUtils.java | 52 ++++
.../SecurityProtectionAutoConfiguration.java | 87 ++++++
.../main/resources/META-INF/spring.factories | 3 +
...curityProtectionAutoConfigurationTest.java | 189 +++++++++++++
spring-cloud-tencent-polaris-context/pom.xml | 10 +
.../extend/tsf/TsfContextConfigModifier.java | 8 +
.../tsf/TsfCoreEnvironmentPostProcessor.java | 4 +
.../FailedEventApplicationListener.java | 69 +++++
.../tsf/annotation/EnableTsf.java | 13 +-
.../main/resources/META-INF/spring.factories | 3 +-
.../FailedEventApplicationListenerTest.java | 154 +++++++++++
spring-cloud-tencent-rpc-enhancement/pom.xml | 6 +
.../RpcEnhancementAutoConfiguration.java | 28 +-
.../feign/EnhancedFeignBeanPostProcessor.java | 2 +-
...hancedFeignBlockingLoadBalancerClient.java | 2 +-
.../feign/EnhancedFeignClient.java | 2 +-
.../filter/EnhancedReactiveFilter.java | 2 +-
.../filter/EnhancedServletFilter.java | 2 +-
.../EnhancedRestTemplateWrapInterceptor.java | 4 +-
...PolarisLoadBalancerRequestTransformer.java | 2 +-
.../scg/EnhancedGatewayGlobalFilter.java | 5 +-
...hancedWebClientExchangeFilterFunction.java | 45 +++-
...sLoadBalancerClientRequestTransformer.java | 4 +-
.../RibbonLoadBalancerClientAspect.java | 5 +-
.../zuul/EnhancedErrorZuulFilter.java | 2 +-
.../zuul/EnhancedPostZuulFilter.java | 2 +-
.../zuul/EnhancedRouteZuulFilter.java | 2 +-
.../zuul/EnhancedZuulPluginRunner.java | 2 +-
.../plugin/DefaultEnhancedPluginRunner.java | 26 +-
.../transformer/InstanceTransformer.java | 11 +-
.../RpcEnhancementAutoConfigurationTest.java | 2 +-
.../EnhancedFeignBeanPostProcessorTest.java | 2 +-
.../feign/EnhancedFeignClientTest.java | 2 +-
...risLoadBalancerRequestTransformerTest.java | 10 +-
.../scg/EnhancedGatewayGlobalFilterTest.java | 2 +-
...edWebClientExchangeFilterFunctionTest.java | 10 +-
...dBalancerClientRequestTransformerTest.java | 10 +-
.../DefaultEnhancedPluginRunnerTest.java | 90 +++++++
.../plugin/EnhancedPluginContextTest.java | 1 +
168 files changed, 4196 insertions(+), 319 deletions(-)
create mode 100644 spring-cloud-starter-tencent-polaris-auth/src/main/java/org/springframework/tsf/auth/annotation/EnableTsfAuth.java
delete mode 100644 spring-cloud-starter-tencent-polaris-auth/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
create mode 100644 spring-cloud-starter-tencent-polaris-auth/src/test/java/com/tencent/cloud/polaris/auth/config/PolarisAuthPropertiesTest.java
rename spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/{ => instrument}/feign/PolarisCircuitBreakerFallbackFactory.java (97%)
rename spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/{ => instrument}/feign/PolarisCircuitBreakerNameResolver.java (97%)
rename spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/{ => instrument}/feign/PolarisFeignCircuitBreaker.java (97%)
rename spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/{ => instrument}/feign/PolarisFeignCircuitBreakerInvocationHandler.java (98%)
rename spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/{ => instrument}/reactor/PolarisCircuitBreakerFluxOperator.java (96%)
rename spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/{ => instrument}/reactor/PolarisCircuitBreakerMonoOperator.java (96%)
rename spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/{ => instrument}/reactor/PolarisCircuitBreakerReactorSubscriber.java (98%)
rename spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/{ => instrument}/reactor/PolarisCircuitBreakerReactorTransformer.java (96%)
rename spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/{ => instrument}/resttemplate/PolarisCircuitBreaker.java (94%)
rename spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/{ => instrument}/resttemplate/PolarisCircuitBreakerFallback.java (88%)
rename spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/{ => instrument}/resttemplate/PolarisCircuitBreakerHttpResponse.java (97%)
create mode 100644 spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/org/springframework/cloud/tsf/circuitbreaker/annotation/EnableTsfCircuitBreaker.java
create mode 100644 spring-cloud-starter-tencent-polaris-circuitbreaker/src/test/java/com/tencent/cloud/polaris/circuitbreaker/common/PolarisResultToErrorCodeTest.java
rename spring-cloud-starter-tencent-polaris-circuitbreaker/src/test/java/com/tencent/cloud/polaris/circuitbreaker/{ => instrument}/feign/PolarisCircuitBreakerNameResolverTest.java (98%)
create mode 100644 spring-cloud-starter-tencent-polaris-circuitbreaker/src/test/java/com/tencent/cloud/polaris/circuitbreaker/instrument/feign/PolarisFeignCircuitBreakerInvocationHandlerTest.java
rename spring-cloud-starter-tencent-polaris-circuitbreaker/src/test/java/com/tencent/cloud/polaris/circuitbreaker/{ => instrument}/feign/PolarisFeignCircuitBreakerTargeterTest.java (98%)
create mode 100644 spring-cloud-starter-tencent-polaris-circuitbreaker/src/test/java/com/tencent/cloud/polaris/circuitbreaker/instrument/feign/PolarisFeignCircuitBreakerTest.java
create mode 100644 spring-cloud-starter-tencent-polaris-config/src/test/java/com/tencent/cloud/polaris/config/adapter/PolarisRefreshEntireContextRefresherTest.java
create mode 100644 spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/discovery/refresh/ServiceInstanceChangeCallback.java
create mode 100644 spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/discovery/refresh/ServiceInstanceChangeCallbackManager.java
rename spring-cloud-tencent-examples/quickstart-example/quickstart-caller-service/src/main/java/com/tencent/cloud/quickstart/caller/circuitbreaker/CustomFallback.java => spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/discovery/refresh/ServiceInstanceChangeListener.java (55%)
create mode 100644 spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/eager/config/PolarisEagerLoadAutoConfiguration.java
create mode 100644 spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/eager/instrument/feign/FeignEagerLoadSmartLifecycle.java
rename spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/{tsf/registry => registry/tsf}/TsfApiPolarisRegistrationCustomizer.java (97%)
rename spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/{tsf/registry => registry/tsf}/TsfDiscoveryRegistryAutoConfiguration.java (98%)
rename spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/{tsf/registry => registry/tsf}/TsfPortPolarisRegistrationCustomizer.java (98%)
rename spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/{tsf/registry => registry/tsf}/TsfServletRegistrationCustomizer.java (98%)
create mode 100644 spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/tsf/serviceregistry/watch/ConsulServiceChangeCallback.java
create mode 100644 spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/tsf/serviceregistry/watch/ConsulServiceChangeListener.java
create mode 100644 spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/tsf/serviceregistry/watch/LocalServiceChangeListener.java
create mode 100644 spring-cloud-starter-tencent-polaris-ratelimit/src/main/java/org/springframework/tsf/ratelimit/annotation/EnableTsfRateLimit.java
rename spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/{ => instrument}/feign/PolarisCachingSpringLoadBalanceFactory.java (97%)
rename spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/{ => instrument}/feign/PolarisFeignLoadBalancer.java (98%)
rename spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/{ => instrument}/feign/RouterLabelFeignInterceptor.java (96%)
rename spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/{ => instrument}/resttemplate/PolarisInterceptorRetryPolicy.java (97%)
rename spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/{ => instrument}/resttemplate/PolarisLoadBalancerInterceptor.java (96%)
rename spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/{ => instrument}/resttemplate/PolarisRetryLoadBalancerInterceptor.java (97%)
rename spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/{ => instrument}/resttemplate/RouterContextFactory.java (98%)
rename spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/{ => instrument}/resttemplate/RouterContextHelper.java (97%)
rename spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/{ => instrument}/resttemplate/RouterLabelRestTemplateInterceptor.java (96%)
rename spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/{ => instrument}/scg/PolarisLoadBalancerClientFilter.java (99%)
rename spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/{ => instrument}/scg/RouterLabelGlobalFilter.java (97%)
create mode 100644 spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/tsf/lane/annotation/EnableTsfLane.java
create mode 100644 spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/tsf/femas/adaptor/tsf/governance/zonefilter/EnableTsfZoneFilter.java
create mode 100644 spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/tsf/unit/annotation/EnableTsfUnit.java
create mode 100644 spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/tsf/unit/annotation/TsfUnitCall.java
create mode 100644 spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/tsf/unit/annotation/TsfUnitCustomerIdentifier.java
create mode 100644 spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/tsf/unit/annotation/TsfUnitLocalCall.java
create mode 100644 spring-cloud-starter-tencent-polaris-router/src/main/java/org/springframework/cloud/tsf/route/annotation/EnableTsfRoute.java
rename spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/{ => instrument}/feign/PolarisCachingSpringLoadBalanceFactoryTest.java (98%)
rename spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/{ => instrument}/feign/PolarisFeignLoadBalancerTest.java (98%)
rename spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/{ => instrument}/feign/RouterLabelFeignInterceptorTest.java (98%)
rename spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/{ => instrument}/feign/SimpleLoadBalancer.java (96%)
rename spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/{ => instrument}/resttemplate/PolarisLoadBalancerInterceptorTest.java (99%)
rename spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/{ => instrument}/resttemplate/RouterContextFactoryTest.java (98%)
rename spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/{ => instrument}/resttemplate/RouterLabelRestTemplateInterceptorTest.java (98%)
rename spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/{ => instrument}/scg/PolarisLoadBalancerClientFilterTest.java (99%)
rename spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/{ => instrument}/scg/RouterLabelGlobalFilterTest.java (98%)
create mode 100644 spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/async/PolarisAsyncConfiguration.java
create mode 100644 spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/metadata/CrossThreadMetadataContext.java
create mode 100644 spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/util/FeignUtil.java
create mode 100644 spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/util/PolarisCompletableFutureUtils.java
rename spring-cloud-tencent-commons/src/main/java/org/springframework/tsf/core/{context => }/TsfContext.java (80%)
create mode 100644 spring-cloud-tencent-commons/src/main/java/org/springframework/tsf/core/util/TsfSpringContextAware.java
create mode 100644 spring-cloud-tencent-examples/quickstart-example/quickstart-callee-service-a/src/main/java/com/tencent/cloud/quickstart/callee/service/CalleeServiceChangeCallback.java
create mode 100644 spring-cloud-tencent-examples/quickstart-example/quickstart-callee-service-a/src/main/java/com/tencent/cloud/quickstart/callee/service/FaultToleranceService.java
create mode 100644 spring-cloud-tencent-examples/tsf-example/consumer-demo/src/main/java/com/tencent/cloud/tsf/demo/consumer/controller/SdkBaseTest.java
create mode 100644 spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-fault-tolerance/pom.xml
create mode 100644 spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-fault-tolerance/src/main/java/com/tencent/cloud/plugin/faulttolerance/annotation/FaultTolerance.java
create mode 100644 spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-fault-tolerance/src/main/java/com/tencent/cloud/plugin/faulttolerance/common/FallbackMethod.java
create mode 100644 spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-fault-tolerance/src/main/java/com/tencent/cloud/plugin/faulttolerance/config/FaultToleranceAutoConfiguration.java
create mode 100644 spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-fault-tolerance/src/main/java/com/tencent/cloud/plugin/faulttolerance/instrument/FaultToleranceAspect.java
create mode 100644 spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-fault-tolerance/src/main/java/com/tencent/cloud/plugin/faulttolerance/model/FaultToleranceStrategy.java
create mode 100644 spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-fault-tolerance/src/main/java/org/springframework/cloud/tsf/faulttolerance/annotation/EnableTsfFaultTolerance.java
create mode 100644 spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-fault-tolerance/src/main/java/org/springframework/cloud/tsf/faulttolerance/annotation/TsfFaultTolerance.java
create mode 100644 spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-fault-tolerance/src/main/java/org/springframework/cloud/tsf/faulttolerance/annotation/TsfFaultToleranceProperty.java
create mode 100644 spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-fault-tolerance/src/main/java/org/springframework/cloud/tsf/faulttolerance/model/TsfFaultToleranceStragety.java
create mode 100644 spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-fault-tolerance/src/main/resources/META-INF/spring.factories
create mode 100644 spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-fault-tolerance/src/test/java/com/tencent/cloud/plugin/faulttolerance/integration/FaultToleranceService.java
create mode 100644 spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-fault-tolerance/src/test/java/com/tencent/cloud/plugin/faulttolerance/integration/FaultToleranceTest.java
create mode 100644 spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-trace-plugin/src/main/java/com/tencent/tsf/monitor/annotation/EnableTsfMonitor.java
create mode 100644 spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-trace-plugin/src/main/java/com/tencent/tsf/sleuth/annotation/EnableTsfSleuth.java
create mode 100644 spring-cloud-tencent-plugin-starters/spring-cloud-tencent-security-protection-plugin/pom.xml
create mode 100644 spring-cloud-tencent-plugin-starters/spring-cloud-tencent-security-protection-plugin/src/main/java/com/tencent/cloud/plugin/protection/ExitUtils.java
create mode 100644 spring-cloud-tencent-plugin-starters/spring-cloud-tencent-security-protection-plugin/src/main/java/com/tencent/cloud/plugin/protection/SecurityProtectionAutoConfiguration.java
create mode 100644 spring-cloud-tencent-plugin-starters/spring-cloud-tencent-security-protection-plugin/src/main/resources/META-INF/spring.factories
create mode 100644 spring-cloud-tencent-plugin-starters/spring-cloud-tencent-security-protection-plugin/src/test/java/com/tencent/cloud/plugin/protection/SecurityProtectionAutoConfigurationTest.java
create mode 100644 spring-cloud-tencent-polaris-context/src/main/java/com/tencent/cloud/polaris/context/listener/FailedEventApplicationListener.java
create mode 100644 spring-cloud-tencent-polaris-context/src/test/java/com/tencent/cloud/polaris/context/listener/FailedEventApplicationListenerTest.java
rename spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/{ => instrument}/feign/EnhancedFeignBeanPostProcessor.java (98%)
rename spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/{ => instrument}/feign/EnhancedFeignBlockingLoadBalancerClient.java (95%)
rename spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/{ => instrument}/feign/EnhancedFeignClient.java (99%)
rename spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/{ => instrument}/filter/EnhancedReactiveFilter.java (98%)
rename spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/{ => instrument}/filter/EnhancedServletFilter.java (98%)
rename spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/{ => instrument}/resttemplate/EnhancedRestTemplateWrapInterceptor.java (96%)
rename spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/{ => instrument}/resttemplate/PolarisLoadBalancerRequestTransformer.java (96%)
rename spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/{ => instrument}/scg/EnhancedGatewayGlobalFilter.java (97%)
rename spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/{ => instrument}/webclient/EnhancedWebClientExchangeFilterFunction.java (69%)
rename spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/{ => instrument}/webclient/PolarisLoadBalancerClientRequestTransformer.java (88%)
rename spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/{ => instrument}/webclient/RibbonLoadBalancerClientAspect.java (88%)
rename spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/{ => instrument}/zuul/EnhancedErrorZuulFilter.java (98%)
rename spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/{ => instrument}/zuul/EnhancedPostZuulFilter.java (98%)
rename spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/{ => instrument}/zuul/EnhancedRouteZuulFilter.java (98%)
rename spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/{ => instrument}/zuul/EnhancedZuulPluginRunner.java (98%)
rename spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/{ => instrument}/feign/EnhancedFeignBeanPostProcessorTest.java (98%)
rename spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/{ => instrument}/feign/EnhancedFeignClientTest.java (99%)
rename spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/{ => instrument}/resttemplate/PolarisLoadBalancerRequestTransformerTest.java (90%)
rename spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/{ => instrument}/scg/EnhancedGatewayGlobalFilterTest.java (98%)
rename spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/{ => instrument}/webclient/EnhancedWebClientExchangeFilterFunctionTest.java (96%)
rename spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/{ => instrument}/webclient/PolarisLoadBalancerClientRequestTransformerTest.java (91%)
create mode 100644 spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/plugin/DefaultEnhancedPluginRunnerTest.java
diff --git a/CHANGELOG.md b/CHANGELOG.md
index fbf9c68e8..f5e94ea57 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -25,3 +25,4 @@
- [docs:update circuit breaker examples.](https://github.com/Tencent/spring-cloud-tencent/pull/1521)
- [feat:support zuul circuit breaker fallback response.](https://github.com/Tencent/spring-cloud-tencent/pull/1522)
- [feat:support auth.](https://github.com/Tencent/spring-cloud-tencent/pull/1541)
+- [feat:support smooth upgrade from tsf. ](https://github.com/Tencent/spring-cloud-tencent/pull/1542)
diff --git a/spring-cloud-starter-tencent-all/pom.xml b/spring-cloud-starter-tencent-all/pom.xml
index a2a5e53f0..31c46e67a 100644
--- a/spring-cloud-starter-tencent-all/pom.xml
+++ b/spring-cloud-starter-tencent-all/pom.xml
@@ -59,6 +59,17 @@
com.tencent.cloud
spring-cloud-starter-tencent-polaris-auth
+
+
+ com.tencent.cloud
+ spring-cloud-starter-tencent-fault-tolerance
+
+
+ org.springframework.boot
+ spring-boot-starter-logging
+
+
+
diff --git a/spring-cloud-starter-tencent-metadata-transfer/pom.xml b/spring-cloud-starter-tencent-metadata-transfer/pom.xml
index 35b783daa..34658ad47 100644
--- a/spring-cloud-starter-tencent-metadata-transfer/pom.xml
+++ b/spring-cloud-starter-tencent-metadata-transfer/pom.xml
@@ -15,11 +15,6 @@
-
- com.tencent.cloud
- spring-cloud-tencent-commons
-
-
com.tencent.cloud
spring-cloud-tencent-rpc-enhancement
diff --git a/spring-cloud-starter-tencent-metadata-transfer/src/test/java/com/tencent/cloud/metadata/core/EncodeTransferMedataScgFilterTest.java b/spring-cloud-starter-tencent-metadata-transfer/src/test/java/com/tencent/cloud/metadata/core/EncodeTransferMedataScgFilterTest.java
index f0c1eb8d0..6941dfc34 100644
--- a/spring-cloud-starter-tencent-metadata-transfer/src/test/java/com/tencent/cloud/metadata/core/EncodeTransferMedataScgFilterTest.java
+++ b/spring-cloud-starter-tencent-metadata-transfer/src/test/java/com/tencent/cloud/metadata/core/EncodeTransferMedataScgFilterTest.java
@@ -27,8 +27,8 @@ 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 com.tencent.cloud.rpc.enhancement.instrument.scg.EnhancedGatewayGlobalFilter;
import com.tencent.cloud.rpc.enhancement.plugin.DefaultEnhancedPluginRunner;
-import com.tencent.cloud.rpc.enhancement.scg.EnhancedGatewayGlobalFilter;
import org.assertj.core.util.Maps;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
diff --git a/spring-cloud-starter-tencent-polaris-auth/src/main/java/org/springframework/tsf/auth/annotation/EnableTsfAuth.java b/spring-cloud-starter-tencent-polaris-auth/src/main/java/org/springframework/tsf/auth/annotation/EnableTsfAuth.java
new file mode 100644
index 000000000..03983dd7a
--- /dev/null
+++ b/spring-cloud-starter-tencent-polaris-auth/src/main/java/org/springframework/tsf/auth/annotation/EnableTsfAuth.java
@@ -0,0 +1,42 @@
+/*
+ * Tencent is pleased to support the open source community by making spring-cloud-tencent available.
+ *
+ * Copyright (C) 2021 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 org.springframework.tsf.auth.annotation;
+
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Empty annotation. Compatible with old versions TSF SDK.
+ *
+ * Deprecated since 2.0.0.0.
+ *
+ * @author Haotian Zhang
+ */
+@Deprecated
+@Target(ElementType.TYPE)
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+@Inherited
+public @interface EnableTsfAuth {
+
+}
diff --git a/spring-cloud-starter-tencent-polaris-auth/src/main/resources/META-INF/spring.factories b/spring-cloud-starter-tencent-polaris-auth/src/main/resources/META-INF/spring.factories
index 7cb82fb0c..e1df3dff9 100644
--- a/spring-cloud-starter-tencent-polaris-auth/src/main/resources/META-INF/spring.factories
+++ b/spring-cloud-starter-tencent-polaris-auth/src/main/resources/META-INF/spring.factories
@@ -1,2 +1,5 @@
+org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
+ com.tencent.cloud.polaris.auth.config.PolarisAuthPropertiesAutoConfiguration,\
+ com.tencent.cloud.polaris.auth.config.PolarisAuthAutoConfiguration
org.springframework.cloud.bootstrap.BootstrapConfiguration=\
com.tencent.cloud.polaris.auth.config.PolarisAuthPropertiesBootstrapConfiguration
diff --git a/spring-cloud-starter-tencent-polaris-auth/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/spring-cloud-starter-tencent-polaris-auth/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
deleted file mode 100644
index 5c6ccbddf..000000000
--- a/spring-cloud-starter-tencent-polaris-auth/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
+++ /dev/null
@@ -1,2 +0,0 @@
-com.tencent.cloud.polaris.auth.config.PolarisAuthPropertiesAutoConfiguration
-com.tencent.cloud.polaris.auth.config.PolarisAuthAutoConfiguration
diff --git a/spring-cloud-starter-tencent-polaris-auth/src/test/java/com/tencent/cloud/polaris/auth/config/PolarisAuthPropertiesTest.java b/spring-cloud-starter-tencent-polaris-auth/src/test/java/com/tencent/cloud/polaris/auth/config/PolarisAuthPropertiesTest.java
new file mode 100644
index 000000000..9c7493f40
--- /dev/null
+++ b/spring-cloud-starter-tencent-polaris-auth/src/test/java/com/tencent/cloud/polaris/auth/config/PolarisAuthPropertiesTest.java
@@ -0,0 +1,45 @@
+/*
+ * Tencent is pleased to support the open source community by making spring-cloud-tencent available.
+ *
+ * Copyright (C) 2021 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.polaris.auth.config;
+
+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;
+
+/**
+ * Test for {@link PolarisAuthProperties}.
+ *
+ * @author Haotian Zhang
+ */
+public class PolarisAuthPropertiesTest {
+
+ private final ApplicationContextRunner applicationContextRunner = new ApplicationContextRunner()
+ .withConfiguration(AutoConfigurations.of(PolarisAuthPropertiesAutoConfiguration.class))
+ .withPropertyValues("spring.cloud.polaris.auth.enabled=false");
+
+ @Test
+ public void testGetAndSet() {
+ this.applicationContextRunner.run(context -> {
+ PolarisAuthProperties properties = context.getBean(PolarisAuthProperties.class);
+ assertThat(properties.isEnabled()).isFalse();
+ });
+ }
+}
diff --git a/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/config/PolarisCircuitBreakerFeignClientAutoConfiguration.java b/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/config/PolarisCircuitBreakerFeignClientAutoConfiguration.java
index 896d2fd87..cd3a43a87 100644
--- a/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/config/PolarisCircuitBreakerFeignClientAutoConfiguration.java
+++ b/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/config/PolarisCircuitBreakerFeignClientAutoConfiguration.java
@@ -17,8 +17,8 @@
package com.tencent.cloud.polaris.circuitbreaker.config;
-import com.tencent.cloud.polaris.circuitbreaker.feign.PolarisCircuitBreakerNameResolver;
-import com.tencent.cloud.polaris.circuitbreaker.feign.PolarisFeignCircuitBreaker;
+import com.tencent.cloud.polaris.circuitbreaker.instrument.feign.PolarisCircuitBreakerNameResolver;
+import com.tencent.cloud.polaris.circuitbreaker.instrument.feign.PolarisFeignCircuitBreaker;
import feign.Feign;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
diff --git a/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/feign/PolarisCircuitBreakerFallbackFactory.java b/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/instrument/feign/PolarisCircuitBreakerFallbackFactory.java
similarity index 97%
rename from spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/feign/PolarisCircuitBreakerFallbackFactory.java
rename to spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/instrument/feign/PolarisCircuitBreakerFallbackFactory.java
index 648ffd841..4429fcabc 100644
--- a/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/feign/PolarisCircuitBreakerFallbackFactory.java
+++ b/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/instrument/feign/PolarisCircuitBreakerFallbackFactory.java
@@ -15,7 +15,7 @@
* specific language governing permissions and limitations under the License.
*/
-package com.tencent.cloud.polaris.circuitbreaker.feign;
+package com.tencent.cloud.polaris.circuitbreaker.instrument.feign;
import java.io.IOException;
import java.lang.reflect.Method;
diff --git a/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/feign/PolarisCircuitBreakerNameResolver.java b/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/instrument/feign/PolarisCircuitBreakerNameResolver.java
similarity index 97%
rename from spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/feign/PolarisCircuitBreakerNameResolver.java
rename to spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/instrument/feign/PolarisCircuitBreakerNameResolver.java
index e238ffaf6..9ad08a50c 100644
--- a/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/feign/PolarisCircuitBreakerNameResolver.java
+++ b/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/instrument/feign/PolarisCircuitBreakerNameResolver.java
@@ -15,7 +15,7 @@
* specific language governing permissions and limitations under the License.
*/
-package com.tencent.cloud.polaris.circuitbreaker.feign;
+package com.tencent.cloud.polaris.circuitbreaker.instrument.feign;
import java.lang.reflect.Method;
import java.net.URI;
diff --git a/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/feign/PolarisFeignCircuitBreaker.java b/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/instrument/feign/PolarisFeignCircuitBreaker.java
similarity index 97%
rename from spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/feign/PolarisFeignCircuitBreaker.java
rename to spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/instrument/feign/PolarisFeignCircuitBreaker.java
index 4044430c4..8a5d8845a 100644
--- a/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/feign/PolarisFeignCircuitBreaker.java
+++ b/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/instrument/feign/PolarisFeignCircuitBreaker.java
@@ -15,7 +15,7 @@
* specific language governing permissions and limitations under the License.
*/
-package com.tencent.cloud.polaris.circuitbreaker.feign;
+package com.tencent.cloud.polaris.circuitbreaker.instrument.feign;
import java.lang.reflect.Field;
diff --git a/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/feign/PolarisFeignCircuitBreakerInvocationHandler.java b/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/instrument/feign/PolarisFeignCircuitBreakerInvocationHandler.java
similarity index 98%
rename from spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/feign/PolarisFeignCircuitBreakerInvocationHandler.java
rename to spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/instrument/feign/PolarisFeignCircuitBreakerInvocationHandler.java
index 24e26f7df..207fcefeb 100644
--- a/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/feign/PolarisFeignCircuitBreakerInvocationHandler.java
+++ b/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/instrument/feign/PolarisFeignCircuitBreakerInvocationHandler.java
@@ -15,7 +15,7 @@
* specific language governing permissions and limitations under the License.
*/
-package com.tencent.cloud.polaris.circuitbreaker.feign;
+package com.tencent.cloud.polaris.circuitbreaker.instrument.feign;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
diff --git a/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/reactor/PolarisCircuitBreakerFluxOperator.java b/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/instrument/reactor/PolarisCircuitBreakerFluxOperator.java
similarity index 96%
rename from spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/reactor/PolarisCircuitBreakerFluxOperator.java
rename to spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/instrument/reactor/PolarisCircuitBreakerFluxOperator.java
index 0b0daca50..0d760c7ac 100644
--- a/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/reactor/PolarisCircuitBreakerFluxOperator.java
+++ b/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/instrument/reactor/PolarisCircuitBreakerFluxOperator.java
@@ -15,7 +15,7 @@
* specific language governing permissions and limitations under the License.
*/
-package com.tencent.cloud.polaris.circuitbreaker.reactor;
+package com.tencent.cloud.polaris.circuitbreaker.instrument.reactor;
import com.tencent.polaris.circuitbreak.api.InvokeHandler;
import com.tencent.polaris.circuitbreak.client.exception.CallAbortedException;
diff --git a/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/reactor/PolarisCircuitBreakerMonoOperator.java b/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/instrument/reactor/PolarisCircuitBreakerMonoOperator.java
similarity index 96%
rename from spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/reactor/PolarisCircuitBreakerMonoOperator.java
rename to spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/instrument/reactor/PolarisCircuitBreakerMonoOperator.java
index 8b478b81c..129f49e79 100644
--- a/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/reactor/PolarisCircuitBreakerMonoOperator.java
+++ b/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/instrument/reactor/PolarisCircuitBreakerMonoOperator.java
@@ -15,7 +15,7 @@
* specific language governing permissions and limitations under the License.
*/
-package com.tencent.cloud.polaris.circuitbreaker.reactor;
+package com.tencent.cloud.polaris.circuitbreaker.instrument.reactor;
import com.tencent.polaris.circuitbreak.api.InvokeHandler;
import com.tencent.polaris.circuitbreak.client.exception.CallAbortedException;
diff --git a/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/reactor/PolarisCircuitBreakerReactorSubscriber.java b/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/instrument/reactor/PolarisCircuitBreakerReactorSubscriber.java
similarity index 98%
rename from spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/reactor/PolarisCircuitBreakerReactorSubscriber.java
rename to spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/instrument/reactor/PolarisCircuitBreakerReactorSubscriber.java
index 20fdc4f3e..ea876250d 100644
--- a/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/reactor/PolarisCircuitBreakerReactorSubscriber.java
+++ b/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/instrument/reactor/PolarisCircuitBreakerReactorSubscriber.java
@@ -15,7 +15,7 @@
* specific language governing permissions and limitations under the License.
*/
-package com.tencent.cloud.polaris.circuitbreaker.reactor;
+package com.tencent.cloud.polaris.circuitbreaker.instrument.reactor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
diff --git a/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/reactor/PolarisCircuitBreakerReactorTransformer.java b/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/instrument/reactor/PolarisCircuitBreakerReactorTransformer.java
similarity index 96%
rename from spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/reactor/PolarisCircuitBreakerReactorTransformer.java
rename to spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/instrument/reactor/PolarisCircuitBreakerReactorTransformer.java
index 9814d1d06..0a40e2b01 100644
--- a/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/reactor/PolarisCircuitBreakerReactorTransformer.java
+++ b/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/instrument/reactor/PolarisCircuitBreakerReactorTransformer.java
@@ -15,7 +15,7 @@
* specific language governing permissions and limitations under the License.
*/
-package com.tencent.cloud.polaris.circuitbreaker.reactor;
+package com.tencent.cloud.polaris.circuitbreaker.instrument.reactor;
import java.util.function.Function;
diff --git a/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/resttemplate/PolarisCircuitBreaker.java b/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/instrument/resttemplate/PolarisCircuitBreaker.java
similarity index 94%
rename from spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/resttemplate/PolarisCircuitBreaker.java
rename to spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/instrument/resttemplate/PolarisCircuitBreaker.java
index a6636fb68..8d90f553b 100644
--- a/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/resttemplate/PolarisCircuitBreaker.java
+++ b/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/instrument/resttemplate/PolarisCircuitBreaker.java
@@ -15,7 +15,7 @@
* specific language governing permissions and limitations under the License.
*/
-package com.tencent.cloud.polaris.circuitbreaker.resttemplate;
+package com.tencent.cloud.polaris.circuitbreaker.instrument.resttemplate;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
@@ -28,12 +28,15 @@ import java.lang.annotation.Target;
* if coded fallback or fallbackClass provided, RestTemplate will always return fallback when any exception occurs,
* if none coded fallback or fallbackClass provided, RestTemplate will return fallback response from Polaris server when fallback occurs.
* fallback and fallbackClass cannot provide at same time.
+ *
+ * Deprecated since 2.0.0.0.
*
* @author sean yu
*/
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
+@Deprecated
public @interface PolarisCircuitBreaker {
/**
diff --git a/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/resttemplate/PolarisCircuitBreakerFallback.java b/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/instrument/resttemplate/PolarisCircuitBreakerFallback.java
similarity index 88%
rename from spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/resttemplate/PolarisCircuitBreakerFallback.java
rename to spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/instrument/resttemplate/PolarisCircuitBreakerFallback.java
index ccbc3073b..737ae851a 100644
--- a/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/resttemplate/PolarisCircuitBreakerFallback.java
+++ b/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/instrument/resttemplate/PolarisCircuitBreakerFallback.java
@@ -15,13 +15,16 @@
* specific language governing permissions and limitations under the License.
*/
-package com.tencent.cloud.polaris.circuitbreaker.resttemplate;
+package com.tencent.cloud.polaris.circuitbreaker.instrument.resttemplate;
/**
* PolarisCircuitBreakerFallback.
+ *
+ * Deprecated since 2.0.0.0.
*
* @author sean yu
*/
+@Deprecated
public interface PolarisCircuitBreakerFallback {
PolarisCircuitBreakerHttpResponse fallback();
diff --git a/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/resttemplate/PolarisCircuitBreakerHttpResponse.java b/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/instrument/resttemplate/PolarisCircuitBreakerHttpResponse.java
similarity index 97%
rename from spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/resttemplate/PolarisCircuitBreakerHttpResponse.java
rename to spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/instrument/resttemplate/PolarisCircuitBreakerHttpResponse.java
index d43304770..84ad93a16 100644
--- a/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/resttemplate/PolarisCircuitBreakerHttpResponse.java
+++ b/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/instrument/resttemplate/PolarisCircuitBreakerHttpResponse.java
@@ -15,7 +15,7 @@
* specific language governing permissions and limitations under the License.
*/
-package com.tencent.cloud.polaris.circuitbreaker.resttemplate;
+package com.tencent.cloud.polaris.circuitbreaker.instrument.resttemplate;
import java.io.ByteArrayInputStream;
import java.io.IOException;
diff --git a/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/reporter/CircuitBreakerPlugin.java b/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/reporter/CircuitBreakerPlugin.java
index 07655acbc..092b3684c 100644
--- a/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/reporter/CircuitBreakerPlugin.java
+++ b/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/reporter/CircuitBreakerPlugin.java
@@ -21,7 +21,7 @@ import com.tencent.cloud.common.constant.ContextConstant;
import com.tencent.cloud.common.metadata.MetadataContext;
import com.tencent.cloud.common.metadata.MetadataContextHolder;
import com.tencent.cloud.polaris.circuitbreaker.PolarisCircuitBreaker;
-import com.tencent.cloud.polaris.circuitbreaker.resttemplate.PolarisCircuitBreakerHttpResponse;
+import com.tencent.cloud.polaris.circuitbreaker.instrument.resttemplate.PolarisCircuitBreakerHttpResponse;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPlugin;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginContext;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType;
diff --git a/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/org/springframework/cloud/openfeign/PolarisFeignCircuitBreakerTargeter.java b/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/org/springframework/cloud/openfeign/PolarisFeignCircuitBreakerTargeter.java
index 0d94fe973..1da37f4f0 100644
--- a/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/org/springframework/cloud/openfeign/PolarisFeignCircuitBreakerTargeter.java
+++ b/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/org/springframework/cloud/openfeign/PolarisFeignCircuitBreakerTargeter.java
@@ -17,7 +17,7 @@
package org.springframework.cloud.openfeign;
-import com.tencent.cloud.polaris.circuitbreaker.feign.PolarisFeignCircuitBreaker;
+import com.tencent.cloud.polaris.circuitbreaker.instrument.feign.PolarisFeignCircuitBreaker;
import feign.Feign;
import feign.Target;
diff --git a/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/org/springframework/cloud/tsf/circuitbreaker/annotation/EnableTsfCircuitBreaker.java b/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/org/springframework/cloud/tsf/circuitbreaker/annotation/EnableTsfCircuitBreaker.java
new file mode 100644
index 000000000..3c546ca61
--- /dev/null
+++ b/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/org/springframework/cloud/tsf/circuitbreaker/annotation/EnableTsfCircuitBreaker.java
@@ -0,0 +1,40 @@
+/*
+ * Tencent is pleased to support the open source community by making spring-cloud-tencent available.
+ *
+ * Copyright (C) 2021 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 org.springframework.cloud.tsf.circuitbreaker.annotation;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Empty annotation. Compatible with old versions TSF SDK.
+ *
+ * Deprecated since 2.0.0.0.
+ *
+ * @author Haotian Zhang
+ */
+@Deprecated
+@Target(ElementType.TYPE)
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+@Inherited
+public @interface EnableTsfCircuitBreaker {
+}
diff --git a/spring-cloud-starter-tencent-polaris-circuitbreaker/src/test/java/com/tencent/cloud/polaris/circuitbreaker/common/PolarisResultToErrorCodeTest.java b/spring-cloud-starter-tencent-polaris-circuitbreaker/src/test/java/com/tencent/cloud/polaris/circuitbreaker/common/PolarisResultToErrorCodeTest.java
new file mode 100644
index 000000000..6555e4882
--- /dev/null
+++ b/spring-cloud-starter-tencent-polaris-circuitbreaker/src/test/java/com/tencent/cloud/polaris/circuitbreaker/common/PolarisResultToErrorCodeTest.java
@@ -0,0 +1,95 @@
+/*
+ * Tencent is pleased to support the open source community by making spring-cloud-tencent available.
+ *
+ * Copyright (C) 2021 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.polaris.circuitbreaker.common;
+
+import java.lang.reflect.Method;
+
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+import org.springframework.web.reactive.function.client.WebClientResponseException;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * Test for ${@link PolarisResultToErrorCode}.
+ *
+ * @author Shedfree Wu
+ */
+@ExtendWith(MockitoExtension.class)
+class PolarisResultToErrorCodeTest {
+
+ private final PolarisResultToErrorCode converter = new PolarisResultToErrorCode();
+
+ @Test
+ void testOnSuccess() {
+ assertThat(converter.onSuccess("any value")).isEqualTo(200);
+ }
+
+ @Test
+ void testOnErrorWithWebClientResponseException() {
+ // Given
+ WebClientResponseException exception = WebClientResponseException.create(
+ 404, "Not Found", null, null, null);
+
+ // When
+ int errorCode = converter.onError(exception);
+
+ // Then
+ assertThat(errorCode).isEqualTo(404);
+ }
+
+ @Test
+ void testOnErrorWithCircuitBreakerStatusCodeException() {
+ // When
+ int errorCode = converter.onError(new RuntimeException("test"));
+
+ // Then
+ assertThat(errorCode).isEqualTo(-1);
+ }
+
+ @Test
+ void testOnErrorWithUnknownException() {
+ // Given
+ RuntimeException exception = new RuntimeException("Unknown error");
+
+ // When
+ int errorCode = converter.onError(exception);
+
+ // Then
+ assertThat(errorCode).isEqualTo(-1);
+ }
+
+ @Test
+ void testCheckClassExist() throws Exception {
+ // Given
+ Method checkClassExist = PolarisResultToErrorCode.class.getDeclaredMethod("checkClassExist", String.class);
+ checkClassExist.setAccessible(true);
+
+ PolarisResultToErrorCode converter = new PolarisResultToErrorCode();
+
+ // test exist class
+ boolean result1 = (boolean) checkClassExist.invoke(converter, "java.lang.String");
+ assertThat(result1).isTrue();
+
+ // test not exist class
+ boolean result2 = (boolean) checkClassExist.invoke(converter, "com.nonexistent.Class");
+ assertThat(result2).isFalse();
+ }
+}
diff --git a/spring-cloud-starter-tencent-polaris-circuitbreaker/src/test/java/com/tencent/cloud/polaris/circuitbreaker/config/PolarisCircuitBreakerAutoConfigurationTest.java b/spring-cloud-starter-tencent-polaris-circuitbreaker/src/test/java/com/tencent/cloud/polaris/circuitbreaker/config/PolarisCircuitBreakerAutoConfigurationTest.java
index 1c1f6529d..81c528acb 100644
--- a/spring-cloud-starter-tencent-polaris-circuitbreaker/src/test/java/com/tencent/cloud/polaris/circuitbreaker/config/PolarisCircuitBreakerAutoConfigurationTest.java
+++ b/spring-cloud-starter-tencent-polaris-circuitbreaker/src/test/java/com/tencent/cloud/polaris/circuitbreaker/config/PolarisCircuitBreakerAutoConfigurationTest.java
@@ -18,7 +18,7 @@
package com.tencent.cloud.polaris.circuitbreaker.config;
import com.tencent.cloud.polaris.circuitbreaker.common.CircuitBreakerConfigModifier;
-import com.tencent.cloud.polaris.circuitbreaker.feign.PolarisCircuitBreakerNameResolver;
+import com.tencent.cloud.polaris.circuitbreaker.instrument.feign.PolarisCircuitBreakerNameResolver;
import com.tencent.cloud.polaris.context.config.PolarisContextAutoConfiguration;
import com.tencent.cloud.rpc.enhancement.config.RpcEnhancementAutoConfiguration;
import org.junit.jupiter.api.Test;
diff --git a/spring-cloud-starter-tencent-polaris-circuitbreaker/src/test/java/com/tencent/cloud/polaris/circuitbreaker/feign/PolarisCircuitBreakerNameResolverTest.java b/spring-cloud-starter-tencent-polaris-circuitbreaker/src/test/java/com/tencent/cloud/polaris/circuitbreaker/instrument/feign/PolarisCircuitBreakerNameResolverTest.java
similarity index 98%
rename from spring-cloud-starter-tencent-polaris-circuitbreaker/src/test/java/com/tencent/cloud/polaris/circuitbreaker/feign/PolarisCircuitBreakerNameResolverTest.java
rename to spring-cloud-starter-tencent-polaris-circuitbreaker/src/test/java/com/tencent/cloud/polaris/circuitbreaker/instrument/feign/PolarisCircuitBreakerNameResolverTest.java
index 42fa1f2f6..86fccc9ea 100644
--- a/spring-cloud-starter-tencent-polaris-circuitbreaker/src/test/java/com/tencent/cloud/polaris/circuitbreaker/feign/PolarisCircuitBreakerNameResolverTest.java
+++ b/spring-cloud-starter-tencent-polaris-circuitbreaker/src/test/java/com/tencent/cloud/polaris/circuitbreaker/instrument/feign/PolarisCircuitBreakerNameResolverTest.java
@@ -15,7 +15,7 @@
* specific language governing permissions and limitations under the License.
*/
-package com.tencent.cloud.polaris.circuitbreaker.feign;
+package com.tencent.cloud.polaris.circuitbreaker.instrument.feign;
import java.lang.reflect.Method;
diff --git a/spring-cloud-starter-tencent-polaris-circuitbreaker/src/test/java/com/tencent/cloud/polaris/circuitbreaker/instrument/feign/PolarisFeignCircuitBreakerInvocationHandlerTest.java b/spring-cloud-starter-tencent-polaris-circuitbreaker/src/test/java/com/tencent/cloud/polaris/circuitbreaker/instrument/feign/PolarisFeignCircuitBreakerInvocationHandlerTest.java
new file mode 100644
index 000000000..2b142e802
--- /dev/null
+++ b/spring-cloud-starter-tencent-polaris-circuitbreaker/src/test/java/com/tencent/cloud/polaris/circuitbreaker/instrument/feign/PolarisFeignCircuitBreakerInvocationHandlerTest.java
@@ -0,0 +1,216 @@
+/*
+ * Tencent is pleased to support the open source community by making spring-cloud-tencent available.
+ *
+ * Copyright (C) 2021 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.polaris.circuitbreaker.instrument.feign;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.HashMap;
+import java.util.Map;
+
+import com.tencent.cloud.polaris.circuitbreaker.exception.FallbackWrapperException;
+import com.tencent.polaris.api.pojo.CircuitBreakerStatus;
+import com.tencent.polaris.circuitbreak.client.exception.CallAbortedException;
+import feign.InvocationHandlerFactory;
+import feign.Target;
+import feign.codec.Decoder;
+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.junit.jupiter.MockitoExtension;
+
+import org.springframework.cloud.openfeign.FallbackFactory;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+/**
+ * Test for ${@link PolarisFeignCircuitBreakerInvocationHandler}.
+ *
+ * @author Shedfree Wu
+ */
+@ExtendWith(MockitoExtension.class)
+class PolarisFeignCircuitBreakerInvocationHandlerTest {
+
+ @Mock
+ private Target> target;
+
+ @Mock
+ private InvocationHandlerFactory.MethodHandler methodHandler;
+
+ @Mock
+ private FallbackFactory fallbackFactory;
+
+ @Mock
+ private Decoder decoder;
+
+ private Map dispatch;
+ private PolarisFeignCircuitBreakerInvocationHandler handler;
+
+ private Method testMethod;
+
+ @BeforeEach
+ void setUp() throws Exception {
+ dispatch = new HashMap<>();
+
+ testMethod = TestInterface.class.getDeclaredMethod("testMethod");
+ dispatch.put(testMethod, methodHandler);
+
+ handler = new PolarisFeignCircuitBreakerInvocationHandler(
+ target,
+ dispatch,
+ fallbackFactory,
+ decoder
+ );
+ }
+
+ @Test
+ void testConstructorWithNullTarget() {
+ assertThatThrownBy(() ->
+ new PolarisFeignCircuitBreakerInvocationHandler(
+ null, dispatch, fallbackFactory, decoder
+ )
+ ).isInstanceOf(NullPointerException.class);
+
+ }
+
+ @Test
+ void testConstructorWithNullDispatch() {
+ assertThatThrownBy(() ->
+ new PolarisFeignCircuitBreakerInvocationHandler(
+ target, null, fallbackFactory, decoder
+ )).isInstanceOf(NullPointerException.class);
+ }
+
+ @Test
+ void testToFallbackMethod() throws Exception {
+ Method method = TestInterface.class.getMethod("testMethod");
+ Map testDispatch = new HashMap<>();
+ testDispatch.put(method, methodHandler);
+
+ Map result = PolarisFeignCircuitBreakerInvocationHandler.toFallbackMethod(testDispatch);
+
+ assertThat(result).isNotNull();
+ assertThat(result.containsKey(method)).isTrue();
+ assertThat(result.get(method)).isEqualTo(method);
+ }
+
+ @Test
+ void testEqualsMethod() throws Throwable {
+ Method equalsMethod = Object.class.getMethod("equals", Object.class);
+ Object mockProxy = mock(Object.class);
+
+ // Test equals with null
+ assertThat((Boolean) handler.invoke(mockProxy, equalsMethod, new Object[] {null})).isFalse();
+
+ // Test equals with non-proxy object
+ assertThat((Boolean) handler.invoke(mockProxy, equalsMethod, new Object[] {new Object()})).isFalse();
+ }
+
+ @Test
+ void testToStringMethod() throws Throwable {
+ Method toStringMethod = Object.class.getMethod("toString");
+ Object mockProxy = mock(Object.class);
+ when(target.toString()).thenReturn("TestTarget");
+
+ assertThat(handler.invoke(mockProxy, toStringMethod, null)).isEqualTo("TestTarget");
+ }
+
+ @Test
+ void testCustomFallbackFactoryWithFallbackError() throws Throwable {
+ // Arrange
+ handler = new PolarisFeignCircuitBreakerInvocationHandler(target, dispatch, fallbackFactory, decoder);
+ Exception originalException = new RuntimeException("Original error");
+
+ when(methodHandler.invoke(any())).thenThrow(originalException);
+ TestImpl testImpl = new TestImpl();
+ when(fallbackFactory.create(any())).thenReturn(testImpl);
+
+ // Act
+ assertThatThrownBy(() -> handler.invoke(null, testMethod, new Object[] {})).isInstanceOf(FallbackWrapperException.class);
+ }
+
+ @Test
+ void testCustomFallbackFactoryWithFallbackError2() throws Throwable {
+ // Arrange
+ handler = new PolarisFeignCircuitBreakerInvocationHandler(target, dispatch, fallbackFactory, decoder);
+ Exception originalException = new RuntimeException("Original error");
+
+ when(methodHandler.invoke(any())).thenThrow(originalException);
+ TestImpl2 testImpl = new TestImpl2();
+ when(fallbackFactory.create(any())).thenReturn(testImpl);
+
+ // Act
+ assertThatThrownBy(() -> handler.invoke(null, testMethod, new Object[] {})).
+ isInstanceOf(RuntimeException.class).hasMessage("test");
+ }
+
+ @Test
+ void testDefaultFallbackCreation() throws Throwable {
+ // Arrange
+ handler = new PolarisFeignCircuitBreakerInvocationHandler(target, dispatch, null, decoder);
+ CircuitBreakerStatus.FallbackInfo fallbackInfo = new CircuitBreakerStatus.FallbackInfo(200, new HashMap<>(), "mock body");
+ CallAbortedException originalException = new CallAbortedException("test rule", fallbackInfo);
+
+ Object expected = new Object();
+ when(methodHandler.invoke(any())).thenThrow(originalException);
+ when(decoder.decode(any(), any())).thenReturn(expected);
+
+ // Act
+ Object result = handler.invoke(null, testMethod, new Object[] {});
+
+ // Verify
+ assertThat(result).isEqualTo(expected);
+ }
+
+ @Test
+ void testEquals() {
+ PolarisFeignCircuitBreakerInvocationHandler testHandler = new PolarisFeignCircuitBreakerInvocationHandler(
+ target,
+ dispatch,
+ fallbackFactory,
+ decoder
+ );
+
+ assertThat(testHandler).isEqualTo(handler);
+ assertThat(testHandler.hashCode()).isEqualTo(handler.hashCode());
+ }
+
+ interface TestInterface {
+ String testMethod() throws InvocationTargetException;
+ }
+
+ static class TestImpl implements TestInterface {
+
+ @Override
+ public String testMethod() throws InvocationTargetException {
+ throw new InvocationTargetException(new RuntimeException("test"));
+ }
+ }
+
+ static class TestImpl2 implements TestInterface {
+
+ @Override
+ public String testMethod() throws InvocationTargetException {
+ throw new RuntimeException("test");
+ }
+ }
+}
diff --git a/spring-cloud-starter-tencent-polaris-circuitbreaker/src/test/java/com/tencent/cloud/polaris/circuitbreaker/feign/PolarisFeignCircuitBreakerTargeterTest.java b/spring-cloud-starter-tencent-polaris-circuitbreaker/src/test/java/com/tencent/cloud/polaris/circuitbreaker/instrument/feign/PolarisFeignCircuitBreakerTargeterTest.java
similarity index 98%
rename from spring-cloud-starter-tencent-polaris-circuitbreaker/src/test/java/com/tencent/cloud/polaris/circuitbreaker/feign/PolarisFeignCircuitBreakerTargeterTest.java
rename to spring-cloud-starter-tencent-polaris-circuitbreaker/src/test/java/com/tencent/cloud/polaris/circuitbreaker/instrument/feign/PolarisFeignCircuitBreakerTargeterTest.java
index 94ed5e849..9fa584a45 100644
--- a/spring-cloud-starter-tencent-polaris-circuitbreaker/src/test/java/com/tencent/cloud/polaris/circuitbreaker/feign/PolarisFeignCircuitBreakerTargeterTest.java
+++ b/spring-cloud-starter-tencent-polaris-circuitbreaker/src/test/java/com/tencent/cloud/polaris/circuitbreaker/instrument/feign/PolarisFeignCircuitBreakerTargeterTest.java
@@ -15,7 +15,7 @@
* specific language governing permissions and limitations under the License.
*/
-package com.tencent.cloud.polaris.circuitbreaker.feign;
+package com.tencent.cloud.polaris.circuitbreaker.instrument.feign;
import feign.Feign;
import feign.RequestLine;
diff --git a/spring-cloud-starter-tencent-polaris-circuitbreaker/src/test/java/com/tencent/cloud/polaris/circuitbreaker/instrument/feign/PolarisFeignCircuitBreakerTest.java b/spring-cloud-starter-tencent-polaris-circuitbreaker/src/test/java/com/tencent/cloud/polaris/circuitbreaker/instrument/feign/PolarisFeignCircuitBreakerTest.java
new file mode 100644
index 000000000..2805d9264
--- /dev/null
+++ b/spring-cloud-starter-tencent-polaris-circuitbreaker/src/test/java/com/tencent/cloud/polaris/circuitbreaker/instrument/feign/PolarisFeignCircuitBreakerTest.java
@@ -0,0 +1,133 @@
+/*
+ * Tencent is pleased to support the open source community by making spring-cloud-tencent available.
+ *
+ * Copyright (C) 2021 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.polaris.circuitbreaker.instrument.feign;
+
+import feign.Feign;
+import feign.RequestLine;
+import feign.Target;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import org.springframework.cloud.openfeign.FallbackFactory;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+
+/**
+ * Tests for {@link PolarisFeignCircuitBreaker}.
+ */
+public class PolarisFeignCircuitBreakerTest {
+
+ private PolarisFeignCircuitBreaker.Builder builder;
+
+ @BeforeEach
+ public void setUp() {
+ builder = PolarisFeignCircuitBreaker.builder();
+ }
+
+ @Test
+ public void testBuilderNotNull() {
+ assertThat(builder).isNotNull();
+ }
+
+ @Test
+ public void testTargetWithFallback() {
+ // Mock the target
+ Class targetType = MyService.class;
+ String name = "myService";
+ Target target = mock(Target.class);
+
+ // mock return value
+ when(target.type()).thenReturn(targetType);
+ when(target.name()).thenReturn(name);
+
+ // Mock the fallback
+ MyService fallback = mock(MyService.class);
+ when(fallback.sayHello()).thenReturn("Fallback Hello");
+
+ // Call the target method
+ MyService result = builder.target(target, fallback);
+
+ // Verify that the result is not null and the fallback factory is used
+ assertThat(result).isNotNull();
+ assertThat(result.sayHello()).isEqualTo("Fallback Hello");
+ }
+
+ @Test
+ public void testTargetWithFallbackFactory() {
+ // Mock the target and fallback factory
+ Class targetType = MyService.class;
+ String name = "myService";
+ Target target = mock(Target.class);
+
+ // mock return value
+ when(target.type()).thenReturn(targetType);
+ when(target.name()).thenReturn(name);
+
+ FallbackFactory fallbackFactory = mock(FallbackFactory.class);
+
+ // Mock the fallback from the factory
+ MyService fallback = mock(MyService.class);
+ when(fallback.sayHello()).thenReturn("Fallback Hello");
+ when(fallbackFactory.create(any())).thenReturn(fallback);
+
+ // Call the target method
+ MyService result = builder.target(target, fallbackFactory);
+
+ // Verify that the result is not null and the fallback factory is used
+ assertThat(result).isNotNull();
+ assertThat(result.sayHello()).isEqualTo("Fallback Hello");
+ }
+
+ @Test
+ public void testTargetWithoutFallback() {
+ // Mock the target
+ Class targetType = MyService.class;
+ String name = "myService";
+ Target target = mock(Target.class);
+
+ // mock return value
+ when(target.type()).thenReturn(targetType);
+ when(target.name()).thenReturn(name);
+
+ // Call the target method
+ MyService result = builder.target(target);
+
+ // Verify that the result is not null
+ assertThat(result).isNotNull();
+ // Additional verifications can be added here based on the implementation
+ }
+
+ @Test
+ public void testBuildWithNullableFallbackFactory() {
+ // Call the build method with a null fallback factory
+ Feign feign = builder.build(null);
+
+ // Verify that the Feign instance is not null
+ assertThat(feign).isNotNull();
+ // Additional verifications can be added here based on the implementation
+ }
+
+ public interface MyService {
+ @RequestLine("GET /hello")
+ String sayHello();
+ }
+}
diff --git a/spring-cloud-starter-tencent-polaris-config/src/test/java/com/tencent/cloud/polaris/config/adapter/PolarisRefreshEntireContextRefresherTest.java b/spring-cloud-starter-tencent-polaris-config/src/test/java/com/tencent/cloud/polaris/config/adapter/PolarisRefreshEntireContextRefresherTest.java
new file mode 100644
index 000000000..dc90f2e37
--- /dev/null
+++ b/spring-cloud-starter-tencent-polaris-config/src/test/java/com/tencent/cloud/polaris/config/adapter/PolarisRefreshEntireContextRefresherTest.java
@@ -0,0 +1,209 @@
+/*
+ * Tencent is pleased to support the open source community by making spring-cloud-tencent available.
+ *
+ * Copyright (C) 2021 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.polaris.config.adapter;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.HashSet;
+import java.util.Set;
+
+import com.tencent.cloud.polaris.config.config.PolarisConfigProperties;
+import com.tencent.cloud.polaris.config.spring.property.SpringValueRegistry;
+import com.tencent.polaris.configuration.api.core.ConfigFileService;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import org.springframework.cloud.context.environment.EnvironmentChangeEvent;
+import org.springframework.cloud.context.refresh.ContextRefresher;
+import org.springframework.context.ConfigurableApplicationContext;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoInteractions;
+import static org.mockito.Mockito.when;
+
+/**
+ * Tests for {@link PolarisRefreshEntireContextRefresher}.
+ *
+ * @author Shedfree Wu
+ */
+public class PolarisRefreshEntireContextRefresherTest {
+ @Mock
+ private PolarisConfigProperties polarisConfigProperties;
+
+ @Mock
+ private SpringValueRegistry springValueRegistry;
+
+ @Mock
+ private ConfigFileService configFileService;
+
+ @Mock
+ private ContextRefresher contextRefresher;
+
+ @Mock
+ private ConfigurableApplicationContext applicationContext;
+
+ @Mock
+ private PolarisConfigCustomExtensionLayer mockExtensionLayer;
+
+ private PolarisRefreshEntireContextRefresher refresher;
+
+ @BeforeEach
+ void setUp() {
+ MockitoAnnotations.openMocks(this);
+ refresher = new PolarisRefreshEntireContextRefresher(
+ polarisConfigProperties,
+ springValueRegistry,
+ configFileService,
+ contextRefresher
+ );
+ refresher.setApplicationContext(applicationContext);
+ }
+
+ @Test
+ void testRefreshSpringValue() {
+ // test refreshSpringValue method, it should do nothing
+ refresher.refreshSpringValue("test.key");
+
+ // Verify
+ verifyNoInteractions(contextRefresher);
+ verifyNoInteractions(springValueRegistry);
+ }
+
+ @Test
+ void testRefreshConfigurationPropertiesWithRefreshScope() {
+ // Arrange
+ Set changeKeys = new HashSet<>();
+ changeKeys.add("test.key1");
+ changeKeys.add("test.key2");
+
+ // mock test.key1 in refresh scope
+ when(springValueRegistry.isRefreshScopeKey("test.key1")).thenReturn(true);
+
+ // Act
+ refresher.refreshConfigurationProperties(changeKeys);
+
+ // Verify
+ verify(contextRefresher, times(1)).refresh();
+ verifyNoInteractions(applicationContext);
+ }
+
+ @Test
+ void testRefreshConfigurationPropertiesWithoutRefreshScope() {
+ // Arrange
+ Set changeKeys = new HashSet<>();
+ changeKeys.add("test.key1");
+ changeKeys.add("test.key2");
+
+ // mock a key not in refresh scope
+ when(springValueRegistry.isRefreshScopeKey(anyString())).thenReturn(false);
+
+ // Act
+ refresher.refreshConfigurationProperties(changeKeys);
+
+ // Verify
+ verify(contextRefresher, never()).refresh();
+ verify(applicationContext, times(1))
+ .publishEvent(any(EnvironmentChangeEvent.class));
+ }
+
+ @Test
+ void testSetApplicationContext() {
+ // Arrange
+ ConfigurableApplicationContext newContext = mock(ConfigurableApplicationContext.class);
+
+ // Act
+ refresher.setApplicationContext(newContext);
+
+ // Verify
+ Set changeKeys = new HashSet<>();
+ changeKeys.add("test.key");
+ when(springValueRegistry.isRefreshScopeKey(anyString())).thenReturn(false);
+
+ refresher.refreshConfigurationProperties(changeKeys);
+ verify(newContext, times(1)).publishEvent(any(EnvironmentChangeEvent.class));
+ }
+
+ @Test
+ void testRefreshConfigurationPropertiesWithEmptyChangeKeys() {
+ // Arrange
+ Set changeKeys = new HashSet<>();
+
+ // Act
+ refresher.refreshConfigurationProperties(changeKeys);
+
+ // Verify
+ verify(contextRefresher, never()).refresh();
+ verify(applicationContext, times(1))
+ .publishEvent(any(EnvironmentChangeEvent.class));
+ }
+
+ @Test
+ void testRefreshConfigurationPropertiesWithMultipleRefreshScopeKeys() {
+ // Arrange
+ Set changeKeys = new HashSet<>();
+ changeKeys.add("test.key1");
+ changeKeys.add("test.key2");
+ changeKeys.add("test.key3");
+
+ // mock multiple keys in refresh scope
+ when(springValueRegistry.isRefreshScopeKey(anyString())).thenReturn(true);
+
+ // Act
+ refresher.refreshConfigurationProperties(changeKeys);
+
+ // Verify
+ verify(contextRefresher, times(1)).refresh();
+ verifyNoInteractions(applicationContext);
+ }
+
+ @Test
+ void testPolarisConfigCustomExtensionLayer() throws Exception {
+ refresher.setRegistered(true);
+
+ Field field = PolarisConfigPropertyAutoRefresher.class
+ .getDeclaredField("polarisConfigCustomExtensionLayer");
+ field.setAccessible(true);
+ field.set(refresher, mockExtensionLayer);
+
+ Method method = PolarisConfigPropertyAutoRefresher.class
+ .getDeclaredMethod("customInitRegisterPolarisConfig", PolarisConfigPropertyAutoRefresher.class);
+ method.setAccessible(true);
+ method.invoke(refresher, refresher);
+
+
+ method = PolarisConfigPropertyAutoRefresher.class.getDeclaredMethod(
+ "customRegisterPolarisConfigPublishChangeListener",
+ PolarisPropertySource.class, PolarisPropertySource.class);
+
+ method.setAccessible(true);
+ method.invoke(refresher, null, null);
+
+ // Verify
+ verify(mockExtensionLayer, times(1)).initRegisterConfig(refresher);
+
+ }
+
+}
diff --git a/spring-cloud-starter-tencent-polaris-contract/src/main/java/com/tencent/cloud/polaris/contract/PolarisContractReporter.java b/spring-cloud-starter-tencent-polaris-contract/src/main/java/com/tencent/cloud/polaris/contract/PolarisContractReporter.java
index 5f1fb605b..66e2e01bb 100644
--- a/spring-cloud-starter-tencent-polaris-contract/src/main/java/com/tencent/cloud/polaris/contract/PolarisContractReporter.java
+++ b/spring-cloud-starter-tencent-polaris-contract/src/main/java/com/tencent/cloud/polaris/contract/PolarisContractReporter.java
@@ -25,6 +25,7 @@ import java.util.Map;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.ObjectMapper;
+import com.tencent.cloud.common.metadata.MetadataContext;
import com.tencent.cloud.common.util.GzipUtil;
import com.tencent.cloud.polaris.PolarisDiscoveryProperties;
import com.tencent.cloud.polaris.contract.config.PolarisContractProperties;
@@ -57,7 +58,7 @@ import org.springframework.util.CollectionUtils;
*/
public class PolarisContractReporter implements ApplicationListener {
- private final Logger LOG = LoggerFactory.getLogger(PolarisContractReporter.class);
+ private static final Logger LOG = LoggerFactory.getLogger(PolarisContractReporter.class);
private final org.springdoc.webmvc.api.MultipleOpenApiResource multipleOpenApiWebMvcResource;
private final org.springdoc.webflux.api.MultipleOpenApiResource multipleOpenApiWebFluxResource;
@@ -100,7 +101,7 @@ public class PolarisContractReporter implements ApplicationListener
com.tencent.cloud
spring-cloud-tencent-rpc-enhancement
+
+
+ spring-security-crypto
+ org.springframework.security
+
+
com.tencent.cloud
diff --git a/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/discovery/refresh/PolarisRefreshConfiguration.java b/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/discovery/refresh/PolarisRefreshConfiguration.java
index a0da4c1d5..793f0dd13 100644
--- a/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/discovery/refresh/PolarisRefreshConfiguration.java
+++ b/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/discovery/refresh/PolarisRefreshConfiguration.java
@@ -17,8 +17,8 @@
package com.tencent.cloud.polaris.discovery.refresh;
-import com.tencent.cloud.polaris.context.ConditionalOnPolarisEnabled;
import com.tencent.cloud.polaris.context.PolarisSDKContextManager;
+import com.tencent.cloud.polaris.discovery.ConditionalOnPolarisDiscoveryEnabled;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
@@ -30,13 +30,19 @@ import org.springframework.context.annotation.Configuration;
* @author Haotian Zhang
*/
@Configuration(proxyBeanMethods = false)
-@ConditionalOnPolarisEnabled
+@ConditionalOnPolarisDiscoveryEnabled
public class PolarisRefreshConfiguration {
@Bean
@ConditionalOnMissingBean
- public PolarisServiceStatusChangeListener polarisServiceChangeListener() {
- return new PolarisServiceStatusChangeListener();
+ public PolarisServiceStatusChangeListener polarisServiceChangeListener(ServiceInstanceChangeCallbackManager serviceInstanceChangeCallbackManager) {
+ return new PolarisServiceStatusChangeListener(serviceInstanceChangeCallbackManager);
+ }
+
+ @Bean
+ @ConditionalOnMissingBean
+ public ServiceInstanceChangeCallbackManager serviceInstanceChangeCallbackManager() {
+ return new ServiceInstanceChangeCallbackManager();
}
@Bean
diff --git a/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/discovery/refresh/PolarisServiceStatusChangeListener.java b/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/discovery/refresh/PolarisServiceStatusChangeListener.java
index 65efbb77e..bf4a829db 100644
--- a/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/discovery/refresh/PolarisServiceStatusChangeListener.java
+++ b/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/discovery/refresh/PolarisServiceStatusChangeListener.java
@@ -17,14 +17,18 @@
package com.tencent.cloud.polaris.discovery.refresh;
+import java.util.ArrayList;
+import java.util.List;
import java.util.Set;
import java.util.concurrent.atomic.AtomicLong;
import java.util.stream.Collectors;
import com.google.common.collect.Sets;
import com.tencent.polaris.api.plugin.registry.AbstractResourceEventListener;
+import com.tencent.polaris.api.pojo.Instance;
import com.tencent.polaris.api.pojo.RegistryCacheValue;
import com.tencent.polaris.api.pojo.ServiceEventKey;
+import com.tencent.polaris.api.utils.CollectionUtils;
import com.tencent.polaris.client.pojo.ServiceInstancesByProto;
import com.tencent.polaris.client.pojo.ServicesByProto;
import org.slf4j.Logger;
@@ -34,7 +38,6 @@ import org.springframework.cloud.client.discovery.event.HeartbeatEvent;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.lang.NonNull;
-import org.springframework.util.CollectionUtils;
/**
* Change listener of Polaris service info. When service info is created or deleted, or, instance of service is from
@@ -42,7 +45,8 @@ import org.springframework.util.CollectionUtils;
*
* @author Haotian Zhang
*/
-public class PolarisServiceStatusChangeListener extends AbstractResourceEventListener implements ApplicationEventPublisherAware {
+public class PolarisServiceStatusChangeListener extends AbstractResourceEventListener
+ implements ApplicationEventPublisherAware {
/**
* Index of service info status.
@@ -50,9 +54,13 @@ public class PolarisServiceStatusChangeListener extends AbstractResourceEventLis
public static final AtomicLong INDEX = new AtomicLong(0);
private static final Logger LOG = LoggerFactory.getLogger(PolarisServiceStatusChangeListener.class);
-
+ private final ServiceInstanceChangeCallbackManager serviceInstanceChangeCallbackManager;
private ApplicationEventPublisher publisher;
+ public PolarisServiceStatusChangeListener(ServiceInstanceChangeCallbackManager serviceInstanceChangeCallbackManager) {
+ this.serviceInstanceChangeCallbackManager = serviceInstanceChangeCallbackManager;
+ }
+
@Override
public void onResourceUpdated(ServiceEventKey svcEventKey, RegistryCacheValue oldValue,
RegistryCacheValue newValue) {
@@ -88,6 +96,22 @@ public class PolarisServiceStatusChangeListener extends AbstractResourceEventLis
// Trigger reload of gateway route cache.
this.publisher.publishEvent(new HeartbeatEvent(this, INDEX.getAndIncrement()));
}
+
+ List oldInstances = new ArrayList<>();
+ List newInstances = new ArrayList<>();
+ if (CollectionUtils.isNotEmpty(oldIns.getInstances())) {
+ oldInstances.addAll(oldIns.getInstances());
+ }
+ if (CollectionUtils.isNotEmpty(newIns.getInstances())) {
+ newInstances.addAll(newIns.getInstances());
+ }
+
+ try {
+ this.serviceInstanceChangeCallbackManager.handle(svcEventKey.getService(), oldInstances, newInstances);
+ }
+ catch (Throwable throwable) {
+ LOG.error("Service[{}] instance status change callback failed.", svcEventKey.getService(), throwable);
+ }
}
}
}
diff --git a/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/discovery/refresh/ServiceInstanceChangeCallback.java b/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/discovery/refresh/ServiceInstanceChangeCallback.java
new file mode 100644
index 000000000..5be96585b
--- /dev/null
+++ b/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/discovery/refresh/ServiceInstanceChangeCallback.java
@@ -0,0 +1,32 @@
+/*
+ * Tencent is pleased to support the open source community by making spring-cloud-tencent available.
+ *
+ * Copyright (C) 2021 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.polaris.discovery.refresh;
+
+import java.util.List;
+
+import com.tencent.polaris.api.pojo.Instance;
+
+/**
+ * Callback for service instance change.
+ *
+ * @author Haotian Zhang
+ */
+public interface ServiceInstanceChangeCallback {
+
+ void callback(List currentServiceInstances, List addServiceInstances, List deleteServiceInstances);
+}
diff --git a/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/discovery/refresh/ServiceInstanceChangeCallbackManager.java b/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/discovery/refresh/ServiceInstanceChangeCallbackManager.java
new file mode 100644
index 000000000..0199b2a42
--- /dev/null
+++ b/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/discovery/refresh/ServiceInstanceChangeCallbackManager.java
@@ -0,0 +1,145 @@
+/*
+ * Tencent is pleased to support the open source community by making spring-cloud-tencent available.
+ *
+ * Copyright (C) 2021 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.polaris.discovery.refresh;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ScheduledThreadPoolExecutor;
+
+import com.tencent.cloud.common.util.ApplicationContextAwareUtils;
+import com.tencent.cloud.polaris.discovery.PolarisDiscoveryClient;
+import com.tencent.cloud.polaris.discovery.reactive.PolarisReactiveDiscoveryClient;
+import com.tencent.polaris.api.pojo.Instance;
+import com.tencent.polaris.api.utils.StringUtils;
+import com.tencent.polaris.client.util.NamedThreadFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import reactor.util.annotation.NonNull;
+
+import org.springframework.beans.factory.config.BeanPostProcessor;
+import org.springframework.boot.context.event.ApplicationReadyEvent;
+import org.springframework.context.ApplicationListener;
+import org.springframework.util.CollectionUtils;
+
+/**
+ * Call back manager for service instance change.
+ *
+ * @author Haotian Zhang
+ */
+public class ServiceInstanceChangeCallbackManager implements ApplicationListener, BeanPostProcessor {
+
+ private static final Logger LOG = LoggerFactory.getLogger(ServiceInstanceChangeCallbackManager.class);
+
+ private final ConcurrentHashMap> callbackMap = new ConcurrentHashMap<>();
+
+ private final ScheduledThreadPoolExecutor serviceChangeListenerExecutor;
+
+ public ServiceInstanceChangeCallbackManager() {
+ this.serviceChangeListenerExecutor = new ScheduledThreadPoolExecutor(4, new NamedThreadFactory("service-change-listener"));
+ }
+
+ public void handle(String serviceName, List oldInstances, List newInstances) {
+
+ List addInstances = new ArrayList<>();
+ List deleteInstances = new ArrayList<>();
+
+ // calculate add instances.
+ for (Instance instance : newInstances) {
+ if (!oldInstances.contains(instance)) {
+ addInstances.add(instance);
+ }
+ }
+ // calculate delete instances.
+ for (Instance instance : oldInstances) {
+ if (!newInstances.contains(instance)) {
+ deleteInstances.add(instance);
+ }
+ }
+
+ if ((!CollectionUtils.isEmpty(addInstances) || !CollectionUtils.isEmpty(deleteInstances))
+ && callbackMap.containsKey(serviceName)) {
+ List callbacks = callbackMap.get(serviceName);
+
+ for (ServiceInstanceChangeCallback callback : callbacks) {
+ serviceChangeListenerExecutor.execute(() -> {
+ try {
+ callback.callback(newInstances, addInstances, deleteInstances);
+ }
+ catch (Exception e) {
+ LOG.error("exception in callback, service name:{}, ", serviceName, e);
+ }
+ });
+ }
+ }
+ }
+
+ @Override
+ public synchronized Object postProcessAfterInitialization(Object bean, String beanName) {
+ Class> clz = bean.getClass();
+
+ if (!ServiceInstanceChangeCallback.class.isAssignableFrom(clz)) {
+ return bean;
+ }
+
+ String serviceName = null;
+ if (clz.isAnnotationPresent(ServiceInstanceChangeListener.class)) {
+ ServiceInstanceChangeListener serviceInstanceChangeListener = clz.getAnnotation(ServiceInstanceChangeListener.class);
+ serviceName = serviceInstanceChangeListener.serviceName();
+ }
+
+ if (StringUtils.isBlank(serviceName)) {
+ return bean;
+ }
+
+ // process callback
+ if (callbackMap.containsKey(serviceName)) {
+ List callbacks = callbackMap.get(serviceName);
+ callbacks.add((ServiceInstanceChangeCallback) bean);
+ }
+ else {
+ List callbacks = new ArrayList<>();
+ callbacks.add((ServiceInstanceChangeCallback) bean);
+ callbackMap.put(serviceName, callbacks);
+ }
+
+ return bean;
+ }
+
+ @Override
+ public void onApplicationEvent(@NonNull ApplicationReadyEvent event) {
+ PolarisDiscoveryClient polarisDiscoveryClient = ApplicationContextAwareUtils.getBeanIfExists(PolarisDiscoveryClient.class);
+ PolarisReactiveDiscoveryClient polarisReactiveDiscoveryClient = ApplicationContextAwareUtils.getBeanIfExists(PolarisReactiveDiscoveryClient.class);
+ for (String serviceName : callbackMap.keySet()) {
+ try {
+ if (polarisDiscoveryClient != null) {
+ polarisDiscoveryClient.getInstances(serviceName);
+ }
+ else if (polarisReactiveDiscoveryClient != null) {
+ polarisReactiveDiscoveryClient.getInstances(serviceName).subscribe();
+ }
+ else {
+ LOG.warn("[{}] no discovery client found.", serviceName);
+ }
+ }
+ catch (Throwable throwable) {
+ LOG.error("Get instances of service [{}] failed.", serviceName, throwable);
+ }
+ }
+ }
+}
diff --git a/spring-cloud-tencent-examples/quickstart-example/quickstart-caller-service/src/main/java/com/tencent/cloud/quickstart/caller/circuitbreaker/CustomFallback.java b/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/discovery/refresh/ServiceInstanceChangeListener.java
similarity index 55%
rename from spring-cloud-tencent-examples/quickstart-example/quickstart-caller-service/src/main/java/com/tencent/cloud/quickstart/caller/circuitbreaker/CustomFallback.java
rename to spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/discovery/refresh/ServiceInstanceChangeListener.java
index 6fa073388..b3b31a2d1 100644
--- a/spring-cloud-tencent-examples/quickstart-example/quickstart-caller-service/src/main/java/com/tencent/cloud/quickstart/caller/circuitbreaker/CustomFallback.java
+++ b/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/discovery/refresh/ServiceInstanceChangeListener.java
@@ -15,29 +15,28 @@
* specific language governing permissions and limitations under the License.
*/
-package com.tencent.cloud.quickstart.caller.circuitbreaker;
+package com.tencent.cloud.polaris.discovery.refresh;
-import java.util.HashMap;
-
-import com.tencent.cloud.polaris.circuitbreaker.resttemplate.PolarisCircuitBreakerFallback;
-import com.tencent.cloud.polaris.circuitbreaker.resttemplate.PolarisCircuitBreakerHttpResponse;
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
import org.springframework.stereotype.Component;
/**
- * CustomFallback.
- *
- * @author sean yu
+ * @author Haotian Zhang
*/
+@Target({ElementType.TYPE})
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
@Component
-public class CustomFallback implements PolarisCircuitBreakerFallback {
- @Override
- public PolarisCircuitBreakerHttpResponse fallback() {
- return new PolarisCircuitBreakerHttpResponse(
- 200,
- new HashMap() {{
- put("Content-Type", "application/json");
- }},
- "{\"msg\": \"this is a fallback class\"}");
- }
+public @interface ServiceInstanceChangeListener {
+
+ /**
+ * listen service name.
+ * @return service name
+ */
+ String serviceName();
}
diff --git a/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/eager/config/PolarisEagerLoadAutoConfiguration.java b/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/eager/config/PolarisEagerLoadAutoConfiguration.java
new file mode 100644
index 000000000..179833b67
--- /dev/null
+++ b/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/eager/config/PolarisEagerLoadAutoConfiguration.java
@@ -0,0 +1,44 @@
+/*
+ * Tencent is pleased to support the open source community by making spring-cloud-tencent available.
+ *
+ * Copyright (C) 2021 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.polaris.eager.config;
+
+import com.tencent.cloud.polaris.discovery.PolarisDiscoveryClient;
+import com.tencent.cloud.polaris.discovery.reactive.PolarisReactiveDiscoveryClient;
+import com.tencent.cloud.polaris.eager.instrument.feign.FeignEagerLoadSmartLifecycle;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+@ConditionalOnProperty(name = "spring.cloud.polaris.discovery.eager-load.enabled", havingValue = "true")
+public class PolarisEagerLoadAutoConfiguration {
+
+ @Bean
+ @ConditionalOnClass(name = "feign.Feign")
+ @ConditionalOnProperty(name = "spring.cloud.polaris.discovery.eager-load.feign.enabled", havingValue = "true", matchIfMissing = true)
+ public FeignEagerLoadSmartLifecycle feignEagerLoadSmartLifecycle(
+ ApplicationContext applicationContext, @Autowired(required = false) PolarisDiscoveryClient polarisDiscoveryClient,
+ @Autowired(required = false) PolarisReactiveDiscoveryClient polarisReactiveDiscoveryClient) {
+ return new FeignEagerLoadSmartLifecycle(applicationContext, polarisDiscoveryClient, polarisReactiveDiscoveryClient);
+ }
+}
+
diff --git a/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/eager/instrument/feign/FeignEagerLoadSmartLifecycle.java b/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/eager/instrument/feign/FeignEagerLoadSmartLifecycle.java
new file mode 100644
index 000000000..ca4e0e0a9
--- /dev/null
+++ b/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/eager/instrument/feign/FeignEagerLoadSmartLifecycle.java
@@ -0,0 +1,94 @@
+/*
+ * Tencent is pleased to support the open source community by making spring-cloud-tencent available.
+ *
+ * Copyright (C) 2021 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.polaris.eager.instrument.feign;
+
+import com.tencent.cloud.common.util.FeignUtil;
+import com.tencent.cloud.polaris.discovery.PolarisDiscoveryClient;
+import com.tencent.cloud.polaris.discovery.reactive.PolarisReactiveDiscoveryClient;
+import com.tencent.polaris.api.utils.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.SmartLifecycle;
+
+public class FeignEagerLoadSmartLifecycle implements SmartLifecycle {
+
+ private static final Logger LOG = LoggerFactory.getLogger(FeignEagerLoadSmartLifecycle.class);
+
+ private final ApplicationContext applicationContext;
+
+ private final PolarisDiscoveryClient polarisDiscoveryClient;
+
+ private final PolarisReactiveDiscoveryClient polarisReactiveDiscoveryClient;
+
+ public FeignEagerLoadSmartLifecycle(ApplicationContext applicationContext, PolarisDiscoveryClient polarisDiscoveryClient,
+ PolarisReactiveDiscoveryClient polarisReactiveDiscoveryClient) {
+ this.applicationContext = applicationContext;
+ this.polarisDiscoveryClient = polarisDiscoveryClient;
+ this.polarisReactiveDiscoveryClient = polarisReactiveDiscoveryClient;
+ }
+
+ @Override
+ public void start() {
+ LOG.info("feign eager-load start");
+ for (String name : applicationContext.getBeanDefinitionNames()) {
+ try {
+ if (name.contains(FeignUtil.FEIGN_CLIENT_SPECIF) && !name.startsWith(FeignUtil.FEIGN_CLIENT_DEFAULT)) {
+ String feignName = FeignUtil.analysisFeignName(name, applicationContext);
+ if (StringUtils.isNotBlank(feignName)) {
+ LOG.info("[{}] eager-load start", feignName);
+ if (polarisDiscoveryClient != null) {
+ polarisDiscoveryClient.getInstances(feignName);
+ }
+ else if (polarisReactiveDiscoveryClient != null) {
+ polarisReactiveDiscoveryClient.getInstances(feignName).subscribe();
+ }
+ else {
+ LOG.warn("[{}] no discovery client found.", feignName);
+ }
+ LOG.info("[{}] eager-load end", feignName);
+ }
+ else {
+ LOG.warn("feign name is blank.");
+ }
+ }
+ }
+ catch (Exception e) {
+ LOG.error("[{}] eager-load failed.", name, e);
+ }
+ }
+ LOG.info("feign eager-load end");
+
+ }
+
+ @Override
+ public void stop() {
+
+ }
+
+ @Override
+ public boolean isRunning() {
+ return false;
+ }
+
+ @Override
+ public int getPhase() {
+ return 10;
+ }
+}
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 ff4c87c4b..71de4be33 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
@@ -237,7 +237,7 @@ public class PolarisServiceRegistry implements ServiceRegistry
+ * Deprecated since 2.0.0.0.
+ *
+ * @author Haotian Zhang
+ */
+@Deprecated
+public interface ConsulServiceChangeCallback {
+
+ /** Service change callback function.
+ * @param currentServices Currently available services list
+ * @param addServices Newly added services list
+ * @param deleteServices Removed services list
+ */
+ void callback(List currentServices, List addServices, List deleteServices);
+}
diff --git a/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/tsf/serviceregistry/watch/ConsulServiceChangeListener.java b/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/tsf/serviceregistry/watch/ConsulServiceChangeListener.java
new file mode 100644
index 000000000..8caf4575d
--- /dev/null
+++ b/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/tsf/serviceregistry/watch/ConsulServiceChangeListener.java
@@ -0,0 +1,53 @@
+/*
+ * Tencent is pleased to support the open source community by making spring-cloud-tencent available.
+ *
+ * Copyright (C) 2021 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.tsf.serviceregistry.watch;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import org.springframework.stereotype.Component;
+
+/**
+ * Empty annotation. Compatible with old versions TSF SDK.
+ *
+ * Deprecated since 2.0.0.0.
+ *
+ * @author Haotian Zhang
+ */
+@Deprecated
+@Target({ElementType.TYPE})
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+@Component
+public @interface ConsulServiceChangeListener {
+
+ /**
+ * 监听的服务名.
+ * @return 监听的服务名
+ */
+ String serviceName();
+
+ /**
+ * 监听的命名空间,true 时为全局命名空间,false 为本命名空间.
+ * @return 监听的命名空间
+ */
+ boolean global() default false;
+}
diff --git a/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/tsf/serviceregistry/watch/LocalServiceChangeListener.java b/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/tsf/serviceregistry/watch/LocalServiceChangeListener.java
new file mode 100644
index 000000000..be6c14340
--- /dev/null
+++ b/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/tsf/serviceregistry/watch/LocalServiceChangeListener.java
@@ -0,0 +1,47 @@
+/*
+ * Tencent is pleased to support the open source community by making spring-cloud-tencent available.
+ *
+ * Copyright (C) 2021 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.tsf.serviceregistry.watch;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import org.springframework.stereotype.Component;
+
+/**
+ * Empty annotation. Compatible with old versions TSF SDK.
+ *
+ * Deprecated since 2.0.0.0.
+ *
+ * @author Haotian Zhang
+ */
+@Deprecated
+@Target({ElementType.TYPE})
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+@Component
+public @interface LocalServiceChangeListener {
+
+ /**
+ * 回调的 currentServices 是否包含当前实例.
+ * @return 是否包含当前实例.
+ */
+ boolean excludeLocalInstance() default false;
+}
diff --git a/spring-cloud-starter-tencent-polaris-discovery/src/main/resources/META-INF/additional-spring-configuration-metadata.json b/spring-cloud-starter-tencent-polaris-discovery/src/main/resources/META-INF/additional-spring-configuration-metadata.json
index a8ebda064..aa0a4ec1a 100644
--- a/spring-cloud-starter-tencent-polaris-discovery/src/main/resources/META-INF/additional-spring-configuration-metadata.json
+++ b/spring-cloud-starter-tencent-polaris-discovery/src/main/resources/META-INF/additional-spring-configuration-metadata.json
@@ -78,6 +78,18 @@
"defaultValue": false,
"description": "Zero protection test connectivity switch. Default: false."
},
+ {
+ "name": "spring.cloud.polaris.discovery.eager-load.enabled",
+ "type": "java.lang.Boolean",
+ "defaultValue": false,
+ "description": "Eager load switch. Default: false."
+ },
+ {
+ "name": "spring.cloud.polaris.discovery.eager-load.feign.enabled",
+ "type": "java.lang.Boolean",
+ "defaultValue": true,
+ "description": "Feign eager load switch. Default: true."
+ },
{
"name": "spring.cloud.nacos.discovery.enabled",
"type": "java.lang.Boolean",
diff --git a/spring-cloud-starter-tencent-polaris-discovery/src/main/resources/META-INF/spring.factories b/spring-cloud-starter-tencent-polaris-discovery/src/main/resources/META-INF/spring.factories
index 036bfd464..081f684c3 100644
--- a/spring-cloud-starter-tencent-polaris-discovery/src/main/resources/META-INF/spring.factories
+++ b/spring-cloud-starter-tencent-polaris-discovery/src/main/resources/META-INF/spring.factories
@@ -3,6 +3,7 @@ org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.tencent.cloud.polaris.discovery.PolarisDiscoveryAutoConfiguration,\
com.tencent.cloud.polaris.registry.PolarisServiceRegistryAutoConfiguration,\
com.tencent.cloud.polaris.endpoint.PolarisDiscoveryEndpointAutoConfiguration,\
- com.tencent.cloud.polaris.tsf.registry.TsfDiscoveryRegistryAutoConfiguration
+ com.tencent.cloud.polaris.registry.tsf.TsfDiscoveryRegistryAutoConfiguration,\
+ com.tencent.cloud.polaris.eager.config.PolarisEagerLoadAutoConfiguration
org.springframework.cloud.bootstrap.BootstrapConfiguration=\
com.tencent.cloud.polaris.DiscoveryPropertiesBootstrapAutoConfiguration
diff --git a/spring-cloud-starter-tencent-polaris-discovery/src/test/java/com/tencent/cloud/polaris/discovery/refresh/PolarisServiceStatusChangeListenerTest.java b/spring-cloud-starter-tencent-polaris-discovery/src/test/java/com/tencent/cloud/polaris/discovery/refresh/PolarisServiceStatusChangeListenerTest.java
index 4d8492260..983ba4f13 100644
--- a/spring-cloud-starter-tencent-polaris-discovery/src/test/java/com/tencent/cloud/polaris/discovery/refresh/PolarisServiceStatusChangeListenerTest.java
+++ b/spring-cloud-starter-tencent-polaris-discovery/src/test/java/com/tencent/cloud/polaris/discovery/refresh/PolarisServiceStatusChangeListenerTest.java
@@ -61,7 +61,7 @@ public class PolarisServiceStatusChangeListenerTest {
@Test
public void testOnResourceUpdated() {
- PolarisServiceStatusChangeListener polarisServiceStatusChangeListener = new PolarisServiceStatusChangeListener();
+ PolarisServiceStatusChangeListener polarisServiceStatusChangeListener = new PolarisServiceStatusChangeListener(mock(ServiceInstanceChangeCallbackManager.class));
polarisServiceStatusChangeListener.setApplicationEventPublisher(publisher);
// Service update event
diff --git a/spring-cloud-starter-tencent-polaris-ratelimit/src/main/java/com/tencent/cloud/polaris/ratelimit/filter/QuotaCheckReactiveFilter.java b/spring-cloud-starter-tencent-polaris-ratelimit/src/main/java/com/tencent/cloud/polaris/ratelimit/filter/QuotaCheckReactiveFilter.java
index 02a77ed76..07a13e6e2 100644
--- a/spring-cloud-starter-tencent-polaris-ratelimit/src/main/java/com/tencent/cloud/polaris/ratelimit/filter/QuotaCheckReactiveFilter.java
+++ b/spring-cloud-starter-tencent-polaris-ratelimit/src/main/java/com/tencent/cloud/polaris/ratelimit/filter/QuotaCheckReactiveFilter.java
@@ -104,6 +104,7 @@ public class QuotaCheckReactiveFilter implements WebFilter, Ordered {
quotaResponse = QuotaCheckUtils.getQuota(limitAPI, localNamespace, localService, 1, path);
if (quotaResponse.getCode() == QuotaResultCode.QuotaResultLimited) {
+ LOG.info("block by ratelimit rule, uri:{}", exchange.getRequest().getURI());
ServerHttpResponse response = exchange.getResponse();
DataBuffer dataBuffer;
if (Objects.nonNull(quotaResponse.getActiveRule())
diff --git a/spring-cloud-starter-tencent-polaris-ratelimit/src/main/java/com/tencent/cloud/polaris/ratelimit/filter/QuotaCheckServletFilter.java b/spring-cloud-starter-tencent-polaris-ratelimit/src/main/java/com/tencent/cloud/polaris/ratelimit/filter/QuotaCheckServletFilter.java
index 0828efeec..a93d26686 100644
--- a/spring-cloud-starter-tencent-polaris-ratelimit/src/main/java/com/tencent/cloud/polaris/ratelimit/filter/QuotaCheckServletFilter.java
+++ b/spring-cloud-starter-tencent-polaris-ratelimit/src/main/java/com/tencent/cloud/polaris/ratelimit/filter/QuotaCheckServletFilter.java
@@ -98,6 +98,7 @@ public class QuotaCheckServletFilter extends OncePerRequestFilter {
try {
quotaResponse = QuotaCheckUtils.getQuota(limitAPI, localNamespace, localService, 1, request.getRequestURI());
if (quotaResponse.getCode() == QuotaResultCode.QuotaResultLimited) {
+ LOG.info("block by ratelimit rule, uri:{}", request.getRequestURI());
if (Objects.nonNull(quotaResponse.getActiveRule())
&& StringUtils.isNotBlank(quotaResponse.getActiveRule().getCustomResponse().getBody())) {
response.setStatus(polarisRateLimitProperties.getRejectHttpCode());
diff --git a/spring-cloud-starter-tencent-polaris-ratelimit/src/main/java/org/springframework/tsf/ratelimit/annotation/EnableTsfRateLimit.java b/spring-cloud-starter-tencent-polaris-ratelimit/src/main/java/org/springframework/tsf/ratelimit/annotation/EnableTsfRateLimit.java
new file mode 100644
index 000000000..c1cd0ee6e
--- /dev/null
+++ b/spring-cloud-starter-tencent-polaris-ratelimit/src/main/java/org/springframework/tsf/ratelimit/annotation/EnableTsfRateLimit.java
@@ -0,0 +1,40 @@
+/*
+ * Tencent is pleased to support the open source community by making spring-cloud-tencent available.
+ *
+ * Copyright (C) 2021 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 org.springframework.tsf.ratelimit.annotation;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Empty annotation. Compatible with old versions TSF SDK.
+ *
+ * Deprecated since 2.0.0.0.
+ *
+ * @author Haotian Zhang
+ */
+@Deprecated
+@Target(ElementType.TYPE)
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+@Inherited
+public @interface EnableTsfRateLimit {
+}
diff --git a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/beanprocessor/LoadBalancerClientFilterBeanPostProcessor.java b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/beanprocessor/LoadBalancerClientFilterBeanPostProcessor.java
index 655e38a3e..37eadf698 100644
--- a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/beanprocessor/LoadBalancerClientFilterBeanPostProcessor.java
+++ b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/beanprocessor/LoadBalancerClientFilterBeanPostProcessor.java
@@ -23,7 +23,7 @@ import com.tencent.cloud.common.metadata.StaticMetadataManager;
import com.tencent.cloud.common.util.BeanFactoryUtils;
import com.tencent.cloud.polaris.context.config.PolarisContextProperties;
import com.tencent.cloud.polaris.router.RouterRuleLabelResolver;
-import com.tencent.cloud.polaris.router.scg.PolarisLoadBalancerClientFilter;
+import com.tencent.cloud.polaris.router.instrument.scg.PolarisLoadBalancerClientFilter;
import com.tencent.cloud.polaris.router.spi.SpringWebRouterLabelResolver;
import org.springframework.beans.BeansException;
diff --git a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/beanprocessor/LoadBalancerInterceptorBeanPostProcessor.java b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/beanprocessor/LoadBalancerInterceptorBeanPostProcessor.java
index d4dc73ac9..bcfcf3159 100644
--- a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/beanprocessor/LoadBalancerInterceptorBeanPostProcessor.java
+++ b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/beanprocessor/LoadBalancerInterceptorBeanPostProcessor.java
@@ -17,8 +17,8 @@
package com.tencent.cloud.polaris.router.beanprocessor;
-import com.tencent.cloud.polaris.router.resttemplate.PolarisLoadBalancerInterceptor;
-import com.tencent.cloud.polaris.router.resttemplate.RouterContextFactory;
+import com.tencent.cloud.polaris.router.instrument.resttemplate.PolarisLoadBalancerInterceptor;
+import com.tencent.cloud.polaris.router.instrument.resttemplate.RouterContextFactory;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginRunner;
import org.springframework.beans.BeansException;
diff --git a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/beanprocessor/RetryLoadBalancerInterceptorBeanPostProcessor.java b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/beanprocessor/RetryLoadBalancerInterceptorBeanPostProcessor.java
index c29d96d0c..b869d18c8 100644
--- a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/beanprocessor/RetryLoadBalancerInterceptorBeanPostProcessor.java
+++ b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/beanprocessor/RetryLoadBalancerInterceptorBeanPostProcessor.java
@@ -17,8 +17,8 @@
package com.tencent.cloud.polaris.router.beanprocessor;
-import com.tencent.cloud.polaris.router.resttemplate.PolarisRetryLoadBalancerInterceptor;
-import com.tencent.cloud.polaris.router.resttemplate.RouterContextFactory;
+import com.tencent.cloud.polaris.router.instrument.resttemplate.PolarisRetryLoadBalancerInterceptor;
+import com.tencent.cloud.polaris.router.instrument.resttemplate.RouterContextFactory;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginRunner;
import org.springframework.beans.BeansException;
diff --git a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/FeignAutoConfiguration.java b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/FeignAutoConfiguration.java
index 7d6a21d4e..b83f360c9 100644
--- a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/FeignAutoConfiguration.java
+++ b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/FeignAutoConfiguration.java
@@ -17,8 +17,8 @@
package com.tencent.cloud.polaris.router.config;
-import com.tencent.cloud.polaris.router.feign.PolarisCachingSpringLoadBalanceFactory;
-import com.tencent.cloud.polaris.router.feign.RouterLabelFeignInterceptor;
+import com.tencent.cloud.polaris.router.instrument.feign.PolarisCachingSpringLoadBalanceFactory;
+import com.tencent.cloud.polaris.router.instrument.feign.RouterLabelFeignInterceptor;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.cloud.netflix.ribbon.RibbonClients;
diff --git a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/FeignLoadBalancerConfiguration.java b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/FeignLoadBalancerConfiguration.java
index 29e377b62..ec6d8b942 100644
--- a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/FeignLoadBalancerConfiguration.java
+++ b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/FeignLoadBalancerConfiguration.java
@@ -19,7 +19,7 @@ package com.tencent.cloud.polaris.router.config;
import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.ILoadBalancer;
-import com.tencent.cloud.polaris.router.feign.PolarisFeignLoadBalancer;
+import com.tencent.cloud.polaris.router.instrument.feign.PolarisFeignLoadBalancer;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass;
diff --git a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/RouterAutoConfiguration.java b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/RouterAutoConfiguration.java
index 7fdf3dc9b..588a8b642 100644
--- a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/RouterAutoConfiguration.java
+++ b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/RouterAutoConfiguration.java
@@ -32,19 +32,19 @@ import com.tencent.cloud.polaris.router.config.properties.PolarisMetadataRouterP
import com.tencent.cloud.polaris.router.config.properties.PolarisNamespaceRouterProperties;
import com.tencent.cloud.polaris.router.config.properties.PolarisNearByRouterProperties;
import com.tencent.cloud.polaris.router.config.properties.PolarisRuleBasedRouterProperties;
+import com.tencent.cloud.polaris.router.instrument.resttemplate.RouterContextFactory;
+import com.tencent.cloud.polaris.router.instrument.resttemplate.RouterLabelRestTemplateInterceptor;
+import com.tencent.cloud.polaris.router.instrument.scg.RouterLabelGlobalFilter;
import com.tencent.cloud.polaris.router.interceptor.MetadataRouterRequestInterceptor;
import com.tencent.cloud.polaris.router.interceptor.NamespaceRouterRequestInterceptor;
import com.tencent.cloud.polaris.router.interceptor.NearbyRouterRequestInterceptor;
import com.tencent.cloud.polaris.router.interceptor.RuleBasedRouterRequestInterceptor;
-import com.tencent.cloud.polaris.router.resttemplate.RouterContextFactory;
-import com.tencent.cloud.polaris.router.resttemplate.RouterLabelRestTemplateInterceptor;
-import com.tencent.cloud.polaris.router.scg.RouterLabelGlobalFilter;
import com.tencent.cloud.polaris.router.spi.ServletRouterLabelResolver;
import com.tencent.cloud.polaris.router.spi.SpringWebRouterLabelResolver;
import com.tencent.cloud.polaris.router.zuul.PolarisRibbonRoutingFilter;
import com.tencent.cloud.polaris.router.zuul.RouterLabelZuulFilter;
+import com.tencent.cloud.rpc.enhancement.instrument.zuul.EnhancedZuulPluginRunner;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginRunner;
-import com.tencent.cloud.rpc.enhancement.zuul.EnhancedZuulPluginRunner;
import org.springframework.beans.factory.SmartInitializingSingleton;
import org.springframework.beans.factory.annotation.Autowired;
diff --git a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/feign/PolarisCachingSpringLoadBalanceFactory.java b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/instrument/feign/PolarisCachingSpringLoadBalanceFactory.java
similarity index 97%
rename from spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/feign/PolarisCachingSpringLoadBalanceFactory.java
rename to spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/instrument/feign/PolarisCachingSpringLoadBalanceFactory.java
index 09aa68fed..6e88aeb38 100644
--- a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/feign/PolarisCachingSpringLoadBalanceFactory.java
+++ b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/instrument/feign/PolarisCachingSpringLoadBalanceFactory.java
@@ -15,7 +15,7 @@
* specific language governing permissions and limitations under the License.
*/
-package com.tencent.cloud.polaris.router.feign;
+package com.tencent.cloud.polaris.router.instrument.feign;
import java.util.Map;
diff --git a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/feign/PolarisFeignLoadBalancer.java b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/instrument/feign/PolarisFeignLoadBalancer.java
similarity index 98%
rename from spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/feign/PolarisFeignLoadBalancer.java
rename to spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/instrument/feign/PolarisFeignLoadBalancer.java
index 186755759..19bfd41cf 100644
--- a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/feign/PolarisFeignLoadBalancer.java
+++ b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/instrument/feign/PolarisFeignLoadBalancer.java
@@ -15,7 +15,7 @@
* specific language governing permissions and limitations under the License.
*/
-package com.tencent.cloud.polaris.router.feign;
+package com.tencent.cloud.polaris.router.instrument.feign;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
diff --git a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/feign/RouterLabelFeignInterceptor.java b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/instrument/feign/RouterLabelFeignInterceptor.java
similarity index 96%
rename from spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/feign/RouterLabelFeignInterceptor.java
rename to spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/instrument/feign/RouterLabelFeignInterceptor.java
index 066d03bd1..ff2b3e77f 100644
--- a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/feign/RouterLabelFeignInterceptor.java
+++ b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/instrument/feign/RouterLabelFeignInterceptor.java
@@ -15,7 +15,7 @@
* specific language governing permissions and limitations under the License.
*/
-package com.tencent.cloud.polaris.router.feign;
+package com.tencent.cloud.polaris.router.instrument.feign;
import com.tencent.cloud.common.constant.OrderConstant;
import com.tencent.cloud.common.metadata.MetadataContextHolder;
diff --git a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/resttemplate/PolarisInterceptorRetryPolicy.java b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/instrument/resttemplate/PolarisInterceptorRetryPolicy.java
similarity index 97%
rename from spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/resttemplate/PolarisInterceptorRetryPolicy.java
rename to spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/instrument/resttemplate/PolarisInterceptorRetryPolicy.java
index 1ecc81e36..f7462f96b 100644
--- a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/resttemplate/PolarisInterceptorRetryPolicy.java
+++ b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/instrument/resttemplate/PolarisInterceptorRetryPolicy.java
@@ -15,7 +15,7 @@
* specific language governing permissions and limitations under the License.
*/
-package com.tencent.cloud.polaris.router.resttemplate;
+package com.tencent.cloud.polaris.router.instrument.resttemplate;
import com.tencent.cloud.polaris.router.PolarisRouterContext;
diff --git a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/resttemplate/PolarisLoadBalancerInterceptor.java b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/instrument/resttemplate/PolarisLoadBalancerInterceptor.java
similarity index 96%
rename from spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/resttemplate/PolarisLoadBalancerInterceptor.java
rename to spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/instrument/resttemplate/PolarisLoadBalancerInterceptor.java
index 7e6924555..787cf7fed 100644
--- a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/resttemplate/PolarisLoadBalancerInterceptor.java
+++ b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/instrument/resttemplate/PolarisLoadBalancerInterceptor.java
@@ -15,14 +15,14 @@
* specific language governing permissions and limitations under the License.
*/
-package com.tencent.cloud.polaris.router.resttemplate;
+package com.tencent.cloud.polaris.router.instrument.resttemplate;
import java.io.IOException;
import java.net.URI;
import com.tencent.cloud.polaris.router.PolarisRouterContext;
+import com.tencent.cloud.rpc.enhancement.instrument.resttemplate.EnhancedRestTemplateWrapInterceptor;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginRunner;
-import com.tencent.cloud.rpc.enhancement.resttemplate.EnhancedRestTemplateWrapInterceptor;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.cloud.client.loadbalancer.LoadBalancerInterceptor;
diff --git a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/resttemplate/PolarisRetryLoadBalancerInterceptor.java b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/instrument/resttemplate/PolarisRetryLoadBalancerInterceptor.java
similarity index 97%
rename from spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/resttemplate/PolarisRetryLoadBalancerInterceptor.java
rename to spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/instrument/resttemplate/PolarisRetryLoadBalancerInterceptor.java
index 7bf0e9e20..4c83dbb41 100644
--- a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/resttemplate/PolarisRetryLoadBalancerInterceptor.java
+++ b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/instrument/resttemplate/PolarisRetryLoadBalancerInterceptor.java
@@ -15,14 +15,14 @@
* specific language governing permissions and limitations under the License.
*/
-package com.tencent.cloud.polaris.router.resttemplate;
+package com.tencent.cloud.polaris.router.instrument.resttemplate;
import java.io.IOException;
import java.net.URI;
import com.tencent.cloud.polaris.router.PolarisRouterContext;
+import com.tencent.cloud.rpc.enhancement.instrument.resttemplate.EnhancedRestTemplateWrapInterceptor;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginRunner;
-import com.tencent.cloud.rpc.enhancement.resttemplate.EnhancedRestTemplateWrapInterceptor;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
diff --git a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/resttemplate/RouterContextFactory.java b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/instrument/resttemplate/RouterContextFactory.java
similarity index 98%
rename from spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/resttemplate/RouterContextFactory.java
rename to spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/instrument/resttemplate/RouterContextFactory.java
index 4c6c6ec8f..f9b2f7a47 100644
--- a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/resttemplate/RouterContextFactory.java
+++ b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/instrument/resttemplate/RouterContextFactory.java
@@ -15,7 +15,7 @@
* specific language governing permissions and limitations under the License.
*/
-package com.tencent.cloud.polaris.router.resttemplate;
+package com.tencent.cloud.polaris.router.instrument.resttemplate;
import java.util.Collections;
import java.util.Comparator;
diff --git a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/resttemplate/RouterContextHelper.java b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/instrument/resttemplate/RouterContextHelper.java
similarity index 97%
rename from spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/resttemplate/RouterContextHelper.java
rename to spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/instrument/resttemplate/RouterContextHelper.java
index 7c662f25b..628e9be5c 100644
--- a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/resttemplate/RouterContextHelper.java
+++ b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/instrument/resttemplate/RouterContextHelper.java
@@ -15,7 +15,7 @@
* specific language governing permissions and limitations under the License.
*/
-package com.tencent.cloud.polaris.router.resttemplate;
+package com.tencent.cloud.polaris.router.instrument.resttemplate;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
diff --git a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/resttemplate/RouterLabelRestTemplateInterceptor.java b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/instrument/resttemplate/RouterLabelRestTemplateInterceptor.java
similarity index 96%
rename from spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/resttemplate/RouterLabelRestTemplateInterceptor.java
rename to spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/instrument/resttemplate/RouterLabelRestTemplateInterceptor.java
index c5b51873d..41f569872 100644
--- a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/resttemplate/RouterLabelRestTemplateInterceptor.java
+++ b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/instrument/resttemplate/RouterLabelRestTemplateInterceptor.java
@@ -15,7 +15,7 @@
* specific language governing permissions and limitations under the License.
*/
-package com.tencent.cloud.polaris.router.resttemplate;
+package com.tencent.cloud.polaris.router.instrument.resttemplate;
import java.io.IOException;
diff --git a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/scg/PolarisLoadBalancerClientFilter.java b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/instrument/scg/PolarisLoadBalancerClientFilter.java
similarity index 99%
rename from spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/scg/PolarisLoadBalancerClientFilter.java
rename to spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/instrument/scg/PolarisLoadBalancerClientFilter.java
index 73ae69e6d..762a128d9 100644
--- a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/scg/PolarisLoadBalancerClientFilter.java
+++ b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/instrument/scg/PolarisLoadBalancerClientFilter.java
@@ -15,7 +15,7 @@
* specific language governing permissions and limitations under the License.
*/
-package com.tencent.cloud.polaris.router.scg;
+package com.tencent.cloud.polaris.router.instrument.scg;
import java.net.URI;
import java.util.Collections;
diff --git a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/scg/RouterLabelGlobalFilter.java b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/instrument/scg/RouterLabelGlobalFilter.java
similarity index 97%
rename from spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/scg/RouterLabelGlobalFilter.java
rename to spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/instrument/scg/RouterLabelGlobalFilter.java
index c9a70c29a..099c781d4 100644
--- a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/scg/RouterLabelGlobalFilter.java
+++ b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/instrument/scg/RouterLabelGlobalFilter.java
@@ -15,7 +15,7 @@
* specific language governing permissions and limitations under the License.
*/
-package com.tencent.cloud.polaris.router.scg;
+package com.tencent.cloud.polaris.router.instrument.scg;
import com.tencent.cloud.common.metadata.MetadataContextHolder;
import com.tencent.cloud.metadata.provider.ReactiveMetadataProvider;
diff --git a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/zuul/PolarisRibbonRoutingFilter.java b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/zuul/PolarisRibbonRoutingFilter.java
index c8a788e83..ee59ac981 100644
--- a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/zuul/PolarisRibbonRoutingFilter.java
+++ b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/zuul/PolarisRibbonRoutingFilter.java
@@ -38,7 +38,7 @@ import com.tencent.cloud.common.util.expresstion.ServletExpressionLabelUtils;
import com.tencent.cloud.polaris.router.PolarisRouterContext;
import com.tencent.cloud.polaris.router.RouterRuleLabelResolver;
import com.tencent.cloud.polaris.router.spi.ServletRouterLabelResolver;
-import com.tencent.cloud.rpc.enhancement.zuul.EnhancedZuulPluginRunner;
+import com.tencent.cloud.rpc.enhancement.instrument.zuul.EnhancedZuulPluginRunner;
import com.tencent.polaris.circuitbreak.client.exception.CallAbortedException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
diff --git a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/tsf/lane/annotation/EnableTsfLane.java b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/tsf/lane/annotation/EnableTsfLane.java
new file mode 100644
index 000000000..76c5e7d9a
--- /dev/null
+++ b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/tsf/lane/annotation/EnableTsfLane.java
@@ -0,0 +1,41 @@
+/*
+ * Tencent is pleased to support the open source community by making spring-cloud-tencent available.
+ *
+ * Copyright (C) 2021 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.lane.annotation;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Empty annotation. Compatible with old versions TSF SDK.
+ *
+ * Deprecated since 2.0.0.0.
+ *
+ * @author Haotian Zhang
+ */
+@Deprecated
+@Target(ElementType.TYPE)
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+@Inherited
+public @interface EnableTsfLane {
+
+}
diff --git a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/tsf/femas/adaptor/tsf/governance/zonefilter/EnableTsfZoneFilter.java b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/tsf/femas/adaptor/tsf/governance/zonefilter/EnableTsfZoneFilter.java
new file mode 100644
index 000000000..9c0f7707c
--- /dev/null
+++ b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/tsf/femas/adaptor/tsf/governance/zonefilter/EnableTsfZoneFilter.java
@@ -0,0 +1,41 @@
+/*
+ * Tencent is pleased to support the open source community by making spring-cloud-tencent available.
+ *
+ * Copyright (C) 2021 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.tsf.femas.adaptor.tsf.governance.zonefilter;
+
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Empty annotation. Compatible with old versions TSF SDK.
+ *
+ * Deprecated since 2.0.0.0.
+ *
+ * @author Haotian Zhang
+ */
+@Deprecated
+@Target(ElementType.TYPE)
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+@Inherited
+public @interface EnableTsfZoneFilter {
+}
diff --git a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/tsf/unit/annotation/EnableTsfUnit.java b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/tsf/unit/annotation/EnableTsfUnit.java
new file mode 100644
index 000000000..b0f255b24
--- /dev/null
+++ b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/tsf/unit/annotation/EnableTsfUnit.java
@@ -0,0 +1,41 @@
+/*
+ * Tencent is pleased to support the open source community by making spring-cloud-tencent available.
+ *
+ * Copyright (C) 2021 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.tsf.unit.annotation;
+
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Empty annotation. Compatible with old versions TSF SDK.
+ *
+ * Deprecated since 2.0.0.0.
+ *
+ * @author Haotian Zhang
+ */
+@Deprecated
+@Target(ElementType.TYPE)
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+@Inherited
+public @interface EnableTsfUnit {
+}
diff --git a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/tsf/unit/annotation/TsfUnitCall.java b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/tsf/unit/annotation/TsfUnitCall.java
new file mode 100644
index 000000000..e79641333
--- /dev/null
+++ b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/tsf/unit/annotation/TsfUnitCall.java
@@ -0,0 +1,46 @@
+/*
+ * Tencent is pleased to support the open source community by making spring-cloud-tencent available.
+ *
+ * Copyright (C) 2021 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.tsf.unit.annotation;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Empty annotation. Compatible with old versions TSF SDK.
+ *
+ * Deprecated since 2.0.0.0.
+ *
+ * @author Haotian Zhang
+ */
+@Deprecated
+@Target(ElementType.TYPE)
+@Retention(RetentionPolicy.RUNTIME)
+@Inherited
+@Documented
+public @interface TsfUnitCall {
+
+ // 单元化下的业务系统名
+ String systemName() default "";
+
+ // 单元化下的是否调用GDU服务
+ boolean global() default false;
+}
diff --git a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/tsf/unit/annotation/TsfUnitCustomerIdentifier.java b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/tsf/unit/annotation/TsfUnitCustomerIdentifier.java
new file mode 100644
index 000000000..1eba44616
--- /dev/null
+++ b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/tsf/unit/annotation/TsfUnitCustomerIdentifier.java
@@ -0,0 +1,40 @@
+/*
+ * Tencent is pleased to support the open source community by making spring-cloud-tencent available.
+ *
+ * Copyright (C) 2021 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.tsf.unit.annotation;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Empty annotation. Compatible with old versions TSF SDK.
+ *
+ * Deprecated since 2.0.0.0.
+ *
+ * @author Haotian Zhang
+ */
+@Deprecated
+@Target(ElementType.PARAMETER)
+@Retention(RetentionPolicy.RUNTIME)
+@Inherited
+@Documented
+public @interface TsfUnitCustomerIdentifier {
+}
diff --git a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/tsf/unit/annotation/TsfUnitLocalCall.java b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/tsf/unit/annotation/TsfUnitLocalCall.java
new file mode 100644
index 000000000..4e49e6717
--- /dev/null
+++ b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/tsf/unit/annotation/TsfUnitLocalCall.java
@@ -0,0 +1,44 @@
+/*
+ * Tencent is pleased to support the open source community by making spring-cloud-tencent available.
+ *
+ * Copyright (C) 2021 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.tsf.unit.annotation;
+
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Empty annotation. Compatible with old versions TSF SDK.
+ *
+ * Deprecated since 2.0.0.0.
+ *
+ * @author Haotian Zhang
+ */
+@Deprecated
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+@Inherited
+@Documented
+public @interface TsfUnitLocalCall {
+ String className() default "";
+
+ String methodName() default "";
+}
diff --git a/spring-cloud-starter-tencent-polaris-router/src/main/java/org/springframework/cloud/tsf/route/annotation/EnableTsfRoute.java b/spring-cloud-starter-tencent-polaris-router/src/main/java/org/springframework/cloud/tsf/route/annotation/EnableTsfRoute.java
new file mode 100644
index 000000000..ac9fabca8
--- /dev/null
+++ b/spring-cloud-starter-tencent-polaris-router/src/main/java/org/springframework/cloud/tsf/route/annotation/EnableTsfRoute.java
@@ -0,0 +1,41 @@
+/*
+ * Tencent is pleased to support the open source community by making spring-cloud-tencent available.
+ *
+ * Copyright (C) 2021 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 org.springframework.cloud.tsf.route.annotation;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Empty annotation. Compatible with old versions TSF SDK.
+ *
+ * Deprecated since 2.0.0.0.
+ *
+ * @author Haotian Zhang
+ */
+@Deprecated
+@Target(ElementType.TYPE)
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+@Inherited
+public @interface EnableTsfRoute {
+}
+
diff --git a/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/feign/PolarisCachingSpringLoadBalanceFactoryTest.java b/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/instrument/feign/PolarisCachingSpringLoadBalanceFactoryTest.java
similarity index 98%
rename from spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/feign/PolarisCachingSpringLoadBalanceFactoryTest.java
rename to spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/instrument/feign/PolarisCachingSpringLoadBalanceFactoryTest.java
index 92c996208..0f3e95b81 100644
--- a/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/feign/PolarisCachingSpringLoadBalanceFactoryTest.java
+++ b/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/instrument/feign/PolarisCachingSpringLoadBalanceFactoryTest.java
@@ -15,7 +15,7 @@
* specific language governing permissions and limitations under the License.
*/
-package com.tencent.cloud.polaris.router.feign;
+package com.tencent.cloud.polaris.router.instrument.feign;
import com.netflix.client.config.DefaultClientConfigImpl;
import com.netflix.loadbalancer.ILoadBalancer;
diff --git a/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/feign/PolarisFeignLoadBalancerTest.java b/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/instrument/feign/PolarisFeignLoadBalancerTest.java
similarity index 98%
rename from spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/feign/PolarisFeignLoadBalancerTest.java
rename to spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/instrument/feign/PolarisFeignLoadBalancerTest.java
index eb7f90f34..deb4bebb3 100644
--- a/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/feign/PolarisFeignLoadBalancerTest.java
+++ b/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/instrument/feign/PolarisFeignLoadBalancerTest.java
@@ -15,7 +15,7 @@
* specific language governing permissions and limitations under the License.
*/
-package com.tencent.cloud.polaris.router.feign;
+package com.tencent.cloud.polaris.router.instrument.feign;
import java.util.ArrayList;
import java.util.Collection;
diff --git a/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/feign/RouterLabelFeignInterceptorTest.java b/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/instrument/feign/RouterLabelFeignInterceptorTest.java
similarity index 98%
rename from spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/feign/RouterLabelFeignInterceptorTest.java
rename to spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/instrument/feign/RouterLabelFeignInterceptorTest.java
index bdb3b7c33..d4cc36b0c 100644
--- a/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/feign/RouterLabelFeignInterceptorTest.java
+++ b/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/instrument/feign/RouterLabelFeignInterceptorTest.java
@@ -15,7 +15,7 @@
* specific language governing permissions and limitations under the License.
*/
-package com.tencent.cloud.polaris.router.feign;
+package com.tencent.cloud.polaris.router.instrument.feign;
import java.util.Collections;
import java.util.HashMap;
diff --git a/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/feign/SimpleLoadBalancer.java b/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/instrument/feign/SimpleLoadBalancer.java
similarity index 96%
rename from spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/feign/SimpleLoadBalancer.java
rename to spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/instrument/feign/SimpleLoadBalancer.java
index 439956c71..f871aeb81 100644
--- a/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/feign/SimpleLoadBalancer.java
+++ b/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/instrument/feign/SimpleLoadBalancer.java
@@ -15,7 +15,7 @@
* specific language governing permissions and limitations under the License.
*/
-package com.tencent.cloud.polaris.router.feign;
+package com.tencent.cloud.polaris.router.instrument.feign;
import java.util.Collections;
import java.util.List;
diff --git a/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/resttemplate/PolarisLoadBalancerInterceptorTest.java b/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/instrument/resttemplate/PolarisLoadBalancerInterceptorTest.java
similarity index 99%
rename from spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/resttemplate/PolarisLoadBalancerInterceptorTest.java
rename to spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/instrument/resttemplate/PolarisLoadBalancerInterceptorTest.java
index 46fa2d6b3..1c70e056f 100644
--- a/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/resttemplate/PolarisLoadBalancerInterceptorTest.java
+++ b/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/instrument/resttemplate/PolarisLoadBalancerInterceptorTest.java
@@ -15,7 +15,7 @@
* specific language governing permissions and limitations under the License.
*/
-package com.tencent.cloud.polaris.router.resttemplate;
+package com.tencent.cloud.polaris.router.instrument.resttemplate;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
diff --git a/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/resttemplate/RouterContextFactoryTest.java b/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/instrument/resttemplate/RouterContextFactoryTest.java
similarity index 98%
rename from spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/resttemplate/RouterContextFactoryTest.java
rename to spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/instrument/resttemplate/RouterContextFactoryTest.java
index 64eded89e..fd7c57693 100644
--- a/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/resttemplate/RouterContextFactoryTest.java
+++ b/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/instrument/resttemplate/RouterContextFactoryTest.java
@@ -15,7 +15,7 @@
* specific language governing permissions and limitations under the License.
*/
-package com.tencent.cloud.polaris.router.resttemplate;
+package com.tencent.cloud.polaris.router.instrument.resttemplate;
import java.net.URI;
import java.util.Collections;
diff --git a/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/resttemplate/RouterLabelRestTemplateInterceptorTest.java b/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/instrument/resttemplate/RouterLabelRestTemplateInterceptorTest.java
similarity index 98%
rename from spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/resttemplate/RouterLabelRestTemplateInterceptorTest.java
rename to spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/instrument/resttemplate/RouterLabelRestTemplateInterceptorTest.java
index 94cf9d66e..e3a8d48f7 100644
--- a/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/resttemplate/RouterLabelRestTemplateInterceptorTest.java
+++ b/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/instrument/resttemplate/RouterLabelRestTemplateInterceptorTest.java
@@ -15,7 +15,7 @@
* specific language governing permissions and limitations under the License.
*/
-package com.tencent.cloud.polaris.router.resttemplate;
+package com.tencent.cloud.polaris.router.instrument.resttemplate;
import java.net.URI;
diff --git a/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/scg/PolarisLoadBalancerClientFilterTest.java b/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/instrument/scg/PolarisLoadBalancerClientFilterTest.java
similarity index 99%
rename from spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/scg/PolarisLoadBalancerClientFilterTest.java
rename to spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/instrument/scg/PolarisLoadBalancerClientFilterTest.java
index fda325c29..a018435d9 100644
--- a/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/scg/PolarisLoadBalancerClientFilterTest.java
+++ b/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/instrument/scg/PolarisLoadBalancerClientFilterTest.java
@@ -15,7 +15,7 @@
* specific language governing permissions and limitations under the License.
*/
-package com.tencent.cloud.polaris.router.scg;
+package com.tencent.cloud.polaris.router.instrument.scg;
import java.net.URI;
import java.util.HashMap;
diff --git a/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/scg/RouterLabelGlobalFilterTest.java b/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/instrument/scg/RouterLabelGlobalFilterTest.java
similarity index 98%
rename from spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/scg/RouterLabelGlobalFilterTest.java
rename to spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/instrument/scg/RouterLabelGlobalFilterTest.java
index 49587db95..da18bfe95 100644
--- a/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/scg/RouterLabelGlobalFilterTest.java
+++ b/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/instrument/scg/RouterLabelGlobalFilterTest.java
@@ -15,7 +15,7 @@
* specific language governing permissions and limitations under the License.
*/
-package com.tencent.cloud.polaris.router.scg;
+package com.tencent.cloud.polaris.router.instrument.scg;
import com.tencent.cloud.common.metadata.MetadataContextHolder;
import com.tencent.polaris.metadata.core.MessageMetadataContainer;
diff --git a/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/zuul/PolarisRibbonRoutingFilterTest.java b/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/zuul/PolarisRibbonRoutingFilterTest.java
index b6a6fda1c..0cbd74a45 100644
--- a/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/zuul/PolarisRibbonRoutingFilterTest.java
+++ b/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/zuul/PolarisRibbonRoutingFilterTest.java
@@ -37,7 +37,7 @@ import com.tencent.cloud.polaris.loadbalancer.PolarisLoadBalancer;
import com.tencent.cloud.polaris.router.PolarisRouterContext;
import com.tencent.cloud.polaris.router.RouterRuleLabelResolver;
import com.tencent.cloud.polaris.router.spi.ServletRouterLabelResolver;
-import com.tencent.cloud.rpc.enhancement.zuul.EnhancedZuulPluginRunner;
+import com.tencent.cloud.rpc.enhancement.instrument.zuul.EnhancedZuulPluginRunner;
import okhttp3.OkHttpClient;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
diff --git a/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/async/PolarisAsyncConfiguration.java b/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/async/PolarisAsyncConfiguration.java
new file mode 100644
index 000000000..ace5628bb
--- /dev/null
+++ b/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/async/PolarisAsyncConfiguration.java
@@ -0,0 +1,83 @@
+/*
+ * Tencent is pleased to support the open source community by making spring-cloud-tencent available.
+ *
+ * Copyright (C) 2021 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.common.async;
+
+import java.util.concurrent.Executor;
+import java.util.concurrent.ThreadPoolExecutor;
+
+import com.tencent.cloud.plugin.threadlocal.TaskExecutorWrapper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
+import org.springframework.beans.factory.config.BeanDefinition;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Primary;
+import org.springframework.context.annotation.Role;
+import org.springframework.core.task.TaskExecutor;
+import org.springframework.scheduling.annotation.AsyncConfigurer;
+import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
+
+import static com.tencent.cloud.common.metadata.CrossThreadMetadataContext.CROSS_THREAD_METADATA_CONTEXT_CONSUMER;
+import static com.tencent.cloud.common.metadata.CrossThreadMetadataContext.CROSS_THREAD_METADATA_CONTEXT_SUPPLIER;
+
+/**
+ * polaris async executor for @Async .
+ *
+ * @author Haotian Zhang
+ */
+@Configuration
+@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
+@ConditionalOnProperty(name = "spring.cloud.tencent.async.enabled")
+public class PolarisAsyncConfiguration implements AsyncConfigurer {
+
+ private static final Logger logger = LoggerFactory.getLogger(PolarisAsyncConfiguration.class);
+
+ @Primary
+ @Bean("polarisAsyncExecutor")
+ public TaskExecutor polarisAsyncExecutor() {
+ ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
+ int corePoolSize = 10;
+ executor.setCorePoolSize(corePoolSize);
+ int maxPoolSize = 50;
+ executor.setMaxPoolSize(maxPoolSize);
+ int queueCapacity = 10;
+ executor.setQueueCapacity(queueCapacity);
+ executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
+ String threadNamePrefix = "polaris-async-executor-";
+ executor.setThreadNamePrefix(threadNamePrefix);
+ executor.setWaitForTasksToCompleteOnShutdown(true);
+ executor.setAwaitTerminationSeconds(5);
+ executor.initialize();
+ TaskExecutor executorWrapper = new TaskExecutorWrapper<>(executor, CROSS_THREAD_METADATA_CONTEXT_SUPPLIER, CROSS_THREAD_METADATA_CONTEXT_CONSUMER);
+ logger.info("Created async executor with corePoolSize:{}, maxPoolSize:{}, queueCapacity:{}", corePoolSize, maxPoolSize, queueCapacity);
+ return executorWrapper;
+ }
+
+ @Override
+ public Executor getAsyncExecutor() {
+ return polarisAsyncExecutor();
+ }
+
+ @Override
+ public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
+ return (ex, method, params) -> logger.error("Execute asynchronous tasks '{}' failed.", method, ex);
+ }
+}
diff --git a/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/metadata/CrossThreadMetadataContext.java b/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/metadata/CrossThreadMetadataContext.java
new file mode 100644
index 000000000..f8ae7c239
--- /dev/null
+++ b/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/metadata/CrossThreadMetadataContext.java
@@ -0,0 +1,68 @@
+/*
+ * Tencent is pleased to support the open source community by making spring-cloud-tencent available.
+ *
+ * Copyright (C) 2021 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.common.metadata;
+
+import java.util.function.Consumer;
+import java.util.function.Supplier;
+
+import com.tencent.cloud.common.util.JacksonUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Metadata Context for cross thread.
+ *
+ * @author Haotian Zhang
+ */
+public class CrossThreadMetadataContext {
+
+ private static final Logger LOG = LoggerFactory.getLogger(CrossThreadMetadataContext.class);
+
+ /**
+ * Get metadata context from previous thread.
+ */
+ public static final Supplier CROSS_THREAD_METADATA_CONTEXT_SUPPLIER = () -> {
+ CrossThreadMetadataContext crossThreadMetadataContext = new CrossThreadMetadataContext();
+ crossThreadMetadataContext.setMetadataContext(MetadataContextHolder.get());
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Context map is got: {}", JacksonUtils.serialize2Json(crossThreadMetadataContext));
+ }
+ return crossThreadMetadataContext;
+ };
+
+ /**
+ * Set metadata context to current thread.
+ */
+ public static final Consumer CROSS_THREAD_METADATA_CONTEXT_CONSUMER = crossThreadMetadataContext -> {
+ MetadataContextHolder.set(crossThreadMetadataContext.getMetadataContext());
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Context map is set: {}", JacksonUtils.serialize2Json(crossThreadMetadataContext));
+ }
+ };
+
+ private MetadataContext metadataContext;
+
+ public MetadataContext getMetadataContext() {
+ return metadataContext;
+ }
+
+ public void setMetadataContext(MetadataContext metadataContext) {
+ this.metadataContext = metadataContext;
+ }
+}
diff --git a/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/metadata/MetadataContext.java b/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/metadata/MetadataContext.java
index 9af0859d2..733d69057 100644
--- a/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/metadata/MetadataContext.java
+++ b/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/metadata/MetadataContext.java
@@ -142,8 +142,8 @@ public class MetadataContext extends com.tencent.polaris.metadata.core.manager.M
return values;
}
- public void putMetadataAsMap(MetadataType metadataType, TransitiveType transitiveType, boolean downstream, Map values) {
- MetadataContainer metadataContainer = getMetadataContainer(metadataType, downstream);
+ public void putMetadataAsMap(MetadataType metadataType, TransitiveType transitiveType, boolean caller, Map values) {
+ MetadataContainer metadataContainer = getMetadataContainer(metadataType, caller);
for (Map.Entry entry : values.entrySet()) {
metadataContainer.putMetadataStringValue(entry.getKey(), entry.getValue(), transitiveType);
}
diff --git a/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/metadata/MetadataContextHolder.java b/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/metadata/MetadataContextHolder.java
index d3a27fcea..55473bfd8 100644
--- a/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/metadata/MetadataContextHolder.java
+++ b/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/metadata/MetadataContextHolder.java
@@ -158,24 +158,25 @@ public final class MetadataContextHolder {
Map dynamicApplicationMetadata, MetadataProvider callerMetadataProvider) {
com.tencent.polaris.metadata.core.manager.MetadataContextHolder.refresh(metadataManager -> {
// caller transitive metadata to local custom transitive metadata
- MetadataContainer metadataContainerUpstream = metadataManager.getMetadataContainer(MetadataType.CUSTOM, false);
+ MetadataContainer calleeCustomMetadataContainer = metadataManager.getMetadataContainer(MetadataType.CUSTOM, false);
if (!CollectionUtils.isEmpty(dynamicTransitiveMetadata)) {
for (Map.Entry entry : dynamicTransitiveMetadata.entrySet()) {
- metadataContainerUpstream.putMetadataStringValue(entry.getKey(), entry.getValue(), TransitiveType.PASS_THROUGH);
+ calleeCustomMetadataContainer.putMetadataStringValue(entry.getKey(), entry.getValue(), TransitiveType.PASS_THROUGH);
}
}
// caller disposable metadata to caller custom disposable metadata
- MetadataContainer metadataContainerDownstream = metadataManager.getMetadataContainer(MetadataType.CUSTOM, false);
+ MetadataContainer callerCustomMetadataContainer = metadataManager.getMetadataContainer(MetadataType.CUSTOM, true);
if (!CollectionUtils.isEmpty(dynamicDisposableMetadata)) {
for (Map.Entry entry : dynamicDisposableMetadata.entrySet()) {
- metadataContainerDownstream.putMetadataStringValue(entry.getKey(), entry.getValue(), TransitiveType.NONE);
+ calleeCustomMetadataContainer.putMetadataStringValue(entry.getKey(), entry.getValue(), TransitiveType.NONE);
+ callerCustomMetadataContainer.putMetadataStringValue(entry.getKey(), entry.getValue(), TransitiveType.DISPOSABLE);
}
}
// caller application metadata to caller application disposable metadata
- MetadataContainer applicationMetadataContainerDownstream = metadataManager.getMetadataContainer(MetadataType.APPLICATION, true);
+ MetadataContainer callerApplicationMetadataContainer = metadataManager.getMetadataContainer(MetadataType.APPLICATION, true);
if (!CollectionUtils.isEmpty(dynamicApplicationMetadata)) {
for (Map.Entry entry : dynamicApplicationMetadata.entrySet()) {
- applicationMetadataContainerDownstream.putMetadataStringValue(entry.getKey(), entry.getValue(), TransitiveType.DISPOSABLE);
+ callerApplicationMetadataContainer.putMetadataStringValue(entry.getKey(), entry.getValue(), TransitiveType.DISPOSABLE);
}
}
diff --git a/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/util/ApplicationContextAwareUtils.java b/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/util/ApplicationContextAwareUtils.java
index 66cdedd1f..474a9512c 100644
--- a/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/util/ApplicationContextAwareUtils.java
+++ b/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/util/ApplicationContextAwareUtils.java
@@ -84,4 +84,18 @@ public class ApplicationContextAwareUtils implements ApplicationContextAware {
}
return property;
}
+
+ public static T getBean(Class requiredType) {
+ return applicationContext.getBean(requiredType);
+ }
+
+ public static T getBeanIfExists(Class requiredType) {
+ try {
+ return applicationContext.getBean(requiredType);
+ }
+ catch (Throwable e) {
+ LOGGER.warn("get bean failed, bean type: {}", requiredType.getName());
+ return null;
+ }
+ }
}
diff --git a/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/util/FeignUtil.java b/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/util/FeignUtil.java
new file mode 100644
index 000000000..4306e087e
--- /dev/null
+++ b/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/util/FeignUtil.java
@@ -0,0 +1,83 @@
+/*
+ * Tencent is pleased to support the open source community by making spring-cloud-tencent available.
+ *
+ * Copyright (C) 2021 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.common.util;
+
+import org.springframework.context.ApplicationContext;
+import org.springframework.util.StringUtils;
+
+/**
+ * @author heihuliliu
+ */
+public final class FeignUtil {
+
+ /**
+ * Feign client spec.
+ */
+ public static final String FEIGN_CLIENT_SPECIF = ".FeignClientSpecification";
+
+ /**
+ * Default Feign client spec.
+ */
+ public static final String FEIGN_CLIENT_DEFAULT = "default.";
+
+ /**
+ * regular expression that parses ${xxx} .
+ */
+ public static final String REGEX = "^[$][{](.*)[}]$";
+
+ /**
+ * replacement of ${xxx}.
+ */
+ public static final String REPLACEMENT = "$1";
+
+ private FeignUtil() {
+
+ }
+
+ /**
+ * TODO If @FeignClient specifies contextId, the service name will not be obtained correctly, but the contextId will be obtained.
+ *
+ * @param name feign name.
+ * @param context application context.
+ * @return service name.
+ */
+ public static String analysisFeignName(String name, ApplicationContext context) {
+ String feignName = "";
+ String feignPath = name.substring(0, name.indexOf(FEIGN_CLIENT_SPECIF));
+ // Handle the case where the service name is a variable
+ if (feignPath.matches(REGEX)) {
+ feignPath = context.getEnvironment().getProperty(feignPath.replaceAll(REGEX, REPLACEMENT));
+ }
+ if (StringUtils.hasText(feignPath)) {
+ // The case of multi-level paths
+ String[] feignNames = feignPath.split("/");
+ if (feignNames.length > 1) {
+ for (int i = 0; i < feignNames.length; i++) {
+ if (StringUtils.hasText(feignNames[i])) {
+ feignName = feignNames[i];
+ break;
+ }
+ }
+ }
+ else {
+ feignName = feignNames[0];
+ }
+ }
+ return feignName;
+ }
+}
diff --git a/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/util/PolarisCompletableFutureUtils.java b/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/util/PolarisCompletableFutureUtils.java
new file mode 100644
index 000000000..ce30ceedf
--- /dev/null
+++ b/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/util/PolarisCompletableFutureUtils.java
@@ -0,0 +1,45 @@
+/*
+ * Tencent is pleased to support the open source community by making spring-cloud-tencent available.
+ *
+ * Copyright (C) 2021 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.common.util;
+
+import java.util.concurrent.CompletableFuture;
+import java.util.function.Supplier;
+
+import com.tencent.polaris.threadlocal.cross.CompletableFutureUtils;
+
+import static com.tencent.cloud.common.metadata.CrossThreadMetadataContext.CROSS_THREAD_METADATA_CONTEXT_CONSUMER;
+import static com.tencent.cloud.common.metadata.CrossThreadMetadataContext.CROSS_THREAD_METADATA_CONTEXT_SUPPLIER;
+
+/**
+ * Polaris CompletableFuture Utils.
+ *
+ * @author Haotian Zhang
+ */
+public final class PolarisCompletableFutureUtils {
+
+ private PolarisCompletableFutureUtils() {
+ }
+
+ public static CompletableFuture supplyAsync(Supplier supplier) {
+ return CompletableFutureUtils.supplyAsync(supplier, CROSS_THREAD_METADATA_CONTEXT_SUPPLIER, CROSS_THREAD_METADATA_CONTEXT_CONSUMER);
+ }
+
+ public static CompletableFuture runAsync(Runnable runnable) {
+ return CompletableFutureUtils.runAsync(runnable, CROSS_THREAD_METADATA_CONTEXT_SUPPLIER, CROSS_THREAD_METADATA_CONTEXT_CONSUMER);
+ }
+}
diff --git a/spring-cloud-tencent-commons/src/main/java/org/springframework/tsf/core/context/TsfContext.java b/spring-cloud-tencent-commons/src/main/java/org/springframework/tsf/core/TsfContext.java
similarity index 80%
rename from spring-cloud-tencent-commons/src/main/java/org/springframework/tsf/core/context/TsfContext.java
rename to spring-cloud-tencent-commons/src/main/java/org/springframework/tsf/core/TsfContext.java
index 2e6093458..577b82549 100644
--- a/spring-cloud-tencent-commons/src/main/java/org/springframework/tsf/core/context/TsfContext.java
+++ b/spring-cloud-tencent-commons/src/main/java/org/springframework/tsf/core/TsfContext.java
@@ -15,10 +15,11 @@
* specific language governing permissions and limitations under the License.
*/
-package org.springframework.tsf.core.context;
+package org.springframework.tsf.core;
import java.nio.charset.StandardCharsets;
import java.util.Collections;
+import java.util.HashMap;
import java.util.Map;
import com.tencent.cloud.common.metadata.MetadataContext;
@@ -32,6 +33,7 @@ public final class TsfContext {
static final int MAX_KEY_LENGTH = 32;
static final int MAX_VALUE_LENGTH = 128;
+ private static final String CUSTOM_METADATA = "tsf-custom-metadata";
private TsfContext() {
@@ -74,4 +76,19 @@ public final class TsfContext {
MAX_VALUE_LENGTH));
}
}
+
+ public static void putCustomMetadata(Object customMetadata) {
+ if (customMetadata == null) {
+ return;
+ }
+ MetadataContext tsfCoreContext = MetadataContextHolder.get();
+ Map tagMap = new HashMap<>();
+ try {
+ tagMap.put(CUSTOM_METADATA, customMetadata.toString());
+ }
+ catch (Throwable throwable) {
+ throw new RuntimeException("Failed to parse custom metadata", throwable);
+ }
+ tsfCoreContext.putMetadataAsMap(MetadataType.CUSTOM, TransitiveType.NONE, false, tagMap);
+ }
}
diff --git a/spring-cloud-tencent-commons/src/main/java/org/springframework/tsf/core/util/TsfSpringContextAware.java b/spring-cloud-tencent-commons/src/main/java/org/springframework/tsf/core/util/TsfSpringContextAware.java
new file mode 100644
index 000000000..557a131d8
--- /dev/null
+++ b/spring-cloud-tencent-commons/src/main/java/org/springframework/tsf/core/util/TsfSpringContextAware.java
@@ -0,0 +1,69 @@
+/*
+ * Tencent is pleased to support the open source community by making spring-cloud-tencent available.
+ *
+ * Copyright (C) 2021 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 org.springframework.tsf.core.util;
+
+import com.tencent.cloud.common.util.ApplicationContextAwareUtils;
+
+import org.springframework.beans.BeansException;
+import org.springframework.context.ApplicationContext;
+
+/**
+ * Spring context utils.
+ *
+ * Deprecated since 2.0.0.0.
+ *
+ * @author hongweizhu
+ */
+@Deprecated
+public class TsfSpringContextAware {
+
+ /**
+ * Get application context.
+ * @return application context
+ */
+ public static ApplicationContext getApplicationContext() {
+ return ApplicationContextAwareUtils.getApplicationContext();
+ }
+
+ public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
+ // do nothing.
+ }
+
+ /**
+ * Get application property.
+ * @param key property name
+ * @return property value
+ */
+ public static String getProperties(String key) {
+ return ApplicationContextAwareUtils.getProperties(key);
+ }
+
+ /**
+ * Get application property. If null, return default.
+ * @param key property name
+ * @param defaultValue default value
+ * @return property value
+ */
+ public static String getProperties(String key, String defaultValue) {
+ return ApplicationContextAwareUtils.getProperties(key, defaultValue);
+ }
+
+ public static T getBean(Class requiredType) {
+ return ApplicationContextAwareUtils.getBean(requiredType);
+ }
+}
diff --git a/spring-cloud-tencent-commons/src/main/resources/META-INF/additional-spring-configuration-metadata.json b/spring-cloud-tencent-commons/src/main/resources/META-INF/additional-spring-configuration-metadata.json
index 291e26dbe..9df3e2d80 100644
--- a/spring-cloud-tencent-commons/src/main/resources/META-INF/additional-spring-configuration-metadata.json
+++ b/spring-cloud-tencent-commons/src/main/resources/META-INF/additional-spring-configuration-metadata.json
@@ -19,6 +19,12 @@
"name": "spring.cloud.tencent.metadata.headers",
"type": "java.util.List",
"description": "Custom transitive http header key list."
+ },
+ {
+ "name": "spring.cloud.tencent.async.enabled",
+ "type": "java.lang.Boolean",
+ "defaultValue": false,
+ "description": "Async support switch. Default: false."
}
]
}
diff --git a/spring-cloud-tencent-dependencies/pom.xml b/spring-cloud-tencent-dependencies/pom.xml
index 545864582..751023f9e 100644
--- a/spring-cloud-tencent-dependencies/pom.xml
+++ b/spring-cloud-tencent-dependencies/pom.xml
@@ -73,13 +73,13 @@
2.0.2.0-Hoxton.SR12-SNAPSHOT
- 2.0.0.0
+ 2.0.0.1
32.1.3-jre
1.2.13
1.7.0
1.5.24
4.5.1
- 1.12.10
+ 1.12.19
2.15.3
3.21.7
2.9.9
@@ -232,6 +232,18 @@
${revision}
+
+ com.tencent.cloud
+ spring-cloud-starter-tencent-fault-tolerance
+ ${revision}
+
+
+
+ com.tencent.cloud
+ spring-cloud-tencent-security-protection-plugin
+ ${revision}
+
+
com.google.guava
diff --git a/spring-cloud-tencent-examples/quickstart-example/quickstart-callee-service-a/src/main/java/com/tencent/cloud/quickstart/callee/QuickstartCalleeController.java b/spring-cloud-tencent-examples/quickstart-example/quickstart-callee-service-a/src/main/java/com/tencent/cloud/quickstart/callee/QuickstartCalleeController.java
index f4f805a32..56ed7aca1 100644
--- a/spring-cloud-tencent-examples/quickstart-example/quickstart-callee-service-a/src/main/java/com/tencent/cloud/quickstart/callee/QuickstartCalleeController.java
+++ b/spring-cloud-tencent-examples/quickstart-example/quickstart-callee-service-a/src/main/java/com/tencent/cloud/quickstart/callee/QuickstartCalleeController.java
@@ -22,6 +22,7 @@ import java.net.URLDecoder;
import com.tencent.cloud.common.constant.MetadataConstant;
import com.tencent.cloud.quickstart.callee.config.DataSourceProperties;
+import com.tencent.cloud.quickstart.callee.service.FaultToleranceService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -59,6 +60,9 @@ public class QuickstartCalleeController {
@Autowired
private DataSourceProperties dataSourceProperties;
+ @Autowired
+ private FaultToleranceService faultToleranceService;
+
/**
* Get sum of two value.
* @param value1 value 1
@@ -126,7 +130,22 @@ public class QuickstartCalleeController {
@GetMapping("/test/{num}/echo")
public String test(@PathVariable int num) {
- LOG.info("Quickstart Callee Service [%s] is detected right.", num);
+ LOG.info("Quickstart Callee Service [{}] is detected right.", num);
return String.format("Quickstart Callee Service [%s] is detected right.", num);
}
+
+ @GetMapping("/faultTolerance/failFast")
+ public String faultToleranceFailFast() {
+ return faultToleranceService.failFast();
+ }
+
+ @GetMapping("/faultTolerance/failOver")
+ public String faultToleranceFailOver() {
+ return faultToleranceService.failOver();
+ }
+
+ @GetMapping("/faultTolerance/forking")
+ public String faultToleranceForking() {
+ return faultToleranceService.forking();
+ }
}
diff --git a/spring-cloud-tencent-examples/quickstart-example/quickstart-callee-service-a/src/main/java/com/tencent/cloud/quickstart/callee/service/CalleeServiceChangeCallback.java b/spring-cloud-tencent-examples/quickstart-example/quickstart-callee-service-a/src/main/java/com/tencent/cloud/quickstart/callee/service/CalleeServiceChangeCallback.java
new file mode 100644
index 000000000..c4ac75b17
--- /dev/null
+++ b/spring-cloud-tencent-examples/quickstart-example/quickstart-callee-service-a/src/main/java/com/tencent/cloud/quickstart/callee/service/CalleeServiceChangeCallback.java
@@ -0,0 +1,60 @@
+/*
+ * Tencent is pleased to support the open source community by making spring-cloud-tencent available.
+ *
+ * Copyright (C) 2021 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.quickstart.callee.service;
+
+import java.util.List;
+
+import com.tencent.cloud.polaris.discovery.refresh.ServiceInstanceChangeCallback;
+import com.tencent.cloud.polaris.discovery.refresh.ServiceInstanceChangeListener;
+import com.tencent.polaris.api.pojo.Instance;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.springframework.stereotype.Component;
+
+/**
+ * Call back for QuickstartCalleeService.
+ *
+ * @author Haotian Zhang
+ */
+@Component
+@ServiceInstanceChangeListener(serviceName = "QuickstartCalleeService")
+public class CalleeServiceChangeCallback implements ServiceInstanceChangeCallback {
+
+ private static final Logger LOG = LoggerFactory.getLogger(CalleeServiceChangeCallback.class);
+
+ @Override
+ public void callback(List currentServiceInstances, List addServiceInstances, List deleteServiceInstances) {
+ String current = generateNodeList(currentServiceInstances);
+ String add = generateNodeList(addServiceInstances);
+ String delete = generateNodeList(deleteServiceInstances);
+ LOG.info("current: {}, add: {}, delete: {}", current, add, delete);
+ }
+
+ private String generateNodeList(List deleteServiceInstances) {
+ StringBuilder nodeListStr = new StringBuilder("[");
+ for (Instance instance : deleteServiceInstances) {
+ if (nodeListStr.length() > 1) {
+ nodeListStr.append(", ");
+ }
+ nodeListStr.append(instance.getHost()).append(":").append(instance.getPort());
+ }
+ nodeListStr.append("]");
+ return nodeListStr.toString();
+ }
+}
diff --git a/spring-cloud-tencent-examples/quickstart-example/quickstart-callee-service-a/src/main/java/com/tencent/cloud/quickstart/callee/service/FaultToleranceService.java b/spring-cloud-tencent-examples/quickstart-example/quickstart-callee-service-a/src/main/java/com/tencent/cloud/quickstart/callee/service/FaultToleranceService.java
new file mode 100644
index 000000000..cc913de7f
--- /dev/null
+++ b/spring-cloud-tencent-examples/quickstart-example/quickstart-callee-service-a/src/main/java/com/tencent/cloud/quickstart/callee/service/FaultToleranceService.java
@@ -0,0 +1,62 @@
+/*
+ * Tencent is pleased to support the open source community by making spring-cloud-tencent available.
+ *
+ * Copyright (C) 2021 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.quickstart.callee.service;
+
+import java.util.concurrent.atomic.AtomicInteger;
+
+import com.tencent.cloud.plugin.faulttolerance.annotation.FaultTolerance;
+import com.tencent.cloud.plugin.faulttolerance.model.FaultToleranceStrategy;
+
+import org.springframework.stereotype.Service;
+
+/**
+ * Service for fault tolerance.
+ *
+ * @author Haotian Zhang
+ */
+@Service
+public class FaultToleranceService {
+
+ private final AtomicInteger failOverCount = new AtomicInteger(0);
+ private final AtomicInteger forkingCount = new AtomicInteger(0);
+
+ @FaultTolerance(strategy = FaultToleranceStrategy.FAIL_FAST, fallbackMethod = "fallback")
+ public String failFast() {
+ throw new RuntimeException("NO");
+ }
+
+ public String fallback() {
+ return "fallback";
+ }
+
+ @FaultTolerance(strategy = FaultToleranceStrategy.FAIL_OVER, maxAttempts = 3)
+ public String failOver() {
+ if (failOverCount.incrementAndGet() % 4 == 0) {
+ return "OK";
+ }
+ throw new RuntimeException("NO");
+ }
+
+ @FaultTolerance(strategy = FaultToleranceStrategy.FORKING, parallelism = 4)
+ public String forking() {
+ if (forkingCount.incrementAndGet() % 4 == 0) {
+ return "OK";
+ }
+ throw new RuntimeException("NO");
+ }
+}
diff --git a/spring-cloud-tencent-examples/quickstart-example/quickstart-caller-service/src/main/java/com/tencent/cloud/quickstart/caller/QuickstartCallerApplication.java b/spring-cloud-tencent-examples/quickstart-example/quickstart-caller-service/src/main/java/com/tencent/cloud/quickstart/caller/QuickstartCallerApplication.java
index 0f6d71ad5..ae4bac993 100644
--- a/spring-cloud-tencent-examples/quickstart-example/quickstart-caller-service/src/main/java/com/tencent/cloud/quickstart/caller/QuickstartCallerApplication.java
+++ b/spring-cloud-tencent-examples/quickstart-example/quickstart-caller-service/src/main/java/com/tencent/cloud/quickstart/caller/QuickstartCallerApplication.java
@@ -17,9 +17,6 @@
package com.tencent.cloud.quickstart.caller;
-import com.tencent.cloud.polaris.circuitbreaker.resttemplate.PolarisCircuitBreaker;
-import com.tencent.cloud.quickstart.caller.circuitbreaker.CustomFallback;
-
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
@@ -50,27 +47,7 @@ public class QuickstartCallerApplication {
@Bean
@LoadBalanced
- public RestTemplate defaultRestTemplate() {
- DefaultUriBuilderFactory uriBuilderFactory = new DefaultUriBuilderFactory("http://QuickstartCalleeService");
- RestTemplate restTemplate = new RestTemplate();
- restTemplate.setUriTemplateHandler(uriBuilderFactory);
- return restTemplate;
- }
-
- @Bean
- @LoadBalanced
- @PolarisCircuitBreaker
- public RestTemplate restTemplateFallbackFromPolaris() {
- DefaultUriBuilderFactory uriBuilderFactory = new DefaultUriBuilderFactory("http://QuickstartCalleeService");
- RestTemplate restTemplate = new RestTemplate();
- restTemplate.setUriTemplateHandler(uriBuilderFactory);
- return restTemplate;
- }
-
- @Bean
- @LoadBalanced
- @PolarisCircuitBreaker(fallbackClass = CustomFallback.class)
- public RestTemplate restTemplateFallbackFromCode() {
+ public RestTemplate calleeRestTemplate() {
DefaultUriBuilderFactory uriBuilderFactory = new DefaultUriBuilderFactory("http://QuickstartCalleeService");
RestTemplate restTemplate = new RestTemplate();
restTemplate.setUriTemplateHandler(uriBuilderFactory);
diff --git a/spring-cloud-tencent-examples/quickstart-example/quickstart-caller-service/src/main/java/com/tencent/cloud/quickstart/caller/circuitbreaker/CircuitBreakerController.java b/spring-cloud-tencent-examples/quickstart-example/quickstart-caller-service/src/main/java/com/tencent/cloud/quickstart/caller/circuitbreaker/CircuitBreakerController.java
index a8d6045f5..a3fff2fd5 100644
--- a/spring-cloud-tencent-examples/quickstart-example/quickstart-caller-service/src/main/java/com/tencent/cloud/quickstart/caller/circuitbreaker/CircuitBreakerController.java
+++ b/spring-cloud-tencent-examples/quickstart-example/quickstart-caller-service/src/main/java/com/tencent/cloud/quickstart/caller/circuitbreaker/CircuitBreakerController.java
@@ -49,16 +49,8 @@ public class CircuitBreakerController {
private CircuitBreakerQuickstartCalleeServiceWithFallback circuitBreakerQuickstartCalleeServiceWithFallback;
@Autowired
- @Qualifier("defaultRestTemplate")
- private RestTemplate defaultRestTemplate;
-
- @Autowired
- @Qualifier("restTemplateFallbackFromPolaris")
- private RestTemplate restTemplateFallbackFromPolaris;
-
- @Autowired
- @Qualifier("restTemplateFallbackFromCode")
- private RestTemplate restTemplateFallbackFromCode;
+ @Qualifier("calleeRestTemplate")
+ private RestTemplate calleeRestTemplate;
@Autowired
private CircuitBreakerFactory circuitBreakerFactory;
@@ -110,7 +102,7 @@ public class CircuitBreakerController {
public String circuitBreakRestTemplate() {
return circuitBreakerFactory
.create(MetadataContext.LOCAL_NAMESPACE + "#QuickstartCalleeService#/quickstart/callee/circuitBreak#http#GET")
- .run(() -> defaultRestTemplate.getForObject("/quickstart/callee/circuitBreak", String.class),
+ .run(() -> calleeRestTemplate.getForObject("/quickstart/callee/circuitBreak", String.class),
throwable -> "trigger the refuse for service callee."
);
}
@@ -122,17 +114,7 @@ public class CircuitBreakerController {
@GetMapping("/rest/fallbackFromPolaris/wildcard/{uid}")
public ResponseEntity circuitBreakRestTemplateFallbackFromPolarisWildcard(@PathVariable String uid) {
String path = String.format("/quickstart/callee/circuitBreak/wildcard/%s", uid);
- return restTemplateFallbackFromPolaris.getForEntity(path, String.class);
- }
-
- /**
- * RestTemplate wildcard circuit breaker with fallback from code.
- * @return circuit breaker information of callee
- */
- @GetMapping("/rest/fallbackFromCode/wildcard/{uid}")
- public ResponseEntity circuitBreakRestTemplateFallbackFromCodeWildcard(@PathVariable String uid) {
- String path = String.format("/quickstart/callee/circuitBreak/wildcard/%s", uid);
- return restTemplateFallbackFromCode.getForEntity(path, String.class);
+ return calleeRestTemplate.getForEntity(path, String.class);
}
/**
@@ -142,21 +124,7 @@ public class CircuitBreakerController {
@GetMapping("/rest/fallbackFromPolaris")
public ResponseEntity circuitBreakRestTemplateFallbackFromPolaris() {
try {
- return restTemplateFallbackFromPolaris.getForEntity("/quickstart/callee/circuitBreak", String.class);
- }
- catch (HttpClientErrorException | HttpServerErrorException httpClientErrorException) {
- return new ResponseEntity<>(httpClientErrorException.getResponseBodyAsString(), httpClientErrorException.getStatusCode());
- }
- }
-
- /**
- * RestTemplate circuit breaker with fallback from code.
- * @return circuit breaker information of callee
- */
- @GetMapping("/rest/fallbackFromCode")
- public ResponseEntity circuitBreakRestTemplateFallbackFromCode() {
- try {
- return restTemplateFallbackFromCode.getForEntity("/quickstart/callee/circuitBreak", String.class);
+ return calleeRestTemplate.getForEntity("/quickstart/callee/circuitBreak", String.class);
}
catch (HttpClientErrorException | HttpServerErrorException httpClientErrorException) {
return new ResponseEntity<>(httpClientErrorException.getResponseBodyAsString(), httpClientErrorException.getStatusCode());
diff --git a/spring-cloud-tencent-examples/tsf-example/consumer-demo/pom.xml b/spring-cloud-tencent-examples/tsf-example/consumer-demo/pom.xml
index 44abeeb31..ca0dc4358 100644
--- a/spring-cloud-tencent-examples/tsf-example/consumer-demo/pom.xml
+++ b/spring-cloud-tencent-examples/tsf-example/consumer-demo/pom.xml
@@ -14,27 +14,7 @@
com.tencent.cloud
- spring-cloud-starter-tencent-polaris-discovery
-
-
-
- com.tencent.cloud
- spring-cloud-starter-tencent-polaris-config
-
-
-
- com.tencent.cloud
- spring-cloud-starter-tencent-polaris-contract
-
-
-
- com.tencent.cloud
- spring-cloud-starter-tencent-polaris-router
-
-
-
- com.tencent.cloud
- spring-cloud-starter-tencent-polaris-circuitbreaker
+ spring-cloud-starter-tencent-all
@@ -46,16 +26,6 @@
org.springframework.cloud
spring-cloud-starter-openfeign
-
-
- com.tencent.cloud
- spring-cloud-starter-tencent-metadata-transfer
-
-
-
- com.tencent.cloud
- spring-cloud-starter-tencent-trace-plugin
-
diff --git a/spring-cloud-tencent-examples/tsf-example/consumer-demo/src/main/java/com/tencent/cloud/tsf/demo/consumer/ConsumerApplication.java b/spring-cloud-tencent-examples/tsf-example/consumer-demo/src/main/java/com/tencent/cloud/tsf/demo/consumer/ConsumerApplication.java
index d5479c2fd..7b7f3f91d 100644
--- a/spring-cloud-tencent-examples/tsf-example/consumer-demo/src/main/java/com/tencent/cloud/tsf/demo/consumer/ConsumerApplication.java
+++ b/spring-cloud-tencent-examples/tsf-example/consumer-demo/src/main/java/com/tencent/cloud/tsf/demo/consumer/ConsumerApplication.java
@@ -17,8 +17,6 @@
package com.tencent.cloud.tsf.demo.consumer;
-import com.tencent.cloud.polaris.circuitbreaker.resttemplate.PolarisCircuitBreaker;
-
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
@@ -37,7 +35,6 @@ public class ConsumerApplication {
@LoadBalanced
@Bean
- @PolarisCircuitBreaker
public RestTemplate restTemplate() {
return new RestTemplate();
}
diff --git a/spring-cloud-tencent-examples/tsf-example/consumer-demo/src/main/java/com/tencent/cloud/tsf/demo/consumer/controller/ConsumerController.java b/spring-cloud-tencent-examples/tsf-example/consumer-demo/src/main/java/com/tencent/cloud/tsf/demo/consumer/controller/ConsumerController.java
index 3173935f2..605147ece 100644
--- a/spring-cloud-tencent-examples/tsf-example/consumer-demo/src/main/java/com/tencent/cloud/tsf/demo/consumer/controller/ConsumerController.java
+++ b/spring-cloud-tencent-examples/tsf-example/consumer-demo/src/main/java/com/tencent/cloud/tsf/demo/consumer/controller/ConsumerController.java
@@ -19,14 +19,17 @@ package com.tencent.cloud.tsf.demo.consumer.controller;
import java.util.HashMap;
import java.util.Map;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
+import com.tencent.cloud.common.util.PolarisCompletableFutureUtils;
import com.tencent.cloud.tsf.demo.consumer.proxy.ProviderDemoService;
import com.tencent.cloud.tsf.demo.consumer.proxy.ProviderService;
import com.tencent.polaris.api.utils.StringUtils;
import com.tencent.polaris.circuitbreak.client.exception.CallAbortedException;
import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.tsf.core.context.TsfContext;
+import org.springframework.tsf.core.TsfContext;
import org.springframework.tsf.core.entity.Tag;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
@@ -62,7 +65,30 @@ public class ConsumerController {
catch (CallAbortedException callAbortedException) {
return callAbortedException.getMessage();
}
+ }
+
+ @RequestMapping(value = "/echo-rest-async/{str}", method = RequestMethod.GET)
+ public String restAsync(@PathVariable String str,
+ @RequestParam(required = false) String tagName,
+ @RequestParam(required = false) String tagValue) throws ExecutionException, InterruptedException {
+ if (StringUtils.isNotBlank(tagName)) {
+ TsfContext.putTag(tagName, tagValue);
+ }
+ TsfContext.putTag("operation", "rest");
+ Map mTags = new HashMap<>();
+ mTags.put("rest-trace-key1", "value1");
+ mTags.put("rest-trace-key2", "value2");
+ TsfContext.putTags(mTags, Tag.ControlFlag.TRANSITIVE);
+ CompletableFuture echoFuture = PolarisCompletableFutureUtils.supplyAsync(() -> {
+ try {
+ return restTemplate.getForObject("http://provider-demo/echo/" + str, String.class);
+ }
+ catch (CallAbortedException callAbortedException) {
+ return callAbortedException.getMessage();
+ }
+ });
+ return echoFuture.get();
}
@RequestMapping(value = "/echo-feign/{str}", method = RequestMethod.GET)
diff --git a/spring-cloud-tencent-examples/tsf-example/consumer-demo/src/main/java/com/tencent/cloud/tsf/demo/consumer/controller/SdkBaseTest.java b/spring-cloud-tencent-examples/tsf-example/consumer-demo/src/main/java/com/tencent/cloud/tsf/demo/consumer/controller/SdkBaseTest.java
new file mode 100644
index 000000000..c90065c18
--- /dev/null
+++ b/spring-cloud-tencent-examples/tsf-example/consumer-demo/src/main/java/com/tencent/cloud/tsf/demo/consumer/controller/SdkBaseTest.java
@@ -0,0 +1,54 @@
+/*
+ * Tencent is pleased to support the open source community by making spring-cloud-tencent available.
+ *
+ * Copyright (C) 2021 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.demo.consumer.controller;
+
+import com.tencent.polaris.api.utils.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.tsf.core.TsfContext;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.client.RestTemplate;
+
+@RestController
+public class SdkBaseTest {
+
+ private static final Logger LOG = LoggerFactory.getLogger(SdkBaseTest.class);
+
+ @Autowired
+ private RestTemplate restTemplate;
+
+ // 调用一次provider接口
+ @RequestMapping(value = "/echo-once/{str}", method = RequestMethod.GET)
+ public String restOnceProvider(@PathVariable String str,
+ @RequestParam(required = false) String tagName,
+ @RequestParam(required = false) String tagValue) {
+ if (!StringUtils.isEmpty(tagName)) {
+ TsfContext.putTag(tagName, tagValue);
+ }
+ LOG.info("start call echo-once");
+ String result = restTemplate.getForObject("http://provider-demo/echo/" + str, String.class);
+ LOG.info("end call echo-once, the result is : " + result);
+ return result;
+ }
+}
diff --git a/spring-cloud-tencent-examples/tsf-example/provider-demo/pom.xml b/spring-cloud-tencent-examples/tsf-example/provider-demo/pom.xml
index 16282e5b5..88adb4e5e 100644
--- a/spring-cloud-tencent-examples/tsf-example/provider-demo/pom.xml
+++ b/spring-cloud-tencent-examples/tsf-example/provider-demo/pom.xml
@@ -14,29 +14,8 @@
com.tencent.cloud
- spring-cloud-starter-tencent-polaris-discovery
+ spring-cloud-starter-tencent-all
-
-
- com.tencent.cloud
- spring-cloud-starter-tencent-polaris-config
-
-
-
- com.tencent.cloud
- spring-cloud-starter-tencent-polaris-contract
-
-
-
- com.tencent.cloud
- spring-cloud-starter-tencent-polaris-ratelimit
-
-
-
- com.tencent.cloud
- spring-cloud-starter-tencent-polaris-auth
-
-
org.springframework.boot
spring-boot-starter-web
@@ -45,14 +24,6 @@
org.springframework.boot
spring-boot-starter-actuator
-
- com.tencent.cloud
- spring-cloud-starter-tencent-metadata-transfer
-
-
- com.tencent.cloud
- spring-cloud-starter-tencent-trace-plugin
-
diff --git a/spring-cloud-tencent-plugin-starters/pom.xml b/spring-cloud-tencent-plugin-starters/pom.xml
index 702dfeca4..4159c7843 100644
--- a/spring-cloud-tencent-plugin-starters/pom.xml
+++ b/spring-cloud-tencent-plugin-starters/pom.xml
@@ -21,6 +21,8 @@
spring-cloud-tencent-lossless-plugin
spring-cloud-starter-tencent-threadlocal-plugin
spring-cloud-starter-tencent-trace-plugin
+ spring-cloud-starter-tencent-fault-tolerance
+ spring-cloud-tencent-security-protection-plugin
diff --git a/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-fault-tolerance/pom.xml b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-fault-tolerance/pom.xml
new file mode 100644
index 000000000..f22d224e7
--- /dev/null
+++ b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-fault-tolerance/pom.xml
@@ -0,0 +1,34 @@
+
+
+
+ spring-cloud-tencent-plugin-starters
+ com.tencent.cloud
+ ${revision}
+ ../pom.xml
+
+ 4.0.0
+
+ spring-cloud-starter-tencent-fault-tolerance
+ Spring Cloud Starter Tencent Fault Tolerance Plugin
+
+
+
+ org.springframework.cloud
+ spring-cloud-context
+
+
+
+ org.springframework.boot
+ spring-boot-starter-aop
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
\ No newline at end of file
diff --git a/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-fault-tolerance/src/main/java/com/tencent/cloud/plugin/faulttolerance/annotation/FaultTolerance.java b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-fault-tolerance/src/main/java/com/tencent/cloud/plugin/faulttolerance/annotation/FaultTolerance.java
new file mode 100644
index 000000000..28f4642d6
--- /dev/null
+++ b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-fault-tolerance/src/main/java/com/tencent/cloud/plugin/faulttolerance/annotation/FaultTolerance.java
@@ -0,0 +1,95 @@
+/*
+ * Tencent is pleased to support the open source community by making spring-cloud-tencent available.
+ *
+ * Copyright (C) 2021 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.plugin.faulttolerance.annotation;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import com.tencent.cloud.plugin.faulttolerance.model.FaultToleranceStrategy;
+
+/**
+ * Annotation for Fault Tolerance.
+ *
+ * @author Haotian Zhang
+ */
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+@Inherited
+public @interface FaultTolerance {
+
+ /**
+ * Specifies a method to process fallback logic.
+ * A fallback method should be defined in the same class where is @FaultTolerance.
+ * Also, a fallback method should have same signature to a method.
+ * for example:
+ *
+ *
@FaultTolerance(fallbackMethod = "getByIdFallback").
+ * public String getById(String id) {
+ * // original method implementation
+ * }
+ * public String getByIdFallback(String id) {
+ * // fallback method implementation
+ * }
+ *
+ *
+ * @return method name
+ */
+ String fallbackMethod() default "";
+
+ /**
+ * Defines exceptions which should be ignored.
+ *
+ * @return exceptions to ignore
+ */
+ Class extends Throwable>[] ignoreExceptions() default {};
+
+ /**
+ * Defines exceptions which should be retried.
+ * Default is all exceptions.
+ *
+ * @return exceptions to wrap
+ */
+ Class extends Throwable>[] raisedExceptions() default {};
+
+ /**
+ * Defines the fault tolerance strategy, the default is fast fail strategy.
+ * @see FaultToleranceStrategy
+ *
+ * @return the fault tolerance strategy
+ */
+ FaultToleranceStrategy strategy() default FaultToleranceStrategy.FAIL_FAST;
+
+ /**
+ * Number of retries, only used under {@link FaultToleranceStrategy}.FAIL_OVER strategy. Default is 0.
+ *
+ * @return the maximum number of retry attempts
+ */
+ int maxAttempts() default 0;
+
+ /**
+ * The parallelism of forking is only used under the {@link FaultToleranceStrategy}.FORKING strategy.
+ *
+ * @return the parallelism level
+ */
+ int parallelism() default 1;
+}
diff --git a/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-fault-tolerance/src/main/java/com/tencent/cloud/plugin/faulttolerance/common/FallbackMethod.java b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-fault-tolerance/src/main/java/com/tencent/cloud/plugin/faulttolerance/common/FallbackMethod.java
new file mode 100644
index 000000000..84671502b
--- /dev/null
+++ b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-fault-tolerance/src/main/java/com/tencent/cloud/plugin/faulttolerance/common/FallbackMethod.java
@@ -0,0 +1,43 @@
+/*
+ * Tencent is pleased to support the open source community by making spring-cloud-tencent available.
+ *
+ * Copyright (C) 2021 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.plugin.faulttolerance.common;
+
+import java.lang.reflect.Method;
+
+/**
+ * Fallback method for fault-tolerance.
+ *
+ * @author zhixinzxliu
+ */
+public class FallbackMethod {
+
+ /**
+ * Absent fallback method.
+ */
+ public static final FallbackMethod ABSENT = new FallbackMethod(null);
+
+ private final Method method;
+
+ public FallbackMethod(Method method) {
+ this.method = method;
+ }
+
+ public Method getMethod() {
+ return method;
+ }
+}
diff --git a/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-fault-tolerance/src/main/java/com/tencent/cloud/plugin/faulttolerance/config/FaultToleranceAutoConfiguration.java b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-fault-tolerance/src/main/java/com/tencent/cloud/plugin/faulttolerance/config/FaultToleranceAutoConfiguration.java
new file mode 100644
index 000000000..41246bcee
--- /dev/null
+++ b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-fault-tolerance/src/main/java/com/tencent/cloud/plugin/faulttolerance/config/FaultToleranceAutoConfiguration.java
@@ -0,0 +1,42 @@
+/*
+ * Tencent is pleased to support the open source community by making spring-cloud-tencent available.
+ *
+ * Copyright (C) 2021 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.plugin.faulttolerance.config;
+
+import com.tencent.cloud.plugin.faulttolerance.instrument.FaultToleranceAspect;
+
+import org.springframework.beans.factory.support.RootBeanDefinition;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Role;
+
+/**
+ * FaultTolerance Auto-Configuration.
+ *
+ * @author Haotian Zhang
+ */
+@Configuration(proxyBeanMethods = false)
+@Role(RootBeanDefinition.ROLE_INFRASTRUCTURE)
+public class FaultToleranceAutoConfiguration {
+
+ @Bean
+ @ConditionalOnMissingBean
+ public FaultToleranceAspect faultToleranceAspect() {
+ return new FaultToleranceAspect();
+ }
+}
diff --git a/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-fault-tolerance/src/main/java/com/tencent/cloud/plugin/faulttolerance/instrument/FaultToleranceAspect.java b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-fault-tolerance/src/main/java/com/tencent/cloud/plugin/faulttolerance/instrument/FaultToleranceAspect.java
new file mode 100644
index 000000000..91803eba3
--- /dev/null
+++ b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-fault-tolerance/src/main/java/com/tencent/cloud/plugin/faulttolerance/instrument/FaultToleranceAspect.java
@@ -0,0 +1,248 @@
+/*
+ * Tencent is pleased to support the open source community by making spring-cloud-tencent available.
+ *
+ * Copyright (C) 2021 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.plugin.faulttolerance.instrument;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+import com.tencent.cloud.plugin.faulttolerance.annotation.FaultTolerance;
+import com.tencent.cloud.plugin.faulttolerance.common.FallbackMethod;
+import com.tencent.cloud.plugin.faulttolerance.model.FaultToleranceStrategy;
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.aspectj.lang.annotation.Around;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Pointcut;
+import org.aspectj.lang.reflect.MethodSignature;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.springframework.cloud.tsf.faulttolerance.annotation.TsfFaultTolerance;
+import org.springframework.cloud.tsf.faulttolerance.model.TsfFaultToleranceStragety;
+
+/**
+ * Fault tolerance.
+ *
+ * @author zhixinzxliu, Haotian Zhang
+ */
+@Aspect
+public class FaultToleranceAspect {
+
+ private static final Logger logger = LoggerFactory.getLogger(FaultToleranceAspect.class);
+
+ private final Map fallbackMethodMap = new ConcurrentHashMap<>();
+ private final ExecutorService executorService = Executors.newCachedThreadPool();
+
+ @Pointcut("@annotation(org.springframework.cloud.tsf.faulttolerance.annotation.TsfFaultTolerance)"
+ + " || @annotation(com.tencent.cloud.plugin.faulttolerance.annotation.FaultTolerance)")
+ public void faultToleranceAnnotationPointcut() {
+ }
+
+ @Around("faultToleranceAnnotationPointcut()")
+ public Object methodsAnnotatedWithFaultTolerance(final ProceedingJoinPoint joinPoint) throws Throwable {
+ MethodSignature signature = (MethodSignature) joinPoint.getSignature();
+ FaultTolerance faultTolerance = signature.getMethod().getAnnotation(FaultTolerance.class);
+ TsfFaultTolerance tsfFaultTolerance = signature.getMethod().getAnnotation(TsfFaultTolerance.class);
+
+ Object result;
+ try {
+ // Invoke job in parallel. Whoever returns the result first will use it.
+ // The latter result will be ignored directly.
+ // If all exceptions occur, an exception will be thrown.
+ if (faultTolerance != null
+ && faultTolerance.strategy() == FaultToleranceStrategy.FORKING
+ && faultTolerance.parallelism() > 1) {
+ List> jobs = generateJobs(faultTolerance.parallelism(), joinPoint);
+ result = executorService.invokeAny(jobs);
+ }
+ else if (tsfFaultTolerance != null &&
+ tsfFaultTolerance.strategy() == TsfFaultToleranceStragety.FORKING &&
+ tsfFaultTolerance.parallelism() > 1) {
+ List> jobs = generateJobs(tsfFaultTolerance.parallelism(), joinPoint);
+ result = executorService.invokeAny(jobs);
+ }
+ else {
+ result = joinPoint.proceed();
+ }
+ }
+ catch (Throwable throwable) {
+ return execFaultToleranceLogic(joinPoint, faultTolerance, tsfFaultTolerance, throwable);
+ }
+
+ return result;
+ }
+
+ private Object execFaultToleranceLogic(ProceedingJoinPoint joinPoint, FaultTolerance faultTolerance, TsfFaultTolerance tsfFaultTolerance, Throwable throwable) throws Throwable {
+ if (!needExecuteFaultTolerance(faultTolerance, tsfFaultTolerance, throwable)) {
+ throw throwable;
+ }
+
+ // 重试逻辑
+ if ((faultTolerance != null && faultTolerance.strategy() == FaultToleranceStrategy.FAIL_OVER)
+ || (tsfFaultTolerance != null && tsfFaultTolerance.strategy() == TsfFaultToleranceStragety.FAIL_OVER)) {
+ int maxAttempts = faultTolerance != null ? faultTolerance.maxAttempts() : tsfFaultTolerance.maxAttempts();
+ while (maxAttempts > 0) {
+ try {
+ return joinPoint.proceed();
+ }
+ catch (Throwable throwable1) {
+ if (!needExecuteFaultTolerance(faultTolerance, tsfFaultTolerance, throwable1)) {
+ throw throwable1;
+ }
+
+ logger.error("The {} time retry error, will continue retry {} times.", maxAttempts, maxAttempts - 1, throwable1);
+ }
+ finally {
+ maxAttempts--;
+ }
+ }
+ }
+
+ MethodSignature signature = (MethodSignature) joinPoint.getSignature();
+ Method method = signature.getMethod();
+ if (method == null) {
+ throw throwable;
+ }
+
+ FallbackMethod fallbackMethod = fallbackMethodMap.get(method);
+ if (fallbackMethod == null) {
+ fallbackMethod = resolveFallbackMethod(joinPoint);
+ fallbackMethodMap.putIfAbsent(method, fallbackMethod);
+ }
+ if (fallbackMethod.getMethod() != null) {
+ return fallbackMethod.getMethod().invoke(joinPoint.getTarget(), joinPoint.getArgs());
+ }
+
+ throw throwable;
+ }
+
+ private List> generateJobs(int parallelism, final ProceedingJoinPoint joinPoint) {
+ List> jobs = new ArrayList<>();
+
+ for (int i = 0; i < parallelism; i++) {
+ jobs.add(() -> {
+ try {
+ return joinPoint.proceed();
+ }
+ catch (Throwable t) {
+ throw new RuntimeException(t);
+ }
+ });
+ }
+
+ return jobs;
+ }
+
+ /**
+ * 1. If the user sets ignoreExceptions and the current exception is a subclass of one of them,
+ * the fault-tolerant logic will not be executed.
+ * 2. If the user does not set ignoreExceptions or the current exception is not a subclass of ignoreExceptions
+ * and meets the following conditions, fault-tolerant logic will be executed:
+ * 2.1. If the user does not set raisedExceptions, fault tolerance logic will be executed.
+ * 2.2. The user has set raisedExceptions, and the current exception is a subclass of one of the raisedExceptions set by the user.
+ */
+ private boolean needExecuteFaultTolerance(FaultTolerance faultTolerance, TsfFaultTolerance tsfFaultTolerance, Throwable throwable) {
+ if (faultTolerance == null && tsfFaultTolerance == null) {
+ return false;
+ }
+ Class extends Throwable>[] ignoreExceptions = faultTolerance != null ? faultTolerance.ignoreExceptions() : null;
+ if (ignoreExceptions == null || ignoreExceptions.length == 0) {
+ ignoreExceptions = tsfFaultTolerance != null ? tsfFaultTolerance.ignoreExceptions() : null;
+ }
+ Class extends Throwable>[] raisedExceptions = faultTolerance != null ? faultTolerance.raisedExceptions() : null;
+ if (raisedExceptions == null || raisedExceptions.length == 0) {
+ raisedExceptions = tsfFaultTolerance != null ? tsfFaultTolerance.raisedExceptions() : null;
+ }
+
+ try {
+
+ if (ignoreExceptions != null) {
+ for (Class extends Throwable> ignoreException : ignoreExceptions) {
+ if (ignoreException.isAssignableFrom(throwable.getClass())) {
+ logger.debug("The exception {} is ignored.", throwable.getClass().getName());
+ return false;
+ }
+ }
+ }
+
+ if (raisedExceptions == null || raisedExceptions.length == 0) {
+ return true;
+ }
+ else {
+ for (Class extends Throwable> raisedException : raisedExceptions) {
+ if (raisedException.isAssignableFrom(throwable.getClass())) {
+ return true;
+ }
+ }
+ }
+ }
+ catch (Throwable throwable1) {
+ logger.warn("Check exception {} failed.", throwable.getClass().getName(), throwable1);
+ return false;
+ }
+
+ return false;
+ }
+
+ protected FallbackMethod resolveFallbackMethod(ProceedingJoinPoint joinPoint) {
+ MethodSignature signature = (MethodSignature) joinPoint.getSignature();
+ FaultTolerance faultTolerance = signature.getMethod().getAnnotation(FaultTolerance.class);
+ TsfFaultTolerance tsfFaultTolerance = signature.getMethod().getAnnotation(TsfFaultTolerance.class);
+
+ String fallbackMethodName = faultTolerance != null ? faultTolerance.fallbackMethod() : tsfFaultTolerance.fallbackMethod();
+ Class> targetClass = joinPoint.getTarget().getClass();
+ Class>[] parameterTypes = signature.getMethod().getParameterTypes();
+
+ Method method = getDeclaredMethodFor(targetClass, fallbackMethodName, false, parameterTypes);
+
+ if (method == null) {
+ return FallbackMethod.ABSENT;
+ }
+ else {
+ if (signature.getMethod().getReturnType().isAssignableFrom(method.getReturnType())) {
+ return new FallbackMethod(method);
+ }
+ else {
+ return FallbackMethod.ABSENT;
+ }
+ }
+ }
+
+ private Method getDeclaredMethodFor(Class> clazz, String name, boolean inRecursive, Class>... parameterTypes) {
+ try {
+ return clazz.getDeclaredMethod(name, parameterTypes);
+ }
+ catch (NoSuchMethodException e) {
+ if (!inRecursive) {
+ logger.warn("Fallback method not found! Classname = {}, methodName = {}, parameterTypes = {}",
+ clazz.getName(), name, Arrays.toString(parameterTypes));
+ }
+ Class> superClass = clazz.getSuperclass();
+ if (superClass != null) {
+ return getDeclaredMethodFor(superClass, name, true, parameterTypes);
+ }
+ }
+ return null;
+ }
+}
diff --git a/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-fault-tolerance/src/main/java/com/tencent/cloud/plugin/faulttolerance/model/FaultToleranceStrategy.java b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-fault-tolerance/src/main/java/com/tencent/cloud/plugin/faulttolerance/model/FaultToleranceStrategy.java
new file mode 100644
index 000000000..b2563b507
--- /dev/null
+++ b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-fault-tolerance/src/main/java/com/tencent/cloud/plugin/faulttolerance/model/FaultToleranceStrategy.java
@@ -0,0 +1,37 @@
+/*
+ * Tencent is pleased to support the open source community by making spring-cloud-tencent available.
+ *
+ * Copyright (C) 2021 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.plugin.faulttolerance.model;
+
+public enum FaultToleranceStrategy {
+ /**
+ * Fails directly. For downstream services without idempotence, fail fast is recommended.
+ */
+ FAIL_FAST,
+
+ /**
+ * If the request is wrong, it will be retried.
+ */
+ FAIL_OVER,
+
+ /**
+ * Sending multiple requests at the same time requires the user to configure the degree of parallelism.
+ * For example, if two requests are sent at the same time, whichever one returns first will return the result.
+ * If the first request is an exception, it will wait for another request, and if all are exceptions, an exception will be returned.
+ */
+ FORKING
+}
diff --git a/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-fault-tolerance/src/main/java/org/springframework/cloud/tsf/faulttolerance/annotation/EnableTsfFaultTolerance.java b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-fault-tolerance/src/main/java/org/springframework/cloud/tsf/faulttolerance/annotation/EnableTsfFaultTolerance.java
new file mode 100644
index 000000000..80ad9cfab
--- /dev/null
+++ b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-fault-tolerance/src/main/java/org/springframework/cloud/tsf/faulttolerance/annotation/EnableTsfFaultTolerance.java
@@ -0,0 +1,40 @@
+/*
+ * Tencent is pleased to support the open source community by making spring-cloud-tencent available.
+ *
+ * Copyright (C) 2021 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 org.springframework.cloud.tsf.faulttolerance.annotation;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Empty annotation. Compatible with old versions TSF SDK.
+ *
+ * Deprecated since 2.0.0.0.
+ *
+ * @author Haotian Zhang
+ */
+@Deprecated
+@Target(ElementType.TYPE)
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+@Inherited
+public @interface EnableTsfFaultTolerance {
+}
diff --git a/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-fault-tolerance/src/main/java/org/springframework/cloud/tsf/faulttolerance/annotation/TsfFaultTolerance.java b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-fault-tolerance/src/main/java/org/springframework/cloud/tsf/faulttolerance/annotation/TsfFaultTolerance.java
new file mode 100644
index 000000000..9a47304ba
--- /dev/null
+++ b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-fault-tolerance/src/main/java/org/springframework/cloud/tsf/faulttolerance/annotation/TsfFaultTolerance.java
@@ -0,0 +1,95 @@
+/*
+ * Tencent is pleased to support the open source community by making spring-cloud-tencent available.
+ *
+ * Copyright (C) 2021 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 org.springframework.cloud.tsf.faulttolerance.annotation;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import org.springframework.cloud.tsf.faulttolerance.model.TsfFaultToleranceStragety;
+
+/**
+ * Deprecated since 2.0.0.0.
+ *
+ * @author zhixinzxiliu
+ */
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+@Inherited
+@Deprecated
+public @interface TsfFaultTolerance {
+ /**
+ * Specifies a method to process fallback logic.
+ * A fallback method should be defined in the same class where is TsfFaultTolerance.
+ * Also a fallback method should have same signature to a method.
+ * for example:
+ *
+ * @TsfFaultTolerance(fallbackMethod = "getByIdFallback")
+ * public String getById(String id) {...}
+ *
+ * public String getByIdFallback(String id) {...}
+ *
+ *
+ * @return method name
+ */
+ String fallbackMethod() default "";
+
+ /**
+ * Specifies command properties.
+ *
+ * @return command properties
+ */
+ TsfFaultToleranceProperty[] properties() default {};
+
+ /**
+ * Defines exceptions which should be ignored.
+ *
+ * @return exceptions to ignore
+ */
+ Class extends Throwable>[] ignoreExceptions() default {};
+
+ /**
+ * Defines exceptions which should be retry.
+ * Default is all exceptions.
+ *
+ * @return exceptions to wrap
+ */
+ Class extends Throwable>[] raisedExceptions() default {};
+
+ /**
+ * 设置容错策略,默认为快速失败策略.
+ * @return 当前使用的容错策略枚举值
+ */
+ TsfFaultToleranceStragety strategy() default TsfFaultToleranceStragety.FAIL_FAST;
+
+ /**
+ * 重试次数,只在Failover策略下用到.
+ * @return 最大重试次数,0表示不重试
+ */
+ int maxAttempts() default 0;
+
+ /**
+ * forking 的并行度,只在Forking策略下用到.
+ * @return 并行执行的线程数,默认为1
+ */
+ int parallelism() default 1;
+}
diff --git a/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-fault-tolerance/src/main/java/org/springframework/cloud/tsf/faulttolerance/annotation/TsfFaultToleranceProperty.java b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-fault-tolerance/src/main/java/org/springframework/cloud/tsf/faulttolerance/annotation/TsfFaultToleranceProperty.java
new file mode 100644
index 000000000..5c4a91ad0
--- /dev/null
+++ b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-fault-tolerance/src/main/java/org/springframework/cloud/tsf/faulttolerance/annotation/TsfFaultToleranceProperty.java
@@ -0,0 +1,54 @@
+/*
+ * Tencent is pleased to support the open source community by making spring-cloud-tencent available.
+ *
+ * Copyright (C) 2021 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 org.springframework.cloud.tsf.faulttolerance.annotation;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * This annotation allows specify TsfFaultTolerance properties in the following format:
+ * property name = property value.
+ *
+ * Deprecated since 2.0.0.0.
+ *
+ * @author zhixinzxliu
+ */
+@Target({ElementType.METHOD})
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+@Deprecated
+public @interface TsfFaultToleranceProperty {
+
+ /**
+ * Property name.
+ *
+ * @return name
+ */
+ String name();
+
+ /**
+ * Property value.
+ *
+ * @return value
+ */
+ String value();
+
+}
diff --git a/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-fault-tolerance/src/main/java/org/springframework/cloud/tsf/faulttolerance/model/TsfFaultToleranceStragety.java b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-fault-tolerance/src/main/java/org/springframework/cloud/tsf/faulttolerance/model/TsfFaultToleranceStragety.java
new file mode 100644
index 000000000..1e0e874a4
--- /dev/null
+++ b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-fault-tolerance/src/main/java/org/springframework/cloud/tsf/faulttolerance/model/TsfFaultToleranceStragety.java
@@ -0,0 +1,41 @@
+/*
+ * Tencent is pleased to support the open source community by making spring-cloud-tencent available.
+ *
+ * Copyright (C) 2021 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 org.springframework.cloud.tsf.faulttolerance.model;
+
+/**
+ * Deprecated since 2.0.0.0.
+ */
+@Deprecated
+public enum TsfFaultToleranceStragety {
+ /**
+ * Fails directly. For downstream services without idempotence, fail fast is recommended.
+ */
+ FAIL_FAST,
+
+ /**
+ * If the request is wrong, it will be retried.
+ */
+ FAIL_OVER,
+
+ /**
+ * Sending multiple requests at the same time requires the user to configure the degree of parallelism.
+ * For example, if two requests are sent at the same time, whichever one returns first will return the result.
+ * If the first request is an exception, it will wait for another request, and if all are exceptions, an exception will be returned.
+ */
+ FORKING
+}
diff --git a/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-fault-tolerance/src/main/resources/META-INF/spring.factories b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-fault-tolerance/src/main/resources/META-INF/spring.factories
new file mode 100644
index 000000000..31521a910
--- /dev/null
+++ b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-fault-tolerance/src/main/resources/META-INF/spring.factories
@@ -0,0 +1,3 @@
+org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
+ com.tencent.cloud.plugin.faulttolerance.config.FaultToleranceAutoConfiguration
+
diff --git a/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-fault-tolerance/src/test/java/com/tencent/cloud/plugin/faulttolerance/integration/FaultToleranceService.java b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-fault-tolerance/src/test/java/com/tencent/cloud/plugin/faulttolerance/integration/FaultToleranceService.java
new file mode 100644
index 000000000..7bba88ac8
--- /dev/null
+++ b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-fault-tolerance/src/test/java/com/tencent/cloud/plugin/faulttolerance/integration/FaultToleranceService.java
@@ -0,0 +1,73 @@
+/*
+ * Tencent is pleased to support the open source community by making spring-cloud-tencent available.
+ *
+ * Copyright (C) 2021 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.plugin.faulttolerance.integration;
+
+import java.util.concurrent.atomic.AtomicInteger;
+
+import com.tencent.cloud.plugin.faulttolerance.annotation.FaultTolerance;
+import com.tencent.cloud.plugin.faulttolerance.model.FaultToleranceStrategy;
+
+/**
+ * Fault tolerance test service.
+ *
+ * @author Haotian Zhang
+ */
+public class FaultToleranceService {
+
+ private final AtomicInteger failFastCount = new AtomicInteger(0);
+ private final AtomicInteger failOverCount = new AtomicInteger(0);
+ private final AtomicInteger forkingCount = new AtomicInteger(0);
+
+ @FaultTolerance(strategy = FaultToleranceStrategy.FAIL_FAST, fallbackMethod = "fallback")
+ public String failFast() {
+ failFastCount.getAndIncrement();
+ throw new RuntimeException("NO");
+ }
+
+ public String fallback() {
+ return "fallback";
+ }
+
+ @FaultTolerance(strategy = FaultToleranceStrategy.FAIL_OVER, maxAttempts = 3)
+ public String failOver() {
+ if (failOverCount.incrementAndGet() % 4 == 0) {
+ return "OK";
+ }
+ throw new RuntimeException("NO");
+ }
+
+ @FaultTolerance(strategy = FaultToleranceStrategy.FORKING, parallelism = 4)
+ public String forking() {
+ if (forkingCount.incrementAndGet() % 4 == 0) {
+ return "OK";
+ }
+ throw new RuntimeException("NO");
+ }
+
+ public int getFailFastCount() {
+ return failFastCount.get();
+ }
+
+ public int getFailOverCount() {
+ return failOverCount.get();
+ }
+
+ public int getForkingCount() {
+ return forkingCount.get();
+ }
+}
diff --git a/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-fault-tolerance/src/test/java/com/tencent/cloud/plugin/faulttolerance/integration/FaultToleranceTest.java b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-fault-tolerance/src/test/java/com/tencent/cloud/plugin/faulttolerance/integration/FaultToleranceTest.java
new file mode 100644
index 000000000..dd931d13d
--- /dev/null
+++ b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-fault-tolerance/src/test/java/com/tencent/cloud/plugin/faulttolerance/integration/FaultToleranceTest.java
@@ -0,0 +1,74 @@
+/*
+ * Tencent is pleased to support the open source community by making spring-cloud-tencent available.
+ *
+ * Copyright (C) 2021 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.plugin.faulttolerance.integration;
+
+import com.tencent.cloud.plugin.faulttolerance.config.FaultToleranceAutoConfiguration;
+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.EnableAutoConfiguration;
+import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.test.context.junit.jupiter.SpringExtension;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * Integration test for Fault Tolerance.
+ *
+ * @author Haotian Zhang
+ */
+@ExtendWith(SpringExtension.class)
+@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, classes = FaultToleranceTest.TestApplication.class)
+public class FaultToleranceTest {
+
+ @Autowired
+ private FaultToleranceService testService;
+
+ @Test
+ public void testFailFast() {
+ assertThat(testService.failFast()).isEqualTo("fallback");
+ assertThat(testService.getFailFastCount()).isEqualTo(1);
+ }
+
+ @Test
+ public void testFailOver() {
+ assertThat(testService.failOver()).isEqualTo("OK");
+ assertThat(testService.getFailOverCount()).isEqualTo(4);
+ }
+
+ @Test
+ public void testForking() {
+ assertThat(testService.forking()).isEqualTo("OK");
+ assertThat(testService.getForkingCount()).isEqualTo(4);
+ }
+
+ @Configuration
+ @EnableAutoConfiguration
+ @ImportAutoConfiguration(FaultToleranceAutoConfiguration.class)
+ public static class TestApplication {
+
+ @Bean
+ public FaultToleranceService faultToleranceService() {
+ return new FaultToleranceService();
+ }
+ }
+}
diff --git a/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-trace-plugin/src/main/java/com/tencent/tsf/monitor/annotation/EnableTsfMonitor.java b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-trace-plugin/src/main/java/com/tencent/tsf/monitor/annotation/EnableTsfMonitor.java
new file mode 100644
index 000000000..801f6e973
--- /dev/null
+++ b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-trace-plugin/src/main/java/com/tencent/tsf/monitor/annotation/EnableTsfMonitor.java
@@ -0,0 +1,41 @@
+/*
+ * Tencent is pleased to support the open source community by making spring-cloud-tencent available.
+ *
+ * Copyright (C) 2021 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.tsf.monitor.annotation;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Empty annotation. Compatible with old versions TSF SDK.
+ *
+ * Deprecated since 2.0.0.0.
+ *
+ * @author Haotian Zhang
+ */
+@Deprecated
+@Target(ElementType.TYPE)
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+@Inherited
+public @interface EnableTsfMonitor {
+
+}
diff --git a/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-trace-plugin/src/main/java/com/tencent/tsf/sleuth/annotation/EnableTsfSleuth.java b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-trace-plugin/src/main/java/com/tencent/tsf/sleuth/annotation/EnableTsfSleuth.java
new file mode 100644
index 000000000..6d74007b1
--- /dev/null
+++ b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-trace-plugin/src/main/java/com/tencent/tsf/sleuth/annotation/EnableTsfSleuth.java
@@ -0,0 +1,41 @@
+/*
+ * Tencent is pleased to support the open source community by making spring-cloud-tencent available.
+ *
+ * Copyright (C) 2021 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.tsf.sleuth.annotation;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Empty annotation. Compatible with old versions TSF SDK.
+ *
+ * Deprecated since 2.0.0.0.
+ *
+ * @author Haotian Zhang
+ */
+@Deprecated
+@Target(ElementType.TYPE)
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+@Inherited
+public @interface EnableTsfSleuth {
+
+}
diff --git a/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-trace-plugin/src/main/resources/META-INF/spring.factories b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-trace-plugin/src/main/resources/META-INF/spring.factories
index 6042016a6..b6956bd18 100644
--- a/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-trace-plugin/src/main/resources/META-INF/spring.factories
+++ b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-trace-plugin/src/main/resources/META-INF/spring.factories
@@ -1,5 +1,5 @@
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
- com.tencent.cloud.plugin.trace.config.TraceConfigModifierAutoConfiguration,\
- com.tencent.cloud.plugin.trace.config.TraceEnhancedPluginAutoConfiguration
+ com.tencent.cloud.plugin.trace.config.TraceConfigModifierAutoConfiguration,\
+ com.tencent.cloud.plugin.trace.config.TraceEnhancedPluginAutoConfiguration
org.springframework.cloud.bootstrap.BootstrapConfiguration=\
com.tencent.cloud.plugin.trace.config.TraceConfigModifierBootstrapAutoConfiguration
diff --git a/spring-cloud-tencent-plugin-starters/spring-cloud-tencent-security-protection-plugin/pom.xml b/spring-cloud-tencent-plugin-starters/spring-cloud-tencent-security-protection-plugin/pom.xml
new file mode 100644
index 000000000..1674db4e8
--- /dev/null
+++ b/spring-cloud-tencent-plugin-starters/spring-cloud-tencent-security-protection-plugin/pom.xml
@@ -0,0 +1,59 @@
+
+
+
+ spring-cloud-tencent-plugin-starters
+ com.tencent.cloud
+ ${revision}
+ ../pom.xml
+
+ 4.0.0
+
+ spring-cloud-tencent-security-protection-plugin
+ Spring Cloud Tencent Lossless Plugin
+
+
+
+
+ org.springframework.boot
+ spring-boot-autoconfigure
+
+
+
+ org.springframework
+ spring-beans
+
+
+
+ org.slf4j
+ slf4j-api
+
+
+
+ org.springframework
+ spring-webmvc
+ true
+
+
+
+ org.springframework
+ spring-webflux
+ true
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+ org.mockito
+ mockito-inline
+ test
+
+
+
+
+
diff --git a/spring-cloud-tencent-plugin-starters/spring-cloud-tencent-security-protection-plugin/src/main/java/com/tencent/cloud/plugin/protection/ExitUtils.java b/spring-cloud-tencent-plugin-starters/spring-cloud-tencent-security-protection-plugin/src/main/java/com/tencent/cloud/plugin/protection/ExitUtils.java
new file mode 100644
index 000000000..2bf12db99
--- /dev/null
+++ b/spring-cloud-tencent-plugin-starters/spring-cloud-tencent-security-protection-plugin/src/main/java/com/tencent/cloud/plugin/protection/ExitUtils.java
@@ -0,0 +1,52 @@
+/*
+ * Tencent is pleased to support the open source community by making spring-cloud-tencent available.
+ *
+ * Copyright (C) 2021 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.plugin.protection;
+
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ConfigurableApplicationContext;
+
+/**
+ * ExitUtils.
+ *
+ * @author Shedfree Wu
+ */
+public final class ExitUtils {
+
+ private ExitUtils() {
+
+ }
+
+ public static void exit(ApplicationContext context) {
+ exit(context, 3000);
+ }
+
+ public static void exit(ApplicationContext context, int delay) {
+ if (context instanceof ConfigurableApplicationContext) {
+ ConfigurableApplicationContext configurableContext = (ConfigurableApplicationContext) context;
+ configurableContext.close();
+ }
+
+ try {
+ Thread.sleep(delay);
+ }
+ catch (InterruptedException e) {
+ // do nothing
+ }
+ System.exit(0);
+ }
+}
diff --git a/spring-cloud-tencent-plugin-starters/spring-cloud-tencent-security-protection-plugin/src/main/java/com/tencent/cloud/plugin/protection/SecurityProtectionAutoConfiguration.java b/spring-cloud-tencent-plugin-starters/spring-cloud-tencent-security-protection-plugin/src/main/java/com/tencent/cloud/plugin/protection/SecurityProtectionAutoConfiguration.java
new file mode 100644
index 000000000..589240c63
--- /dev/null
+++ b/spring-cloud-tencent-plugin-starters/spring-cloud-tencent-security-protection-plugin/src/main/java/com/tencent/cloud/plugin/protection/SecurityProtectionAutoConfiguration.java
@@ -0,0 +1,87 @@
+/*
+ * Tencent is pleased to support the open source community by making spring-cloud-tencent available.
+ *
+ * Copyright (C) 2021 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.plugin.protection;
+
+
+import java.util.List;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.springframework.beans.factory.InitializingBean;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.function.RouterFunction;
+
+/**
+ * SecurityProtectionAutoConfiguration.
+ *
+ * @author Shedfree Wu
+ */
+@Configuration
+public class SecurityProtectionAutoConfiguration {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(SecurityProtectionAutoConfiguration.class);
+
+ @Configuration
+ @ConditionalOnProperty(name = "spring.cloud.tencent.security.protection.servlet.enabled", matchIfMissing = true)
+ @ConditionalOnClass(name = {"org.springframework.web.servlet.function.RouterFunction"})
+ static class ServletProtectionConfiguration implements InitializingBean {
+
+ @Autowired(required = false)
+ List routerFunctions;
+
+ @Autowired
+ ApplicationContext applicationContext;
+
+ @Override
+ public void afterPropertiesSet() {
+ if (routerFunctions != null && !routerFunctions.isEmpty()) {
+ LOGGER.error("Detected the presence of webmvc RouterFunction-related beans, which may trigger the CVE-2024-38819 vulnerability. The program will soon exit.");
+ LOGGER.error("routerFunctions:{}: ", routerFunctions);
+
+ ExitUtils.exit(applicationContext);
+ }
+ }
+ }
+
+ @Configuration
+ @ConditionalOnProperty(name = "spring.cloud.tencent.security.protection.reactive.enabled", matchIfMissing = true)
+ @ConditionalOnClass(name = {"org.springframework.web.reactive.function.server.RouterFunction"})
+ static class ReactiveProtectionConfiguration implements InitializingBean {
+
+ @Autowired(required = false)
+ List routerFunctions;
+
+ @Autowired
+ ApplicationContext applicationContext;
+
+ @Override
+ public void afterPropertiesSet() {
+ if (routerFunctions != null && !routerFunctions.isEmpty()) {
+ LOGGER.error("Detected the presence of webflux RouterFunction-related beans, which may trigger the CVE-2024-38819 vulnerability. The program will soon exit.");
+ LOGGER.error("routerFunctions:{}: ", routerFunctions);
+ ExitUtils.exit(applicationContext);
+ }
+ }
+ }
+
+}
diff --git a/spring-cloud-tencent-plugin-starters/spring-cloud-tencent-security-protection-plugin/src/main/resources/META-INF/spring.factories b/spring-cloud-tencent-plugin-starters/spring-cloud-tencent-security-protection-plugin/src/main/resources/META-INF/spring.factories
new file mode 100644
index 000000000..3e0f0ee08
--- /dev/null
+++ b/spring-cloud-tencent-plugin-starters/spring-cloud-tencent-security-protection-plugin/src/main/resources/META-INF/spring.factories
@@ -0,0 +1,3 @@
+# Auto Configuration
+org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
+com.tencent.cloud.plugin.protection.SecurityProtectionAutoConfiguration
\ No newline at end of file
diff --git a/spring-cloud-tencent-plugin-starters/spring-cloud-tencent-security-protection-plugin/src/test/java/com/tencent/cloud/plugin/protection/SecurityProtectionAutoConfigurationTest.java b/spring-cloud-tencent-plugin-starters/spring-cloud-tencent-security-protection-plugin/src/test/java/com/tencent/cloud/plugin/protection/SecurityProtectionAutoConfigurationTest.java
new file mode 100644
index 000000000..cb93c89ea
--- /dev/null
+++ b/spring-cloud-tencent-plugin-starters/spring-cloud-tencent-security-protection-plugin/src/test/java/com/tencent/cloud/plugin/protection/SecurityProtectionAutoConfigurationTest.java
@@ -0,0 +1,189 @@
+/*
+ * Tencent is pleased to support the open source community by making spring-cloud-tencent available.
+ *
+ * Copyright (C) 2021 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.plugin.protection;
+
+import java.security.Permission;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+import org.springframework.context.ConfigurableApplicationContext;
+import org.springframework.web.servlet.function.RouterFunction;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+
+/**
+ * Test for {@link SecurityProtectionAutoConfiguration}.
+ */
+@ExtendWith(MockitoExtension.class)
+class SecurityProtectionAutoConfigurationTest {
+
+ @Mock
+ private ConfigurableApplicationContext applicationContext;
+
+ @Test
+ void testServletProtectionNoRouterFunctions() {
+ // Arrange
+ SecurityProtectionAutoConfiguration.ServletProtectionConfiguration config =
+ new SecurityProtectionAutoConfiguration.ServletProtectionConfiguration();
+ config.applicationContext = applicationContext;
+ config.routerFunctions = null;
+
+ // Act
+ config.afterPropertiesSet();
+
+ // Verify
+ // Should not call exit when no RouterFunctions present
+ verify(applicationContext, never()).close();
+ }
+
+ @Test
+ void testServletProtectionEmptyRouterFunctions() {
+ // Arrange
+ SecurityProtectionAutoConfiguration.ServletProtectionConfiguration config =
+ new SecurityProtectionAutoConfiguration.ServletProtectionConfiguration();
+ config.applicationContext = applicationContext;
+ config.routerFunctions = new ArrayList<>();
+
+ // Act
+ config.afterPropertiesSet();
+
+ // Verify
+ // Should not call exit when RouterFunctions list is empty
+ verify(applicationContext, never()).close();
+ }
+
+ @Test
+ void testServletProtectionWithRouterFunctions() {
+ // Arrange
+ SecurityProtectionAutoConfiguration.ServletProtectionConfiguration config =
+ new SecurityProtectionAutoConfiguration.ServletProtectionConfiguration();
+ config.applicationContext = mock(ConfigurableApplicationContext.class);
+ List routerFunctions = new ArrayList<>();
+ routerFunctions.add(mock(RouterFunction.class));
+ config.routerFunctions = routerFunctions;
+
+ SecurityManager originalSecurityManager = System.getSecurityManager();
+ System.setSecurityManager(new ExitSecurityManager());
+
+ try {
+ config.afterPropertiesSet();
+ }
+ catch (SecurityException e) {
+ // Ignore
+ }
+ finally {
+ System.setSecurityManager(originalSecurityManager);
+ }
+ }
+
+ @Test
+ void testReactiveProtectionNoRouterFunctions() {
+ // Arrange
+ SecurityProtectionAutoConfiguration.ReactiveProtectionConfiguration config =
+ new SecurityProtectionAutoConfiguration.ReactiveProtectionConfiguration();
+ config.applicationContext = applicationContext;
+ config.routerFunctions = null;
+
+ // Act
+ config.afterPropertiesSet();
+
+ // Verify
+ verify(applicationContext, never()).close();
+ }
+
+ @Test
+ void testReactiveProtectionEmptyRouterFunctions() {
+ // Arrange
+ SecurityProtectionAutoConfiguration.ReactiveProtectionConfiguration config =
+ new SecurityProtectionAutoConfiguration.ReactiveProtectionConfiguration();
+ config.applicationContext = applicationContext;
+ config.routerFunctions = new ArrayList<>();
+
+ // Act
+ config.afterPropertiesSet();
+
+ // Verify
+ verify(applicationContext, never()).close();
+ }
+
+ @Test
+ void testReactiveProtectionWithRouterFunctions() {
+ // Arrange
+ SecurityProtectionAutoConfiguration.ReactiveProtectionConfiguration config =
+ new SecurityProtectionAutoConfiguration.ReactiveProtectionConfiguration();
+ config.applicationContext = mock(ConfigurableApplicationContext.class);
+ List routerFunctions = new ArrayList<>();
+ routerFunctions.add(mock(org.springframework.web.reactive.function.server.RouterFunction.class));
+ config.routerFunctions = routerFunctions;
+
+ SecurityManager originalSecurityManager = System.getSecurityManager();
+ System.setSecurityManager(new ExitSecurityManager());
+
+ try {
+ config.afterPropertiesSet();
+ }
+ catch (SecurityException e) {
+ // Ignore
+ }
+ finally {
+ System.setSecurityManager(originalSecurityManager);
+ }
+ }
+
+ @Test
+ void testInterruptedExceptionHandling() throws InterruptedException {
+ // Arrange
+ ConfigurableApplicationContext mockContext = mock(ConfigurableApplicationContext.class);
+ Thread testThread = new Thread(() -> ExitUtils.exit(mockContext, 3000));
+
+
+
+ SecurityManager originalSecurityManager = System.getSecurityManager();
+ System.setSecurityManager(new ExitSecurityManager());
+
+ try {
+ // Act
+ testThread.start();
+ testThread.interrupt();
+ Thread.sleep(6000);
+ }
+ catch (SecurityException e) {
+ // Ignore
+ }
+ finally {
+ System.setSecurityManager(originalSecurityManager);
+ }
+ }
+
+ public static class ExitSecurityManager extends SecurityManager {
+
+ @Override
+ public void checkPermission(Permission perm) {
+ if (perm.getName().contains("exitVM")) {
+ throw new SecurityException("System.exit is not allowed");
+ }
+ }
+ }
+}
diff --git a/spring-cloud-tencent-polaris-context/pom.xml b/spring-cloud-tencent-polaris-context/pom.xml
index 185c74bd1..375fe7799 100644
--- a/spring-cloud-tencent-polaris-context/pom.xml
+++ b/spring-cloud-tencent-polaris-context/pom.xml
@@ -179,6 +179,16 @@
com.tencent.polaris
registry-memory
+
+
+ error_prone_annotations
+ com.google.errorprone
+
+
+ j2objc-annotations
+ com.google.j2objc
+
+
diff --git a/spring-cloud-tencent-polaris-context/src/main/java/com/tencent/cloud/polaris/context/config/extend/tsf/TsfContextConfigModifier.java b/spring-cloud-tencent-polaris-context/src/main/java/com/tencent/cloud/polaris/context/config/extend/tsf/TsfContextConfigModifier.java
index 13f060de8..5c589c4e6 100644
--- a/spring-cloud-tencent-polaris-context/src/main/java/com/tencent/cloud/polaris/context/config/extend/tsf/TsfContextConfigModifier.java
+++ b/spring-cloud-tencent-polaris-context/src/main/java/com/tencent/cloud/polaris/context/config/extend/tsf/TsfContextConfigModifier.java
@@ -21,6 +21,7 @@ import com.tencent.cloud.common.constant.OrderConstant;
import com.tencent.cloud.polaris.context.PolarisConfigModifier;
import com.tencent.cloud.polaris.context.config.extend.consul.ConsulProperties;
import com.tencent.polaris.api.config.plugin.DefaultPlugins;
+import com.tencent.polaris.api.utils.StringUtils;
import com.tencent.polaris.factory.config.ConfigurationImpl;
import com.tencent.polaris.plugins.event.tsf.TsfEventReporterConfig;
@@ -45,6 +46,13 @@ public class TsfContextConfigModifier implements PolarisConfigModifier {
configuration.getGlobal().getEventReporter().getReporters().add(DefaultPlugins.TSF_EVENT_REPORTER_TYPE);
TsfEventReporterConfig tsfEventReporterConfig = new TsfEventReporterConfig();
+ if (StringUtils.isNotBlank(tsfCoreProperties.getEventMasterIp())) {
+ tsfEventReporterConfig.setEnable(true);
+ }
+ else {
+ tsfEventReporterConfig.setEnable(false);
+ return;
+ }
tsfEventReporterConfig.setEventMasterIp(tsfCoreProperties.getEventMasterIp());
tsfEventReporterConfig.setEventMasterPort(tsfCoreProperties.getEventMasterPort());
tsfEventReporterConfig.setAppId(tsfCoreProperties.getAppId());
diff --git a/spring-cloud-tencent-polaris-context/src/main/java/com/tencent/cloud/polaris/context/config/extend/tsf/TsfCoreEnvironmentPostProcessor.java b/spring-cloud-tencent-polaris-context/src/main/java/com/tencent/cloud/polaris/context/config/extend/tsf/TsfCoreEnvironmentPostProcessor.java
index 35dac9350..73c0317ef 100644
--- a/spring-cloud-tencent-polaris-context/src/main/java/com/tencent/cloud/polaris/context/config/extend/tsf/TsfCoreEnvironmentPostProcessor.java
+++ b/spring-cloud-tencent-polaris-context/src/main/java/com/tencent/cloud/polaris/context/config/extend/tsf/TsfCoreEnvironmentPostProcessor.java
@@ -126,6 +126,10 @@ public final class TsfCoreEnvironmentPostProcessor implements EnvironmentPostPro
defaultProperties.put("spring.cloud.polaris.discovery.zero-protection.enabled", "true");
defaultProperties.put("spring.cloud.polaris.discovery.zero-protection.is-need-test-connectivity", "true");
defaultProperties.put("spring.cloud.discovery.client.health-indicator.enabled", "false");
+ String warmupEnabled = environment.getProperty("spring.cloud.polaris.warmup.enabled");
+ if (StringUtils.isBlank(warmupEnabled)) {
+ defaultProperties.put("spring.cloud.polaris.warmup.enabled", true);
+ }
// contract
defaultProperties.put("spring.cloud.polaris.contract.enabled", environment.getProperty("tsf.swagger.enabled", "true"));
diff --git a/spring-cloud-tencent-polaris-context/src/main/java/com/tencent/cloud/polaris/context/listener/FailedEventApplicationListener.java b/spring-cloud-tencent-polaris-context/src/main/java/com/tencent/cloud/polaris/context/listener/FailedEventApplicationListener.java
new file mode 100644
index 000000000..b963141e3
--- /dev/null
+++ b/spring-cloud-tencent-polaris-context/src/main/java/com/tencent/cloud/polaris/context/listener/FailedEventApplicationListener.java
@@ -0,0 +1,69 @@
+/*
+ * Tencent is pleased to support the open source community by making spring-cloud-tencent available.
+ *
+ * Copyright (C) 2021 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.polaris.context.listener;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.springframework.beans.BeansException;
+import org.springframework.boot.context.event.ApplicationFailedEvent;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+import org.springframework.context.ApplicationEvent;
+import org.springframework.context.ApplicationListener;
+import org.springframework.context.ConfigurableApplicationContext;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * Failed event listener.
+ *
+ * @author skyehtzhang
+ */
+@Configuration
+public class FailedEventApplicationListener implements ApplicationListener, ApplicationContextAware {
+
+ private static final Logger logger = LoggerFactory.getLogger(FailedEventApplicationListener.class);
+
+ private ApplicationContext applicationContext;
+
+ @Override
+ public void onApplicationEvent(ApplicationEvent event) {
+ if (event instanceof ApplicationFailedEvent) {
+ ApplicationFailedEvent failedEvent = (ApplicationFailedEvent) event;
+ if (failedEvent.getException() != null) {
+ logger.error("[onApplicationEvent] exception in failed event", failedEvent.getException());
+ }
+
+ if (applicationContext instanceof ConfigurableApplicationContext) {
+ ((ConfigurableApplicationContext) applicationContext).close();
+ }
+ try {
+ Thread.sleep(3000);
+ }
+ catch (InterruptedException e) {
+ // do nothing
+ }
+ System.exit(0);
+ }
+ }
+
+ @Override
+ public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
+ this.applicationContext = applicationContext;
+ }
+}
diff --git a/spring-cloud-tencent-polaris-context/src/main/java/org/springframework/tsf/annotation/EnableTsf.java b/spring-cloud-tencent-polaris-context/src/main/java/org/springframework/tsf/annotation/EnableTsf.java
index 890ff9b72..aa90c4258 100644
--- a/spring-cloud-tencent-polaris-context/src/main/java/org/springframework/tsf/annotation/EnableTsf.java
+++ b/spring-cloud-tencent-polaris-context/src/main/java/org/springframework/tsf/annotation/EnableTsf.java
@@ -24,22 +24,17 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
-import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
-import org.springframework.boot.context.properties.EnableConfigurationProperties;
-import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
-
/**
- * Compatible with old versions TSF SDK.
+ * Empty annotation. Compatible with old versions TSF SDK.
+ *
+ * Deprecated since 2.0.0.0.
*
* @author Haotian Zhang
*/
-
+@Deprecated
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
-@EnableAutoConfiguration
-@EnableDiscoveryClient // 服务注册发现
-@EnableConfigurationProperties // 分布式配置
public @interface EnableTsf {
}
diff --git a/spring-cloud-tencent-polaris-context/src/main/resources/META-INF/spring.factories b/spring-cloud-tencent-polaris-context/src/main/resources/META-INF/spring.factories
index ac093c297..7751f48cc 100644
--- a/spring-cloud-tencent-polaris-context/src/main/resources/META-INF/spring.factories
+++ b/spring-cloud-tencent-polaris-context/src/main/resources/META-INF/spring.factories
@@ -6,7 +6,8 @@ org.springframework.cloud.bootstrap.BootstrapConfiguration=\
com.tencent.cloud.polaris.context.config.PolarisContextBootstrapAutoConfiguration,\
com.tencent.cloud.polaris.context.config.extend.tsf.TsfContextBootstrapConfiguration
org.springframework.context.ApplicationListener=\
- com.tencent.cloud.polaris.context.logging.PolarisLoggingApplicationListener
+ com.tencent.cloud.polaris.context.logging.PolarisLoggingApplicationListener,\
+ com.tencent.cloud.polaris.context.listener.FailedEventApplicationListener
org.springframework.boot.env.EnvironmentPostProcessor=\
com.tencent.cloud.polaris.context.config.PolarisContextEnvironmentPostProcessor,\
com.tencent.cloud.polaris.context.config.extend.tsf.TsfCoreEnvironmentPostProcessor
diff --git a/spring-cloud-tencent-polaris-context/src/test/java/com/tencent/cloud/polaris/context/listener/FailedEventApplicationListenerTest.java b/spring-cloud-tencent-polaris-context/src/test/java/com/tencent/cloud/polaris/context/listener/FailedEventApplicationListenerTest.java
new file mode 100644
index 000000000..8e38f769f
--- /dev/null
+++ b/spring-cloud-tencent-polaris-context/src/test/java/com/tencent/cloud/polaris/context/listener/FailedEventApplicationListenerTest.java
@@ -0,0 +1,154 @@
+/*
+ * Tencent is pleased to support the open source community by making spring-cloud-tencent available.
+ *
+ * Copyright (C) 2021 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.polaris.context.listener;
+
+import java.security.Permission;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import org.springframework.boot.context.event.ApplicationFailedEvent;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ConfigurableApplicationContext;
+
+import static org.mockito.Mockito.when;
+
+
+class FailedEventApplicationListenerTest {
+
+ @Mock
+ private ConfigurableApplicationContext mockConfigurableContext;
+
+ @Mock
+ private ApplicationContext mockApplicationContext;
+
+ @Mock
+ private ApplicationFailedEvent mockFailedEvent;
+
+ private FailedEventApplicationListener listener;
+
+ @BeforeEach
+ void setUp() {
+ MockitoAnnotations.openMocks(this);
+ listener = new FailedEventApplicationListener();
+ }
+
+ @Test
+ void testSetApplicationContext() {
+ // Test setting application context
+ listener.setApplicationContext(mockApplicationContext);
+ }
+
+ @Test
+ void testOnApplicationEventWithConfigurableContext() {
+ // Arrange
+ listener.setApplicationContext(mockConfigurableContext);
+ when(mockFailedEvent.getException()).thenReturn(new RuntimeException("Test Exception"));
+
+ SecurityManager originalSecurityManager = System.getSecurityManager();
+ System.setSecurityManager(new ExitSecurityManager());
+
+ try {
+ // Act
+ listener.onApplicationEvent(mockFailedEvent);
+ }
+ catch (SecurityException e) {
+ // Ignore
+ }
+ finally {
+ System.setSecurityManager(originalSecurityManager);
+ }
+ }
+
+ @Test
+ void testOnApplicationEventWithNonConfigurableContext() {
+ // Arrange
+ listener.setApplicationContext(mockApplicationContext);
+ when(mockFailedEvent.getException()).thenReturn(new RuntimeException("Test Exception"));
+
+ SecurityManager originalSecurityManager = System.getSecurityManager();
+ System.setSecurityManager(new ExitSecurityManager());
+
+ try {
+ // Act
+ listener.onApplicationEvent(mockFailedEvent);
+ }
+ catch (SecurityException e) {
+ // Ignore
+ }
+ finally {
+ System.setSecurityManager(originalSecurityManager);
+ }
+ }
+
+ @Test
+ void testOnApplicationEventWithInterruptedException() {
+ // Arrange
+ listener.setApplicationContext(mockConfigurableContext);
+ Thread.currentThread().interrupt(); // Simulate interruption
+
+
+ SecurityManager originalSecurityManager = System.getSecurityManager();
+ System.setSecurityManager(new ExitSecurityManager());
+
+ try {
+ // Act
+ listener.onApplicationEvent(mockFailedEvent);
+ }
+ catch (SecurityException e) {
+ // Ignore
+ }
+ finally {
+ System.setSecurityManager(originalSecurityManager);
+ }
+ }
+
+ @Test
+ void testOnApplicationEventWithNullException() {
+ // Arrange
+ listener.setApplicationContext(mockConfigurableContext);
+ when(mockFailedEvent.getException()).thenReturn(null);
+
+
+ SecurityManager originalSecurityManager = System.getSecurityManager();
+ System.setSecurityManager(new ExitSecurityManager());
+
+ try {
+ // Act
+ listener.onApplicationEvent(mockFailedEvent);
+ }
+ catch (SecurityException e) {
+ // Ignore
+ }
+ finally {
+ System.setSecurityManager(originalSecurityManager);
+ }
+ }
+
+ public static class ExitSecurityManager extends SecurityManager {
+
+ @Override
+ public void checkPermission(Permission perm) {
+ if (perm.getName().contains("exitVM")) {
+ throw new SecurityException("System.exit is not allowed");
+ }
+ }
+ }
+}
diff --git a/spring-cloud-tencent-rpc-enhancement/pom.xml b/spring-cloud-tencent-rpc-enhancement/pom.xml
index bad30193e..6f15acdf3 100644
--- a/spring-cloud-tencent-rpc-enhancement/pom.xml
+++ b/spring-cloud-tencent-rpc-enhancement/pom.xml
@@ -98,6 +98,12 @@
test
+
+ io.projectreactor
+ reactor-test
+ test
+
+
org.mockito
mockito-inline
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 ddcc715c8..e77712413 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
@@ -24,26 +24,26 @@ import com.netflix.zuul.ZuulFilter;
import com.tencent.cloud.polaris.context.ConditionalOnPolarisEnabled;
import com.tencent.cloud.polaris.context.PolarisSDKContextManager;
import com.tencent.cloud.polaris.context.config.PolarisContextAutoConfiguration;
-import com.tencent.cloud.rpc.enhancement.feign.EnhancedFeignBeanPostProcessor;
-import com.tencent.cloud.rpc.enhancement.filter.EnhancedReactiveFilter;
-import com.tencent.cloud.rpc.enhancement.filter.EnhancedServletFilter;
+import com.tencent.cloud.rpc.enhancement.instrument.feign.EnhancedFeignBeanPostProcessor;
+import com.tencent.cloud.rpc.enhancement.instrument.filter.EnhancedReactiveFilter;
+import com.tencent.cloud.rpc.enhancement.instrument.filter.EnhancedServletFilter;
+import com.tencent.cloud.rpc.enhancement.instrument.resttemplate.PolarisLoadBalancerRequestTransformer;
+import com.tencent.cloud.rpc.enhancement.instrument.scg.EnhancedGatewayGlobalFilter;
+import com.tencent.cloud.rpc.enhancement.instrument.webclient.EnhancedWebClientExchangeFilterFunction;
+import com.tencent.cloud.rpc.enhancement.instrument.webclient.PolarisLoadBalancerClientRequestTransformer;
+import com.tencent.cloud.rpc.enhancement.instrument.webclient.RibbonLoadBalancerClientAspect;
+import com.tencent.cloud.rpc.enhancement.instrument.zuul.EnhancedErrorZuulFilter;
+import com.tencent.cloud.rpc.enhancement.instrument.zuul.EnhancedPostZuulFilter;
+import com.tencent.cloud.rpc.enhancement.instrument.zuul.EnhancedRouteZuulFilter;
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.reporter.ExceptionPolarisReporter;
import com.tencent.cloud.rpc.enhancement.plugin.reporter.SuccessPolarisReporter;
-import com.tencent.cloud.rpc.enhancement.resttemplate.PolarisLoadBalancerRequestTransformer;
-import com.tencent.cloud.rpc.enhancement.scg.EnhancedGatewayGlobalFilter;
import com.tencent.cloud.rpc.enhancement.transformer.InstanceTransformer;
import com.tencent.cloud.rpc.enhancement.transformer.PolarisInstanceTransformer;
import com.tencent.cloud.rpc.enhancement.transformer.PolarisRegistrationTransformer;
import com.tencent.cloud.rpc.enhancement.transformer.RegistrationTransformer;
-import com.tencent.cloud.rpc.enhancement.webclient.EnhancedWebClientExchangeFilterFunction;
-import com.tencent.cloud.rpc.enhancement.webclient.PolarisLoadBalancerClientRequestTransformer;
-import com.tencent.cloud.rpc.enhancement.webclient.RibbonLoadBalancerClientAspect;
-import com.tencent.cloud.rpc.enhancement.zuul.EnhancedErrorZuulFilter;
-import com.tencent.cloud.rpc.enhancement.zuul.EnhancedPostZuulFilter;
-import com.tencent.cloud.rpc.enhancement.zuul.EnhancedRouteZuulFilter;
import org.springframework.beans.factory.SmartInitializingSingleton;
import org.springframework.beans.factory.annotation.Autowired;
@@ -56,7 +56,6 @@ 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;
@@ -180,11 +179,6 @@ public class RpcEnhancementAutoConfiguration {
@ConditionalOnClass(name = "org.springframework.web.client.RestTemplate")
protected static class PolarisRestTemplateAutoConfiguration {
- @LoadBalanced
- @Autowired(required = false)
- private List restTemplates = Collections.emptyList();
-
-
@Bean
@ConditionalOnMissingBean
@ConditionalOnClass(name = {"org.springframework.cloud.client.loadbalancer.LoadBalancerRequestTransformer"})
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/instrument/feign/EnhancedFeignBeanPostProcessor.java
similarity index 98%
rename from spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/feign/EnhancedFeignBeanPostProcessor.java
rename to spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/instrument/feign/EnhancedFeignBeanPostProcessor.java
index ca1d2d50b..38c045b97 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/instrument/feign/EnhancedFeignBeanPostProcessor.java
@@ -15,7 +15,7 @@
* specific language governing permissions and limitations under the License.
*/
-package com.tencent.cloud.rpc.enhancement.feign;
+package com.tencent.cloud.rpc.enhancement.instrument.feign;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginRunner;
import feign.Client;
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/instrument/feign/EnhancedFeignBlockingLoadBalancerClient.java
similarity index 95%
rename from spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/feign/EnhancedFeignBlockingLoadBalancerClient.java
rename to spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/instrument/feign/EnhancedFeignBlockingLoadBalancerClient.java
index 25de16b28..86ba9def4 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/instrument/feign/EnhancedFeignBlockingLoadBalancerClient.java
@@ -15,7 +15,7 @@
* specific language governing permissions and limitations under the License.
*/
-package com.tencent.cloud.rpc.enhancement.feign;
+package com.tencent.cloud.rpc.enhancement.instrument.feign;
import feign.Client;
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/instrument/feign/EnhancedFeignClient.java
similarity index 99%
rename from spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/feign/EnhancedFeignClient.java
rename to spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/instrument/feign/EnhancedFeignClient.java
index 1f912325c..ad60f858d 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/instrument/feign/EnhancedFeignClient.java
@@ -15,7 +15,7 @@
* specific language governing permissions and limitations under the License.
*/
-package com.tencent.cloud.rpc.enhancement.feign;
+package com.tencent.cloud.rpc.enhancement.instrument.feign;
import java.io.IOException;
import java.net.URI;
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/instrument/filter/EnhancedReactiveFilter.java
similarity index 98%
rename from spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/filter/EnhancedReactiveFilter.java
rename to spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/instrument/filter/EnhancedReactiveFilter.java
index d2c935cb5..a830ea79e 100644
--- 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/instrument/filter/EnhancedReactiveFilter.java
@@ -15,7 +15,7 @@
* specific language governing permissions and limitations under the License.
*/
-package com.tencent.cloud.rpc.enhancement.filter;
+package com.tencent.cloud.rpc.enhancement.instrument.filter;
import com.tencent.cloud.common.constant.OrderConstant;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginContext;
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/instrument/filter/EnhancedServletFilter.java
similarity index 98%
rename from spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/filter/EnhancedServletFilter.java
rename to spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/instrument/filter/EnhancedServletFilter.java
index f83537b84..8edd7df97 100644
--- 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/instrument/filter/EnhancedServletFilter.java
@@ -15,7 +15,7 @@
* specific language governing permissions and limitations under the License.
*/
-package com.tencent.cloud.rpc.enhancement.filter;
+package com.tencent.cloud.rpc.enhancement.instrument.filter;
import java.io.IOException;
import java.net.URI;
diff --git a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/resttemplate/EnhancedRestTemplateWrapInterceptor.java b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/instrument/resttemplate/EnhancedRestTemplateWrapInterceptor.java
similarity index 96%
rename from spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/resttemplate/EnhancedRestTemplateWrapInterceptor.java
rename to spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/instrument/resttemplate/EnhancedRestTemplateWrapInterceptor.java
index 880fa4d4d..62ef90c87 100644
--- a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/resttemplate/EnhancedRestTemplateWrapInterceptor.java
+++ b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/instrument/resttemplate/EnhancedRestTemplateWrapInterceptor.java
@@ -15,7 +15,7 @@
* specific language governing permissions and limitations under the License.
*/
-package com.tencent.cloud.rpc.enhancement.resttemplate;
+package com.tencent.cloud.rpc.enhancement.instrument.resttemplate;
import java.io.IOException;
import java.net.URI;
@@ -38,7 +38,7 @@ import org.springframework.cloud.netflix.ribbon.RibbonLoadBalancerClient;
import org.springframework.http.HttpRequest;
import org.springframework.http.client.ClientHttpResponse;
-import static com.tencent.cloud.rpc.enhancement.resttemplate.PolarisLoadBalancerRequestTransformer.LOAD_BALANCER_SERVICE_INSTANCE;
+import static com.tencent.cloud.rpc.enhancement.instrument.resttemplate.PolarisLoadBalancerRequestTransformer.LOAD_BALANCER_SERVICE_INSTANCE;
/**
* EnhancedRestTemplateInterceptor.
diff --git a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/resttemplate/PolarisLoadBalancerRequestTransformer.java b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/instrument/resttemplate/PolarisLoadBalancerRequestTransformer.java
similarity index 96%
rename from spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/resttemplate/PolarisLoadBalancerRequestTransformer.java
rename to spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/instrument/resttemplate/PolarisLoadBalancerRequestTransformer.java
index dd7a5de34..f72ea4c74 100644
--- a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/resttemplate/PolarisLoadBalancerRequestTransformer.java
+++ b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/instrument/resttemplate/PolarisLoadBalancerRequestTransformer.java
@@ -15,7 +15,7 @@
* specific language governing permissions and limitations under the License.
*/
-package com.tencent.cloud.rpc.enhancement.resttemplate;
+package com.tencent.cloud.rpc.enhancement.instrument.resttemplate;
import com.tencent.cloud.common.metadata.MetadataContextHolder;
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/instrument/scg/EnhancedGatewayGlobalFilter.java
similarity index 97%
rename from spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/scg/EnhancedGatewayGlobalFilter.java
rename to spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/instrument/scg/EnhancedGatewayGlobalFilter.java
index 91276976b..4fce65273 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/instrument/scg/EnhancedGatewayGlobalFilter.java
@@ -15,7 +15,7 @@
* specific language governing permissions and limitations under the License.
*/
-package com.tencent.cloud.rpc.enhancement.scg;
+package com.tencent.cloud.rpc.enhancement.instrument.scg;
import java.net.URI;
import java.net.URISyntaxException;
@@ -145,7 +145,8 @@ public class EnhancedGatewayGlobalFilter implements GlobalFilter, Ordered {
Route routeAttr = originExchange.getAttribute(GATEWAY_ROUTE_ATTR);
try {
return new URI(originExchange.getRequest().getURI().getScheme(),
- routeAttr.getUri().getHost(), originExchange.getRequest().getURI().getPath(), originExchange.getRequest().getURI().getRawQuery());
+ routeAttr.getUri().getHost(), originExchange.getRequest().getURI()
+ .getPath(), originExchange.getRequest().getURI().getRawQuery());
}
catch (URISyntaxException e) {
return null;
diff --git a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/webclient/EnhancedWebClientExchangeFilterFunction.java b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/instrument/webclient/EnhancedWebClientExchangeFilterFunction.java
similarity index 69%
rename from spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/webclient/EnhancedWebClientExchangeFilterFunction.java
rename to spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/instrument/webclient/EnhancedWebClientExchangeFilterFunction.java
index c2e599485..73008f51b 100644
--- a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/webclient/EnhancedWebClientExchangeFilterFunction.java
+++ b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/instrument/webclient/EnhancedWebClientExchangeFilterFunction.java
@@ -15,7 +15,11 @@
* specific language governing permissions and limitations under the License.
*/
-package com.tencent.cloud.rpc.enhancement.webclient;
+package com.tencent.cloud.rpc.enhancement.instrument.webclient;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.Optional;
import com.tencent.cloud.common.metadata.MetadataContextHolder;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginContext;
@@ -23,15 +27,18 @@ 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 com.tencent.polaris.api.utils.CollectionUtils;
+import com.tencent.polaris.circuitbreak.client.exception.CallAbortedException;
import reactor.core.publisher.Mono;
import org.springframework.cloud.client.ServiceInstance;
+import org.springframework.http.HttpStatus;
import org.springframework.web.reactive.function.client.ClientRequest;
import org.springframework.web.reactive.function.client.ClientResponse;
import org.springframework.web.reactive.function.client.ExchangeFilterFunction;
import org.springframework.web.reactive.function.client.ExchangeFunction;
-import static com.tencent.cloud.rpc.enhancement.resttemplate.PolarisLoadBalancerRequestTransformer.LOAD_BALANCER_SERVICE_INSTANCE;
+import static com.tencent.cloud.rpc.enhancement.instrument.resttemplate.PolarisLoadBalancerRequestTransformer.LOAD_BALANCER_SERVICE_INSTANCE;
/**
* EnhancedWebClientExchangeFilterFunction.
@@ -53,6 +60,7 @@ public class EnhancedWebClientExchangeFilterFunction implements ExchangeFilterFu
.httpHeaders(originRequest.headers())
.httpMethod(originRequest.method())
.url(originRequest.url())
+ .serviceUrl(getServiceUri(originRequest))
.build();
enhancedPluginContext.setRequest(enhancedRequestContext);
enhancedPluginContext.setOriginRequest(originRequest);
@@ -62,7 +70,21 @@ public class EnhancedWebClientExchangeFilterFunction implements ExchangeFilterFu
.getLoadbalancerMetadata().get(LOAD_BALANCER_SERVICE_INSTANCE), originRequest.url());
// Run post enhanced plugins.
- pluginRunner.run(EnhancedPluginType.Client.PRE, enhancedPluginContext);
+ try {
+ pluginRunner.run(EnhancedPluginType.Client.PRE, enhancedPluginContext);
+ }
+ catch (CallAbortedException e) {
+ if (e.getFallbackInfo() == null) {
+ throw e;
+ }
+ HttpStatus httpStatus = HttpStatus.resolve(e.getFallbackInfo().getCode());
+ ClientResponse.Builder responseBuilder = ClientResponse.create(httpStatus != null ? httpStatus : HttpStatus.INTERNAL_SERVER_ERROR)
+ .body(Optional.of(e.getFallbackInfo().getBody()).orElse(""));
+ if (CollectionUtils.isNotEmpty(e.getFallbackInfo().getHeaders())) {
+ e.getFallbackInfo().getHeaders().forEach(responseBuilder::header);
+ }
+ return Mono.just(responseBuilder.build());
+ }
// request may be changed by plugin
ClientRequest request = (ClientRequest) enhancedPluginContext.getOriginRequest();
long startTime = System.currentTimeMillis();
@@ -91,4 +113,21 @@ public class EnhancedWebClientExchangeFilterFunction implements ExchangeFilterFu
pluginRunner.run(EnhancedPluginType.Client.FINALLY, enhancedPluginContext);
});
}
+
+ private URI getServiceUri(ClientRequest clientRequest) {
+ Object instance = MetadataContextHolder.get()
+ .getLoadbalancerMetadata().get(LOAD_BALANCER_SERVICE_INSTANCE);
+ if (!(instance instanceof ServiceInstance)) {
+ return null;
+ }
+ ServiceInstance serviceInstance = (ServiceInstance) instance;
+ URI uri = clientRequest.url();
+
+ try {
+ return new URI(uri.getScheme(), serviceInstance.getServiceId(), uri.getPath(), uri.getRawQuery());
+ }
+ catch (URISyntaxException e) {
+ return null;
+ }
+ }
}
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/instrument/webclient/PolarisLoadBalancerClientRequestTransformer.java
similarity index 88%
rename from spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/webclient/PolarisLoadBalancerClientRequestTransformer.java
rename to spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/instrument/webclient/PolarisLoadBalancerClientRequestTransformer.java
index 8737d4beb..cf7bb9df0 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/instrument/webclient/PolarisLoadBalancerClientRequestTransformer.java
@@ -15,7 +15,7 @@
* specific language governing permissions and limitations under the License.
*/
-package com.tencent.cloud.rpc.enhancement.webclient;
+package com.tencent.cloud.rpc.enhancement.instrument.webclient;
import com.tencent.cloud.common.metadata.MetadataContextHolder;
@@ -23,7 +23,7 @@ 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;
+import static com.tencent.cloud.rpc.enhancement.instrument.resttemplate.PolarisLoadBalancerRequestTransformer.LOAD_BALANCER_SERVICE_INSTANCE;
/**
* PolarisLoadBalancerClientRequestTransformer.
diff --git a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/webclient/RibbonLoadBalancerClientAspect.java b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/instrument/webclient/RibbonLoadBalancerClientAspect.java
similarity index 88%
rename from spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/webclient/RibbonLoadBalancerClientAspect.java
rename to spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/instrument/webclient/RibbonLoadBalancerClientAspect.java
index 3017417bc..d7b8f0294 100644
--- a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/webclient/RibbonLoadBalancerClientAspect.java
+++ b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/instrument/webclient/RibbonLoadBalancerClientAspect.java
@@ -15,7 +15,8 @@
* specific language governing permissions and limitations under the License.
*/
-package com.tencent.cloud.rpc.enhancement.webclient;
+
+package com.tencent.cloud.rpc.enhancement.instrument.webclient;
import com.tencent.cloud.common.metadata.MetadataContextHolder;
import org.aspectj.lang.ProceedingJoinPoint;
@@ -23,7 +24,7 @@ import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
-import static com.tencent.cloud.rpc.enhancement.resttemplate.PolarisLoadBalancerRequestTransformer.LOAD_BALANCER_SERVICE_INSTANCE;
+import static com.tencent.cloud.rpc.enhancement.instrument.resttemplate.PolarisLoadBalancerRequestTransformer.LOAD_BALANCER_SERVICE_INSTANCE;
/**
* Intercept for RibbonLoadBalancerClient, put host and port to thread local.
diff --git a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/zuul/EnhancedErrorZuulFilter.java b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/instrument/zuul/EnhancedErrorZuulFilter.java
similarity index 98%
rename from spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/zuul/EnhancedErrorZuulFilter.java
rename to spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/instrument/zuul/EnhancedErrorZuulFilter.java
index 248449245..0535184d3 100644
--- a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/zuul/EnhancedErrorZuulFilter.java
+++ b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/instrument/zuul/EnhancedErrorZuulFilter.java
@@ -15,7 +15,7 @@
* specific language governing permissions and limitations under the License.
*/
-package com.tencent.cloud.rpc.enhancement.zuul;
+package com.tencent.cloud.rpc.enhancement.instrument.zuul;
import java.util.ArrayList;
import java.util.Collection;
diff --git a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/zuul/EnhancedPostZuulFilter.java b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/instrument/zuul/EnhancedPostZuulFilter.java
similarity index 98%
rename from spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/zuul/EnhancedPostZuulFilter.java
rename to spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/instrument/zuul/EnhancedPostZuulFilter.java
index e6ca3eaa9..0c53a4971 100644
--- a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/zuul/EnhancedPostZuulFilter.java
+++ b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/instrument/zuul/EnhancedPostZuulFilter.java
@@ -15,7 +15,7 @@
* specific language governing permissions and limitations under the License.
*/
-package com.tencent.cloud.rpc.enhancement.zuul;
+package com.tencent.cloud.rpc.enhancement.instrument.zuul;
import java.util.ArrayList;
import java.util.Collection;
diff --git a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/zuul/EnhancedRouteZuulFilter.java b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/instrument/zuul/EnhancedRouteZuulFilter.java
similarity index 98%
rename from spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/zuul/EnhancedRouteZuulFilter.java
rename to spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/instrument/zuul/EnhancedRouteZuulFilter.java
index 6b900416c..e8830ee4e 100644
--- a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/zuul/EnhancedRouteZuulFilter.java
+++ b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/instrument/zuul/EnhancedRouteZuulFilter.java
@@ -15,7 +15,7 @@
* specific language governing permissions and limitations under the License.
*/
-package com.tencent.cloud.rpc.enhancement.zuul;
+package com.tencent.cloud.rpc.enhancement.instrument.zuul;
import java.net.URI;
import java.net.URISyntaxException;
diff --git a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/zuul/EnhancedZuulPluginRunner.java b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/instrument/zuul/EnhancedZuulPluginRunner.java
similarity index 98%
rename from spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/zuul/EnhancedZuulPluginRunner.java
rename to spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/instrument/zuul/EnhancedZuulPluginRunner.java
index 0499c3ac2..75d856137 100644
--- a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/zuul/EnhancedZuulPluginRunner.java
+++ b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/instrument/zuul/EnhancedZuulPluginRunner.java
@@ -15,7 +15,7 @@
* specific language governing permissions and limitations under the License.
*/
-package com.tencent.cloud.rpc.enhancement.zuul;
+package com.tencent.cloud.rpc.enhancement.instrument.zuul;
import java.net.URI;
import java.net.URISyntaxException;
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 f45e29689..bbb97b38f 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
@@ -73,6 +73,19 @@ public class DefaultEnhancedPluginRunner implements EnhancedPluginRunner {
}
}
+ static Registration getPolarisRegistration(List registration) {
+
+ if (CollectionUtils.isEmpty(registration)) {
+ return null;
+ }
+ for (Registration reg : registration) {
+ if ("com.tencent.cloud.polaris.registry.PolarisRegistration".equals(reg.getClass().getName())) {
+ return reg;
+ }
+ }
+ return registration.get(0);
+ }
+
/**
* run the plugin.
*
@@ -98,17 +111,4 @@ public class DefaultEnhancedPluginRunner implements EnhancedPluginRunner {
public ServiceInstance getLocalServiceInstance() {
return this.localServiceInstance;
}
-
- private static Registration getPolarisRegistration(List registration) {
-
- if (CollectionUtils.isEmpty(registration)) {
- return null;
- }
- for (Registration reg : registration) {
- if ("com.tencent.cloud.polaris.registry.PolarisRegistration".equals(reg.getClass().getName())) {
- return reg;
- }
- }
- return registration.get(0);
- }
}
diff --git a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/transformer/InstanceTransformer.java b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/transformer/InstanceTransformer.java
index 500664d93..77fa49edc 100644
--- a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/transformer/InstanceTransformer.java
+++ b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/transformer/InstanceTransformer.java
@@ -20,6 +20,7 @@ package com.tencent.cloud.rpc.enhancement.transformer;
import com.tencent.cloud.common.metadata.MetadataContext;
import com.tencent.polaris.api.pojo.DefaultInstance;
import com.tencent.polaris.api.pojo.Instance;
+import com.tencent.polaris.api.utils.StringUtils;
import org.springframework.cloud.client.ServiceInstance;
@@ -41,10 +42,18 @@ public interface InstanceTransformer {
instance.setNamespace(MetadataContext.LOCAL_NAMESPACE);
instance.setService(serviceInstance.getServiceId());
instance.setProtocol(serviceInstance.getScheme());
- instance.setId(serviceInstance.getInstanceId());
instance.setHost(serviceInstance.getHost());
instance.setPort(serviceInstance.getPort());
instance.setMetadata(serviceInstance.getMetadata());
+ instance.setWeight(100);
+ instance.setHealthy(true);
+
+ if (StringUtils.isNotEmpty(serviceInstance.getInstanceId())) {
+ instance.setId(serviceInstance.getInstanceId());
+ }
+ else {
+ instance.setId(serviceInstance.getHost() + ":" + serviceInstance.getPort());
+ }
}
void transformCustom(DefaultInstance instance, ServiceInstance serviceInstance);
diff --git a/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/config/RpcEnhancementAutoConfigurationTest.java b/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/config/RpcEnhancementAutoConfigurationTest.java
index 11977254a..30eb27b88 100644
--- a/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/config/RpcEnhancementAutoConfigurationTest.java
+++ b/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/config/RpcEnhancementAutoConfigurationTest.java
@@ -18,7 +18,7 @@
package com.tencent.cloud.rpc.enhancement.config;
import com.tencent.cloud.polaris.context.config.PolarisContextAutoConfiguration;
-import com.tencent.cloud.rpc.enhancement.feign.EnhancedFeignBeanPostProcessor;
+import com.tencent.cloud.rpc.enhancement.instrument.feign.EnhancedFeignBeanPostProcessor;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginRunner;
import com.tencent.cloud.rpc.enhancement.plugin.reporter.ExceptionPolarisReporter;
import com.tencent.cloud.rpc.enhancement.plugin.reporter.SuccessPolarisReporter;
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/instrument/feign/EnhancedFeignBeanPostProcessorTest.java
similarity index 98%
rename from spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/feign/EnhancedFeignBeanPostProcessorTest.java
rename to spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/instrument/feign/EnhancedFeignBeanPostProcessorTest.java
index 04f9e0835..708bb5f2c 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/instrument/feign/EnhancedFeignBeanPostProcessorTest.java
@@ -15,7 +15,7 @@
* specific language governing permissions and limitations under the License.
*/
-package com.tencent.cloud.rpc.enhancement.feign;
+package com.tencent.cloud.rpc.enhancement.instrument.feign;
import feign.Client;
import org.junit.jupiter.api.BeforeEach;
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/instrument/feign/EnhancedFeignClientTest.java
similarity index 99%
rename from spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/feign/EnhancedFeignClientTest.java
rename to spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/instrument/feign/EnhancedFeignClientTest.java
index 396a26c4e..ca4bab8d9 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/instrument/feign/EnhancedFeignClientTest.java
@@ -15,7 +15,7 @@
* specific language governing permissions and limitations under the License.
*/
-package com.tencent.cloud.rpc.enhancement.feign;
+package com.tencent.cloud.rpc.enhancement.instrument.feign;
import java.io.IOException;
import java.util.ArrayList;
diff --git a/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/resttemplate/PolarisLoadBalancerRequestTransformerTest.java b/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/instrument/resttemplate/PolarisLoadBalancerRequestTransformerTest.java
similarity index 90%
rename from spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/resttemplate/PolarisLoadBalancerRequestTransformerTest.java
rename to spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/instrument/resttemplate/PolarisLoadBalancerRequestTransformerTest.java
index 71bbd822f..3da230d61 100644
--- a/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/resttemplate/PolarisLoadBalancerRequestTransformerTest.java
+++ b/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/instrument/resttemplate/PolarisLoadBalancerRequestTransformerTest.java
@@ -15,7 +15,7 @@
* specific language governing permissions and limitations under the License.
*/
-package com.tencent.cloud.rpc.enhancement.resttemplate;
+package com.tencent.cloud.rpc.enhancement.instrument.resttemplate;
import com.tencent.cloud.common.metadata.MetadataContext;
import com.tencent.cloud.common.metadata.MetadataContextHolder;
@@ -36,7 +36,7 @@ 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.cloud.rpc.enhancement.instrument.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;
@@ -66,7 +66,8 @@ public class PolarisLoadBalancerRequestTransformerTest {
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);
+ mockedApplicationContextAwareUtils.when(ApplicationContextAwareUtils::getApplicationContext)
+ .thenReturn(applicationContext);
}
@AfterAll
@@ -83,7 +84,8 @@ public class PolarisLoadBalancerRequestTransformerTest {
@Test
public void test() throws Throwable {
transformer.transformRequest(clientRequest, serviceInstance);
- assertThat(MetadataContextHolder.get().getLoadbalancerMetadata().get(LOAD_BALANCER_SERVICE_INSTANCE)).isEqualTo(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/instrument/scg/EnhancedGatewayGlobalFilterTest.java
similarity index 98%
rename from spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/scg/EnhancedGatewayGlobalFilterTest.java
rename to spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/instrument/scg/EnhancedGatewayGlobalFilterTest.java
index 0c6583a55..21174b5a6 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/instrument/scg/EnhancedGatewayGlobalFilterTest.java
@@ -15,7 +15,7 @@
* specific language governing permissions and limitations under the License.
*/
-package com.tencent.cloud.rpc.enhancement.scg;
+package com.tencent.cloud.rpc.enhancement.instrument.scg;
import java.net.URI;
import java.net.URISyntaxException;
diff --git a/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/webclient/EnhancedWebClientExchangeFilterFunctionTest.java b/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/instrument/webclient/EnhancedWebClientExchangeFilterFunctionTest.java
similarity index 96%
rename from spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/webclient/EnhancedWebClientExchangeFilterFunctionTest.java
rename to spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/instrument/webclient/EnhancedWebClientExchangeFilterFunctionTest.java
index c447bac4b..ef1f319fa 100644
--- a/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/webclient/EnhancedWebClientExchangeFilterFunctionTest.java
+++ b/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/instrument/webclient/EnhancedWebClientExchangeFilterFunctionTest.java
@@ -15,7 +15,7 @@
* specific language governing permissions and limitations under the License.
*/
-package com.tencent.cloud.rpc.enhancement.webclient;
+package com.tencent.cloud.rpc.enhancement.instrument.webclient;
import java.net.URI;
import java.net.URISyntaxException;
@@ -84,7 +84,8 @@ public class EnhancedWebClientExchangeFilterFunctionTest {
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);
+ mockedApplicationContextAwareUtils.when(ApplicationContextAwareUtils::getApplicationContext)
+ .thenReturn(applicationContext);
}
@AfterAll
@@ -97,6 +98,7 @@ public class EnhancedWebClientExchangeFilterFunctionTest {
MetadataContext.LOCAL_NAMESPACE = NAMESPACE_TEST;
MetadataContext.LOCAL_SERVICE = SERVICE_PROVIDER;
}
+
@Test
public void testRun() throws URISyntaxException {
@@ -117,8 +119,8 @@ public class EnhancedWebClientExchangeFilterFunctionTest {
doReturn(Mono.error(new RuntimeException())).when(exchangeFunction).exchange(any());
- assertThatThrownBy(() -> reporter.filter(clientRequest, exchangeFunction).block()).isInstanceOf(RuntimeException.class);
-
+ assertThatThrownBy(() -> reporter.filter(clientRequest, exchangeFunction)
+ .block()).isInstanceOf(RuntimeException.class);
}
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/instrument/webclient/PolarisLoadBalancerClientRequestTransformerTest.java
similarity index 91%
rename from spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/webclient/PolarisLoadBalancerClientRequestTransformerTest.java
rename to spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/instrument/webclient/PolarisLoadBalancerClientRequestTransformerTest.java
index eec316bcc..0519402f1 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/instrument/webclient/PolarisLoadBalancerClientRequestTransformerTest.java
@@ -15,7 +15,7 @@
* specific language governing permissions and limitations under the License.
*/
-package com.tencent.cloud.rpc.enhancement.webclient;
+package com.tencent.cloud.rpc.enhancement.instrument.webclient;
import com.tencent.cloud.common.metadata.MetadataContext;
import com.tencent.cloud.common.metadata.MetadataContextHolder;
@@ -36,7 +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.cloud.rpc.enhancement.instrument.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;
@@ -67,7 +67,8 @@ public class PolarisLoadBalancerClientRequestTransformerTest {
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);
+ mockedApplicationContextAwareUtils.when(ApplicationContextAwareUtils::getApplicationContext)
+ .thenReturn(applicationContext);
}
@AfterAll
@@ -84,6 +85,7 @@ public class PolarisLoadBalancerClientRequestTransformerTest {
@Test
public void test() throws Throwable {
transformer.transformRequest(clientRequest, serviceInstance);
- assertThat(MetadataContextHolder.get().getLoadbalancerMetadata().get(LOAD_BALANCER_SERVICE_INSTANCE)).isEqualTo(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/DefaultEnhancedPluginRunnerTest.java b/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/plugin/DefaultEnhancedPluginRunnerTest.java
new file mode 100644
index 000000000..2b899a1ee
--- /dev/null
+++ b/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/plugin/DefaultEnhancedPluginRunnerTest.java
@@ -0,0 +1,90 @@
+/*
+ * Tencent is pleased to support the open source community by making spring-cloud-tencent available.
+ *
+ * Copyright (C) 2021 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.ArrayList;
+import java.util.List;
+
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+import org.springframework.cloud.client.serviceregistry.Registration;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * Tests for {@link DefaultEnhancedPluginRunner}.
+ *
+ * @author Shedfree Wu
+ */
+@ExtendWith(MockitoExtension.class)
+public class DefaultEnhancedPluginRunnerTest {
+
+ @Test
+ void getPolarisRegistration_WithPolarisRegistration_ReturnsPolarisRegistration() {
+ // Arrange
+ List registrations = new ArrayList<>();
+ Registration normalReg = createMockRegistration();
+ Registration normalReg2 = createMockRegistration();
+ registrations.add(normalReg);
+ registrations.add(normalReg2);
+
+ // Act
+ Registration result = DefaultEnhancedPluginRunner.getPolarisRegistration(registrations);
+
+ // Assert
+ assertThat(result).isSameAs(normalReg);
+ }
+
+ // Helper method to create mock Registration objects
+ private Registration createMockRegistration() {
+ return new Registration() {
+ @Override
+ public String getServiceId() {
+ return null;
+ }
+
+ @Override
+ public String getHost() {
+ return null;
+ }
+
+ @Override
+ public int getPort() {
+ return 0;
+ }
+
+ @Override
+ public boolean isSecure() {
+ return false;
+ }
+
+ @Override
+ public java.net.URI getUri() {
+ return null;
+ }
+
+ @Override
+ public java.util.Map getMetadata() {
+ return null;
+ }
+ };
+ }
+
+}
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 28319b884..59b2a0d23 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
@@ -98,6 +98,7 @@ public class EnhancedPluginContextTest {
EnhancedRequestContext requestContext = new EnhancedRequestContext();
requestContext.setHttpHeaders(new HttpHeaders());
requestContext.setUrl(new URI("/"));
+ requestContext.setServiceUrl(new URI("http://test-service/path"));
requestContext.setHttpMethod(HttpMethod.GET);
EnhancedRequestContext requestContext1 = EnhancedRequestContext.builder()