diff --git a/CHANGELOG.md b/CHANGELOG.md index 91da14b29..185c7d365 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,9 +4,11 @@ - [Bugfix: optimize ratelimit actuator](https://github.com/Tencent/spring-cloud-tencent/pull/413) - [Feature: add rate limit filter debug log](https://github.com/Tencent/spring-cloud-tencent/pull/417) - [Feature: Optimized configuration update](https://github.com/Tencent/spring-cloud-tencent/pull/423) +- [Optimize feign & rest-template circuit-breaker logic](https://github.com/Tencent/spring-cloud-tencent/pull/424) - [[Optimize] improve load-balance ut and support configurable heartbeat interval](https://github.com/Tencent/spring-cloud-tencent/pull/427) - [Feature: add feature-env plugin & add spring cloud gateway staining plugin](https://github.com/Tencent/spring-cloud-tencent/pull/428) - [Optimize: add EncodeTransferMedataRestTemplateInterceptor to RestTemplate](https://github.com/Tencent/spring-cloud-tencent/pull/434) - [feat:enhance Feign and RestTemplate and support Polaris monitor.](https://github.com/Tencent/spring-cloud-tencent/pull/435) - [Optimize: Specification apollo code reference notes](https://github.com/Tencent/spring-cloud-tencent/pull/442) -- [Optimize feign & rest-template circuit-breaker logic](https://github.com/Tencent/spring-cloud-tencent/pull/424) +- [Optimize: optimize router label resolver spi](https://github.com/Tencent/spring-cloud-tencent/pull/449) +- [Feature: add feature env examples](https://github.com/Tencent/spring-cloud-tencent/pull/450) 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 f3763a13f..752ccce00 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 @@ -107,6 +107,7 @@ public class PolarisLoadBalancerCompositeRule extends AbstractLoadBalancerRule { return null; } + ILoadBalancer loadBalancer = new SimpleLoadBalancer(); // 2. filter by router if (key instanceof PolarisRouterContext) { PolarisRouterContext routerContext = (PolarisRouterContext) key; @@ -114,10 +115,12 @@ public class PolarisLoadBalancerCompositeRule extends AbstractLoadBalancerRule { // 3. filter by load balance. // A LoadBalancer needs to be regenerated for each request, // because the list of servers may be different after filtered by router - ILoadBalancer loadBalancer = new SimpleLoadBalancer(); loadBalancer.addServers(serversAfterRouter); - delegateRule.setLoadBalancer(loadBalancer); } + else { + loadBalancer.addServers(allServers); + } + delegateRule.setLoadBalancer(loadBalancer); return delegateRule.choose(key); } 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 2fa66c57b..8cf543252 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 @@ -24,7 +24,7 @@ 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.scg.PolarisLoadBalancerClientFilter; -import com.tencent.cloud.polaris.router.spi.RouterLabelResolver; +import com.tencent.cloud.polaris.router.spi.SpringWebRouterLabelResolver; import org.springframework.beans.BeansException; import org.springframework.beans.factory.BeanFactory; @@ -56,7 +56,7 @@ public class LoadBalancerClientFilterBeanPostProcessor implements BeanPostProces // 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); + List routerLabelResolvers = BeanFactoryUtils.getBeans(factory, SpringWebRouterLabelResolver.class); MetadataLocalProperties metadataLocalProperties = this.factory.getBean(MetadataLocalProperties.class); RouterRuleLabelResolver routerRuleLabelResolver = this.factory.getBean(RouterRuleLabelResolver.class); 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 d888d6185..c97da3a9c 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 @@ -24,7 +24,7 @@ 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.spi.RouterLabelResolver; +import com.tencent.cloud.polaris.router.spi.SpringWebRouterLabelResolver; import org.springframework.beans.BeansException; import org.springframework.beans.factory.BeanFactory; @@ -57,7 +57,7 @@ public class LoadBalancerInterceptorBeanPostProcessor implements BeanPostProcess // 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); + List routerLabelResolvers = BeanFactoryUtils.getBeans(factory, SpringWebRouterLabelResolver.class); MetadataLocalProperties metadataLocalProperties = this.factory.getBean(MetadataLocalProperties.class); RouterRuleLabelResolver routerRuleLabelResolver = this.factory.getBean(RouterRuleLabelResolver.class); 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 752dd1216..b752d4a76 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 @@ -24,7 +24,7 @@ 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 com.tencent.cloud.polaris.router.spi.FeignRouterLabelResolver; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.cloud.netflix.ribbon.RibbonClients; @@ -45,7 +45,7 @@ import org.springframework.lang.Nullable; public class FeignAutoConfiguration { @Bean - public RouterLabelFeignInterceptor routerLabelInterceptor(@Nullable List routerLabelResolvers, + public RouterLabelFeignInterceptor routerLabelInterceptor(@Nullable List routerLabelResolvers, MetadataLocalProperties metadataLocalProperties, RouterRuleLabelResolver routerRuleLabelResolver) { return new RouterLabelFeignInterceptor(routerLabelResolvers, metadataLocalProperties, routerRuleLabelResolver); 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/feign/RouterLabelFeignInterceptor.java index abcd83d1f..9c8dd60bf 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/feign/RouterLabelFeignInterceptor.java @@ -33,7 +33,7 @@ import com.tencent.cloud.common.metadata.config.MetadataLocalProperties; import com.tencent.cloud.common.util.JacksonUtils; import com.tencent.cloud.polaris.router.RouterConstants; import com.tencent.cloud.polaris.router.RouterRuleLabelResolver; -import com.tencent.cloud.polaris.router.spi.RouterLabelResolver; +import com.tencent.cloud.polaris.router.spi.FeignRouterLabelResolver; import feign.RequestInterceptor; import feign.RequestTemplate; import org.slf4j.Logger; @@ -52,11 +52,11 @@ import static com.tencent.cloud.common.constant.ContextConstant.UTF_8; public class RouterLabelFeignInterceptor implements RequestInterceptor, Ordered { private static final Logger LOGGER = LoggerFactory.getLogger(RouterLabelFeignInterceptor.class); - private final List routerLabelResolvers; + private final List routerLabelResolvers; private final MetadataLocalProperties metadataLocalProperties; private final RouterRuleLabelResolver routerRuleLabelResolver; - public RouterLabelFeignInterceptor(List routerLabelResolvers, + public RouterLabelFeignInterceptor(List routerLabelResolvers, MetadataLocalProperties metadataLocalProperties, RouterRuleLabelResolver routerRuleLabelResolver) { if (!CollectionUtils.isEmpty(routerLabelResolvers)) { @@ -82,14 +82,16 @@ public class RouterLabelFeignInterceptor implements RequestInterceptor, Ordered // labels from rule expression String peerServiceName = requestTemplate.feignTarget().name(); - Map ruleExpressionLabels = getRuleExpressionLabels(requestTemplate, peerServiceName); + Set expressionLabelKeys = routerRuleLabelResolver.getExpressionLabelKeys(MetadataContext.LOCAL_NAMESPACE, + MetadataContext.LOCAL_SERVICE, peerServiceName); + Map ruleExpressionLabels = getRuleExpressionLabels(requestTemplate, expressionLabelKeys); labels.putAll(ruleExpressionLabels); - // labels from request + // labels from custom spi if (!CollectionUtils.isEmpty(routerLabelResolvers)) { routerLabelResolvers.forEach(resolver -> { try { - Map customResolvedLabels = resolver.resolve(requestTemplate); + Map customResolvedLabels = resolver.resolve(requestTemplate, expressionLabelKeys); if (!CollectionUtils.isEmpty(customResolvedLabels)) { labels.putAll(customResolvedLabels); } @@ -101,16 +103,10 @@ public class RouterLabelFeignInterceptor implements RequestInterceptor, Ordered } // labels from downstream - Map transitiveLabels = MetadataContextHolder.get() - .getFragmentContext(MetadataContext.FRAGMENT_TRANSITIVE); + Map transitiveLabels = MetadataContextHolder.get().getFragmentContext(MetadataContext.FRAGMENT_TRANSITIVE); labels.putAll(transitiveLabels); // pass label by header - if (labels.size() == 0) { - requestTemplate.header(RouterConstants.ROUTER_LABEL_HEADER); - return; - } - String encodedLabelsContent; try { encodedLabelsContent = URLEncoder.encode(JacksonUtils.serialize2Json(labels), UTF_8); @@ -121,9 +117,7 @@ public class RouterLabelFeignInterceptor implements RequestInterceptor, Ordered requestTemplate.header(RouterConstants.ROUTER_LABEL_HEADER, encodedLabelsContent); } - private Map getRuleExpressionLabels(RequestTemplate requestTemplate, String peerService) { - Set labelKeys = routerRuleLabelResolver.getExpressionLabelKeys(MetadataContext.LOCAL_NAMESPACE, - MetadataContext.LOCAL_SERVICE, peerService); + private Map getRuleExpressionLabels(RequestTemplate requestTemplate, Set labelKeys) { if (CollectionUtils.isEmpty(labelKeys)) { return Collections.emptyMap(); 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/resttemplate/PolarisLoadBalancerInterceptor.java index c427075c9..4702230cd 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/resttemplate/PolarisLoadBalancerInterceptor.java @@ -33,7 +33,7 @@ import com.tencent.cloud.common.metadata.config.MetadataLocalProperties; import com.tencent.cloud.common.util.expresstion.SpringWebExpressionLabelUtils; import com.tencent.cloud.polaris.router.PolarisRouterContext; import com.tencent.cloud.polaris.router.RouterRuleLabelResolver; -import com.tencent.cloud.polaris.router.spi.RouterLabelResolver; +import com.tencent.cloud.polaris.router.spi.SpringWebRouterLabelResolver; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -59,7 +59,7 @@ public class PolarisLoadBalancerInterceptor extends LoadBalancerInterceptor { private final LoadBalancerClient loadBalancer; private final LoadBalancerRequestFactory requestFactory; - private final List routerLabelResolvers; + private final List routerLabelResolvers; private final MetadataLocalProperties metadataLocalProperties; private final RouterRuleLabelResolver routerRuleLabelResolver; @@ -67,7 +67,7 @@ public class PolarisLoadBalancerInterceptor extends LoadBalancerInterceptor { public PolarisLoadBalancerInterceptor(LoadBalancerClient loadBalancer, LoadBalancerRequestFactory requestFactory, - List routerLabelResolvers, + List routerLabelResolvers, MetadataLocalProperties metadataLocalProperties, RouterRuleLabelResolver routerRuleLabelResolver) { super(loadBalancer, requestFactory); @@ -110,7 +110,9 @@ public class PolarisLoadBalancerInterceptor extends LoadBalancerInterceptor { Map labels = new HashMap<>(metadataLocalProperties.getContent()); // labels from rule expression - Map ruleExpressionLabels = getExpressionLabels(request, peerServiceName); + Set expressionLabelKeys = routerRuleLabelResolver.getExpressionLabelKeys(MetadataContext.LOCAL_NAMESPACE, + MetadataContext.LOCAL_SERVICE, peerServiceName); + Map ruleExpressionLabels = getExpressionLabels(request, expressionLabelKeys); if (!CollectionUtils.isEmpty(ruleExpressionLabels)) { labels.putAll(ruleExpressionLabels); } @@ -119,7 +121,7 @@ public class PolarisLoadBalancerInterceptor extends LoadBalancerInterceptor { if (!CollectionUtils.isEmpty(routerLabelResolvers)) { routerLabelResolvers.forEach(resolver -> { try { - Map customResolvedLabels = resolver.resolve(request, body); + Map customResolvedLabels = resolver.resolve(request, body, expressionLabelKeys); if (!CollectionUtils.isEmpty(customResolvedLabels)) { labels.putAll(customResolvedLabels); } @@ -143,10 +145,7 @@ public class PolarisLoadBalancerInterceptor extends LoadBalancerInterceptor { return routerContext; } - private Map getExpressionLabels(HttpRequest request, String peerServiceName) { - Set labelKeys = routerRuleLabelResolver.getExpressionLabelKeys(MetadataContext.LOCAL_NAMESPACE, - MetadataContext.LOCAL_SERVICE, peerServiceName); - + private Map getExpressionLabels(HttpRequest request, Set labelKeys) { if (CollectionUtils.isEmpty(labelKeys)) { return Collections.emptyMap(); } 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 index c610a0c9c..7bbc9eddd 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/scg/PolarisLoadBalancerClientFilter.java @@ -32,7 +32,7 @@ import com.tencent.cloud.common.metadata.config.MetadataLocalProperties; import com.tencent.cloud.common.util.expresstion.SpringWebExpressionLabelUtils; import com.tencent.cloud.polaris.router.PolarisRouterContext; import com.tencent.cloud.polaris.router.RouterRuleLabelResolver; -import com.tencent.cloud.polaris.router.spi.RouterLabelResolver; +import com.tencent.cloud.polaris.router.spi.SpringWebRouterLabelResolver; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -57,14 +57,14 @@ public class PolarisLoadBalancerClientFilter extends LoadBalancerClientFilter { private final MetadataLocalProperties metadataLocalProperties; private final RouterRuleLabelResolver routerRuleLabelResolver; - private final List routerLabelResolvers; + private final List routerLabelResolvers; private final boolean isRibbonLoadBalanceClient; public PolarisLoadBalancerClientFilter(LoadBalancerClient loadBalancer, LoadBalancerProperties properties, MetadataLocalProperties metadataLocalProperties, RouterRuleLabelResolver routerRuleLabelResolver, - List routerLabelResolvers) { + List routerLabelResolvers) { super(loadBalancer, properties); this.metadataLocalProperties = metadataLocalProperties; this.routerRuleLabelResolver = routerRuleLabelResolver; @@ -99,7 +99,9 @@ public class PolarisLoadBalancerClientFilter extends LoadBalancerClientFilter { Map labels = new HashMap<>(metadataLocalProperties.getContent()); // labels from rule expression - Map ruleExpressionLabels = getExpressionLabels(exchange, peerServiceName); + Set expressionLabelKeys = routerRuleLabelResolver.getExpressionLabelKeys(MetadataContext.LOCAL_NAMESPACE, + MetadataContext.LOCAL_SERVICE, peerServiceName); + Map ruleExpressionLabels = getExpressionLabels(exchange, expressionLabelKeys); if (!CollectionUtils.isEmpty(ruleExpressionLabels)) { labels.putAll(ruleExpressionLabels); } @@ -108,7 +110,7 @@ public class PolarisLoadBalancerClientFilter extends LoadBalancerClientFilter { if (!CollectionUtils.isEmpty(routerLabelResolvers)) { routerLabelResolvers.forEach(resolver -> { try { - Map customResolvedLabels = resolver.resolve(exchange); + Map customResolvedLabels = resolver.resolve(exchange, expressionLabelKeys); if (!CollectionUtils.isEmpty(customResolvedLabels)) { labels.putAll(customResolvedLabels); } @@ -132,10 +134,7 @@ public class PolarisLoadBalancerClientFilter extends LoadBalancerClientFilter { return routerContext; } - private Map getExpressionLabels(ServerWebExchange exchange, String peerServiceName) { - Set labelKeys = routerRuleLabelResolver.getExpressionLabelKeys(MetadataContext.LOCAL_NAMESPACE, - MetadataContext.LOCAL_SERVICE, peerServiceName); - + private Map getExpressionLabels(ServerWebExchange exchange, Set labelKeys) { if (CollectionUtils.isEmpty(labelKeys)) { return Collections.emptyMap(); } diff --git a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/spi/FeignRouterLabelResolver.java b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/spi/FeignRouterLabelResolver.java new file mode 100644 index 000000000..05e1366b4 --- /dev/null +++ b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/spi/FeignRouterLabelResolver.java @@ -0,0 +1,41 @@ +/* + * 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.spi; + +import java.util.Map; +import java.util.Set; + +import feign.RequestTemplate; + +import org.springframework.core.Ordered; + +/** + * Router label resolver for feign request. + * @author lepdou 2022-07-20 + */ +public interface FeignRouterLabelResolver extends Ordered { + + /** + * Resolve labels from feign request. User can customize expression parser to extract labels. + * + * @param requestTemplate the feign request. + * @param expressionLabelKeys the expression labels which are configured in router rule. + * @return resolved labels + */ + Map resolve(RequestTemplate requestTemplate, Set expressionLabelKeys); +} diff --git a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/spi/SpringWebRouterLabelResolver.java b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/spi/SpringWebRouterLabelResolver.java new file mode 100644 index 000000000..55db8498b --- /dev/null +++ b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/spi/SpringWebRouterLabelResolver.java @@ -0,0 +1,57 @@ +/* + * Tencent is pleased to support the open source community by making Spring Cloud Tencent available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * Unless required by applicable law or agreed to in writing, software distributed + * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package com.tencent.cloud.polaris.router.spi; + +import java.util.Collections; +import java.util.Map; +import java.util.Set; + +import org.springframework.core.Ordered; +import org.springframework.http.HttpRequest; +import org.springframework.web.server.ServerWebExchange; + +/** + * Router label resolver for spring web http request. + * @author lepdou 2022-07-20 + */ +public interface SpringWebRouterLabelResolver extends Ordered { + + /** + * resolve labels from rest template request. User can customize expression parser to extract labels. + * + * @param request the rest template request. + * @param body the rest template request body. + * @param expressionLabelKeys the expression labels which are configured in router rule. + * @return resolved labels + */ + default Map resolve(HttpRequest request, byte[] body, Set expressionLabelKeys) { + return Collections.emptyMap(); + } + + + /** + * resolve labels from server web exchange. User can customize expression parser to extract labels. + * + * @param exchange the server web exchange. + * @param expressionLabelKeys the expression labels which are configured in router rule. + * @return resolved labels + */ + default Map resolve(ServerWebExchange exchange, Set expressionLabelKeys) { + return Collections.emptyMap(); + } +} diff --git a/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/RouterRuleLabelResolverTest.java b/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/RouterRuleLabelResolverTest.java index a910473ac..e16785c5c 100644 --- a/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/RouterRuleLabelResolverTest.java +++ b/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/RouterRuleLabelResolverTest.java @@ -59,11 +59,13 @@ public class RouterRuleLabelResolverTest { String validKey2 = "${http.query.name}"; String validKey3 = "${http.method}"; String validKey4 = "${http.uri}"; - String invalidKey = "${http.expression.wrong}"; + String validKey5 = "${http.body.customkey}"; + String invalidKey = "$http.expression.wrong}"; labels.put(validKey1, matchString); labels.put(validKey2, matchString); labels.put(validKey3, matchString); labels.put(validKey4, matchString); + labels.put(validKey5, matchString); labels.put(invalidKey, matchString); RoutingProto.Source source1 = RoutingProto.Source.newBuilder().putAllMetadata(labels).build(); @@ -83,11 +85,12 @@ public class RouterRuleLabelResolverTest { Set resolvedExpressionLabelKeys = resolver.getExpressionLabelKeys(testNamespace, testSourceService, testDstService); Assert.assertNotNull(resolvedExpressionLabelKeys); - Assert.assertEquals(4, resolvedExpressionLabelKeys.size()); + Assert.assertEquals(5, resolvedExpressionLabelKeys.size()); Assert.assertTrue(resolvedExpressionLabelKeys.contains(validKey1)); Assert.assertTrue(resolvedExpressionLabelKeys.contains(validKey2)); Assert.assertTrue(resolvedExpressionLabelKeys.contains(validKey3)); Assert.assertTrue(resolvedExpressionLabelKeys.contains(validKey4)); + Assert.assertTrue(resolvedExpressionLabelKeys.contains(validKey5)); Assert.assertFalse(resolvedExpressionLabelKeys.contains(invalidKey)); } } 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/feign/RouterLabelFeignInterceptorTest.java index 83d1db890..a859e44bf 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/feign/RouterLabelFeignInterceptorTest.java @@ -34,7 +34,7 @@ import com.tencent.cloud.common.util.ApplicationContextAwareUtils; import com.tencent.cloud.common.util.JacksonUtils; import com.tencent.cloud.polaris.router.RouterConstants; import com.tencent.cloud.polaris.router.RouterRuleLabelResolver; -import com.tencent.cloud.polaris.router.spi.RouterLabelResolver; +import com.tencent.cloud.polaris.router.spi.FeignRouterLabelResolver; import feign.RequestTemplate; import feign.Target; import org.junit.Assert; @@ -62,7 +62,7 @@ public class RouterLabelFeignInterceptorTest { @Mock private RouterRuleLabelResolver routerRuleLabelResolver; @Mock - private RouterLabelResolver routerLabelResolver; + private FeignRouterLabelResolver routerLabelResolver; @Test public void testResolveRouterLabel() { @@ -96,12 +96,6 @@ public class RouterLabelFeignInterceptorTest { try (MockedStatic mockedMetadataContextHolder = Mockito.mockStatic(MetadataContextHolder.class)) { mockedMetadataContextHolder.when(MetadataContextHolder::get).thenReturn(metadataContext); - // mock custom resolved labels from request - Map customResolvedLabels = new HashMap<>(); - customResolvedLabels.put("k2", "v2"); - customResolvedLabels.put("k3", "v3"); - when(routerLabelResolver.resolve(requestTemplate)).thenReturn(customResolvedLabels); - // mock expression rule labels Set expressionKeys = new HashSet<>(); expressionKeys.add("${http.header.uid}"); @@ -109,6 +103,12 @@ public class RouterLabelFeignInterceptorTest { when(routerRuleLabelResolver.getExpressionLabelKeys(MetadataContext.LOCAL_NAMESPACE, MetadataContext.LOCAL_SERVICE, peerService)).thenReturn(expressionKeys); + // mock custom resolved labels from request + Map customResolvedLabels = new HashMap<>(); + customResolvedLabels.put("k2", "v2"); + customResolvedLabels.put("k3", "v3"); + when(routerLabelResolver.resolve(requestTemplate, expressionKeys)).thenReturn(customResolvedLabels); + // mock local metadata Map localMetadata = new HashMap<>(); localMetadata.put("k3", "v31"); 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 1bc65659e..0da302415 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 @@ -22,7 +22,7 @@ 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.beanprocessor.LoadBalancerInterceptorBeanPostProcessor; -import com.tencent.cloud.polaris.router.spi.RouterLabelResolver; +import com.tencent.cloud.polaris.router.spi.SpringWebRouterLabelResolver; import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; @@ -65,7 +65,7 @@ public class PolarisLoadBalancerBeanPostProcessorTest { when(beanFactory.getBean(RouterRuleLabelResolver.class)).thenReturn(routerRuleLabelResolver); try (MockedStatic mockedBeanFactoryUtils = Mockito.mockStatic(BeanFactoryUtils.class)) { - mockedBeanFactoryUtils.when(() -> BeanFactoryUtils.getBeans(beanFactory, RouterLabelResolver.class)) + mockedBeanFactoryUtils.when(() -> BeanFactoryUtils.getBeans(beanFactory, SpringWebRouterLabelResolver.class)) .thenReturn(null); LoadBalancerInterceptor loadBalancerInterceptor = new LoadBalancerInterceptor(loadBalancerClient, loadBalancerRequestFactory); 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/resttemplate/PolarisLoadBalancerInterceptorTest.java index 66bd4fe5f..bff5116aa 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/resttemplate/PolarisLoadBalancerInterceptorTest.java @@ -33,7 +33,7 @@ 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 com.tencent.cloud.polaris.router.spi.SpringWebRouterLabelResolver; import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; @@ -71,7 +71,7 @@ public class PolarisLoadBalancerInterceptorTest { @Mock private LoadBalancerRequestFactory loadBalancerRequestFactory; @Mock - private RouterLabelResolver routerLabelResolver; + private SpringWebRouterLabelResolver routerLabelResolver; @Mock private MetadataLocalProperties metadataLocalProperties; @Mock @@ -89,19 +89,19 @@ public class PolarisLoadBalancerInterceptorTest { localMetadata.put("k2", "v2"); when(metadataLocalProperties.getContent()).thenReturn(localMetadata); - // mock custom resolved from request - Map customResolvedLabels = new HashMap<>(); - customResolvedLabels.put("k3", "v3"); - customResolvedLabels.put("k4", "v4"); - when(routerLabelResolver.resolve(request, null)).thenReturn(customResolvedLabels); - // mock expression rule labels - Set expressionKeys = new HashSet<>(); expressionKeys.add("${http.method}"); expressionKeys.add("${http.uri}"); when(routerRuleLabelResolver.getExpressionLabelKeys(callerService, callerService, calleeService)).thenReturn(expressionKeys); + // mock custom resolved from request + Map customResolvedLabels = new HashMap<>(); + customResolvedLabels.put("k3", "v3"); + customResolvedLabels.put("k4", "v4"); + when(routerLabelResolver.resolve(request, null, expressionKeys)).thenReturn(customResolvedLabels); + + try (MockedStatic mockedApplicationContextAwareUtils = Mockito.mockStatic(ApplicationContextAwareUtils.class)) { mockedApplicationContextAwareUtils.when(() -> ApplicationContextAwareUtils.getProperties(anyString())) .thenReturn(callerService); @@ -127,7 +127,7 @@ public class PolarisLoadBalancerInterceptorTest { verify(metadataLocalProperties).getContent(); verify(routerRuleLabelResolver).getExpressionLabelKeys(callerService, callerService, calleeService); - verify(routerLabelResolver).resolve(request, null); + verify(routerLabelResolver).resolve(request, null, expressionKeys); } } } @@ -158,7 +158,7 @@ public class PolarisLoadBalancerInterceptorTest { } @Test - public void testRouterContext() throws Exception { + public void testRouterContext() { String callerService = "callerService"; String calleeService = "calleeService"; HttpRequest request = new MockedHttpRequest("http://" + calleeService + "/user/get"); @@ -169,19 +169,18 @@ public class PolarisLoadBalancerInterceptorTest { localMetadata.put("k2", "v2"); when(metadataLocalProperties.getContent()).thenReturn(localMetadata); - // mock custom resolved from request - Map customResolvedLabels = new HashMap<>(); - customResolvedLabels.put("k2", "v22"); - customResolvedLabels.put("k4", "v4"); - when(routerLabelResolver.resolve(request, null)).thenReturn(customResolvedLabels); - // mock expression rule labels - Set expressionKeys = new HashSet<>(); expressionKeys.add("${http.method}"); expressionKeys.add("${http.uri}"); when(routerRuleLabelResolver.getExpressionLabelKeys(callerService, callerService, calleeService)).thenReturn(expressionKeys); + // mock custom resolved from request + Map customResolvedLabels = new HashMap<>(); + customResolvedLabels.put("k2", "v22"); + customResolvedLabels.put("k4", "v4"); + when(routerLabelResolver.resolve(request, null, expressionKeys)).thenReturn(customResolvedLabels); + try (MockedStatic mockedApplicationContextAwareUtils = Mockito.mockStatic(ApplicationContextAwareUtils.class)) { mockedApplicationContextAwareUtils.when(() -> ApplicationContextAwareUtils.getProperties(anyString())) .thenReturn(callerService); @@ -206,7 +205,7 @@ public class PolarisLoadBalancerInterceptorTest { verify(metadataLocalProperties).getContent(); verify(routerRuleLabelResolver).getExpressionLabelKeys(callerService, callerService, calleeService); - verify(routerLabelResolver).resolve(request, null); + verify(routerLabelResolver).resolve(request, null, expressionKeys); Assert.assertEquals("v1", routerContext.getLabels(PolarisRouterContext.TRANSITIVE_LABELS).get("k1")); Assert.assertEquals("v22", routerContext.getLabels(PolarisRouterContext.TRANSITIVE_LABELS).get("k2")); 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 index 469f9d700..2f201507d 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/scg/PolarisLoadBalancerClientFilterTest.java @@ -32,7 +32,7 @@ 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 com.tencent.cloud.polaris.router.spi.SpringWebRouterLabelResolver; import org.junit.AfterClass; import org.junit.Assert; import org.junit.BeforeClass; @@ -73,7 +73,7 @@ public class PolarisLoadBalancerClientFilterTest { @Mock private RouterRuleLabelResolver routerRuleLabelResolver; @Mock - private RouterLabelResolver routerLabelResolver; + private SpringWebRouterLabelResolver routerLabelResolver; @Mock private LoadBalancerClient loadBalancerClient; @Mock @@ -124,7 +124,7 @@ public class PolarisLoadBalancerClientFilterTest { Map customMetadata = new HashMap<>(); customMetadata.put("k2", "v2"); - when(routerLabelResolver.resolve(webExchange)).thenReturn(customMetadata); + when(routerLabelResolver.resolve(webExchange, expressionLabelKeys)).thenReturn(customMetadata); PolarisRouterContext routerContext = polarisLoadBalancerClientFilter.genRouterContext(webExchange, calleeService); @@ -181,7 +181,7 @@ public class PolarisLoadBalancerClientFilterTest { Map customMetadata = new HashMap<>(); customMetadata.put("k2", "v2"); - when(routerLabelResolver.resolve(webExchange)).thenReturn(customMetadata); + when(routerLabelResolver.resolve(webExchange, expressionLabelKeys)).thenReturn(customMetadata); polarisLoadBalancerClientFilter.choose(webExchange); diff --git a/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/util/expresstion/ExpressionLabelUtils.java b/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/util/expresstion/ExpressionLabelUtils.java index f42c5b106..4342a5483 100644 --- a/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/util/expresstion/ExpressionLabelUtils.java +++ b/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/util/expresstion/ExpressionLabelUtils.java @@ -33,6 +33,10 @@ import org.springframework.util.CollectionUtils; */ public final class ExpressionLabelUtils { + /** + * the prefix of expression. + */ + public static final String LABEL_PREFIX = "${"; /** * the expression prefix of header label. */ @@ -77,14 +81,7 @@ public final class ExpressionLabelUtils { if (StringUtils.isEmpty(labelKey)) { return false; } - if (StringUtils.equalsIgnoreCase(LABEL_METHOD, labelKey) || - StringUtils.startsWithIgnoreCase(LABEL_URI, labelKey)) { - return true; - } - return (StringUtils.startsWithIgnoreCase(labelKey, LABEL_HEADER_PREFIX) || - StringUtils.startsWithIgnoreCase(labelKey, LABEL_QUERY_PREFIX) || - StringUtils.startsWithIgnoreCase(labelKey, LABEL_COOKIE_PREFIX)) - && StringUtils.endsWith(labelKey, LABEL_SUFFIX); + return StringUtils.startsWith(labelKey, LABEL_PREFIX) && StringUtils.endsWith(labelKey, LABEL_SUFFIX); } public static String parseHeaderKey(String expression) { diff --git a/spring-cloud-tencent-commons/src/test/java/com/tencent/cloud/common/util/ExpressionLabelUtilsTest.java b/spring-cloud-tencent-commons/src/test/java/com/tencent/cloud/common/util/ExpressionLabelUtilsTest.java index 2e6f13ecc..4369acad8 100644 --- a/spring-cloud-tencent-commons/src/test/java/com/tencent/cloud/common/util/ExpressionLabelUtilsTest.java +++ b/spring-cloud-tencent-commons/src/test/java/com/tencent/cloud/common/util/ExpressionLabelUtilsTest.java @@ -69,12 +69,12 @@ public class ExpressionLabelUtilsTest { Assert.assertTrue(ExpressionLabelUtils.isExpressionLabel(validLabel3)); Assert.assertTrue(ExpressionLabelUtils.isExpressionLabel(validLabel4)); Assert.assertTrue(ExpressionLabelUtils.isExpressionLabel(validLabel5)); - Assert.assertFalse(ExpressionLabelUtils.isExpressionLabel(invalidLabel1)); + Assert.assertTrue(ExpressionLabelUtils.isExpressionLabel(invalidLabel1)); Assert.assertFalse(ExpressionLabelUtils.isExpressionLabel(invalidLabel2)); Assert.assertFalse(ExpressionLabelUtils.isExpressionLabel(invalidLabel3)); Assert.assertFalse(ExpressionLabelUtils.isExpressionLabel(invalidLabel4)); - Assert.assertFalse(ExpressionLabelUtils.isExpressionLabel(invalidLabel5)); - Assert.assertFalse(ExpressionLabelUtils.isExpressionLabel(invalidLabel6)); + Assert.assertTrue(ExpressionLabelUtils.isExpressionLabel(invalidLabel5)); + Assert.assertTrue(ExpressionLabelUtils.isExpressionLabel(invalidLabel6)); Assert.assertFalse(ExpressionLabelUtils.isExpressionLabel(invalidLabel7)); Assert.assertFalse(ExpressionLabelUtils.isExpressionLabel(invalidLabel8)); Assert.assertFalse(ExpressionLabelUtils.isExpressionLabel(invalidLabel9)); 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/CustomFeignRouterLabelResolver.java similarity index 70% rename from spring-cloud-tencent-examples/polaris-router-example/router-caller-service/src/main/java/com/tencent/cloud/polaris/router/example/CustomRouterLabelResolver.java rename to spring-cloud-tencent-examples/polaris-router-example/router-caller-service/src/main/java/com/tencent/cloud/polaris/router/example/CustomFeignRouterLabelResolver.java index 815b2baff..37f2290df 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/CustomFeignRouterLabelResolver.java @@ -13,54 +13,41 @@ * 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.example; import java.util.HashMap; import java.util.Map; +import java.util.Set; import com.google.gson.Gson; -import com.tencent.cloud.polaris.router.spi.RouterLabelResolver; +import com.tencent.cloud.polaris.router.spi.FeignRouterLabelResolver; import feign.RequestTemplate; -import org.springframework.http.HttpRequest; import org.springframework.stereotype.Component; /** - * - * Customize the business tag information obtained from the request - * - *@author lepdou 2022-05-12 + * Custom router label resolver for feign request. + * @author lepdou 2022-07-20 */ @Component -public class CustomRouterLabelResolver implements RouterLabelResolver { +public class CustomFeignRouterLabelResolver implements FeignRouterLabelResolver { private final Gson gson = new Gson(); @Override - public Map resolve(RequestTemplate requestTemplate) { - Map labels = new HashMap<>(); - - User user = gson.fromJson(new String(requestTemplate.body()), User.class); - - labels.put("user", user.getName()); - - return labels; + public int getOrder() { + return 0; } @Override - public Map resolve(HttpRequest request, byte[] body) { + public Map resolve(RequestTemplate requestTemplate, Set expressionLabelKeys) { Map labels = new HashMap<>(); - User user = gson.fromJson(new String(body), User.class); - labels.put("user", user.getName()); - return labels; - } + User user = gson.fromJson(new String(requestTemplate.body()), User.class); + labels.put("user", user.getName()); - @Override - public int getOrder() { - return 0; + return labels; } } diff --git a/spring-cloud-tencent-examples/polaris-router-example/router-caller-service/src/main/java/com/tencent/cloud/polaris/router/example/CustomSpringWebRouterLabelResolver.java b/spring-cloud-tencent-examples/polaris-router-example/router-caller-service/src/main/java/com/tencent/cloud/polaris/router/example/CustomSpringWebRouterLabelResolver.java new file mode 100644 index 000000000..44570366d --- /dev/null +++ b/spring-cloud-tencent-examples/polaris-router-example/router-caller-service/src/main/java/com/tencent/cloud/polaris/router/example/CustomSpringWebRouterLabelResolver.java @@ -0,0 +1,52 @@ +/* + * 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.example; + +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +import com.google.gson.Gson; +import com.tencent.cloud.polaris.router.spi.SpringWebRouterLabelResolver; + +import org.springframework.http.HttpRequest; +import org.springframework.stereotype.Component; + +/** + * Custom router label resolver for spring web request. + * @author lepdou 2022-07-20 + */ +@Component +public class CustomSpringWebRouterLabelResolver implements SpringWebRouterLabelResolver { + private final Gson gson = new Gson(); + + @Override + public int getOrder() { + return 0; + } + + @Override + public Map resolve(HttpRequest request, byte[] body, Set expressionLabelKeys) { + Map labels = new HashMap<>(); + User user = gson.fromJson(new String(body), User.class); + + labels.put("user", user.getName()); + return labels; + } + +} diff --git a/spring-cloud-tencent-examples/polaris-router-featureenv-example/README-zh.md b/spring-cloud-tencent-examples/polaris-router-featureenv-example/README-zh.md new file mode 100644 index 000000000..769682156 --- /dev/null +++ b/spring-cloud-tencent-examples/polaris-router-featureenv-example/README-zh.md @@ -0,0 +1,152 @@ +# 多测试环境样例说明 + +## 一、部署结构 + + + +如上图所示,一共有三个环境: +1. 基线环境,包含 FrontService、MiddleService、BackendService +2. feature1 环境,包含 MiddleService、BackendService +3. feature2 环境,包含 FrontService、BackendService + +并且在入口处,部署网关服务。 + +三条请求链路: +1. 基线环境链路,Gateway -> FrontService(基线) -> MiddleService(基线) -> BackendService(基线) +2. feature1 环境链路,Gateway -> FrontService(基线) -> MiddleService(feature1) -> BackendService(feature1) +3. feature2 环境链路,Gateway -> FrontService(feature2) -> MiddleService(基线) -> BackendService(feature2) + + +## 二、运行样例 + +无需任何代码变更,直接启动 base、feature1、feature2、featureenv-gateway 下所有应用即可。 + +应用默认指向北极星官方的体验环境,启动成功后可直接到体验站点查看服务注册数据。 + +- 管控台地址: http://14.116.241.63:8080/ + - 账号:polaris + - 密码:polaris + +## 三、测试 + +### 方式一:客户端打标 + +#### 基线环境链路 +```` +curl http://127.0.0.1:9999/featureenv-front-example/router/rest +```` +响应结果(base 表示基线环境) +```` +featureenv-front-example[base] -> featureenv-middle-example[base] -> featureenv-backend-example[base] +```` + +#### feature1 环境链路 + +通过 X-Polaris-Metadata-Transitive-featureenv 请求头指定特性环境。 + +```` +curl -H'X-Polaris-Metadata-Transitive-featureenv:feature1' http://127.0.0.1:9999/featureenv-front-example/router/rest +```` +响应结果 +```` +featureenv-front-example[base] -> featureenv-middle-example[feature1] -> featureenv-backend-example[feature1] +```` + +#### feature2 环境链路 + +通过 X-Polaris-Metadata-Transitive-featureenv 请求头指定特性环境。 + +```` +curl -H'X-Polaris-Metadata-Transitive-featureenv:feature2' http://127.0.0.1:9999/featureenv-front-example/router/rest +```` +响应结果 +```` +featureenv-front-example[feature2] -> featureenv-middle-example[base] -> featureenv-backend-example[feature2] +```` + +### 方式二:网关流量染色 + +模拟一种实际的场景,假设客户端请求有一个 uid 请求参数,期望: +1. uid=1000 的请求打到 feature1 环境 +2. uid=2000 的请求打到 feature2 环境 +3. 其它 uid 的请求打到基线环境 + +**配置染色规则** + +配置地址:http://14.116.241.63:8080/#/filegroup-detail?group=featureenv-gateway&namespace=default + +修改 rule/staining.json 配置文件,填写以下规则: + +````json +{ + "rules":[ + { + "conditions":[ + { + "key":"${http.query.uid}", + "values":["1000"], + "operation":"EQUAL" + } + ], + "labels":[ + { + "key":"featureenv", + "value":"feature1" + } + ] + }, + { + "conditions":[ + { + "key":"${http.query.uid}", + "values":["2000"], + "operation":"EQUAL" + } + ], + "labels":[ + { + "key":"featureenv", + "value":"feature2" + } + ] + } + ] +} +```` + +填写完后发布配置即可。 + +#### 基线环境链路 +```` +curl http://127.0.0.1:9999/featureenv-front-example/router/rest?uid=3000 +```` +响应结果(base 表示基线环境) +```` +featureenv-front-example[base] -> featureenv-middle-example[base] -> featureenv-backend-example[base] +```` + +#### feature1 环境链路 + +通过 X-Polaris-Metadata-Transitive-featureenv 请求头指定特性环境。 + +```` +curl http://127.0.0.1:9999/featureenv-front-example/router/rest?uid=1000 +```` +响应结果 +```` +featureenv-front-example[base] -> featureenv-middle-example[feature1] -> featureenv-backend-example[feature1] +```` + +#### feature2 环境链路 + +通过 X-Polaris-Metadata-Transitive-featureenv 请求头指定特性环境。 + +```` +curl http://127.0.0.1:9999/featureenv-front-example/router/rest?uid=2000 +```` +响应结果 +```` +featureenv-front-example[feature2] -> featureenv-middle-example[base] -> featureenv-backend-example[feature2] +```` + + diff --git a/spring-cloud-tencent-examples/polaris-router-featureenv-example/base/base-backend/pom.xml b/spring-cloud-tencent-examples/polaris-router-featureenv-example/base/base-backend/pom.xml new file mode 100644 index 000000000..8c2c1f422 --- /dev/null +++ b/spring-cloud-tencent-examples/polaris-router-featureenv-example/base/base-backend/pom.xml @@ -0,0 +1,16 @@ + + + + polaris-router-featureenv-base + com.tencent.cloud + ${revision} + ../pom.xml + + 4.0.0 + + base-backend + + + diff --git a/spring-cloud-tencent-examples/polaris-router-featureenv-example/base/base-backend/src/main/java/com/tencent/cloud/polaris/router/featureenv/basebackend/BackendController.java b/spring-cloud-tencent-examples/polaris-router-featureenv-example/base/base-backend/src/main/java/com/tencent/cloud/polaris/router/featureenv/basebackend/BackendController.java new file mode 100644 index 000000000..db7121ded --- /dev/null +++ b/spring-cloud-tencent-examples/polaris-router-featureenv-example/base/base-backend/src/main/java/com/tencent/cloud/polaris/router/featureenv/basebackend/BackendController.java @@ -0,0 +1,44 @@ +/* + * 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.featureenv.basebackend; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * @author lepdou 2022-07-20 + */ +@RestController +@RequestMapping("/router") +public class BackendController { + + @Value("${spring.application.name}") + private String appName; + + /** + * Get information of callee. + * @return information of callee + */ + @GetMapping("/rest") + public String rest() { + return appName + "[base]"; + } +} diff --git a/spring-cloud-tencent-examples/polaris-router-featureenv-example/base/base-backend/src/main/java/com/tencent/cloud/polaris/router/featureenv/basebackend/BaseBackendApplication.java b/spring-cloud-tencent-examples/polaris-router-featureenv-example/base/base-backend/src/main/java/com/tencent/cloud/polaris/router/featureenv/basebackend/BaseBackendApplication.java new file mode 100644 index 000000000..755704d1d --- /dev/null +++ b/spring-cloud-tencent-examples/polaris-router-featureenv-example/base/base-backend/src/main/java/com/tencent/cloud/polaris/router/featureenv/basebackend/BaseBackendApplication.java @@ -0,0 +1,34 @@ +/* + * 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.featureenv.basebackend; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.openfeign.EnableFeignClients; + +/** + * @author lepdou 2022-07-20 + */ +@SpringBootApplication +@EnableFeignClients +public class BaseBackendApplication { + + public static void main(String[] args) { + SpringApplication.run(BaseBackendApplication.class, args); + } +} diff --git a/spring-cloud-tencent-examples/polaris-router-featureenv-example/base/base-backend/src/main/resources/bootstrap.yml b/spring-cloud-tencent-examples/polaris-router-featureenv-example/base/base-backend/src/main/resources/bootstrap.yml new file mode 100644 index 000000000..34267f03e --- /dev/null +++ b/spring-cloud-tencent-examples/polaris-router-featureenv-example/base/base-backend/src/main/resources/bootstrap.yml @@ -0,0 +1,15 @@ +server: + session-timeout: 1800 + port: 10002 +spring: + application: + name: featureenv-backend-example + cloud: + polaris: + address: grpc://183.47.111.80:8091 + namespace: default + enabled: true +logging: + level: + org.springframework.cloud.gateway: info + com.tencent.cloud.polaris: debug diff --git a/spring-cloud-tencent-examples/polaris-router-featureenv-example/base/base-front/pom.xml b/spring-cloud-tencent-examples/polaris-router-featureenv-example/base/base-front/pom.xml new file mode 100644 index 000000000..62f304679 --- /dev/null +++ b/spring-cloud-tencent-examples/polaris-router-featureenv-example/base/base-front/pom.xml @@ -0,0 +1,16 @@ + + + + polaris-router-featureenv-base + com.tencent.cloud + ${revision} + ../pom.xml + + 4.0.0 + + base-front + + + diff --git a/spring-cloud-tencent-examples/polaris-router-featureenv-example/base/base-front/src/main/java/com/tencent/cloud/polaris/router/featureenv/basefront/BaseFrontApplication.java b/spring-cloud-tencent-examples/polaris-router-featureenv-example/base/base-front/src/main/java/com/tencent/cloud/polaris/router/featureenv/basefront/BaseFrontApplication.java new file mode 100644 index 000000000..4197f2367 --- /dev/null +++ b/spring-cloud-tencent-examples/polaris-router-featureenv-example/base/base-front/src/main/java/com/tencent/cloud/polaris/router/featureenv/basefront/BaseFrontApplication.java @@ -0,0 +1,34 @@ +/* + * 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.featureenv.basefront; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.openfeign.EnableFeignClients; + +/** + * @author lepdou 2022-07-20 + */ +@SpringBootApplication +@EnableFeignClients +public class BaseFrontApplication { + + public static void main(String[] args) { + SpringApplication.run(BaseFrontApplication.class, args); + } +} diff --git a/spring-cloud-tencent-examples/polaris-router-featureenv-example/base/base-front/src/main/java/com/tencent/cloud/polaris/router/featureenv/basefront/FrontController.java b/spring-cloud-tencent-examples/polaris-router-featureenv-example/base/base-front/src/main/java/com/tencent/cloud/polaris/router/featureenv/basefront/FrontController.java new file mode 100644 index 000000000..08bc61d5e --- /dev/null +++ b/spring-cloud-tencent-examples/polaris-router-featureenv-example/base/base-front/src/main/java/com/tencent/cloud/polaris/router/featureenv/basefront/FrontController.java @@ -0,0 +1,51 @@ +/* + * 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.featureenv.basefront; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * @author lepdou 2022-07-20 + */ +@RestController +@RequestMapping("/router") +public class FrontController { + + @Value("${spring.application.name}") + private String appName; + + @Autowired + private MiddleService middleService; + + /** + * Get information of callee. + * @return information of callee + */ + @GetMapping("/rest") + public String rest() { + String curName = appName + "[base]"; + String resp = middleService.rest(); + + return curName + " -> " + resp; + } +} diff --git a/spring-cloud-tencent-examples/polaris-router-featureenv-example/base/base-front/src/main/java/com/tencent/cloud/polaris/router/featureenv/basefront/MiddleService.java b/spring-cloud-tencent-examples/polaris-router-featureenv-example/base/base-front/src/main/java/com/tencent/cloud/polaris/router/featureenv/basefront/MiddleService.java new file mode 100644 index 000000000..0602481f7 --- /dev/null +++ b/spring-cloud-tencent-examples/polaris-router-featureenv-example/base/base-front/src/main/java/com/tencent/cloud/polaris/router/featureenv/basefront/MiddleService.java @@ -0,0 +1,33 @@ +/* + * 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.featureenv.basefront; + +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.web.bind.annotation.GetMapping; + +/** + * @author lepdou 2022-07-20 + */ +@FeignClient("featureenv-middle-example") +public interface MiddleService { + + @GetMapping("/router/rest") + String rest(); + +} diff --git a/spring-cloud-tencent-examples/polaris-router-featureenv-example/base/base-front/src/main/resources/bootstrap.yml b/spring-cloud-tencent-examples/polaris-router-featureenv-example/base/base-front/src/main/resources/bootstrap.yml new file mode 100644 index 000000000..aab4e3e1d --- /dev/null +++ b/spring-cloud-tencent-examples/polaris-router-featureenv-example/base/base-front/src/main/resources/bootstrap.yml @@ -0,0 +1,15 @@ +server: + session-timeout: 1800 + port: 10000 +spring: + application: + name: featureenv-front-example + cloud: + polaris: + address: grpc://183.47.111.80:8091 + namespace: default + enabled: true +logging: + level: + org.springframework.cloud.gateway: info + com.tencent.cloud.polaris: debug diff --git a/spring-cloud-tencent-examples/polaris-router-featureenv-example/base/base-middle/pom.xml b/spring-cloud-tencent-examples/polaris-router-featureenv-example/base/base-middle/pom.xml new file mode 100644 index 000000000..17cc3b701 --- /dev/null +++ b/spring-cloud-tencent-examples/polaris-router-featureenv-example/base/base-middle/pom.xml @@ -0,0 +1,18 @@ + + + + polaris-router-featureenv-base + com.tencent.cloud + ${revision} + ../pom.xml + + + 4.0.0 + + base-middle + + + + diff --git a/spring-cloud-tencent-examples/polaris-router-featureenv-example/base/base-middle/src/main/java/com/tencent/cloud/polaris/router/featureenv/basemiddle/BackendService.java b/spring-cloud-tencent-examples/polaris-router-featureenv-example/base/base-middle/src/main/java/com/tencent/cloud/polaris/router/featureenv/basemiddle/BackendService.java new file mode 100644 index 000000000..35818bb39 --- /dev/null +++ b/spring-cloud-tencent-examples/polaris-router-featureenv-example/base/base-middle/src/main/java/com/tencent/cloud/polaris/router/featureenv/basemiddle/BackendService.java @@ -0,0 +1,33 @@ +/* + * 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.featureenv.basemiddle; + +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.web.bind.annotation.GetMapping; + +/** + * @author lepdou 2022-07-20 + */ +@FeignClient("featureenv-backend-example") +public interface BackendService { + + @GetMapping("/router/rest") + String rest(); + +} diff --git a/spring-cloud-tencent-examples/polaris-router-featureenv-example/base/base-middle/src/main/java/com/tencent/cloud/polaris/router/featureenv/basemiddle/BaseMiddleApplication.java b/spring-cloud-tencent-examples/polaris-router-featureenv-example/base/base-middle/src/main/java/com/tencent/cloud/polaris/router/featureenv/basemiddle/BaseMiddleApplication.java new file mode 100644 index 000000000..2a88780cf --- /dev/null +++ b/spring-cloud-tencent-examples/polaris-router-featureenv-example/base/base-middle/src/main/java/com/tencent/cloud/polaris/router/featureenv/basemiddle/BaseMiddleApplication.java @@ -0,0 +1,34 @@ +/* + * 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.featureenv.basemiddle; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.openfeign.EnableFeignClients; + +/** + * @author lepdou 2022-07-20 + */ +@SpringBootApplication +@EnableFeignClients +public class BaseMiddleApplication { + + public static void main(String[] args) { + SpringApplication.run(BaseMiddleApplication.class, args); + } +} diff --git a/spring-cloud-tencent-examples/polaris-router-featureenv-example/base/base-middle/src/main/java/com/tencent/cloud/polaris/router/featureenv/basemiddle/MiddleController.java b/spring-cloud-tencent-examples/polaris-router-featureenv-example/base/base-middle/src/main/java/com/tencent/cloud/polaris/router/featureenv/basemiddle/MiddleController.java new file mode 100644 index 000000000..276993caf --- /dev/null +++ b/spring-cloud-tencent-examples/polaris-router-featureenv-example/base/base-middle/src/main/java/com/tencent/cloud/polaris/router/featureenv/basemiddle/MiddleController.java @@ -0,0 +1,51 @@ +/* + * 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.featureenv.basemiddle; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * @author lepdou 2022-07-20 + */ +@RestController +@RequestMapping("/router") +public class MiddleController { + + @Value("${spring.application.name}") + private String appName; + + @Autowired + private BackendService backendService; + + /** + * Get information of callee. + * @return information of callee + */ + @GetMapping("/rest") + public String rest() { + String curName = appName + "[base]"; + String resp = backendService.rest(); + + return curName + " -> " + resp; + } +} diff --git a/spring-cloud-tencent-examples/polaris-router-featureenv-example/base/base-middle/src/main/resources/bootstrap.yml b/spring-cloud-tencent-examples/polaris-router-featureenv-example/base/base-middle/src/main/resources/bootstrap.yml new file mode 100644 index 000000000..d4a9b9312 --- /dev/null +++ b/spring-cloud-tencent-examples/polaris-router-featureenv-example/base/base-middle/src/main/resources/bootstrap.yml @@ -0,0 +1,15 @@ +server: + session-timeout: 1800 + port: 10001 +spring: + application: + name: featureenv-middle-example + cloud: + polaris: + address: grpc://183.47.111.80:8091 + namespace: default + enabled: true +logging: + level: + org.springframework.cloud.gateway: info + com.tencent.cloud.polaris: debug diff --git a/spring-cloud-tencent-examples/polaris-router-featureenv-example/base/pom.xml b/spring-cloud-tencent-examples/polaris-router-featureenv-example/base/pom.xml new file mode 100644 index 000000000..c0bea706e --- /dev/null +++ b/spring-cloud-tencent-examples/polaris-router-featureenv-example/base/pom.xml @@ -0,0 +1,33 @@ + + + + polaris-router-featureenv-example + com.tencent.cloud + ${revision} + ../pom.xml + + 4.0.0 + + polaris-router-featureenv-base + pom + + + base-front + base-middle + base-backend + + + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.cloud + spring-cloud-starter-openfeign + + + diff --git a/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature1/feature1-backend/pom.xml b/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature1/feature1-backend/pom.xml new file mode 100644 index 000000000..57fa48b17 --- /dev/null +++ b/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature1/feature1-backend/pom.xml @@ -0,0 +1,16 @@ + + + + feature1 + com.tencent.cloud + ${revision} + ../pom.xml + + 4.0.0 + + feature1-backend + + + diff --git a/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature1/feature1-backend/src/main/java/com/tencent/cloud/polaris/router/featureenv/feature1backend/BackendController.java b/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature1/feature1-backend/src/main/java/com/tencent/cloud/polaris/router/featureenv/feature1backend/BackendController.java new file mode 100644 index 000000000..9291ba52f --- /dev/null +++ b/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature1/feature1-backend/src/main/java/com/tencent/cloud/polaris/router/featureenv/feature1backend/BackendController.java @@ -0,0 +1,51 @@ +/* + * 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.featureenv.feature1backend; + +import com.tencent.cloud.common.metadata.StaticMetadataManager; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * @author lepdou 2022-07-20 + */ +@RestController +@RequestMapping("/router") +public class BackendController { + + @Autowired + private StaticMetadataManager staticMetadataManager; + + @Value("${spring.application.name}") + private String appName; + + /** + * Get information of callee. + * @return information of callee + */ + @GetMapping("/rest") + public String rest() { + String featureEnv = staticMetadataManager.getMergedStaticMetadata().get("featureenv"); + return appName + "[" + featureEnv + "]"; + } +} diff --git a/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature1/feature1-backend/src/main/java/com/tencent/cloud/polaris/router/featureenv/feature1backend/Feature1BackendApplication.java b/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature1/feature1-backend/src/main/java/com/tencent/cloud/polaris/router/featureenv/feature1backend/Feature1BackendApplication.java new file mode 100644 index 000000000..4af96c17f --- /dev/null +++ b/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature1/feature1-backend/src/main/java/com/tencent/cloud/polaris/router/featureenv/feature1backend/Feature1BackendApplication.java @@ -0,0 +1,34 @@ +/* + * 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.featureenv.feature1backend; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.openfeign.EnableFeignClients; + +/** + * @author lepdou 2022-07-20 + */ +@SpringBootApplication +@EnableFeignClients +public class Feature1BackendApplication { + + public static void main(String[] args) { + SpringApplication.run(Feature1BackendApplication.class, args); + } +} diff --git a/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature1/feature1-backend/src/main/resources/bootstrap.yml b/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature1/feature1-backend/src/main/resources/bootstrap.yml new file mode 100644 index 000000000..04b3ca3a8 --- /dev/null +++ b/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature1/feature1-backend/src/main/resources/bootstrap.yml @@ -0,0 +1,19 @@ +server: + session-timeout: 1800 + port: 11002 +spring: + application: + name: featureenv-backend-example + cloud: + polaris: + address: grpc://183.47.111.80:8091 + namespace: default + enabled: true + tencent: + metadata: + content: + featureenv: feature1 +logging: + level: + org.springframework.cloud.gateway: info + com.tencent.cloud.polaris: debug diff --git a/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature1/feature1-middle/pom.xml b/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature1/feature1-middle/pom.xml new file mode 100644 index 000000000..873bd1394 --- /dev/null +++ b/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature1/feature1-middle/pom.xml @@ -0,0 +1,16 @@ + + + + feature1 + com.tencent.cloud + ${revision} + ../pom.xml + + 4.0.0 + + feature1-middle + + + diff --git a/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature1/feature1-middle/src/main/java/com/tencent/cloud/polaris/router/featureenv/feature1middle/BackendService.java b/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature1/feature1-middle/src/main/java/com/tencent/cloud/polaris/router/featureenv/feature1middle/BackendService.java new file mode 100644 index 000000000..65b91a922 --- /dev/null +++ b/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature1/feature1-middle/src/main/java/com/tencent/cloud/polaris/router/featureenv/feature1middle/BackendService.java @@ -0,0 +1,33 @@ +/* + * 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.featureenv.feature1middle; + +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.web.bind.annotation.GetMapping; + +/** + * @author lepdou 2022-07-20 + */ +@FeignClient("featureenv-backend-example") +public interface BackendService { + + @GetMapping("/router/rest") + String rest(); + +} diff --git a/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature1/feature1-middle/src/main/java/com/tencent/cloud/polaris/router/featureenv/feature1middle/Feature1MiddleApplication.java b/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature1/feature1-middle/src/main/java/com/tencent/cloud/polaris/router/featureenv/feature1middle/Feature1MiddleApplication.java new file mode 100644 index 000000000..c46db04ab --- /dev/null +++ b/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature1/feature1-middle/src/main/java/com/tencent/cloud/polaris/router/featureenv/feature1middle/Feature1MiddleApplication.java @@ -0,0 +1,34 @@ +/* + * 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.featureenv.feature1middle; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.openfeign.EnableFeignClients; + +/** + * @author lepdou 2022-07-20 + */ +@SpringBootApplication +@EnableFeignClients +public class Feature1MiddleApplication { + + public static void main(String[] args) { + SpringApplication.run(Feature1MiddleApplication.class, args); + } +} diff --git a/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature1/feature1-middle/src/main/java/com/tencent/cloud/polaris/router/featureenv/feature1middle/MiddleController.java b/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature1/feature1-middle/src/main/java/com/tencent/cloud/polaris/router/featureenv/feature1middle/MiddleController.java new file mode 100644 index 000000000..41da83613 --- /dev/null +++ b/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature1/feature1-middle/src/main/java/com/tencent/cloud/polaris/router/featureenv/feature1middle/MiddleController.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.featureenv.feature1middle; + +import com.tencent.cloud.common.metadata.StaticMetadataManager; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * @author lepdou 2022-07-20 + */ +@RestController +@RequestMapping("/router") +public class MiddleController { + + @Value("${spring.application.name}") + private String appName; + + @Autowired + private BackendService backendService; + + @Autowired + private StaticMetadataManager staticMetadataManager; + + /** + * Get information of callee. + * @return information of callee + */ + @GetMapping("/rest") + public String rest() { + String featureEnv = staticMetadataManager.getMergedStaticMetadata().get("featureenv"); + + String curName = appName + "[" + featureEnv + "]"; + String resp = backendService.rest(); + + return curName + " -> " + resp; + } +} diff --git a/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature1/feature1-middle/src/main/resources/bootstrap.yml b/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature1/feature1-middle/src/main/resources/bootstrap.yml new file mode 100644 index 000000000..1a46790a3 --- /dev/null +++ b/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature1/feature1-middle/src/main/resources/bootstrap.yml @@ -0,0 +1,19 @@ +server: + session-timeout: 1800 + port: 11001 +spring: + application: + name: featureenv-middle-example + cloud: + polaris: + address: grpc://183.47.111.80:8091 + namespace: default + enabled: true + tencent: + metadata: + content: + featureenv: feature1 +logging: + level: + org.springframework.cloud.gateway: info + com.tencent.cloud.polaris: debug diff --git a/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature1/pom.xml b/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature1/pom.xml new file mode 100644 index 000000000..b364b109c --- /dev/null +++ b/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature1/pom.xml @@ -0,0 +1,32 @@ + + + + polaris-router-featureenv-example + com.tencent.cloud + ${revision} + ../pom.xml + + 4.0.0 + + feature1 + pom + + + feature1-middle + feature1-backend + + + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.cloud + spring-cloud-starter-openfeign + + + diff --git a/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature2/feature2-backend/pom.xml b/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature2/feature2-backend/pom.xml new file mode 100644 index 000000000..bc2f20a6f --- /dev/null +++ b/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature2/feature2-backend/pom.xml @@ -0,0 +1,16 @@ + + + + feature2 + com.tencent.cloud + ${revision} + ../pom.xml + + 4.0.0 + + feature2-backend + + + diff --git a/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature2/feature2-backend/src/main/java/com/tencent/cloud/polaris/router/featureenv/feature2backend/BackendController.java b/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature2/feature2-backend/src/main/java/com/tencent/cloud/polaris/router/featureenv/feature2backend/BackendController.java new file mode 100644 index 000000000..8b416fb8c --- /dev/null +++ b/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature2/feature2-backend/src/main/java/com/tencent/cloud/polaris/router/featureenv/feature2backend/BackendController.java @@ -0,0 +1,51 @@ +/* + * 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.featureenv.feature2backend; + +import com.tencent.cloud.common.metadata.StaticMetadataManager; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * @author lepdou 2022-07-20 + */ +@RestController +@RequestMapping("/router") +public class BackendController { + + @Autowired + private StaticMetadataManager staticMetadataManager; + + @Value("${spring.application.name}") + private String appName; + + /** + * Get information of callee. + * @return information of callee + */ + @GetMapping("/rest") + public String rest() { + String featureEnv = staticMetadataManager.getMergedStaticMetadata().get("featureenv"); + return appName + "[" + featureEnv + "]"; + } +} diff --git a/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature2/feature2-backend/src/main/java/com/tencent/cloud/polaris/router/featureenv/feature2backend/Feature2BackendApplication.java b/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature2/feature2-backend/src/main/java/com/tencent/cloud/polaris/router/featureenv/feature2backend/Feature2BackendApplication.java new file mode 100644 index 000000000..fe1bd3c60 --- /dev/null +++ b/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature2/feature2-backend/src/main/java/com/tencent/cloud/polaris/router/featureenv/feature2backend/Feature2BackendApplication.java @@ -0,0 +1,34 @@ +/* + * 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.featureenv.feature2backend; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.openfeign.EnableFeignClients; + +/** + * @author lepdou 2022-07-20 + */ +@SpringBootApplication +@EnableFeignClients +public class Feature2BackendApplication { + + public static void main(String[] args) { + SpringApplication.run(Feature2BackendApplication.class, args); + } +} diff --git a/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature2/feature2-backend/src/main/resources/bootstrap.yml b/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature2/feature2-backend/src/main/resources/bootstrap.yml new file mode 100644 index 000000000..aece1f3f8 --- /dev/null +++ b/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature2/feature2-backend/src/main/resources/bootstrap.yml @@ -0,0 +1,19 @@ +server: + session-timeout: 1800 + port: 12002 +spring: + application: + name: featureenv-backend-example + cloud: + polaris: + address: grpc://183.47.111.80:8091 + namespace: default + enabled: true + tencent: + metadata: + content: + featureenv: feature2 +logging: + level: + org.springframework.cloud.gateway: info + com.tencent.cloud.polaris: debug diff --git a/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature2/feature2-front/pom.xml b/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature2/feature2-front/pom.xml new file mode 100644 index 000000000..fb4268738 --- /dev/null +++ b/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature2/feature2-front/pom.xml @@ -0,0 +1,17 @@ + + + + feature2 + com.tencent.cloud + ${revision} + ../pom.xml + + 4.0.0 + + feature2-front + + + + diff --git a/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature2/feature2-front/src/main/java/com/tencent/cloud/polaris/router/featureenv/feature2front/Feature2FrontApplication.java b/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature2/feature2-front/src/main/java/com/tencent/cloud/polaris/router/featureenv/feature2front/Feature2FrontApplication.java new file mode 100644 index 000000000..a6b8bd1fa --- /dev/null +++ b/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature2/feature2-front/src/main/java/com/tencent/cloud/polaris/router/featureenv/feature2front/Feature2FrontApplication.java @@ -0,0 +1,34 @@ +/* + * 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.featureenv.feature2front; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.openfeign.EnableFeignClients; + +/** + * @author lepdou 2022-07-20 + */ +@SpringBootApplication +@EnableFeignClients +public class Feature2FrontApplication { + + public static void main(String[] args) { + SpringApplication.run(Feature2FrontApplication.class, args); + } +} diff --git a/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature2/feature2-front/src/main/java/com/tencent/cloud/polaris/router/featureenv/feature2front/FrontController.java b/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature2/feature2-front/src/main/java/com/tencent/cloud/polaris/router/featureenv/feature2front/FrontController.java new file mode 100644 index 000000000..0c019d742 --- /dev/null +++ b/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature2/feature2-front/src/main/java/com/tencent/cloud/polaris/router/featureenv/feature2front/FrontController.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.featureenv.feature2front; + +import com.tencent.cloud.common.metadata.StaticMetadataManager; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * @author lepdou 2022-07-20 + */ +@RestController +@RequestMapping("/router") +public class FrontController { + + @Autowired + private StaticMetadataManager staticMetadataManager; + + @Value("${spring.application.name}") + private String appName; + + @Autowired + private MiddleService middleService; + + /** + * Get information of callee. + * @return information of callee + */ + @GetMapping("/rest") + public String rest() { + String featureEnv = staticMetadataManager.getMergedStaticMetadata().get("featureenv"); + + String curName = appName + "[" + featureEnv + "]"; + String resp = middleService.rest(); + + return curName + " -> " + resp; + } +} diff --git a/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature2/feature2-front/src/main/java/com/tencent/cloud/polaris/router/featureenv/feature2front/MiddleService.java b/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature2/feature2-front/src/main/java/com/tencent/cloud/polaris/router/featureenv/feature2front/MiddleService.java new file mode 100644 index 000000000..2e0690fdd --- /dev/null +++ b/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature2/feature2-front/src/main/java/com/tencent/cloud/polaris/router/featureenv/feature2front/MiddleService.java @@ -0,0 +1,33 @@ +/* + * 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.featureenv.feature2front; + +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.web.bind.annotation.GetMapping; + +/** + * @author lepdou 2022-07-20 + */ +@FeignClient("featureenv-middle-example") +public interface MiddleService { + + @GetMapping("/router/rest") + String rest(); + +} diff --git a/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature2/feature2-front/src/main/resources/bootstrap.yml b/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature2/feature2-front/src/main/resources/bootstrap.yml new file mode 100644 index 000000000..9fdaa2add --- /dev/null +++ b/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature2/feature2-front/src/main/resources/bootstrap.yml @@ -0,0 +1,19 @@ +server: + session-timeout: 1800 + port: 12000 +spring: + application: + name: featureenv-front-example + cloud: + polaris: + address: grpc://183.47.111.80:8091 + namespace: default + enabled: true + tencent: + metadata: + content: + featureenv: feature2 +logging: + level: + org.springframework.cloud.gateway: info + com.tencent.cloud.polaris: debug diff --git a/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature2/pom.xml b/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature2/pom.xml new file mode 100644 index 000000000..f14cbd7d6 --- /dev/null +++ b/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature2/pom.xml @@ -0,0 +1,32 @@ + + + + polaris-router-featureenv-example + com.tencent.cloud + ${revision} + ../pom.xml + + 4.0.0 + + feature2 + pom + + + feature2-front + feature2-backend + + + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.cloud + spring-cloud-starter-openfeign + + + diff --git a/spring-cloud-tencent-examples/polaris-router-featureenv-example/featureenv-gateway/pom.xml b/spring-cloud-tencent-examples/polaris-router-featureenv-example/featureenv-gateway/pom.xml new file mode 100644 index 000000000..f26708819 --- /dev/null +++ b/spring-cloud-tencent-examples/polaris-router-featureenv-example/featureenv-gateway/pom.xml @@ -0,0 +1,30 @@ + + + + polaris-router-featureenv-example + com.tencent.cloud + ${revision} + ../pom.xml + + 4.0.0 + + featureenv-gateway + + + + + org.springframework.cloud + spring-cloud-starter-gateway + + + com.tencent.cloud + spring-cloud-tencent-gateway-plugin + + + com.tencent.cloud + spring-cloud-tencent-featureenv-plugin + + + diff --git a/spring-cloud-tencent-examples/polaris-router-featureenv-example/featureenv-gateway/src/main/java/com/tencent/cloud/polaris/featureenv/gateway/FeatureEnvScgApplication.java b/spring-cloud-tencent-examples/polaris-router-featureenv-example/featureenv-gateway/src/main/java/com/tencent/cloud/polaris/featureenv/gateway/FeatureEnvScgApplication.java new file mode 100644 index 000000000..41835822d --- /dev/null +++ b/spring-cloud-tencent-examples/polaris-router-featureenv-example/featureenv-gateway/src/main/java/com/tencent/cloud/polaris/featureenv/gateway/FeatureEnvScgApplication.java @@ -0,0 +1,33 @@ +/* + * 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.featureenv.gateway; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +/** + * @author lepdou 2022-07-20 + */ +@SpringBootApplication +public class FeatureEnvScgApplication { + + public static void main(String[] args) { + SpringApplication.run(FeatureEnvScgApplication.class, args); + } + +} diff --git a/spring-cloud-tencent-examples/polaris-router-featureenv-example/featureenv-gateway/src/main/resources/bootstrap.yml b/spring-cloud-tencent-examples/polaris-router-featureenv-example/featureenv-gateway/src/main/resources/bootstrap.yml new file mode 100644 index 000000000..6e1972557 --- /dev/null +++ b/spring-cloud-tencent-examples/polaris-router-featureenv-example/featureenv-gateway/src/main/resources/bootstrap.yml @@ -0,0 +1,68 @@ +server: + session-timeout: 1800 + port: 9999 +spring: + application: + name: featureenv-gateway + cloud: + tencent: + plugin: + scg: + staining: + enabled: true + rule-staining: + enabled: true + router: + feature-env: + enabled: true + polaris: + address: grpc://183.47.111.80:8091 + namespace: default + enabled: true + gateway: + discovery: + locator: + enabled: true + 'predicates[0]': + name: Path + args: + patterns: '''/'' + serviceId + ''/**''' + 'filters[0]': + name: RewritePath + args: + regexp: '''/'' + serviceId + ''/(?.*)''' + replacement: '''/$\{remaining}''' + 'filters[1]': + name: Retry + args: + retries: 3 + exceptions: + '[0]': '''java.net.ConnectException''' + '[1]': '''java.io.IOException''' + statuses: + '[0]': '''BAD_GATEWAY''' + '[1]': '''SERVICE_UNAVAILABLE''' + series: + '[0]': '''CLIENT_ERROR''' + methods: + '[0]': '''GET''' + '[1]': '''POST''' + '[2]': '''PUT''' + '[3]': '''DELETE''' + backoff: + firstBackoff: '''100ms''' + maxBackoff: '''500ms''' + factor: 2 + basedOnPreviousValue: false + routes: + - id: featureenv-front-example + uri: lb://featureenv-front-example + predicates: + - Path=/featureenv-front-example/** + filters: + - StripPrefix=1 + +logging: + level: + org.springframework.cloud.gateway: info + com.tencent.cloud.polaris: debug diff --git a/spring-cloud-tencent-examples/polaris-router-featureenv-example/imgs/structs.png b/spring-cloud-tencent-examples/polaris-router-featureenv-example/imgs/structs.png new file mode 100644 index 000000000..2b8a9c8a1 Binary files /dev/null and b/spring-cloud-tencent-examples/polaris-router-featureenv-example/imgs/structs.png differ diff --git a/spring-cloud-tencent-examples/polaris-router-featureenv-example/pom.xml b/spring-cloud-tencent-examples/polaris-router-featureenv-example/pom.xml new file mode 100644 index 000000000..c9308f4ba --- /dev/null +++ b/spring-cloud-tencent-examples/polaris-router-featureenv-example/pom.xml @@ -0,0 +1,34 @@ + + + + spring-cloud-tencent-examples + com.tencent.cloud + ${revision} + ../pom.xml + + 4.0.0 + + polaris-router-featureenv-example + pom + + + base + feature1 + feature2 + featureenv-gateway + + + + + com.tencent.cloud + spring-cloud-starter-tencent-polaris-discovery + + + + com.tencent.cloud + spring-cloud-tencent-featureenv-plugin + + + diff --git a/spring-cloud-tencent-examples/pom.xml b/spring-cloud-tencent-examples/pom.xml index a4c6c9bda..3395e9b04 100644 --- a/spring-cloud-tencent-examples/pom.xml +++ b/spring-cloud-tencent-examples/pom.xml @@ -24,6 +24,7 @@ polaris-router-example metadata-transfer-example polaris-router-grayrelease-example + polaris-router-featureenv-example diff --git a/spring-cloud-tencent-plugin-starters/spring-cloud-tencent-featureenv-plugin/src/main/java/com/tencent/cloud/plugin/featureenv/FeatureEnvRouterRequestInterceptor.java b/spring-cloud-tencent-plugin-starters/spring-cloud-tencent-featureenv-plugin/src/main/java/com/tencent/cloud/plugin/featureenv/FeatureEnvRouterRequestInterceptor.java index eceb569eb..05bbdaf40 100644 --- a/spring-cloud-tencent-plugin-starters/spring-cloud-tencent-featureenv-plugin/src/main/java/com/tencent/cloud/plugin/featureenv/FeatureEnvRouterRequestInterceptor.java +++ b/spring-cloud-tencent-plugin-starters/spring-cloud-tencent-featureenv-plugin/src/main/java/com/tencent/cloud/plugin/featureenv/FeatureEnvRouterRequestInterceptor.java @@ -35,7 +35,7 @@ import org.apache.commons.lang.StringUtils; public class FeatureEnvRouterRequestInterceptor implements RouterRequestInterceptor { private static final String LABEL_KEY_FEATURE_ENV_ROUTER_KEY = "system-feature-env-router-label"; - private static final String DEFAULT_FEATURE_ENV_ROUTER_LABEL = "env"; + private static final String DEFAULT_FEATURE_ENV_ROUTER_LABEL = "featureenv"; private static final String NOT_EXISTED_ENV = "NOT_EXISTED_ENV"; @Override diff --git a/spring-cloud-tencent-plugin-starters/spring-cloud-tencent-featureenv-plugin/src/test/java/com/tencent/cloud/plugin/featureenv/FeatureEnvRouterRequestInterceptorTest.java b/spring-cloud-tencent-plugin-starters/spring-cloud-tencent-featureenv-plugin/src/test/java/com/tencent/cloud/plugin/featureenv/FeatureEnvRouterRequestInterceptorTest.java index b83f587cd..8a5a6f35a 100644 --- a/spring-cloud-tencent-plugin-starters/spring-cloud-tencent-featureenv-plugin/src/test/java/com/tencent/cloud/plugin/featureenv/FeatureEnvRouterRequestInterceptorTest.java +++ b/spring-cloud-tencent-plugin-starters/spring-cloud-tencent-featureenv-plugin/src/test/java/com/tencent/cloud/plugin/featureenv/FeatureEnvRouterRequestInterceptorTest.java @@ -44,7 +44,7 @@ public class FeatureEnvRouterRequestInterceptorTest { @Test public void testDefaultRouterKey() { Map labels = new HashMap<>(); - labels.put("env", "blue"); + labels.put("featureenv", "blue"); PolarisRouterContext routerContext = new PolarisRouterContext(); routerContext.putLabels(PolarisRouterContext.ROUTER_LABELS, labels); @@ -58,7 +58,7 @@ public class FeatureEnvRouterRequestInterceptorTest { Map metadataRouterLabels = request.getRouterMetadata().get(MetadataRouter.ROUTER_TYPE_METADATA); Assert.assertEquals(1, metadataRouterLabels.size()); - Assert.assertEquals("blue", metadataRouterLabels.get("env")); + Assert.assertEquals("blue", metadataRouterLabels.get("featureenv")); } @Test