diff --git a/CHANGELOG.md b/CHANGELOG.md index dbd8440bb..e53681b5d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,3 +6,5 @@ - [Feature: Router support request label.](https://github.com/Tencent/spring-cloud-tencent/pull/165) - [Feature: Support router expression label](https://github.com/Tencent/spring-cloud-tencent/pull/190) - [Add metadata transfer example.](https://github.com/Tencent/spring-cloud-tencent/pull/184) +- [Feature: Support metadata router.](https://github.com/Tencent/spring-cloud-tencent/pull/191) +- [Feature: Misc optimize metadata router.](https://github.com/Tencent/spring-cloud-tencent/pull/192) diff --git a/spring-cloud-starter-tencent-polaris-router/pom.xml b/spring-cloud-starter-tencent-polaris-router/pom.xml index 644612dc0..4e78b9cda 100644 --- a/spring-cloud-starter-tencent-polaris-router/pom.xml +++ b/spring-cloud-starter-tencent-polaris-router/pom.xml @@ -19,6 +19,10 @@ com.tencent.cloud spring-cloud-tencent-polaris-loadbalancer + + com.tencent.cloud + spring-cloud-starter-tencent-metadata-transfer + @@ -43,7 +47,7 @@ spring-boot-starter-web true - + diff --git a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/RouterAutoConfiguration.java b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/RouterAutoConfiguration.java index 5065b09b5..305b4087e 100644 --- a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/RouterAutoConfiguration.java +++ b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/RouterAutoConfiguration.java @@ -18,11 +18,13 @@ package com.tencent.cloud.polaris.router.config; +import java.util.List; + import com.tencent.cloud.common.metadata.config.MetadataLocalProperties; import com.tencent.cloud.polaris.context.ServiceRuleManager; import com.tencent.cloud.polaris.router.RouterRuleLabelResolver; import com.tencent.cloud.polaris.router.feign.PolarisCachingSpringLoadBalanceFactory; -import com.tencent.cloud.polaris.router.feign.RouterLabelInterceptor; +import com.tencent.cloud.polaris.router.feign.RouterLabelFeignInterceptor; import com.tencent.cloud.polaris.router.resttemplate.PolarisLoadBalancerBeanPostProcessor; import com.tencent.cloud.polaris.router.spi.RouterLabelResolver; @@ -45,10 +47,10 @@ import static org.springframework.core.Ordered.HIGHEST_PRECEDENCE; public class RouterAutoConfiguration { @Bean - public RouterLabelInterceptor routerLabelInterceptor(@Nullable RouterLabelResolver resolver, + public RouterLabelFeignInterceptor routerLabelInterceptor(@Nullable List routerLabelResolvers, MetadataLocalProperties metadataLocalProperties, RouterRuleLabelResolver routerRuleLabelResolver) { - return new RouterLabelInterceptor(resolver, metadataLocalProperties, routerRuleLabelResolver); + return new RouterLabelFeignInterceptor(routerLabelResolvers, metadataLocalProperties, routerRuleLabelResolver); } @Bean diff --git a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/feign/RouterLabelInterceptor.java b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/feign/RouterLabelFeignInterceptor.java similarity index 79% rename from spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/feign/RouterLabelInterceptor.java rename to spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/feign/RouterLabelFeignInterceptor.java index 48c3fb667..a8d2a5659 100644 --- a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/feign/RouterLabelInterceptor.java +++ b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/feign/RouterLabelFeignInterceptor.java @@ -19,7 +19,9 @@ package com.tencent.cloud.polaris.router.feign; import java.util.Collections; +import java.util.Comparator; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.Set; @@ -44,17 +46,23 @@ import org.springframework.util.CollectionUtils; * *@author lepdou 2022-05-12 */ -public class RouterLabelInterceptor implements RequestInterceptor, Ordered { - private static final Logger LOGGER = LoggerFactory.getLogger(RouterLabelInterceptor.class); +public class RouterLabelFeignInterceptor implements RequestInterceptor, Ordered { + private static final Logger LOGGER = LoggerFactory.getLogger(RouterLabelFeignInterceptor.class); - private final RouterLabelResolver resolver; + private final List routerLabelResolvers; private final MetadataLocalProperties metadataLocalProperties; private final RouterRuleLabelResolver routerRuleLabelResolver; - public RouterLabelInterceptor(RouterLabelResolver resolver, + public RouterLabelFeignInterceptor(List routerLabelResolvers, MetadataLocalProperties metadataLocalProperties, RouterRuleLabelResolver routerRuleLabelResolver) { - this.resolver = resolver; + if (!CollectionUtils.isEmpty(routerLabelResolvers)) { + routerLabelResolvers.sort(Comparator.comparingInt(Ordered::getOrder)); + this.routerLabelResolvers = routerLabelResolvers; + } + else { + this.routerLabelResolvers = null; + } this.metadataLocalProperties = metadataLocalProperties; this.routerRuleLabelResolver = routerRuleLabelResolver; } @@ -74,16 +82,18 @@ public class RouterLabelInterceptor implements RequestInterceptor, Ordered { labels.putAll(transitiveLabels); // labels from request - if (resolver != null) { - try { - Map customResolvedLabels = resolver.resolve(requestTemplate); - if (!CollectionUtils.isEmpty(customResolvedLabels)) { - labels.putAll(customResolvedLabels); + if (!CollectionUtils.isEmpty(routerLabelResolvers)) { + routerLabelResolvers.forEach(resolver -> { + try { + Map customResolvedLabels = resolver.resolve(requestTemplate); + if (!CollectionUtils.isEmpty(customResolvedLabels)) { + labels.putAll(customResolvedLabels); + } + } + catch (Throwable t) { + LOGGER.error("[SCT][Router] revoke RouterLabelResolver occur some exception. ", t); } - } - catch (Throwable t) { - LOGGER.error("[SCT][Router] revoke RouterLabelResolver occur some exception. ", t); - } + }); } // labels from rule expression diff --git a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/resttemplate/PolarisLoadBalancerBeanPostProcessor.java b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/resttemplate/PolarisLoadBalancerBeanPostProcessor.java index 6fe192003..5bafbd9fb 100644 --- a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/resttemplate/PolarisLoadBalancerBeanPostProcessor.java +++ b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/resttemplate/PolarisLoadBalancerBeanPostProcessor.java @@ -18,7 +18,10 @@ package com.tencent.cloud.polaris.router.resttemplate; +import java.util.List; + import com.tencent.cloud.common.metadata.config.MetadataLocalProperties; +import com.tencent.cloud.common.util.BeanFactoryUtils; import com.tencent.cloud.polaris.router.RouterRuleLabelResolver; import com.tencent.cloud.polaris.router.spi.RouterLabelResolver; @@ -50,12 +53,12 @@ public class PolarisLoadBalancerBeanPostProcessor implements BeanPostProcessor, if (bean instanceof LoadBalancerInterceptor) { LoadBalancerRequestFactory requestFactory = this.factory.getBean(LoadBalancerRequestFactory.class); LoadBalancerClient loadBalancerClient = this.factory.getBean(LoadBalancerClient.class); - RouterLabelResolver routerLabelResolver = this.factory.getBean(RouterLabelResolver.class); + List routerLabelResolvers = BeanFactoryUtils.getBeans(factory, RouterLabelResolver.class); MetadataLocalProperties metadataLocalProperties = this.factory.getBean(MetadataLocalProperties.class); RouterRuleLabelResolver routerRuleLabelResolver = this.factory.getBean(RouterRuleLabelResolver.class); return new PolarisLoadBalancerInterceptor(loadBalancerClient, requestFactory, - routerLabelResolver, metadataLocalProperties, routerRuleLabelResolver); + routerLabelResolvers, metadataLocalProperties, routerRuleLabelResolver); } return bean; } 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 a432830b3..938652497 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 @@ -21,7 +21,9 @@ package com.tencent.cloud.polaris.router.resttemplate; import java.io.IOException; import java.net.URI; import java.util.Collections; +import java.util.Comparator; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.Set; @@ -39,6 +41,7 @@ import org.springframework.cloud.client.loadbalancer.LoadBalancerClient; import org.springframework.cloud.client.loadbalancer.LoadBalancerInterceptor; import org.springframework.cloud.client.loadbalancer.LoadBalancerRequestFactory; import org.springframework.cloud.netflix.ribbon.RibbonLoadBalancerClient; +import org.springframework.core.Ordered; import org.springframework.http.HttpRequest; import org.springframework.http.client.ClientHttpRequestExecution; import org.springframework.http.client.ClientHttpResponse; @@ -56,7 +59,7 @@ public class PolarisLoadBalancerInterceptor extends LoadBalancerInterceptor { private final LoadBalancerClient loadBalancer; private final LoadBalancerRequestFactory requestFactory; - private final RouterLabelResolver resolver; + private final List routerLabelResolvers; private final MetadataLocalProperties metadataLocalProperties; private final RouterRuleLabelResolver routerRuleLabelResolver; @@ -64,16 +67,23 @@ public class PolarisLoadBalancerInterceptor extends LoadBalancerInterceptor { public PolarisLoadBalancerInterceptor(LoadBalancerClient loadBalancer, LoadBalancerRequestFactory requestFactory, - RouterLabelResolver resolver, + List routerLabelResolvers, MetadataLocalProperties metadataLocalProperties, RouterRuleLabelResolver routerRuleLabelResolver) { super(loadBalancer, requestFactory); this.loadBalancer = loadBalancer; this.requestFactory = requestFactory; - this.resolver = resolver; this.metadataLocalProperties = metadataLocalProperties; this.routerRuleLabelResolver = routerRuleLabelResolver; + if (!CollectionUtils.isEmpty(routerLabelResolvers)) { + routerLabelResolvers.sort(Comparator.comparingInt(Ordered::getOrder)); + this.routerLabelResolvers = routerLabelResolvers; + } + else { + this.routerLabelResolvers = null; + } + this.isRibbonLoadBalanceClient = loadBalancer instanceof RibbonLoadBalancerClient; } @@ -104,16 +114,18 @@ public class PolarisLoadBalancerInterceptor extends LoadBalancerInterceptor { labels.putAll(transitiveLabels); // labels from request - if (resolver != null) { - try { - Map customResolvedLabels = resolver.resolve(request, body); - if (!CollectionUtils.isEmpty(customResolvedLabels)) { - labels.putAll(customResolvedLabels); + if (!CollectionUtils.isEmpty(routerLabelResolvers)) { + routerLabelResolvers.forEach(resolver -> { + try { + Map customResolvedLabels = resolver.resolve(request, body); + if (!CollectionUtils.isEmpty(customResolvedLabels)) { + labels.putAll(customResolvedLabels); + } + } + catch (Throwable t) { + LOGGER.error("[SCT][Router] revoke RouterLabelResolver occur some exception. ", t); } - } - catch (Throwable t) { - LOGGER.error("[SCT][Router] revoke RouterLabelResolver occur some exception. ", t); - } + }); } // labels from rule expression diff --git a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/spi/RouterLabelResolver.java b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/spi/RouterLabelResolver.java index 8b2f394d5..49b9ccf4c 100644 --- a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/spi/RouterLabelResolver.java +++ b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/spi/RouterLabelResolver.java @@ -22,6 +22,7 @@ import java.util.Map; import feign.RequestTemplate; +import org.springframework.core.Ordered; import org.springframework.http.HttpRequest; /** @@ -29,7 +30,7 @@ import org.springframework.http.HttpRequest; * * @author lepdou 2022-05-11 */ -public interface RouterLabelResolver { +public interface RouterLabelResolver extends Ordered { /** * resolve labels from feign request. diff --git a/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/util/BeanFactoryUtils.java b/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/util/BeanFactoryUtils.java new file mode 100644 index 000000000..715a154fc --- /dev/null +++ b/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/util/BeanFactoryUtils.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.common.util; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +import org.springframework.beans.factory.BeanFactory; +import org.springframework.beans.factory.support.DefaultListableBeanFactory; + +/** + * the utils for bean factory. + * @author lepdou 2022-05-23 + */ +public class BeanFactoryUtils { + + public static List getBeans(BeanFactory beanFactory, Class requiredType) { + if (!(beanFactory instanceof DefaultListableBeanFactory)) { + throw new RuntimeException("bean factory not support get list bean. factory type = " + beanFactory.getClass() + .getName()); + } + + String[] beanNames = ((DefaultListableBeanFactory) beanFactory).getBeanNamesForType(requiredType); + + if (beanNames.length == 0) { + return Collections.emptyList(); + } + + return Arrays.stream(beanNames).map( + beanName -> beanFactory.getBean(beanName, requiredType) + ).collect(Collectors.toList()); + } +} diff --git a/spring-cloud-tencent-examples/polaris-router-example/router-caller-service/src/main/java/com/tencent/cloud/polaris/router/example/CustomRouterLabelResolver.java b/spring-cloud-tencent-examples/polaris-router-example/router-caller-service/src/main/java/com/tencent/cloud/polaris/router/example/CustomRouterLabelResolver.java index 0eb90aa69..bd289abb9 100644 --- a/spring-cloud-tencent-examples/polaris-router-example/router-caller-service/src/main/java/com/tencent/cloud/polaris/router/example/CustomRouterLabelResolver.java +++ b/spring-cloud-tencent-examples/polaris-router-example/router-caller-service/src/main/java/com/tencent/cloud/polaris/router/example/CustomRouterLabelResolver.java @@ -57,4 +57,9 @@ public class CustomRouterLabelResolver implements RouterLabelResolver { labels.put("user", user.getName()); return labels; } + + @Override + public int getOrder() { + return 0; + } }