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[] ignoreExceptions() default {}; + + /** + * Defines exceptions which should be retried. + * Default is all exceptions. + * + * @return exceptions to wrap + */ + Class[] 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[] ignoreExceptions = faultTolerance != null ? faultTolerance.ignoreExceptions() : null; + if (ignoreExceptions == null || ignoreExceptions.length == 0) { + ignoreExceptions = tsfFaultTolerance != null ? tsfFaultTolerance.ignoreExceptions() : null; + } + Class[] raisedExceptions = faultTolerance != null ? faultTolerance.raisedExceptions() : null; + if (raisedExceptions == null || raisedExceptions.length == 0) { + raisedExceptions = tsfFaultTolerance != null ? tsfFaultTolerance.raisedExceptions() : null; + } + + try { + + if (ignoreExceptions != null) { + for (Class 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 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[] ignoreExceptions() default {}; + + /** + * Defines exceptions which should be retry. + * Default is all exceptions. + * + * @return exceptions to wrap + */ + Class[] 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()