From 68620d9f8fbd86d6660ed36922a52914c53c705b Mon Sep 17 00:00:00 2001 From: lepdou Date: Tue, 14 Jun 2022 18:01:04 +0800 Subject: [PATCH] support spring cloud gateway routers (#230) --- CHANGELOG.md | 1 + .../pom.xml | 6 + .../PolarisLoadBalancerBeanPostProcessor.java | 24 ++- .../PolarisLoadBalancerCompositeRule.java | 6 +- .../router/config/FeignAutoConfiguration.java | 58 ++++++ ...va => FeignLoadBalancerConfiguration.java} | 7 +- .../router/config/RibbonConfiguration.java | 7 +- .../config/RouterAutoConfiguration.java | 29 +-- .../PolarisMetadataRouterProperties.java | 2 +- .../PolarisNearByRouterProperties.java | 2 +- .../PolarisRuleBasedRouterProperties.java | 2 +- .../scg/PolarisLoadBalancerClientFilter.java | 144 +++++++++++++ .../router/spi/RouterLabelResolver.java | 9 + .../main/resources/META-INF/spring.factories | 3 +- .../PolarisLoadBalancerCompositeRuleTest.java | 6 +- ...arisLoadBalancerBeanPostProcessorTest.java | 1 + .../PolarisLoadBalancerClientFilterTest.java | 192 ++++++++++++++++++ .../src/main/resources/bootstrap.yml | 4 + .../gateway-callee-service2/pom.xml | 26 +++ .../callee/GatewayCalleeApplication2.java | 35 ++++ .../callee/GatewayCalleeController.java | 71 +++++++ .../src/main/resources/bootstrap.yml | 14 ++ .../gateway-scg-service/pom.xml | 4 +- .../src/main/resources/bootstrap.yml | 20 +- .../example/CustomRouterLabelResolver.java | 6 + 25 files changed, 622 insertions(+), 57 deletions(-) rename spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/{resttemplate => }/PolarisLoadBalancerBeanPostProcessor.java (64%) create mode 100644 spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/FeignAutoConfiguration.java rename spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/{FeignConfiguration.java => FeignLoadBalancerConfiguration.java} (87%) rename spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/{ => properties}/PolarisMetadataRouterProperties.java (95%) rename spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/{ => properties}/PolarisNearByRouterProperties.java (95%) rename spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/{ => properties}/PolarisRuleBasedRouterProperties.java (95%) create mode 100644 spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/scg/PolarisLoadBalancerClientFilter.java create mode 100644 spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/scg/PolarisLoadBalancerClientFilterTest.java create mode 100644 spring-cloud-tencent-examples/polaris-gateway-example/gateway-callee-service2/pom.xml create mode 100644 spring-cloud-tencent-examples/polaris-gateway-example/gateway-callee-service2/src/main/java/com/tencent/cloud/polaris/gateway/example/callee/GatewayCalleeApplication2.java create mode 100644 spring-cloud-tencent-examples/polaris-gateway-example/gateway-callee-service2/src/main/java/com/tencent/cloud/polaris/gateway/example/callee/GatewayCalleeController.java create mode 100644 spring-cloud-tencent-examples/polaris-gateway-example/gateway-callee-service2/src/main/resources/bootstrap.yml diff --git a/CHANGELOG.md b/CHANGELOG.md index c4a5a2b38..fe9ef2c3f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,3 +2,4 @@ --- [Feature: Add config change listener feature support](https://github.com/Tencent/spring-cloud-tencent/pull/220) +[Feature: Support spring cloud gateway routers](https://github.com/Tencent/spring-cloud-tencent/pull/230) diff --git a/spring-cloud-starter-tencent-polaris-router/pom.xml b/spring-cloud-starter-tencent-polaris-router/pom.xml index 91e482abb..1424f98b5 100644 --- a/spring-cloud-starter-tencent-polaris-router/pom.xml +++ b/spring-cloud-starter-tencent-polaris-router/pom.xml @@ -52,6 +52,12 @@ true + + org.springframework.cloud + spring-cloud-gateway-server + true + + org.springframework.boot spring-boot-starter-test diff --git a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/resttemplate/PolarisLoadBalancerBeanPostProcessor.java b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/PolarisLoadBalancerBeanPostProcessor.java similarity index 64% rename from spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/resttemplate/PolarisLoadBalancerBeanPostProcessor.java rename to spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/PolarisLoadBalancerBeanPostProcessor.java index 5bafbd9fb..33ad50073 100644 --- a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/resttemplate/PolarisLoadBalancerBeanPostProcessor.java +++ b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/PolarisLoadBalancerBeanPostProcessor.java @@ -16,13 +16,14 @@ * */ -package com.tencent.cloud.polaris.router.resttemplate; +package com.tencent.cloud.polaris.router; import java.util.List; import com.tencent.cloud.common.metadata.config.MetadataLocalProperties; import com.tencent.cloud.common.util.BeanFactoryUtils; -import com.tencent.cloud.polaris.router.RouterRuleLabelResolver; +import com.tencent.cloud.polaris.router.resttemplate.PolarisLoadBalancerInterceptor; +import com.tencent.cloud.polaris.router.scg.PolarisLoadBalancerClientFilter; import com.tencent.cloud.polaris.router.spi.RouterLabelResolver; import org.springframework.beans.BeansException; @@ -32,11 +33,14 @@ import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.cloud.client.loadbalancer.LoadBalancerClient; import org.springframework.cloud.client.loadbalancer.LoadBalancerInterceptor; import org.springframework.cloud.client.loadbalancer.LoadBalancerRequestFactory; +import org.springframework.cloud.gateway.config.LoadBalancerProperties; +import org.springframework.cloud.gateway.filter.LoadBalancerClientFilter; /** * Replace LoadBalancerInterceptor with PolarisLoadBalancerInterceptor. * PolarisLoadBalancerInterceptor can pass routing context information. - * + *
+ * Replace LoadBalancerClientFilter with PolarisLoadBalancerClientFilter. *@author lepdou 2022-05-18 */ public class PolarisLoadBalancerBeanPostProcessor implements BeanPostProcessor, BeanFactoryAware { @@ -51,6 +55,8 @@ public class PolarisLoadBalancerBeanPostProcessor implements BeanPostProcessor, @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { if (bean instanceof LoadBalancerInterceptor) { + // Support rest template router. + // Replaces the default LoadBalancerInterceptor implementation and returns a custom PolarisLoadBalancerInterceptor LoadBalancerRequestFactory requestFactory = this.factory.getBean(LoadBalancerRequestFactory.class); LoadBalancerClient loadBalancerClient = this.factory.getBean(LoadBalancerClient.class); List routerLabelResolvers = BeanFactoryUtils.getBeans(factory, RouterLabelResolver.class); @@ -60,6 +66,18 @@ public class PolarisLoadBalancerBeanPostProcessor implements BeanPostProcessor, return new PolarisLoadBalancerInterceptor(loadBalancerClient, requestFactory, routerLabelResolvers, metadataLocalProperties, routerRuleLabelResolver); } + else if (bean instanceof LoadBalancerClientFilter) { + // Support spring cloud gateway router. + // Replaces the default LoadBalancerClientFilter implementation and returns a custom PolarisLoadBalancerClientFilter + LoadBalancerClient loadBalancerClient = this.factory.getBean(LoadBalancerClient.class); + LoadBalancerProperties loadBalancerProperties = this.factory.getBean(LoadBalancerProperties.class); + List routerLabelResolvers = BeanFactoryUtils.getBeans(factory, RouterLabelResolver.class); + MetadataLocalProperties metadataLocalProperties = this.factory.getBean(MetadataLocalProperties.class); + RouterRuleLabelResolver routerRuleLabelResolver = this.factory.getBean(RouterRuleLabelResolver.class); + + return new PolarisLoadBalancerClientFilter(loadBalancerClient, loadBalancerProperties, + metadataLocalProperties, routerRuleLabelResolver, routerLabelResolvers); + } return bean; } } diff --git a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/PolarisLoadBalancerCompositeRule.java b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/PolarisLoadBalancerCompositeRule.java index 4b9dc5900..4be83e682 100644 --- a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/PolarisLoadBalancerCompositeRule.java +++ b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/PolarisLoadBalancerCompositeRule.java @@ -40,9 +40,9 @@ import com.tencent.cloud.common.pojo.PolarisServer; import com.tencent.cloud.polaris.loadbalancer.LoadBalancerUtils; import com.tencent.cloud.polaris.loadbalancer.PolarisWeightedRule; import com.tencent.cloud.polaris.loadbalancer.config.PolarisLoadBalancerProperties; -import com.tencent.cloud.polaris.router.config.PolarisMetadataRouterProperties; -import com.tencent.cloud.polaris.router.config.PolarisNearByRouterProperties; -import com.tencent.cloud.polaris.router.config.PolarisRuleBasedRouterProperties; +import com.tencent.cloud.polaris.router.config.properties.PolarisMetadataRouterProperties; +import com.tencent.cloud.polaris.router.config.properties.PolarisNearByRouterProperties; +import com.tencent.cloud.polaris.router.config.properties.PolarisRuleBasedRouterProperties; import com.tencent.polaris.api.pojo.Instance; import com.tencent.polaris.api.pojo.ServiceInfo; import com.tencent.polaris.api.pojo.ServiceInstances; 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 new file mode 100644 index 000000000..5b87668ea --- /dev/null +++ b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/FeignAutoConfiguration.java @@ -0,0 +1,58 @@ +/* + * Tencent is pleased to support the open source community by making Spring Cloud Tencent available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * Unless required by applicable law or agreed to in writing, software distributed + * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + */ + +package com.tencent.cloud.polaris.router.config; + +import java.util.List; + +import com.tencent.cloud.common.metadata.config.MetadataLocalProperties; +import com.tencent.cloud.polaris.router.RouterRuleLabelResolver; +import com.tencent.cloud.polaris.router.feign.PolarisCachingSpringLoadBalanceFactory; +import com.tencent.cloud.polaris.router.feign.RouterLabelFeignInterceptor; +import com.tencent.cloud.polaris.router.spi.RouterLabelResolver; + +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.cloud.netflix.ribbon.RibbonClients; +import org.springframework.cloud.netflix.ribbon.SpringClientFactory; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.lang.Nullable; + +/** + * configuration for feign singleton components. + * Feign-related components need to be loaded only in the feign environment. + *@author lepdou 2022-06-10 + */ +@Configuration +@ConditionalOnClass(name = {"org.springframework.cloud.openfeign.ribbon.FeignLoadBalancer"}) +@RibbonClients(defaultConfiguration = {FeignLoadBalancerConfiguration.class}) +public class FeignAutoConfiguration { + + @Bean + public RouterLabelFeignInterceptor routerLabelInterceptor(@Nullable List routerLabelResolvers, + MetadataLocalProperties metadataLocalProperties, + RouterRuleLabelResolver routerRuleLabelResolver) { + return new RouterLabelFeignInterceptor(routerLabelResolvers, metadataLocalProperties, routerRuleLabelResolver); + } + + @Bean + public PolarisCachingSpringLoadBalanceFactory polarisCachingSpringLoadBalanceFactory(SpringClientFactory factory) { + return new PolarisCachingSpringLoadBalanceFactory(factory); + } + +} diff --git a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/FeignConfiguration.java b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/FeignLoadBalancerConfiguration.java similarity index 87% rename from spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/FeignConfiguration.java rename to spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/FeignLoadBalancerConfiguration.java index d5d22444e..e6368cc85 100644 --- a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/FeignConfiguration.java +++ b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/FeignLoadBalancerConfiguration.java @@ -25,15 +25,12 @@ import com.tencent.cloud.polaris.router.feign.PolarisFeignLoadBalancer; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.cloud.netflix.ribbon.ServerIntrospector; import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; /** - * configuration for feign component. - * + * configuration for feign load balance components. PolarisFeignLoadBalancer is not singleton bean, Each service corresponds to a PolarisFeignLoadBalancer. *@author lepdou 2022-05-16 */ -@Configuration -public class FeignConfiguration { +public class FeignLoadBalancerConfiguration { @Bean @ConditionalOnMissingBean diff --git a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/RibbonConfiguration.java b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/RibbonConfiguration.java index b9c60fbfb..9bc17b276 100644 --- a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/RibbonConfiguration.java +++ b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/RibbonConfiguration.java @@ -22,16 +22,17 @@ import com.netflix.client.config.IClientConfig; import com.netflix.loadbalancer.IRule; import com.tencent.cloud.polaris.loadbalancer.config.PolarisLoadBalancerProperties; import com.tencent.cloud.polaris.router.PolarisLoadBalancerCompositeRule; +import com.tencent.cloud.polaris.router.config.properties.PolarisMetadataRouterProperties; +import com.tencent.cloud.polaris.router.config.properties.PolarisNearByRouterProperties; +import com.tencent.cloud.polaris.router.config.properties.PolarisRuleBasedRouterProperties; import com.tencent.polaris.router.api.core.RouterAPI; import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; /** - * Auto configuration for ribbon components. + * Configuration for ribbon components. IRule is not singleton bean, Each service corresponds to an IRule. * @author lepdou 2022-05-17 */ -@Configuration public class RibbonConfiguration { @Bean 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 6d274bc1c..e92b0f45d 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 @@ -18,48 +18,31 @@ package com.tencent.cloud.polaris.router.config; -import java.util.List; - -import com.tencent.cloud.common.metadata.config.MetadataLocalProperties; import com.tencent.cloud.polaris.context.ServiceRuleManager; +import com.tencent.cloud.polaris.router.PolarisLoadBalancerBeanPostProcessor; import com.tencent.cloud.polaris.router.RouterRuleLabelResolver; -import com.tencent.cloud.polaris.router.feign.PolarisCachingSpringLoadBalanceFactory; -import com.tencent.cloud.polaris.router.feign.RouterLabelFeignInterceptor; -import com.tencent.cloud.polaris.router.resttemplate.PolarisLoadBalancerBeanPostProcessor; -import com.tencent.cloud.polaris.router.spi.RouterLabelResolver; +import com.tencent.cloud.polaris.router.config.properties.PolarisMetadataRouterProperties; +import com.tencent.cloud.polaris.router.config.properties.PolarisNearByRouterProperties; +import com.tencent.cloud.polaris.router.config.properties.PolarisRuleBasedRouterProperties; import org.springframework.cloud.netflix.ribbon.RibbonClients; -import org.springframework.cloud.netflix.ribbon.SpringClientFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; import org.springframework.core.annotation.Order; -import org.springframework.lang.Nullable; import static org.springframework.core.Ordered.HIGHEST_PRECEDENCE; /** - * router module auto configuration. + * configuration for router module singleton beans. * *@author lepdou 2022-05-11 */ @Configuration -@RibbonClients(defaultConfiguration = {FeignConfiguration.class, RibbonConfiguration.class}) +@RibbonClients(defaultConfiguration = {RibbonConfiguration.class}) @Import({PolarisNearByRouterProperties.class, PolarisMetadataRouterProperties.class, PolarisRuleBasedRouterProperties.class}) public class RouterAutoConfiguration { - @Bean - public RouterLabelFeignInterceptor routerLabelInterceptor(@Nullable List routerLabelResolvers, - MetadataLocalProperties metadataLocalProperties, - RouterRuleLabelResolver routerRuleLabelResolver) { - return new RouterLabelFeignInterceptor(routerLabelResolvers, metadataLocalProperties, routerRuleLabelResolver); - } - - @Bean - public PolarisCachingSpringLoadBalanceFactory polarisCachingSpringLoadBalanceFactory(SpringClientFactory factory) { - return new PolarisCachingSpringLoadBalanceFactory(factory); - } - @Bean @Order(HIGHEST_PRECEDENCE) public PolarisLoadBalancerBeanPostProcessor polarisLoadBalancerBeanPostProcessor() { diff --git a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/PolarisMetadataRouterProperties.java b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/properties/PolarisMetadataRouterProperties.java similarity index 95% rename from spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/PolarisMetadataRouterProperties.java rename to spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/properties/PolarisMetadataRouterProperties.java index 4a20e53f6..70ded3a8c 100644 --- a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/PolarisMetadataRouterProperties.java +++ b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/properties/PolarisMetadataRouterProperties.java @@ -16,7 +16,7 @@ * */ -package com.tencent.cloud.polaris.router.config; +package com.tencent.cloud.polaris.router.config.properties; import org.springframework.boot.context.properties.ConfigurationProperties; diff --git a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/PolarisNearByRouterProperties.java b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/properties/PolarisNearByRouterProperties.java similarity index 95% rename from spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/PolarisNearByRouterProperties.java rename to spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/properties/PolarisNearByRouterProperties.java index 3467b0587..3cd69ca12 100644 --- a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/PolarisNearByRouterProperties.java +++ b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/properties/PolarisNearByRouterProperties.java @@ -16,7 +16,7 @@ * */ -package com.tencent.cloud.polaris.router.config; +package com.tencent.cloud.polaris.router.config.properties; import org.springframework.boot.context.properties.ConfigurationProperties; diff --git a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/PolarisRuleBasedRouterProperties.java b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/properties/PolarisRuleBasedRouterProperties.java similarity index 95% rename from spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/PolarisRuleBasedRouterProperties.java rename to spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/properties/PolarisRuleBasedRouterProperties.java index 89b4bead5..67a17975f 100644 --- a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/PolarisRuleBasedRouterProperties.java +++ b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/properties/PolarisRuleBasedRouterProperties.java @@ -16,7 +16,7 @@ * */ -package com.tencent.cloud.polaris.router.config; +package com.tencent.cloud.polaris.router.config.properties; import org.springframework.boot.context.properties.ConfigurationProperties; 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/scg/PolarisLoadBalancerClientFilter.java new file mode 100644 index 000000000..35de57737 --- /dev/null +++ b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/scg/PolarisLoadBalancerClientFilter.java @@ -0,0 +1,144 @@ +/* + * Tencent is pleased to support the open source community by making Spring Cloud Tencent available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * Unless required by applicable law or agreed to in writing, software distributed + * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + */ + +package com.tencent.cloud.polaris.router.scg; + +import java.net.URI; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import com.tencent.cloud.common.metadata.MetadataContext; +import com.tencent.cloud.common.metadata.MetadataContextHolder; +import com.tencent.cloud.common.metadata.config.MetadataLocalProperties; +import com.tencent.cloud.common.util.ExpressionLabelUtils; +import com.tencent.cloud.polaris.router.PolarisRouterContext; +import com.tencent.cloud.polaris.router.RouterRuleLabelResolver; +import com.tencent.cloud.polaris.router.spi.RouterLabelResolver; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import org.springframework.cloud.client.ServiceInstance; +import org.springframework.cloud.client.loadbalancer.LoadBalancerClient; +import org.springframework.cloud.gateway.config.LoadBalancerProperties; +import org.springframework.cloud.gateway.filter.LoadBalancerClientFilter; +import org.springframework.cloud.netflix.ribbon.RibbonLoadBalancerClient; +import org.springframework.core.Ordered; +import org.springframework.util.CollectionUtils; +import org.springframework.web.server.ServerWebExchange; + +import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR; + +/** + * Replaces the default LoadBalancerClientFilter implementation. + *@author lepdou 2022-06-10 + */ +public class PolarisLoadBalancerClientFilter extends LoadBalancerClientFilter { + private final static Logger LOGGER = LoggerFactory.getLogger(PolarisLoadBalancerClientFilter.class); + + private final MetadataLocalProperties metadataLocalProperties; + private final RouterRuleLabelResolver routerRuleLabelResolver; + private final List routerLabelResolvers; + + private final boolean isRibbonLoadBalanceClient; + + public PolarisLoadBalancerClientFilter(LoadBalancerClient loadBalancer, LoadBalancerProperties properties, + MetadataLocalProperties metadataLocalProperties, + RouterRuleLabelResolver routerRuleLabelResolver, + List routerLabelResolvers) { + super(loadBalancer, properties); + this.metadataLocalProperties = metadataLocalProperties; + this.routerRuleLabelResolver = routerRuleLabelResolver; + + if (!CollectionUtils.isEmpty(routerLabelResolvers)) { + routerLabelResolvers.sort(Comparator.comparingInt(Ordered::getOrder)); + this.routerLabelResolvers = routerLabelResolvers; + } + else { + this.routerLabelResolvers = null; + } + + this.isRibbonLoadBalanceClient = loadBalancer instanceof RibbonLoadBalancerClient; + } + + @Override + protected ServiceInstance choose(ServerWebExchange exchange) { + String peerServiceName = ((URI) exchange.getAttribute(GATEWAY_REQUEST_URL_ATTR)).getHost(); + + if (isRibbonLoadBalanceClient) { + // Pass routing context to ribbon load balancer + PolarisRouterContext routerContext = genRouterContext(exchange, peerServiceName); + return ((RibbonLoadBalancerClient) loadBalancer).choose(peerServiceName, routerContext); + } + else { + return loadBalancer.choose(peerServiceName); + } + } + + PolarisRouterContext genRouterContext(ServerWebExchange exchange, String peerServiceName) { + // local service labels + Map labels = new HashMap<>(metadataLocalProperties.getContent()); + + // labels from rule expression + Map ruleExpressionLabels = getExpressionLabels(exchange, peerServiceName); + if (!CollectionUtils.isEmpty(ruleExpressionLabels)) { + labels.putAll(ruleExpressionLabels); + } + + // labels from request + if (!CollectionUtils.isEmpty(routerLabelResolvers)) { + routerLabelResolvers.forEach(resolver -> { + try { + Map customResolvedLabels = resolver.resolve(exchange); + if (!CollectionUtils.isEmpty(customResolvedLabels)) { + labels.putAll(customResolvedLabels); + } + } + catch (Throwable t) { + LOGGER.error("[SCT][Router] revoke RouterLabelResolver occur some exception. ", t); + } + }); + } + + // labels from downstream + Map transitiveLabels = MetadataContextHolder.get() + .getFragmentContext(MetadataContext.FRAGMENT_TRANSITIVE); + labels.putAll(transitiveLabels); + + PolarisRouterContext routerContext = new PolarisRouterContext(); + + routerContext.setLabels(PolarisRouterContext.RULE_ROUTER_LABELS, labels); + routerContext.setLabels(PolarisRouterContext.TRANSITIVE_LABELS, transitiveLabels); + + return routerContext; + } + + private Map getExpressionLabels(ServerWebExchange exchange, String peerServiceName) { + Set labelKeys = routerRuleLabelResolver.getExpressionLabelKeys(MetadataContext.LOCAL_NAMESPACE, + MetadataContext.LOCAL_SERVICE, peerServiceName); + + if (CollectionUtils.isEmpty(labelKeys)) { + return Collections.emptyMap(); + } + + return ExpressionLabelUtils.resolve(exchange, labelKeys); + } +} diff --git a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/spi/RouterLabelResolver.java b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/spi/RouterLabelResolver.java index 49b9ccf4c..44dbbb471 100644 --- a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/spi/RouterLabelResolver.java +++ b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/spi/RouterLabelResolver.java @@ -24,6 +24,7 @@ import feign.RequestTemplate; import org.springframework.core.Ordered; import org.springframework.http.HttpRequest; +import org.springframework.web.server.ServerWebExchange; /** * The spi for resolving labels from request. @@ -46,4 +47,12 @@ public interface RouterLabelResolver extends Ordered { * @return resolved labels */ Map resolve(HttpRequest request, byte[] body); + + + /** + * resolve labels from server web exchange. + * @param exchange the server web exchange. + * @return resolved labels + */ + Map resolve(ServerWebExchange exchange); } diff --git a/spring-cloud-starter-tencent-polaris-router/src/main/resources/META-INF/spring.factories b/spring-cloud-starter-tencent-polaris-router/src/main/resources/META-INF/spring.factories index d33dcea7f..3b20deb56 100644 --- a/spring-cloud-starter-tencent-polaris-router/src/main/resources/META-INF/spring.factories +++ b/spring-cloud-starter-tencent-polaris-router/src/main/resources/META-INF/spring.factories @@ -1,2 +1,3 @@ org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ - com.tencent.cloud.polaris.router.config.RouterAutoConfiguration + com.tencent.cloud.polaris.router.config.RouterAutoConfiguration,\ + com.tencent.cloud.polaris.router.config.FeignAutoConfiguration diff --git a/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/PolarisLoadBalancerCompositeRuleTest.java b/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/PolarisLoadBalancerCompositeRuleTest.java index 1eccb542c..0d55e9cde 100644 --- a/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/PolarisLoadBalancerCompositeRuleTest.java +++ b/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/PolarisLoadBalancerCompositeRuleTest.java @@ -41,9 +41,9 @@ import com.tencent.cloud.common.pojo.PolarisServer; import com.tencent.cloud.common.util.ApplicationContextAwareUtils; import com.tencent.cloud.polaris.loadbalancer.PolarisWeightedRule; import com.tencent.cloud.polaris.loadbalancer.config.PolarisLoadBalancerProperties; -import com.tencent.cloud.polaris.router.config.PolarisMetadataRouterProperties; -import com.tencent.cloud.polaris.router.config.PolarisNearByRouterProperties; -import com.tencent.cloud.polaris.router.config.PolarisRuleBasedRouterProperties; +import com.tencent.cloud.polaris.router.config.properties.PolarisMetadataRouterProperties; +import com.tencent.cloud.polaris.router.config.properties.PolarisNearByRouterProperties; +import com.tencent.cloud.polaris.router.config.properties.PolarisRuleBasedRouterProperties; import com.tencent.polaris.api.pojo.DefaultInstance; import com.tencent.polaris.api.pojo.DefaultServiceInstances; import com.tencent.polaris.api.pojo.Instance; diff --git a/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/resttemplate/PolarisLoadBalancerBeanPostProcessorTest.java b/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/resttemplate/PolarisLoadBalancerBeanPostProcessorTest.java index e335e83fa..cfcfa5877 100644 --- a/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/resttemplate/PolarisLoadBalancerBeanPostProcessorTest.java +++ b/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/resttemplate/PolarisLoadBalancerBeanPostProcessorTest.java @@ -20,6 +20,7 @@ package com.tencent.cloud.polaris.router.resttemplate; import com.tencent.cloud.common.metadata.config.MetadataLocalProperties; import com.tencent.cloud.common.util.BeanFactoryUtils; +import com.tencent.cloud.polaris.router.PolarisLoadBalancerBeanPostProcessor; import com.tencent.cloud.polaris.router.RouterRuleLabelResolver; import com.tencent.cloud.polaris.router.spi.RouterLabelResolver; import org.junit.Assert; 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/scg/PolarisLoadBalancerClientFilterTest.java new file mode 100644 index 000000000..6010689af --- /dev/null +++ b/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/scg/PolarisLoadBalancerClientFilterTest.java @@ -0,0 +1,192 @@ +/* + * Tencent is pleased to support the open source community by making Spring Cloud Tencent available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * Unless required by applicable law or agreed to in writing, software distributed + * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + */ + +package com.tencent.cloud.polaris.router.scg; + + +import java.net.URI; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +import com.google.common.collect.Lists; +import com.google.common.collect.Sets; +import com.tencent.cloud.common.metadata.MetadataContext; +import com.tencent.cloud.common.metadata.MetadataContextHolder; +import com.tencent.cloud.common.metadata.config.MetadataLocalProperties; +import com.tencent.cloud.common.util.ApplicationContextAwareUtils; +import com.tencent.cloud.polaris.router.PolarisRouterContext; +import com.tencent.cloud.polaris.router.RouterRuleLabelResolver; +import com.tencent.cloud.polaris.router.spi.RouterLabelResolver; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockedStatic; +import org.mockito.Mockito; +import org.mockito.junit.MockitoJUnitRunner; + +import org.springframework.cloud.client.loadbalancer.LoadBalancerClient; +import org.springframework.cloud.gateway.config.LoadBalancerProperties; +import org.springframework.cloud.netflix.ribbon.RibbonLoadBalancerClient; +import org.springframework.mock.http.server.reactive.MockServerHttpRequest; +import org.springframework.mock.web.server.MockServerWebExchange; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR; + +/** + * test for ${@link PolarisLoadBalancerClientFilter} + *@author lepdou 2022-06-13 + */ +@RunWith(MockitoJUnitRunner.class) +public class PolarisLoadBalancerClientFilterTest { + + @Mock + private MetadataLocalProperties metadataLocalProperties; + @Mock + private RouterRuleLabelResolver routerRuleLabelResolver; + @Mock + private RouterLabelResolver routerLabelResolver; + @Mock + private LoadBalancerClient loadBalancerClient; + @Mock + private LoadBalancerProperties loadBalancerProperties; + + private static final String callerService = "callerService"; + private static final String calleeService = "calleeService"; + + private static MockedStatic mockedApplicationContextAwareUtils; + private static MockedStatic mockedMetadataContextHolder; + + @BeforeClass + public static void beforeClass() { + mockedApplicationContextAwareUtils = Mockito.mockStatic(ApplicationContextAwareUtils.class); + mockedApplicationContextAwareUtils.when(() -> ApplicationContextAwareUtils.getProperties(anyString())) + .thenReturn(callerService); + + MetadataContext metadataContext = Mockito.mock(MetadataContext.class); + + // mock transitive metadata + Map transitiveLabels = new HashMap<>(); + transitiveLabels.put("t1", "v1"); + transitiveLabels.put("t2", "v2"); + when(metadataContext.getFragmentContext(MetadataContext.FRAGMENT_TRANSITIVE)).thenReturn(transitiveLabels); + + mockedMetadataContextHolder = Mockito.mockStatic(MetadataContextHolder.class); + mockedMetadataContextHolder.when(MetadataContextHolder::get).thenReturn(metadataContext); + } + + @AfterClass + public static void afterClass() { + mockedApplicationContextAwareUtils.close(); + mockedMetadataContextHolder.close(); + } + + @Test + public void testGenRouterContext() { + PolarisLoadBalancerClientFilter polarisLoadBalancerClientFilter = new PolarisLoadBalancerClientFilter( + loadBalancerClient, loadBalancerProperties, metadataLocalProperties, routerRuleLabelResolver, + Lists.newArrayList(routerLabelResolver)); + + Map localMetadata = new HashMap<>(); + localMetadata.put("env", "blue"); + when(metadataLocalProperties.getContent()).thenReturn(localMetadata); + + Set expressionLabelKeys = Sets.newHashSet("${http.header.k1}", "${http.query.userid}"); + when(routerRuleLabelResolver.getExpressionLabelKeys(anyString(), anyString(), anyString())).thenReturn(expressionLabelKeys); + + MockServerHttpRequest request = MockServerHttpRequest.get("/" + calleeService + "/users") + .header("k1", "v1") + .queryParam("userid", "zhangsan") + .build(); + MockServerWebExchange webExchange = new MockServerWebExchange.Builder(request).build(); + + Map customMetadata = new HashMap<>(); + customMetadata.put("k2", "v2"); + when(routerLabelResolver.resolve(webExchange)).thenReturn(customMetadata); + + PolarisRouterContext routerContext = polarisLoadBalancerClientFilter.genRouterContext(webExchange, calleeService); + + Map routerLabels = routerContext.getLabels(PolarisRouterContext.RULE_ROUTER_LABELS); + Assert.assertEquals("v1", routerLabels.get("${http.header.k1}")); + Assert.assertEquals("zhangsan", routerLabels.get("${http.query.userid}")); + Assert.assertEquals("blue", routerLabels.get("env")); + Assert.assertEquals("v1", routerLabels.get("t1")); + Assert.assertEquals("v2", routerLabels.get("t2")); + } + + @Test + public void testChooseInstanceWithoutRibbon() { + PolarisLoadBalancerClientFilter polarisLoadBalancerClientFilter = new PolarisLoadBalancerClientFilter( + loadBalancerClient, loadBalancerProperties, metadataLocalProperties, routerRuleLabelResolver, + Lists.newArrayList(routerLabelResolver)); + + String url = "/" + calleeService + "/users"; + MockServerHttpRequest request = MockServerHttpRequest.get(url) + .header("k1", "v1") + .queryParam("userid", "zhangsan") + .build(); + MockServerWebExchange webExchange = new MockServerWebExchange.Builder(request).build(); + webExchange.getAttributes().put(GATEWAY_REQUEST_URL_ATTR, URI.create("http://" + calleeService + "/users")); + + polarisLoadBalancerClientFilter.choose(webExchange); + + verify(loadBalancerClient).choose(calleeService); + verify(metadataLocalProperties, times(0)).getContent(); + } + + @Test + public void testChooseInstanceWithRibbon() { + RibbonLoadBalancerClient ribbonLoadBalancerClient = Mockito.mock(RibbonLoadBalancerClient.class); + + PolarisLoadBalancerClientFilter polarisLoadBalancerClientFilter = new PolarisLoadBalancerClientFilter( + ribbonLoadBalancerClient, loadBalancerProperties, metadataLocalProperties, routerRuleLabelResolver, + Lists.newArrayList(routerLabelResolver)); + + Map localMetadata = new HashMap<>(); + localMetadata.put("env", "blue"); + when(metadataLocalProperties.getContent()).thenReturn(localMetadata); + + Set expressionLabelKeys = Sets.newHashSet("${http.header.k1}", "${http.query.userid}"); + when(routerRuleLabelResolver.getExpressionLabelKeys(anyString(), anyString(), anyString())).thenReturn(expressionLabelKeys); + + String url = "/" + calleeService + "/users"; + MockServerHttpRequest request = MockServerHttpRequest.get(url) + .header("k1", "v1") + .queryParam("userid", "zhangsan") + .build(); + MockServerWebExchange webExchange = new MockServerWebExchange.Builder(request).build(); + webExchange.getAttributes().put(GATEWAY_REQUEST_URL_ATTR, URI.create("http://" + calleeService + "/users")); + + Map customMetadata = new HashMap<>(); + customMetadata.put("k2", "v2"); + when(routerLabelResolver.resolve(webExchange)).thenReturn(customMetadata); + + polarisLoadBalancerClientFilter.choose(webExchange); + + verify(ribbonLoadBalancerClient).choose(anyString(), any()); + verify(metadataLocalProperties, times(1)).getContent(); + } +} diff --git a/spring-cloud-tencent-examples/polaris-gateway-example/gateway-callee-service/src/main/resources/bootstrap.yml b/spring-cloud-tencent-examples/polaris-gateway-example/gateway-callee-service/src/main/resources/bootstrap.yml index 2d0d75a41..c6d40440f 100644 --- a/spring-cloud-tencent-examples/polaris-gateway-example/gateway-callee-service/src/main/resources/bootstrap.yml +++ b/spring-cloud-tencent-examples/polaris-gateway-example/gateway-callee-service/src/main/resources/bootstrap.yml @@ -5,6 +5,10 @@ spring: application: name: GatewayCalleeService cloud: + tencent: + metadata: + content: + env: blue polaris: address: grpc://183.47.111.80:8091 namespace: default diff --git a/spring-cloud-tencent-examples/polaris-gateway-example/gateway-callee-service2/pom.xml b/spring-cloud-tencent-examples/polaris-gateway-example/gateway-callee-service2/pom.xml new file mode 100644 index 000000000..6454f43d7 --- /dev/null +++ b/spring-cloud-tencent-examples/polaris-gateway-example/gateway-callee-service2/pom.xml @@ -0,0 +1,26 @@ + + + + polaris-gateway-example + com.tencent.cloud + ${revision} + ../pom.xml + + 4.0.0 + + gateway-callee-service2 + + + + com.tencent.cloud + spring-cloud-starter-tencent-polaris-discovery + + + + org.springframework.boot + spring-boot-starter-web + + + diff --git a/spring-cloud-tencent-examples/polaris-gateway-example/gateway-callee-service2/src/main/java/com/tencent/cloud/polaris/gateway/example/callee/GatewayCalleeApplication2.java b/spring-cloud-tencent-examples/polaris-gateway-example/gateway-callee-service2/src/main/java/com/tencent/cloud/polaris/gateway/example/callee/GatewayCalleeApplication2.java new file mode 100644 index 000000000..5d261d56f --- /dev/null +++ b/spring-cloud-tencent-examples/polaris-gateway-example/gateway-callee-service2/src/main/java/com/tencent/cloud/polaris/gateway/example/callee/GatewayCalleeApplication2.java @@ -0,0 +1,35 @@ +/* + * Tencent is pleased to support the open source community by making Spring Cloud Tencent available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * Unless required by applicable law or agreed to in writing, software distributed + * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package com.tencent.cloud.polaris.gateway.example.callee; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +/** + * Gateway callee application. + * + * @author Haotian Zhang + */ +@SpringBootApplication +public class GatewayCalleeApplication2 { + + public static void main(String[] args) { + SpringApplication.run(GatewayCalleeApplication2.class, args); + } + +} diff --git a/spring-cloud-tencent-examples/polaris-gateway-example/gateway-callee-service2/src/main/java/com/tencent/cloud/polaris/gateway/example/callee/GatewayCalleeController.java b/spring-cloud-tencent-examples/polaris-gateway-example/gateway-callee-service2/src/main/java/com/tencent/cloud/polaris/gateway/example/callee/GatewayCalleeController.java new file mode 100644 index 000000000..40ddeb240 --- /dev/null +++ b/spring-cloud-tencent-examples/polaris-gateway-example/gateway-callee-service2/src/main/java/com/tencent/cloud/polaris/gateway/example/callee/GatewayCalleeController.java @@ -0,0 +1,71 @@ +/* + * Tencent is pleased to support the open source community by making Spring Cloud Tencent available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * Unless required by applicable law or agreed to in writing, software distributed + * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package com.tencent.cloud.polaris.gateway.example.callee; + +import java.io.UnsupportedEncodingException; +import java.net.URLDecoder; + +import com.tencent.cloud.common.constant.MetadataConstant; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * Gateway callee controller. + * + * @author Haotian Zhang + */ +@RestController +@RequestMapping("/gateway/example/callee") +public class GatewayCalleeController { + + private static Logger LOG = LoggerFactory.getLogger(GatewayCalleeController.class); + + @Value("${server.port:0}") + private int port; + + /** + * Get information of callee. + * @return information of callee + */ + @RequestMapping("/info") + public String info() { + LOG.info("Gateway Example Callee [{}] is called.", port); + return String.format("Gateway Example Callee [%s] is called.", port); + } + + /** + * Get metadata in HTTP header. + * + * @param metadataStr metadata string + * @return metadata in HTTP header + * @throws UnsupportedEncodingException encoding exception + */ + @RequestMapping("/echo") + public String echoHeader( + @RequestHeader(MetadataConstant.HeaderName.CUSTOM_METADATA) String metadataStr) + throws UnsupportedEncodingException { + LOG.info(URLDecoder.decode(metadataStr, "UTF-8")); + return URLDecoder.decode(metadataStr, "UTF-8"); + } + +} diff --git a/spring-cloud-tencent-examples/polaris-gateway-example/gateway-callee-service2/src/main/resources/bootstrap.yml b/spring-cloud-tencent-examples/polaris-gateway-example/gateway-callee-service2/src/main/resources/bootstrap.yml new file mode 100644 index 000000000..a0cf12581 --- /dev/null +++ b/spring-cloud-tencent-examples/polaris-gateway-example/gateway-callee-service2/src/main/resources/bootstrap.yml @@ -0,0 +1,14 @@ +server: + session-timeout: 1800 + port: 48082 +spring: + application: + name: GatewayCalleeService + cloud: + tencent: + metadata: + content: + env: green + polaris: + address: grpc://183.47.111.80:8091 + namespace: default diff --git a/spring-cloud-tencent-examples/polaris-gateway-example/gateway-scg-service/pom.xml b/spring-cloud-tencent-examples/polaris-gateway-example/gateway-scg-service/pom.xml index 5e02ccb43..755b04d63 100644 --- a/spring-cloud-tencent-examples/polaris-gateway-example/gateway-scg-service/pom.xml +++ b/spring-cloud-tencent-examples/polaris-gateway-example/gateway-scg-service/pom.xml @@ -26,7 +26,7 @@ com.tencent.cloud - spring-cloud-starter-tencent-metadata-transfer + spring-cloud-starter-tencent-polaris-router @@ -34,4 +34,4 @@ spring-cloud-starter-gateway - \ No newline at end of file + diff --git a/spring-cloud-tencent-examples/polaris-gateway-example/gateway-scg-service/src/main/resources/bootstrap.yml b/spring-cloud-tencent-examples/polaris-gateway-example/gateway-scg-service/src/main/resources/bootstrap.yml index 5d949573b..f50100264 100644 --- a/spring-cloud-tencent-examples/polaris-gateway-example/gateway-scg-service/src/main/resources/bootstrap.yml +++ b/spring-cloud-tencent-examples/polaris-gateway-example/gateway-scg-service/src/main/resources/bootstrap.yml @@ -8,15 +8,13 @@ spring: tencent: metadata: content: - a: 1 + env: blue transitive: - - a + - env polaris: address: grpc://183.47.111.80:8091 namespace: default enabled: true - discovery: - service-list-refresh-interval: 1000 gateway: discovery: locator: @@ -52,13 +50,13 @@ spring: maxBackoff: '''500ms''' factor: 2 basedOnPreviousValue: false -# routes: -# - id: GatewayCalleeService -# uri: lb://GatewayCalleeService -# predicates: -# - Path=/GatewayCalleeService/** -# filters: -# - StripPrefix=1 + routes: + - id: GatewayCalleeService + uri: lb://GatewayCalleeService + predicates: + - Path=/GatewayCalleeService/** + filters: + - StripPrefix=1 logging: level: diff --git a/spring-cloud-tencent-examples/polaris-router-example/router-caller-service/src/main/java/com/tencent/cloud/polaris/router/example/CustomRouterLabelResolver.java b/spring-cloud-tencent-examples/polaris-router-example/router-caller-service/src/main/java/com/tencent/cloud/polaris/router/example/CustomRouterLabelResolver.java index bd289abb9..ea8c2ceb0 100644 --- a/spring-cloud-tencent-examples/polaris-router-example/router-caller-service/src/main/java/com/tencent/cloud/polaris/router/example/CustomRouterLabelResolver.java +++ b/spring-cloud-tencent-examples/polaris-router-example/router-caller-service/src/main/java/com/tencent/cloud/polaris/router/example/CustomRouterLabelResolver.java @@ -27,6 +27,7 @@ import feign.RequestTemplate; import org.springframework.http.HttpRequest; import org.springframework.stereotype.Component; +import org.springframework.web.server.ServerWebExchange; /** * @@ -58,6 +59,11 @@ public class CustomRouterLabelResolver implements RouterLabelResolver { return labels; } + @Override + public Map resolve(ServerWebExchange exchange) { + return null; + } + @Override public int getOrder() { return 0;