From 0bb9ed8ce0a1dd69e09f077c160c7609ace6a5bd Mon Sep 17 00:00:00 2001 From: lepdou Date: Tue, 26 Jul 2022 11:34:07 +0800 Subject: [PATCH] add router actuator endpoint (#464) * optimize ratelimit actuate endpoint and add router actuate endpoint * delete PolarisDiscoveryEndpoint * rename PolarisDiscoveryEndpoint * rename PolarisDiscoveryEndPoint to PolarisDiscoveryEndpoint Co-authored-by: VOPEN.XYZ --- CHANGELOG.md | 1 + .../endpoint/PolarisConfigEndpoint.java | 1 - ...olarisConfigEndpointAutoConfiguration.java | 1 - ...int.java => PolarisDiscoveryEndpoint.java} | 19 ++- ...risDiscoveryEndpointAutoConfiguration.java | 4 +- ...java => PolarisDiscoveryEndpointTest.java} | 9 +- .../pom.xml | 20 +-- .../PolarisRateLimitRuleEndpoint.java | 24 ++-- .../PolarisRateLimitRuleEndpointTests.java | 2 +- .../pom.xml | 12 ++ .../endpoint/PolarisRouterEndpoint.java | 107 ++++++++++++++++ ...olarisRouterEndpointAutoConfiguration.java | 46 +++++++ .../main/resources/META-INF/spring.factories | 3 +- .../endpoint/PolarisRouterEndpointTest.java | 117 ++++++++++++++++++ .../polaris-router-example/pom.xml | 10 ++ .../src/main/resources/bootstrap.yml | 6 + 16 files changed, 336 insertions(+), 46 deletions(-) rename spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/endpoint/{PolarisDiscoveryEndPoint.java => PolarisDiscoveryEndpoint.java} (83%) rename spring-cloud-starter-tencent-polaris-discovery/src/test/java/com/tencent/cloud/polaris/endpoint/{PolarisDiscoveryEndPointTest.java => PolarisDiscoveryEndpointTest.java} (92%) create mode 100644 spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/endpoint/PolarisRouterEndpoint.java create mode 100644 spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/endpoint/PolarisRouterEndpointAutoConfiguration.java create mode 100644 spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/endpoint/PolarisRouterEndpointTest.java diff --git a/CHANGELOG.md b/CHANGELOG.md index 1c2638fa..3fcee34c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,4 +17,5 @@ - [Optimize: rename opertion EQUAL to EQUALS](https://github.com/Tencent/spring-cloud-tencent/pull/457) - [Docs: Add featureenv example readme(en) file](https://github.com/Tencent/spring-cloud-tencent/pull/460) - [docs:update configuration metadata.](https://github.com/Tencent/spring-cloud-tencent/pull/463) +- [Feature: Add router actuate endpoint](https://github.com/Tencent/spring-cloud-tencent/pull/464) - [feat:rename the configuration of reporter.](https://github.com/Tencent/spring-cloud-tencent/pull/465) diff --git a/spring-cloud-starter-tencent-polaris-config/src/main/java/com/tencent/cloud/polaris/config/endpoint/PolarisConfigEndpoint.java b/spring-cloud-starter-tencent-polaris-config/src/main/java/com/tencent/cloud/polaris/config/endpoint/PolarisConfigEndpoint.java index eb9e94f5..108c7409 100644 --- a/spring-cloud-starter-tencent-polaris-config/src/main/java/com/tencent/cloud/polaris/config/endpoint/PolarisConfigEndpoint.java +++ b/spring-cloud-starter-tencent-polaris-config/src/main/java/com/tencent/cloud/polaris/config/endpoint/PolarisConfigEndpoint.java @@ -13,7 +13,6 @@ * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR * CONDITIONS OF ANY KIND, either express or implied. See the License for the * specific language governing permissions and limitations under the License. - * */ package com.tencent.cloud.polaris.config.endpoint; diff --git a/spring-cloud-starter-tencent-polaris-config/src/main/java/com/tencent/cloud/polaris/config/endpoint/PolarisConfigEndpointAutoConfiguration.java b/spring-cloud-starter-tencent-polaris-config/src/main/java/com/tencent/cloud/polaris/config/endpoint/PolarisConfigEndpointAutoConfiguration.java index cb26462e..af2a64cb 100644 --- a/spring-cloud-starter-tencent-polaris-config/src/main/java/com/tencent/cloud/polaris/config/endpoint/PolarisConfigEndpointAutoConfiguration.java +++ b/spring-cloud-starter-tencent-polaris-config/src/main/java/com/tencent/cloud/polaris/config/endpoint/PolarisConfigEndpointAutoConfiguration.java @@ -13,7 +13,6 @@ * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR * CONDITIONS OF ANY KIND, either express or implied. See the License for the * specific language governing permissions and limitations under the License. - * */ package com.tencent.cloud.polaris.config.endpoint; diff --git a/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/endpoint/PolarisDiscoveryEndPoint.java b/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/endpoint/PolarisDiscoveryEndpoint.java similarity index 83% rename from spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/endpoint/PolarisDiscoveryEndPoint.java rename to spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/endpoint/PolarisDiscoveryEndpoint.java index 5e006ac0..248e7943 100644 --- a/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/endpoint/PolarisDiscoveryEndPoint.java +++ b/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/endpoint/PolarisDiscoveryEndpoint.java @@ -39,13 +39,13 @@ import org.springframework.cloud.client.discovery.DiscoveryClient; * @author shuiqingliu */ @Endpoint(id = "polaris-discovery") -public class PolarisDiscoveryEndPoint { +public class PolarisDiscoveryEndpoint { private final PolarisDiscoveryProperties polarisDiscoveryProperties; private final DiscoveryClient polarisDiscoveryClient; private final PolarisDiscoveryHandler polarisDiscoveryHandler; - public PolarisDiscoveryEndPoint(PolarisDiscoveryProperties polarisDiscoveryProperties, DiscoveryClient polarisDiscoveryClient, PolarisDiscoveryHandler polarisDiscoveryHandler) { + public PolarisDiscoveryEndpoint(PolarisDiscoveryProperties polarisDiscoveryProperties, DiscoveryClient polarisDiscoveryClient, PolarisDiscoveryHandler polarisDiscoveryHandler) { this.polarisDiscoveryProperties = polarisDiscoveryProperties; this.polarisDiscoveryClient = polarisDiscoveryClient; this.polarisDiscoveryHandler = polarisDiscoveryHandler; @@ -53,16 +53,16 @@ public class PolarisDiscoveryEndPoint { @ReadOperation public Map polarisDiscovery(@Selector String serviceId) { - Map polarisDisConveryInfo = new HashMap<>(); - polarisDisConveryInfo.put("PolarisDiscoveryProperties", polarisDiscoveryProperties); + Map polarisDiscoveryInfo = new HashMap<>(); + polarisDiscoveryInfo.put("PolarisDiscoveryProperties", polarisDiscoveryProperties); List serviceInstancesInfoList = new ArrayList<>(); if (StringUtils.isNotEmpty(serviceId)) { ServiceInstances serviceInstances = getServiceInstances(serviceId); serviceInstancesInfoList.add(serviceInstances); - polarisDisConveryInfo.put("ServiceInstances", serviceInstancesInfoList); - return polarisDisConveryInfo; + polarisDiscoveryInfo.put("ServiceInstances", serviceInstancesInfoList); + return polarisDiscoveryInfo; } for (String service : polarisDiscoveryClient.getServices()) { @@ -70,13 +70,12 @@ public class PolarisDiscoveryEndPoint { serviceInstancesInfoList.add(serviceInstances); } - polarisDisConveryInfo.put("ServiceInstances", serviceInstancesInfoList); - return polarisDisConveryInfo; + polarisDiscoveryInfo.put("ServiceInstances", serviceInstancesInfoList); + return polarisDiscoveryInfo; } private ServiceInstances getServiceInstances(String serviceId) { InstancesResponse instancesResponse = polarisDiscoveryHandler.getHealthyInstances(serviceId); - ServiceInstances serviceInstances = instancesResponse.toServiceInstances(); - return serviceInstances; + return instancesResponse.toServiceInstances(); } } diff --git a/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/endpoint/PolarisDiscoveryEndpointAutoConfiguration.java b/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/endpoint/PolarisDiscoveryEndpointAutoConfiguration.java index d6b59763..d37229f3 100644 --- a/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/endpoint/PolarisDiscoveryEndpointAutoConfiguration.java +++ b/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/endpoint/PolarisDiscoveryEndpointAutoConfiguration.java @@ -42,8 +42,8 @@ public class PolarisDiscoveryEndpointAutoConfiguration { @Bean @ConditionalOnMissingBean @ConditionalOnAvailableEndpoint - public PolarisDiscoveryEndPoint polarisDiscoveryEndPoint(PolarisDiscoveryProperties polarisDiscoveryProperties, + public PolarisDiscoveryEndpoint polarisDiscoveryEndPoint(PolarisDiscoveryProperties polarisDiscoveryProperties, DiscoveryClient discoveryClient, PolarisDiscoveryHandler polarisDiscoveryHandler) { - return new PolarisDiscoveryEndPoint(polarisDiscoveryProperties, discoveryClient, polarisDiscoveryHandler); + return new PolarisDiscoveryEndpoint(polarisDiscoveryProperties, discoveryClient, polarisDiscoveryHandler); } } diff --git a/spring-cloud-starter-tencent-polaris-discovery/src/test/java/com/tencent/cloud/polaris/endpoint/PolarisDiscoveryEndPointTest.java b/spring-cloud-starter-tencent-polaris-discovery/src/test/java/com/tencent/cloud/polaris/endpoint/PolarisDiscoveryEndpointTest.java similarity index 92% rename from spring-cloud-starter-tencent-polaris-discovery/src/test/java/com/tencent/cloud/polaris/endpoint/PolarisDiscoveryEndPointTest.java rename to spring-cloud-starter-tencent-polaris-discovery/src/test/java/com/tencent/cloud/polaris/endpoint/PolarisDiscoveryEndpointTest.java index ea5562d1..b85de4aa 100644 --- a/spring-cloud-starter-tencent-polaris-discovery/src/test/java/com/tencent/cloud/polaris/endpoint/PolarisDiscoveryEndPointTest.java +++ b/spring-cloud-starter-tencent-polaris-discovery/src/test/java/com/tencent/cloud/polaris/endpoint/PolarisDiscoveryEndpointTest.java @@ -14,7 +14,6 @@ * 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.endpoint; import java.util.Map; @@ -46,13 +45,13 @@ import static org.assertj.core.api.Assertions.assertThat; * * @author shuiqingliu */ -public class PolarisDiscoveryEndPointTest { +public class PolarisDiscoveryEndpointTest { private static NamingServer namingServer; private WebApplicationContextRunner contextRunner = new WebApplicationContextRunner() .withConfiguration(AutoConfigurations.of( - PolarisDiscoveryEndPointTest.PolarisPropertiesConfiguration.class, + PolarisPropertiesConfiguration.class, PolarisDiscoveryClientConfiguration.class, PolarisDiscoveryAutoConfiguration.class, PolarisDiscoveryEndpointAutoConfiguration.class)) @@ -83,9 +82,9 @@ public class PolarisDiscoveryEndPointTest { DiscoveryClient discoveryClient = context .getBean(PolarisDiscoveryClient.class); PolarisDiscoveryHandler polarisDiscoveryHandler = context.getBean(PolarisDiscoveryHandler.class); - PolarisDiscoveryEndPoint polarisDiscoveryEndPoint = new PolarisDiscoveryEndPoint(polarisDiscoveryProperties, discoveryClient, polarisDiscoveryHandler); + PolarisDiscoveryEndpoint polarisDiscoveryEndpoint = new PolarisDiscoveryEndpoint(polarisDiscoveryProperties, discoveryClient, polarisDiscoveryHandler); - Map mapInfo = polarisDiscoveryEndPoint.polarisDiscovery("java_provider_test"); + Map mapInfo = polarisDiscoveryEndpoint.polarisDiscovery("java_provider_test"); assertThat(polarisDiscoveryProperties).isEqualTo(mapInfo.get("PolarisDiscoveryProperties")); diff --git a/spring-cloud-starter-tencent-polaris-ratelimit/pom.xml b/spring-cloud-starter-tencent-polaris-ratelimit/pom.xml index d3499dee..80aaa811 100644 --- a/spring-cloud-starter-tencent-polaris-ratelimit/pom.xml +++ b/spring-cloud-starter-tencent-polaris-ratelimit/pom.xml @@ -80,26 +80,26 @@ org.springframework.boot - spring-boot-starter-test - test + spring-boot-actuator + true - org.springframework.cloud - spring-cloud-starter-netflix-ribbon - test + org.springframework.boot + spring-boot-actuator-autoconfigure + true org.springframework.boot - spring-boot-actuator - true + spring-boot-starter-test + test - org.springframework.boot - spring-boot-actuator-autoconfigure - true + org.springframework.cloud + spring-cloud-starter-netflix-ribbon + test diff --git a/spring-cloud-starter-tencent-polaris-ratelimit/src/main/java/com/tencent/cloud/polaris/ratelimit/endpoint/PolarisRateLimitRuleEndpoint.java b/spring-cloud-starter-tencent-polaris-ratelimit/src/main/java/com/tencent/cloud/polaris/ratelimit/endpoint/PolarisRateLimitRuleEndpoint.java index c9bd5020..d41ebce8 100644 --- a/spring-cloud-starter-tencent-polaris-ratelimit/src/main/java/com/tencent/cloud/polaris/ratelimit/endpoint/PolarisRateLimitRuleEndpoint.java +++ b/spring-cloud-starter-tencent-polaris-ratelimit/src/main/java/com/tencent/cloud/polaris/ratelimit/endpoint/PolarisRateLimitRuleEndpoint.java @@ -24,19 +24,16 @@ import java.util.Map; import com.google.protobuf.InvalidProtocolBufferException; import com.google.protobuf.util.JsonFormat; +import com.tencent.cloud.common.metadata.MetadataContext; import com.tencent.cloud.common.util.JacksonUtils; import com.tencent.cloud.polaris.context.ServiceRuleManager; import com.tencent.cloud.polaris.ratelimit.config.PolarisRateLimitProperties; import com.tencent.polaris.client.pb.RateLimitProto; -import com.tencent.polaris.client.pb.RoutingProto; -import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.boot.actuate.endpoint.annotation.Endpoint; import org.springframework.boot.actuate.endpoint.annotation.ReadOperation; -import org.springframework.boot.actuate.endpoint.annotation.Selector; -import org.springframework.lang.Nullable; import org.springframework.util.CollectionUtils; /** @@ -58,19 +55,17 @@ public class PolarisRateLimitRuleEndpoint { } @ReadOperation - public Map rateLimit(@Selector String namespace, @Selector String service, @Nullable String dstService) { + public Map rateLimit() { + RateLimitProto.RateLimit rateLimit = serviceRuleManager.getServiceRateLimitRule(MetadataContext.LOCAL_NAMESPACE, + MetadataContext.LOCAL_SERVICE); + Map result = new HashMap<>(); - RateLimitProto.RateLimit rateLimit = serviceRuleManager.getServiceRateLimitRule(namespace, service); + result.put("properties", polarisRateLimitProperties); - result.put("namespace", namespace); - result.put("service", service); - result.put("rateLimits", parseRateLimitRule(rateLimit)); + result.put("namespace", MetadataContext.LOCAL_NAMESPACE); + result.put("service", MetadataContext.LOCAL_SERVICE); + result.put("rateLimitRules", parseRateLimitRule(rateLimit)); - if (StringUtils.isEmpty(dstService)) { - return result; - } - List routes = serviceRuleManager.getServiceRouterRule(namespace, service, dstService); - result.put("routes", routes); return result; } @@ -93,5 +88,4 @@ public class PolarisRateLimitRuleEndpoint { } return rateLimitRule; } - } diff --git a/spring-cloud-starter-tencent-polaris-ratelimit/src/test/java/com/tencent/cloud/polaris/ratelimit/endpoint/PolarisRateLimitRuleEndpointTests.java b/spring-cloud-starter-tencent-polaris-ratelimit/src/test/java/com/tencent/cloud/polaris/ratelimit/endpoint/PolarisRateLimitRuleEndpointTests.java index d5d7e6fd..7d8ed9b0 100644 --- a/spring-cloud-starter-tencent-polaris-ratelimit/src/test/java/com/tencent/cloud/polaris/ratelimit/endpoint/PolarisRateLimitRuleEndpointTests.java +++ b/spring-cloud-starter-tencent-polaris-ratelimit/src/test/java/com/tencent/cloud/polaris/ratelimit/endpoint/PolarisRateLimitRuleEndpointTests.java @@ -98,7 +98,7 @@ public class PolarisRateLimitRuleEndpointTests { public void testPolarisRateLimit() { this.contextRunner.run(context -> polarisRateLimitProperties = context.getBean(PolarisRateLimitProperties.class)); PolarisRateLimitRuleEndpoint polarisRateLimitRuleEndpoint = new PolarisRateLimitRuleEndpoint(serviceRuleManager, polarisRateLimitProperties); - Map rateLimit = polarisRateLimitRuleEndpoint.rateLimit("namespaceTest", "TestApp2", "TestApp3"); + Map rateLimit = polarisRateLimitRuleEndpoint.rateLimit(); assertThat(polarisRateLimitProperties).isEqualTo(rateLimit.get("properties")); } diff --git a/spring-cloud-starter-tencent-polaris-router/pom.xml b/spring-cloud-starter-tencent-polaris-router/pom.xml index c152dc93..1f68017e 100644 --- a/spring-cloud-starter-tencent-polaris-router/pom.xml +++ b/spring-cloud-starter-tencent-polaris-router/pom.xml @@ -62,6 +62,18 @@ true + + org.springframework.boot + spring-boot-actuator + true + + + + org.springframework.boot + spring-boot-actuator-autoconfigure + true + + org.springframework.boot spring-boot-starter-test diff --git a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/endpoint/PolarisRouterEndpoint.java b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/endpoint/PolarisRouterEndpoint.java new file mode 100644 index 00000000..a00281d0 --- /dev/null +++ b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/endpoint/PolarisRouterEndpoint.java @@ -0,0 +1,107 @@ +/* + * 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.endpoint; + +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +import com.google.protobuf.InvalidProtocolBufferException; +import com.google.protobuf.MessageOrBuilder; +import com.google.protobuf.util.JsonFormat; +import com.tencent.cloud.common.metadata.MetadataContext; +import com.tencent.cloud.common.util.JacksonUtils; +import com.tencent.cloud.polaris.context.ServiceRuleManager; +import com.tencent.polaris.client.pb.RoutingProto; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import org.springframework.boot.actuate.endpoint.annotation.Endpoint; +import org.springframework.boot.actuate.endpoint.annotation.ReadOperation; +import org.springframework.boot.actuate.endpoint.annotation.Selector; +import org.springframework.util.CollectionUtils; + +/** + * Router actuator endpoint. + * @author lepdou 2022-07-25 + */ +@Endpoint(id = "polaris-router") +public class PolarisRouterEndpoint { + private static final Logger LOGGER = LoggerFactory.getLogger(PolarisRouterEndpoint.class); + + private final ServiceRuleManager serviceRuleManager; + + public PolarisRouterEndpoint(ServiceRuleManager serviceRuleManager) { + this.serviceRuleManager = serviceRuleManager; + } + + @ReadOperation + public Map router(@Selector String dstService) { + List routerRules = serviceRuleManager.getServiceRouterRule(MetadataContext.LOCAL_NAMESPACE, + MetadataContext.LOCAL_SERVICE, dstService); + + Map result = new HashMap<>(); + + List rules = new LinkedList<>(); + result.put("routerRules", rules); + + if (CollectionUtils.isEmpty(routerRules)) { + return result; + } + + for (RoutingProto.Route route : routerRules) { + rules.add(parseRouterRule(route)); + } + + return result; + } + + private Object parseRouterRule(RoutingProto.Route routeRule) { + Map result = new HashMap<>(); + + List sourcePbs = routeRule.getSourcesList(); + List sources = new LinkedList<>(); + for (RoutingProto.Source sourcePb : sourcePbs) { + sources.add(pb2Json(sourcePb)); + } + result.put("sources", sources); + + List destPbs = routeRule.getDestinationsList(); + List destinations = new LinkedList<>(); + for (RoutingProto.Destination destPb : destPbs) { + destinations.add(pb2Json(destPb)); + } + result.put("destinations", destinations); + + return result; + } + + private Object pb2Json(MessageOrBuilder pbObject) { + String jsonStr; + try { + jsonStr = JsonFormat.printer().print(pbObject); + } + catch (InvalidProtocolBufferException e) { + String msg = "parse router rule to json error."; + LOGGER.error(msg, e); + throw new RuntimeException(msg, e); + } + return JacksonUtils.deserialize2Map(jsonStr); + } +} diff --git a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/endpoint/PolarisRouterEndpointAutoConfiguration.java b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/endpoint/PolarisRouterEndpointAutoConfiguration.java new file mode 100644 index 00000000..3cc275bf --- /dev/null +++ b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/endpoint/PolarisRouterEndpointAutoConfiguration.java @@ -0,0 +1,46 @@ +/* + * 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.endpoint; + +import com.tencent.cloud.polaris.context.ConditionalOnPolarisEnabled; +import com.tencent.cloud.polaris.context.ServiceRuleManager; + +import org.springframework.boot.actuate.autoconfigure.endpoint.condition.ConditionalOnAvailableEndpoint; +import org.springframework.boot.actuate.endpoint.annotation.Endpoint; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * The AutoConfiguration for polaris router endpoint. + * + * @author lepdou 2022-07-25 + **/ +@Configuration(proxyBeanMethods = false) +@ConditionalOnClass(Endpoint.class) +@ConditionalOnPolarisEnabled +public class PolarisRouterEndpointAutoConfiguration { + + @Bean + @ConditionalOnMissingBean + @ConditionalOnAvailableEndpoint + public PolarisRouterEndpoint polarisRouterEndpoint(ServiceRuleManager serviceRuleManager) { + return new PolarisRouterEndpoint(serviceRuleManager); + } +} diff --git a/spring-cloud-starter-tencent-polaris-router/src/main/resources/META-INF/spring.factories b/spring-cloud-starter-tencent-polaris-router/src/main/resources/META-INF/spring.factories index 3b20deb5..75f7939c 100644 --- a/spring-cloud-starter-tencent-polaris-router/src/main/resources/META-INF/spring.factories +++ b/spring-cloud-starter-tencent-polaris-router/src/main/resources/META-INF/spring.factories @@ -1,3 +1,4 @@ org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ com.tencent.cloud.polaris.router.config.RouterAutoConfiguration,\ - com.tencent.cloud.polaris.router.config.FeignAutoConfiguration + com.tencent.cloud.polaris.router.config.FeignAutoConfiguration,\ + com.tencent.cloud.polaris.router.endpoint.PolarisRouterEndpointAutoConfiguration diff --git a/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/endpoint/PolarisRouterEndpointTest.java b/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/endpoint/PolarisRouterEndpointTest.java new file mode 100644 index 00000000..27183c2a --- /dev/null +++ b/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/endpoint/PolarisRouterEndpointTest.java @@ -0,0 +1,117 @@ +/* + * 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.endpoint; + +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +import com.google.common.collect.Lists; +import com.tencent.cloud.common.util.ApplicationContextAwareUtils; +import com.tencent.cloud.polaris.context.ServiceRuleManager; +import com.tencent.polaris.client.pb.ModelProto; +import com.tencent.polaris.client.pb.RoutingProto; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockedStatic; +import org.mockito.Mockito; +import org.mockito.junit.MockitoJUnitRunner; + +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.when; + +/** + * Test for {@link PolarisRouterEndpoint} + * @author lepdou 2022-07-25 + */ +@RunWith(MockitoJUnitRunner.class) +public class PolarisRouterEndpointTest { + + private static final String testDestService = "dstService"; + private static MockedStatic mockedApplicationContextAwareUtils; + + @Mock + private ServiceRuleManager serviceRuleManager; + @InjectMocks + private PolarisRouterEndpoint polarisRouterEndpoint; + + @BeforeClass + public static void beforeClass() { + mockedApplicationContextAwareUtils = Mockito.mockStatic(ApplicationContextAwareUtils.class); + mockedApplicationContextAwareUtils.when(() -> ApplicationContextAwareUtils.getProperties(anyString())) + .thenReturn(testDestService); + } + + @AfterClass + public static void afterClass() { + mockedApplicationContextAwareUtils.close(); + } + + @Test + public void testHasRouterRule() { + Map labels = new HashMap<>(); + ModelProto.MatchString matchString = ModelProto.MatchString.getDefaultInstance(); + String validKey1 = "${http.header.uid}"; + String validKey2 = "${http.query.name}"; + String validKey3 = "${http.method}"; + String validKey4 = "${http.uri}"; + 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(); + RoutingProto.Source source2 = RoutingProto.Source.newBuilder().putAllMetadata(labels).build(); + RoutingProto.Source source3 = RoutingProto.Source.newBuilder().putAllMetadata(new HashMap<>()).build(); + + List routes = new LinkedList<>(); + RoutingProto.Route route = RoutingProto.Route.newBuilder() + .addAllSources(Lists.newArrayList(source1, source2, source3)) + .build(); + routes.add(route); + + when(serviceRuleManager.getServiceRouterRule(testDestService, testDestService, testDestService)).thenReturn(routes); + + Map actuator = polarisRouterEndpoint.router(testDestService); + + Assert.assertNotNull(actuator.get("routerRules")); + Assert.assertEquals(1, ((List) actuator.get("routerRules")).size()); + } + + @Test + public void testHasNotRouterRule() { + List routes = new LinkedList<>(); + + when(serviceRuleManager.getServiceRouterRule(testDestService, testDestService, testDestService)).thenReturn(routes); + + Map actuator = polarisRouterEndpoint.router(testDestService); + + Assert.assertNotNull(actuator.get("routerRules")); + Assert.assertEquals(0, ((List) actuator.get("routerRules")).size()); + } +} diff --git a/spring-cloud-tencent-examples/polaris-router-example/pom.xml b/spring-cloud-tencent-examples/polaris-router-example/pom.xml index 37e8aee3..8bd99b3c 100644 --- a/spring-cloud-tencent-examples/polaris-router-example/pom.xml +++ b/spring-cloud-tencent-examples/polaris-router-example/pom.xml @@ -34,6 +34,16 @@ org.springframework.cloud spring-cloud-starter-openfeign + + + org.springframework.boot + spring-boot-actuator + + + + org.springframework.boot + spring-boot-actuator-autoconfigure + diff --git a/spring-cloud-tencent-examples/polaris-router-example/router-caller-service/src/main/resources/bootstrap.yml b/spring-cloud-tencent-examples/polaris-router-example/router-caller-service/src/main/resources/bootstrap.yml index e8f79333..7a53c2f0 100644 --- a/spring-cloud-tencent-examples/polaris-router-example/router-caller-service/src/main/resources/bootstrap.yml +++ b/spring-cloud-tencent-examples/polaris-router-example/router-caller-service/src/main/resources/bootstrap.yml @@ -14,3 +14,9 @@ spring: enabled: true loadbalancer: enabled: true +management: + endpoints: + web: + exposure: + include: + - polaris-router