From f5bb38c8c70ae48b9e57f67762845127a8867b1c Mon Sep 17 00:00:00 2001 From: Fishtail <49390359+fuyuwei01@users.noreply.github.com> Date: Tue, 13 Aug 2024 16:24:45 +0800 Subject: [PATCH] feat: support lossless online/offline (#1377) Co-authored-by: Haotian Zhang <skyebefreeman@qq.com> Co-authored-by: andrew shan <45474304+andrewshan@users.noreply.github.com> --- CHANGELOG.md | 1 + .../registry/PolarisServiceRegistry.java | 21 +- .../cloud/common/constant/OrderConstant.java | 5 + .../cloud/common}/util/OkHttpUtil.java | 10 +- .../tencent/cloud/common/util/UrlUtils.java | 78 +++++++ .../cloud/common}/util/OkHttpUtilTest.java | 12 +- .../cloud/common/util/UrlUtilsTest.java | 68 +++++++ spring-cloud-tencent-coverage/pom.xml | 5 + spring-cloud-tencent-dependencies/pom.xml | 6 + .../lossless-callee-service/pom.xml | 63 ++++++ .../callee/LosslessCalleeController.java | 95 +++++++++ .../callee/LosslessCalleeService.java | 29 +++ .../src/main/resources/bootstrap.yml | 36 ++++ .../lossless-nacos-callee-service/pom.xml | 69 +++++++ .../callee/LosslessNacosCalleeController.java | 95 +++++++++ .../callee/LosslessNacosCalleeService.java | 31 +++ .../src/main/resources/bootstrap.yml | 28 +++ .../lossless-example/pom.xml | 25 +++ spring-cloud-tencent-examples/pom.xml | 1 + spring-cloud-tencent-plugin-starters/pom.xml | 1 + .../pom.xml | 2 +- ...acosDiscoveryAdapterAutoConfiguration.java | 9 + .../transformer/NacosInstanceTransformer.java | 1 + .../NacosRegistrationTransformer.java | 43 ++++ .../pom.xml | 75 +++++++ .../lossless/LosslessRegistryAspect.java | 104 ++++++++++ .../SpringCloudLosslessActionProvider.java | 95 +++++++++ .../config/LosslessAutoConfiguration.java | 54 +++++ .../config/LosslessConfigModifier.java | 59 ++++++ .../lossless/config/LosslessProperties.java | 75 +++++++ .../LosslessPropertiesAutoConfiguration.java | 44 ++++ ...slessPropertiesBootstrapConfiguration.java | 35 ++++ ...itional-spring-configuration-metadata.json | 10 + .../main/resources/META-INF/spring.factories | 2 + ...ot.autoconfigure.AutoConfiguration.imports | 1 + .../lossless/LosslessConfigModifierTest.java | 91 +++++++++ .../lossless/LosslessPropertiesTest.java | 40 ++++ .../lossless/LosslessRegistryAspectTest.java | 191 ++++++++++++++++++ .../AutoServiceRegistrationUtils.java | 29 +++ .../context/PolarisSDKContextManager.java | 16 ++ .../RpcEnhancementAutoConfiguration.java | 12 +- .../PolarisRegistrationTransformer.java | 25 +++ .../transformer/RegistrationTransformer.java | 55 +++++ 43 files changed, 1727 insertions(+), 20 deletions(-) rename {spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris => spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common}/util/OkHttpUtil.java (88%) create mode 100644 spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/util/UrlUtils.java rename {spring-cloud-starter-tencent-polaris-discovery/src/test/java/com/tencent/cloud/polaris => spring-cloud-tencent-commons/src/test/java/com/tencent/cloud/common}/util/OkHttpUtilTest.java (82%) create mode 100644 spring-cloud-tencent-commons/src/test/java/com/tencent/cloud/common/util/UrlUtilsTest.java create mode 100644 spring-cloud-tencent-examples/lossless-example/lossless-callee-service/pom.xml create mode 100644 spring-cloud-tencent-examples/lossless-example/lossless-callee-service/src/main/java/com/tencent/cloud/lossless/callee/LosslessCalleeController.java create mode 100644 spring-cloud-tencent-examples/lossless-example/lossless-callee-service/src/main/java/com/tencent/cloud/lossless/callee/LosslessCalleeService.java create mode 100644 spring-cloud-tencent-examples/lossless-example/lossless-callee-service/src/main/resources/bootstrap.yml create mode 100644 spring-cloud-tencent-examples/lossless-example/lossless-nacos-callee-service/pom.xml create mode 100644 spring-cloud-tencent-examples/lossless-example/lossless-nacos-callee-service/src/main/java/com/tencent/cloud/lossless/nacos/callee/LosslessNacosCalleeController.java create mode 100644 spring-cloud-tencent-examples/lossless-example/lossless-nacos-callee-service/src/main/java/com/tencent/cloud/lossless/nacos/callee/LosslessNacosCalleeService.java create mode 100644 spring-cloud-tencent-examples/lossless-example/lossless-nacos-callee-service/src/main/resources/bootstrap.yml create mode 100644 spring-cloud-tencent-examples/lossless-example/pom.xml create mode 100644 spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-discovery-adapter-plugin/src/main/java/com/tencent/cloud/plugin/discovery/adapter/transformer/NacosRegistrationTransformer.java create mode 100644 spring-cloud-tencent-plugin-starters/spring-cloud-tencent-lossless-plugin/pom.xml create mode 100644 spring-cloud-tencent-plugin-starters/spring-cloud-tencent-lossless-plugin/src/main/java/com/tencent/cloud/plugin/lossless/LosslessRegistryAspect.java create mode 100644 spring-cloud-tencent-plugin-starters/spring-cloud-tencent-lossless-plugin/src/main/java/com/tencent/cloud/plugin/lossless/SpringCloudLosslessActionProvider.java create mode 100644 spring-cloud-tencent-plugin-starters/spring-cloud-tencent-lossless-plugin/src/main/java/com/tencent/cloud/plugin/lossless/config/LosslessAutoConfiguration.java create mode 100644 spring-cloud-tencent-plugin-starters/spring-cloud-tencent-lossless-plugin/src/main/java/com/tencent/cloud/plugin/lossless/config/LosslessConfigModifier.java create mode 100644 spring-cloud-tencent-plugin-starters/spring-cloud-tencent-lossless-plugin/src/main/java/com/tencent/cloud/plugin/lossless/config/LosslessProperties.java create mode 100644 spring-cloud-tencent-plugin-starters/spring-cloud-tencent-lossless-plugin/src/main/java/com/tencent/cloud/plugin/lossless/config/LosslessPropertiesAutoConfiguration.java create mode 100644 spring-cloud-tencent-plugin-starters/spring-cloud-tencent-lossless-plugin/src/main/java/com/tencent/cloud/plugin/lossless/config/LosslessPropertiesBootstrapConfiguration.java create mode 100644 spring-cloud-tencent-plugin-starters/spring-cloud-tencent-lossless-plugin/src/main/resources/META-INF/additional-spring-configuration-metadata.json create mode 100644 spring-cloud-tencent-plugin-starters/spring-cloud-tencent-lossless-plugin/src/main/resources/META-INF/spring.factories create mode 100644 spring-cloud-tencent-plugin-starters/spring-cloud-tencent-lossless-plugin/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports create mode 100644 spring-cloud-tencent-plugin-starters/spring-cloud-tencent-lossless-plugin/src/test/java/com/tencent/cloud/plugin/lossless/LosslessConfigModifierTest.java create mode 100644 spring-cloud-tencent-plugin-starters/spring-cloud-tencent-lossless-plugin/src/test/java/com/tencent/cloud/plugin/lossless/LosslessPropertiesTest.java create mode 100644 spring-cloud-tencent-plugin-starters/spring-cloud-tencent-lossless-plugin/src/test/java/com/tencent/cloud/plugin/lossless/LosslessRegistryAspectTest.java create mode 100644 spring-cloud-tencent-plugin-starters/spring-cloud-tencent-lossless-plugin/src/test/java/org/springframework/cloud/client/serviceregistry/AutoServiceRegistrationUtils.java create mode 100644 spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/transformer/PolarisRegistrationTransformer.java create mode 100644 spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/transformer/RegistrationTransformer.java diff --git a/CHANGELOG.md b/CHANGELOG.md index 8ec260317..d5599378a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,3 +5,4 @@ - [fix:fix ApplicationContextAwareUtils NPE bug.](https://github.com/Tencent/spring-cloud-tencent/pull/1296) - [feat:upgrade jacoco version.](https://github.com/Tencent/spring-cloud-tencent/pull/1307) - [fix: fix RouterLabelRestTemplateInterceptor add response headers exception with httpclient5.](https://github.com/Tencent/spring-cloud-tencent/pull/1376) +- [feat: support lossless online and offline](https://github.com/Tencent/spring-cloud-tencent/pull/1377) diff --git a/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/registry/PolarisServiceRegistry.java b/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/registry/PolarisServiceRegistry.java index ebc16be98..43aeaa8c7 100644 --- a/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/registry/PolarisServiceRegistry.java +++ b/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/registry/PolarisServiceRegistry.java @@ -25,10 +25,10 @@ import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import com.tencent.cloud.common.metadata.StaticMetadataManager; +import com.tencent.cloud.common.util.OkHttpUtil; import com.tencent.cloud.polaris.PolarisDiscoveryProperties; import com.tencent.cloud.polaris.context.PolarisSDKContextManager; import com.tencent.cloud.polaris.discovery.PolarisDiscoveryHandler; -import com.tencent.cloud.polaris.util.OkHttpUtil; import com.tencent.cloud.rpc.enhancement.stat.config.PolarisStatProperties; import com.tencent.polaris.api.config.global.StatReporterConfig; import com.tencent.polaris.api.core.ProviderAPI; @@ -176,7 +176,7 @@ public class PolarisServiceRegistry implements ServiceRegistry<PolarisRegistrati public void deregister(PolarisRegistration registration) { LOGGER.info("De-registering from Polaris Server now..."); - if (StringUtils.isEmpty(registration.getServiceId())) { + if (StringUtils.isEmpty(registration.getServiceId()) || !PolarisSDKContextManager.isRegistered) { LOGGER.warn("No dom to de-register for polaris client..."); return; } @@ -191,6 +191,8 @@ public class PolarisServiceRegistry implements ServiceRegistry<PolarisRegistrati try { ProviderAPI providerClient = polarisSDKContextManager.getProviderAPI(); providerClient.deRegister(deRegisterRequest); + PolarisSDKContextManager.isRegistered = false; + LOGGER.info("De-registration finished."); } catch (Exception e) { LOGGER.error("ERR_POLARIS_DEREGISTER, de-register failed...{},", registration, e); @@ -199,8 +201,6 @@ public class PolarisServiceRegistry implements ServiceRegistry<PolarisRegistrati if (null != heartbeatExecutor) { heartbeatExecutor.shutdown(); } - LOGGER.info("De-registration finished."); - PolarisSDKContextManager.isRegistered = false; } } @@ -238,21 +238,14 @@ public class PolarisServiceRegistry implements ServiceRegistry<PolarisRegistrati public void heartbeat(InstanceHeartbeatRequest heartbeatRequest) { heartbeatExecutor.scheduleWithFixedDelay(() -> { try { - String healthCheckEndpoint = polarisDiscoveryProperties.getHealthCheckUrl(); // If the health check passes, the heartbeat will be reported. // If it does not pass, the heartbeat will not be reported. - if (!healthCheckEndpoint.startsWith("/")) { - healthCheckEndpoint = "/" + healthCheckEndpoint; - } - - String healthCheckUrl = String.format("http://%s:%s%s", heartbeatRequest.getHost(), - heartbeatRequest.getPort(), healthCheckEndpoint); - Map<String, String> headers = new HashMap<>(1); headers.put(HttpHeaders.USER_AGENT, "polaris"); - if (!OkHttpUtil.get(healthCheckUrl, headers)) { + if (!OkHttpUtil.checkUrl(heartbeatRequest.getHost(), heartbeatRequest.getPort(), + polarisDiscoveryProperties.getHealthCheckUrl(), headers)) { LOGGER.error("backend service health check failed. health check endpoint = {}", - healthCheckEndpoint); + polarisDiscoveryProperties.getHealthCheckUrl()); return; } diff --git a/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/constant/OrderConstant.java b/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/constant/OrderConstant.java index ac7aa169f..ee0d8e763 100644 --- a/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/constant/OrderConstant.java +++ b/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/constant/OrderConstant.java @@ -172,6 +172,11 @@ public class OrderConstant { */ public static Integer STAT_REPORTER_ORDER = 1; + /** + * Order of lossless configuration modifier. + */ + public static Integer LOSSLESS_ORDER = 2; + /** * Order of service contract configuration modifier. */ diff --git a/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/util/OkHttpUtil.java b/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/util/OkHttpUtil.java similarity index 88% rename from spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/util/OkHttpUtil.java rename to spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/util/OkHttpUtil.java index f8580ee19..e34d79f56 100644 --- a/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/util/OkHttpUtil.java +++ b/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/util/OkHttpUtil.java @@ -15,7 +15,7 @@ * specific language governing permissions and limitations under the License. */ -package com.tencent.cloud.polaris.util; +package com.tencent.cloud.common.util; import java.io.BufferedReader; import java.io.InputStreamReader; @@ -87,4 +87,12 @@ public final class OkHttpUtil { } return false; } + + public static boolean checkUrl(String host, Integer port, String endpoint, Map<String, String> headers) { + if (!endpoint.startsWith("/")) { + endpoint = "/" + endpoint; + } + String checkUrl = String.format("http://%s:%s%s", host, port, endpoint); + return get(checkUrl, headers); + } } diff --git a/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/util/UrlUtils.java b/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/util/UrlUtils.java new file mode 100644 index 000000000..6190f33c4 --- /dev/null +++ b/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/util/UrlUtils.java @@ -0,0 +1,78 @@ +/* + * 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.io.UnsupportedEncodingException; +import java.net.URLDecoder; +import java.net.URLEncoder; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import org.springframework.util.StringUtils; + +import static com.tencent.cloud.common.constant.ContextConstant.UTF_8; + +/** + * Utils for URLDecoder/URLEncoder. + * + * @author Shedfree Wu + */ +public final class UrlUtils { + + private static final Logger LOG = LoggerFactory.getLogger(UrlUtils.class); + + private UrlUtils() { + } + + public static String decode(String s) { + return decode(s, UTF_8); + } + + public static String decode(String s, String enc) { + if (!StringUtils.hasText(s)) { + return s; + } + try { + return URLDecoder.decode(s, enc); + } + catch (UnsupportedEncodingException e) { + LOG.warn("Runtime system does not support {} coding. s:{}, msg:{}", enc, s, e.getMessage()); + // return original string + return s; + } + } + + public static String encode(String s) { + return encode(s, UTF_8); + } + + public static String encode(String s, String enc) { + if (!StringUtils.hasText(s)) { + return s; + } + try { + return URLEncoder.encode(s, enc); + } + catch (UnsupportedEncodingException e) { + LOG.warn("Runtime system does not support {} coding. s:{}, msg:{}", enc, s, e.getMessage()); + // return original string + return s; + } + } +} diff --git a/spring-cloud-starter-tencent-polaris-discovery/src/test/java/com/tencent/cloud/polaris/util/OkHttpUtilTest.java b/spring-cloud-tencent-commons/src/test/java/com/tencent/cloud/common/util/OkHttpUtilTest.java similarity index 82% rename from spring-cloud-starter-tencent-polaris-discovery/src/test/java/com/tencent/cloud/polaris/util/OkHttpUtilTest.java rename to spring-cloud-tencent-commons/src/test/java/com/tencent/cloud/common/util/OkHttpUtilTest.java index b718e88e9..2e250e3d8 100644 --- a/spring-cloud-starter-tencent-polaris-discovery/src/test/java/com/tencent/cloud/polaris/util/OkHttpUtilTest.java +++ b/spring-cloud-tencent-commons/src/test/java/com/tencent/cloud/common/util/OkHttpUtilTest.java @@ -15,7 +15,7 @@ * specific language governing permissions and limitations under the License. */ -package com.tencent.cloud.polaris.util; +package com.tencent.cloud.common.util; import org.assertj.core.util.Maps; import org.junit.jupiter.api.Test; @@ -37,7 +37,13 @@ import static org.assertj.core.api.Assertions.assertThat; * @author Haotian Zhang */ @ExtendWith(SpringExtension.class) -@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = OkHttpUtilTest.TestApplication.class, properties = {"spring.application.name=test", "spring.cloud.polaris.discovery.register=false"}) +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, + classes = OkHttpUtilTest.TestApplication.class, + properties = { + "spring.application.name=test", + "spring.cloud.polaris.discovery.register=false", + "spring.cloud.gateway.enabled=false" + }) public class OkHttpUtilTest { @LocalServerPort @@ -46,6 +52,8 @@ public class OkHttpUtilTest { @Test public void testGet() { assertThat(OkHttpUtil.get("http://localhost:" + port + "/test", Maps.newHashMap("key", "value"))).isTrue(); + assertThat(OkHttpUtil.checkUrl("localhost", port, "/test", Maps.newHashMap("key", "value"))).isTrue(); + assertThat(OkHttpUtil.checkUrl("localhost", port, "test", Maps.newHashMap("key", "value"))).isTrue(); assertThat(OkHttpUtil.get("http://localhost:" + port + "/error", Maps.newHashMap("key", "value"))).isFalse(); assertThat(OkHttpUtil.get("http://localhost:55555/error", Maps.newHashMap("key", "value"))).isFalse(); } diff --git a/spring-cloud-tencent-commons/src/test/java/com/tencent/cloud/common/util/UrlUtilsTest.java b/spring-cloud-tencent-commons/src/test/java/com/tencent/cloud/common/util/UrlUtilsTest.java new file mode 100644 index 000000000..3d77d047c --- /dev/null +++ b/spring-cloud-tencent-commons/src/test/java/com/tencent/cloud/common/util/UrlUtilsTest.java @@ -0,0 +1,68 @@ +/* + * 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 org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Utils for {@link UrlUtils}. + * + * @author Shedfree Wu + */ +public class UrlUtilsTest { + + @Test + public void testEncodeDecode1() { + String expectEncodeValue = "a%2Fb"; + String origin = "a/b"; + String encode1 = UrlUtils.encode(origin); + assertThat(expectEncodeValue).isEqualTo(encode1); + // encode twice is different + String encode2 = UrlUtils.encode(encode1); + assertThat(encode1).isNotEqualTo(encode2); + // test decode + assertThat(origin).isEqualTo(UrlUtils.decode(encode1)); + } + + @Test + public void testEncodeDecode2() { + + String origin = null; + String encode1 = UrlUtils.encode(origin); + assertThat(encode1).isNull(); + + origin = ""; + encode1 = UrlUtils.encode(origin); + assertThat(encode1).isEqualTo(origin); + } + + @Test + public void testError() { + String origin = "a/b"; + String encode = UrlUtils.encode(origin, "error-enc"); + assertThat(encode).isEqualTo(origin); + + encode = "a%2Fb"; + String decode = UrlUtils.decode(encode, "error-enc"); + assertThat(decode).isEqualTo(encode); + } + +} diff --git a/spring-cloud-tencent-coverage/pom.xml b/spring-cloud-tencent-coverage/pom.xml index 15aef4a4e..8481f826b 100644 --- a/spring-cloud-tencent-coverage/pom.xml +++ b/spring-cloud-tencent-coverage/pom.xml @@ -83,6 +83,11 @@ <groupId>com.tencent.cloud</groupId> <artifactId>spring-cloud-tencent-gateway-plugin</artifactId> </dependency> + + <dependency> + <groupId>com.tencent.cloud</groupId> + <artifactId>spring-cloud-tencent-lossless-plugin</artifactId> + </dependency> </dependencies> <build> diff --git a/spring-cloud-tencent-dependencies/pom.xml b/spring-cloud-tencent-dependencies/pom.xml index ee0e5588e..968400e35 100644 --- a/spring-cloud-tencent-dependencies/pom.xml +++ b/spring-cloud-tencent-dependencies/pom.xml @@ -190,6 +190,12 @@ <version>${revision}</version> </dependency> + <dependency> + <groupId>com.tencent.cloud</groupId> + <artifactId>spring-cloud-tencent-lossless-plugin</artifactId> + <version>${revision}</version> + </dependency> + <!-- third part framework dependencies --> <dependency> <groupId>com.google.guava</groupId> diff --git a/spring-cloud-tencent-examples/lossless-example/lossless-callee-service/pom.xml b/spring-cloud-tencent-examples/lossless-example/lossless-callee-service/pom.xml new file mode 100644 index 000000000..9117a7314 --- /dev/null +++ b/spring-cloud-tencent-examples/lossless-example/lossless-callee-service/pom.xml @@ -0,0 +1,63 @@ +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <artifactId>lossless-example</artifactId> + <groupId>com.tencent.cloud</groupId> + <version>${revision}</version> + <relativePath>../pom.xml</relativePath> + </parent> + <artifactId>lossless-callee-service</artifactId> + <name>Spring Cloud Starter Tencent Lossless Callee Service Example</name> + + <dependencies> + <dependency> + <groupId>com.tencent.cloud</groupId> + <artifactId>spring-cloud-starter-tencent-all</artifactId> + </dependency> + + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-webflux</artifactId> + </dependency> + + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-actuator</artifactId> + </dependency> + + <dependency> + <groupId>com.tencent.cloud</groupId> + <artifactId>spring-cloud-tencent-lossless-plugin</artifactId> + </dependency> + </dependencies> + + <build> + <plugins> + <plugin> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-maven-plugin</artifactId> + <executions> + <execution> + <goals> + <goal>repackage</goal> + </goals> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-source-plugin</artifactId> + <version>3.2.0</version> + <executions> + <execution> + <id>attach-sources</id> + <goals> + <goal>jar</goal> + </goals> + </execution> + </executions> + </plugin> + </plugins> + </build> +</project> diff --git a/spring-cloud-tencent-examples/lossless-example/lossless-callee-service/src/main/java/com/tencent/cloud/lossless/callee/LosslessCalleeController.java b/spring-cloud-tencent-examples/lossless-example/lossless-callee-service/src/main/java/com/tencent/cloud/lossless/callee/LosslessCalleeController.java new file mode 100644 index 000000000..ec7347c91 --- /dev/null +++ b/spring-cloud-tencent-examples/lossless-example/lossless-callee-service/src/main/java/com/tencent/cloud/lossless/callee/LosslessCalleeController.java @@ -0,0 +1,95 @@ +/* + * 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.lossless.callee; + +import java.io.UnsupportedEncodingException; +import java.net.URLDecoder; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; + +import com.tencent.cloud.common.constant.MetadataConstant; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import static com.tencent.cloud.common.constant.ContextConstant.UTF_8; + +@RestController +@RequestMapping("/lossless/callee") +public class LosslessCalleeController { + + private static final Logger LOG = LoggerFactory.getLogger(LosslessCalleeController.class); + + @Value("${lossless.healthy.delay.second:0}") + private int healthyDelay; + + private final AtomicBoolean calledHealthyEndpoint = new AtomicBoolean(false); + + private final AtomicInteger healthy = new AtomicInteger(0); + + @GetMapping("/health") + public ResponseEntity<String> health() { + if (healthy.get() == 1) { + return new ResponseEntity<>("OK", HttpStatus.OK); + } + else { + if (calledHealthyEndpoint.compareAndSet(false, true)) { + Thread thread = new Thread(new Runnable() { + @Override + public void run() { + if (healthyDelay > 0) { + try { + Thread.sleep(healthyDelay * 1000L); + } + catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + healthy.set(1); + } + }); + thread.start(); + } + return new ResponseEntity<>("NOK", HttpStatus.SERVICE_UNAVAILABLE); + } + } + + /** + * Get metadata in HTTP query. + * + * @param metadataStr metadata string + * @return metadata in HTTP header + * @throws UnsupportedEncodingException encoding exception + */ + @RequestMapping("/echo") + public String echoHeader(@RequestHeader(MetadataConstant.HeaderName.CUSTOM_METADATA) String metadataStr) + throws UnsupportedEncodingException { + LOG.info(URLDecoder.decode(metadataStr, UTF_8)); + metadataStr = URLDecoder.decode(metadataStr, UTF_8); + return metadataStr; + } + +} diff --git a/spring-cloud-tencent-examples/lossless-example/lossless-callee-service/src/main/java/com/tencent/cloud/lossless/callee/LosslessCalleeService.java b/spring-cloud-tencent-examples/lossless-example/lossless-callee-service/src/main/java/com/tencent/cloud/lossless/callee/LosslessCalleeService.java new file mode 100644 index 000000000..542653ba0 --- /dev/null +++ b/spring-cloud-tencent-examples/lossless-example/lossless-callee-service/src/main/java/com/tencent/cloud/lossless/callee/LosslessCalleeService.java @@ -0,0 +1,29 @@ +/* + * 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.lossless.callee; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class LosslessCalleeService { + public static void main(String[] args) { + SpringApplication.run(LosslessCalleeService.class, args); + } +} diff --git a/spring-cloud-tencent-examples/lossless-example/lossless-callee-service/src/main/resources/bootstrap.yml b/spring-cloud-tencent-examples/lossless-example/lossless-callee-service/src/main/resources/bootstrap.yml new file mode 100644 index 000000000..cdd07b831 --- /dev/null +++ b/spring-cloud-tencent-examples/lossless-example/lossless-callee-service/src/main/resources/bootstrap.yml @@ -0,0 +1,36 @@ +server: + port: 48090 +spring: + application: + name: LosslessCalleeService + cloud: + polaris: + address: grpc://119.91.66.223:8091 + namespace: default + enabled: true + discovery: + enabled: true + register: true + contract: + exposure: true + report: + enabled: true + stat: + enabled: true + port: 28084 + lossless: + enabled: true + healthCheckPath: /lossless/callee/health + healthCheckInterval: 5000 +lossless: + healthy: + delay: + second: 20 +management: + endpoints: + web: + exposure: + include: + - polaris-discovery + - polaris-ratelimit + - polaris-config \ No newline at end of file diff --git a/spring-cloud-tencent-examples/lossless-example/lossless-nacos-callee-service/pom.xml b/spring-cloud-tencent-examples/lossless-example/lossless-nacos-callee-service/pom.xml new file mode 100644 index 000000000..2be4b3bc1 --- /dev/null +++ b/spring-cloud-tencent-examples/lossless-example/lossless-nacos-callee-service/pom.xml @@ -0,0 +1,69 @@ +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <artifactId>lossless-example</artifactId> + <groupId>com.tencent.cloud</groupId> + <version>${revision}</version> + <relativePath>../pom.xml</relativePath> + </parent> + <groupId>com.tencent.polaris</groupId> + <artifactId>lossless-nacos-callee-service</artifactId> + <name>Spring Cloud Starter Tencent Lossless Nacos Callee Service Example</name> + + <dependencies> + <dependency> + <groupId>com.alibaba.cloud</groupId> + <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> + <version>2023.0.0.0-RC1</version> + </dependency> + + <dependency> + <groupId>com.tencent.cloud</groupId> + <artifactId>spring-cloud-starter-tencent-discovery-adapter-plugin</artifactId> + </dependency> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-webflux</artifactId> + </dependency> + + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-actuator</artifactId> + </dependency> + + <dependency> + <groupId>com.tencent.cloud</groupId> + <artifactId>spring-cloud-tencent-lossless-plugin</artifactId> + </dependency> + </dependencies> + + <build> + <plugins> + <plugin> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-maven-plugin</artifactId> + <executions> + <execution> + <goals> + <goal>repackage</goal> + </goals> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-source-plugin</artifactId> + <version>3.2.0</version> + <executions> + <execution> + <id>attach-sources</id> + <goals> + <goal>jar</goal> + </goals> + </execution> + </executions> + </plugin> + </plugins> + </build> +</project> diff --git a/spring-cloud-tencent-examples/lossless-example/lossless-nacos-callee-service/src/main/java/com/tencent/cloud/lossless/nacos/callee/LosslessNacosCalleeController.java b/spring-cloud-tencent-examples/lossless-example/lossless-nacos-callee-service/src/main/java/com/tencent/cloud/lossless/nacos/callee/LosslessNacosCalleeController.java new file mode 100644 index 000000000..ea96f64b3 --- /dev/null +++ b/spring-cloud-tencent-examples/lossless-example/lossless-nacos-callee-service/src/main/java/com/tencent/cloud/lossless/nacos/callee/LosslessNacosCalleeController.java @@ -0,0 +1,95 @@ +/* + * 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.lossless.nacos.callee; + +import java.io.UnsupportedEncodingException; +import java.net.URLDecoder; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; + +import com.tencent.cloud.common.constant.MetadataConstant; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import static com.tencent.cloud.common.constant.ContextConstant.UTF_8; + +@RestController +@RequestMapping("/lossless/nacos/callee") +public class LosslessNacosCalleeController { + + private static final Logger LOG = LoggerFactory.getLogger(LosslessNacosCalleeController.class); + + @Value("${lossless.healthy.delay.second:0}") + private int healthyDelay; + + private final AtomicBoolean calledHealthyEndpoint = new AtomicBoolean(false); + + private final AtomicInteger healthy = new AtomicInteger(0); + + @GetMapping("/health") + public ResponseEntity<String> health() { + if (healthy.get() == 1) { + return new ResponseEntity<>("OK", HttpStatus.OK); + } + else { + if (calledHealthyEndpoint.compareAndSet(false, true)) { + Thread thread = new Thread(new Runnable() { + @Override + public void run() { + if (healthyDelay > 0) { + try { + Thread.sleep(healthyDelay * 1000L); + } + catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + healthy.set(1); + } + }); + thread.start(); + } + return new ResponseEntity<>("NOK", HttpStatus.SERVICE_UNAVAILABLE); + } + } + + /** + * Get metadata in HTTP query. + * + * @param metadataStr metadata string + * @return metadata in HTTP header + * @throws UnsupportedEncodingException encoding exception + */ + @RequestMapping("/echo") + public String echoHeader(@RequestHeader(MetadataConstant.HeaderName.CUSTOM_METADATA) String metadataStr) + throws UnsupportedEncodingException { + LOG.info(URLDecoder.decode(metadataStr, UTF_8)); + metadataStr = URLDecoder.decode(metadataStr, UTF_8); + return metadataStr; + } + +} diff --git a/spring-cloud-tencent-examples/lossless-example/lossless-nacos-callee-service/src/main/java/com/tencent/cloud/lossless/nacos/callee/LosslessNacosCalleeService.java b/spring-cloud-tencent-examples/lossless-example/lossless-nacos-callee-service/src/main/java/com/tencent/cloud/lossless/nacos/callee/LosslessNacosCalleeService.java new file mode 100644 index 000000000..a2d29436a --- /dev/null +++ b/spring-cloud-tencent-examples/lossless-example/lossless-nacos-callee-service/src/main/java/com/tencent/cloud/lossless/nacos/callee/LosslessNacosCalleeService.java @@ -0,0 +1,31 @@ +/* + * 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.lossless.nacos.callee; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class LosslessNacosCalleeService { + + public static void main(String[] args) { + SpringApplication.run(LosslessNacosCalleeService.class, args); + } + +} diff --git a/spring-cloud-tencent-examples/lossless-example/lossless-nacos-callee-service/src/main/resources/bootstrap.yml b/spring-cloud-tencent-examples/lossless-example/lossless-nacos-callee-service/src/main/resources/bootstrap.yml new file mode 100644 index 000000000..1487942e9 --- /dev/null +++ b/spring-cloud-tencent-examples/lossless-example/lossless-nacos-callee-service/src/main/resources/bootstrap.yml @@ -0,0 +1,28 @@ +server: + port: 48091 +spring: + application: + name: LosslessNacosCalleeService + cloud: + nacos: + discovery: + server-addr: 9.134.5.52:8848 + enabled: true + namespace: "test1" + polaris: + lossless: + enabled: true + healthCheckPath: /lossless/nacos/callee/health + healthCheckInterval: 5000 +lossless: + healthy: + delay: + second: 20 +management: + endpoints: + web: + exposure: + include: + - polaris-discovery + - polaris-ratelimit + - polaris-config \ No newline at end of file diff --git a/spring-cloud-tencent-examples/lossless-example/pom.xml b/spring-cloud-tencent-examples/lossless-example/pom.xml new file mode 100644 index 000000000..ddd10b8a6 --- /dev/null +++ b/spring-cloud-tencent-examples/lossless-example/pom.xml @@ -0,0 +1,25 @@ +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <parent> + <artifactId>spring-cloud-tencent-examples</artifactId> + <groupId>com.tencent.cloud</groupId> + <version>${revision}</version> + <relativePath>../pom.xml</relativePath> + </parent> + <modules> + <module>lossless-callee-service</module> + <module>lossless-nacos-callee-service</module> + </modules> + <modelVersion>4.0.0</modelVersion> + + <artifactId>lossless-example</artifactId> + <packaging>pom</packaging> + <name>Spring Cloud Starter Tencent Lossless Example</name> + + <dependencies> + <dependency> + <groupId>org.springframework.cloud</groupId> + <artifactId>spring-cloud-starter-bootstrap</artifactId> + </dependency> + </dependencies> +</project> diff --git a/spring-cloud-tencent-examples/pom.xml b/spring-cloud-tencent-examples/pom.xml index c7e0c5a94..c1747dd44 100644 --- a/spring-cloud-tencent-examples/pom.xml +++ b/spring-cloud-tencent-examples/pom.xml @@ -21,6 +21,7 @@ <module>polaris-router-grayrelease-example</module> <module>polaris-router-featureenv-example</module> <module>quickstart-example</module> + <module>lossless-example</module> </modules> <properties> diff --git a/spring-cloud-tencent-plugin-starters/pom.xml b/spring-cloud-tencent-plugin-starters/pom.xml index bc2f153b9..0258ceeea 100644 --- a/spring-cloud-tencent-plugin-starters/pom.xml +++ b/spring-cloud-tencent-plugin-starters/pom.xml @@ -18,6 +18,7 @@ <module>spring-cloud-tencent-featureenv-plugin</module> <module>spring-cloud-tencent-gateway-plugin</module> <module>spring-cloud-starter-tencent-discovery-adapter-plugin</module> + <module>spring-cloud-tencent-lossless-plugin</module> </modules> </project> diff --git a/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-discovery-adapter-plugin/pom.xml b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-discovery-adapter-plugin/pom.xml index d33b5dd57..4d5a1b3f4 100644 --- a/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-discovery-adapter-plugin/pom.xml +++ b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-discovery-adapter-plugin/pom.xml @@ -24,7 +24,7 @@ <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> <version>2021.1</version> - <scope>test</scope> + <optional>true</optional> </dependency> <dependency> diff --git a/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-discovery-adapter-plugin/src/main/java/com/tencent/cloud/plugin/discovery/adapter/config/NacosDiscoveryAdapterAutoConfiguration.java b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-discovery-adapter-plugin/src/main/java/com/tencent/cloud/plugin/discovery/adapter/config/NacosDiscoveryAdapterAutoConfiguration.java index 594ba0976..6e9474c47 100644 --- a/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-discovery-adapter-plugin/src/main/java/com/tencent/cloud/plugin/discovery/adapter/config/NacosDiscoveryAdapterAutoConfiguration.java +++ b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-discovery-adapter-plugin/src/main/java/com/tencent/cloud/plugin/discovery/adapter/config/NacosDiscoveryAdapterAutoConfiguration.java @@ -19,8 +19,10 @@ package com.tencent.cloud.plugin.discovery.adapter.config; import com.tencent.cloud.plugin.discovery.adapter.transformer.NacosInstanceTransformer; +import com.tencent.cloud.plugin.discovery.adapter.transformer.NacosRegistrationTransformer; import com.tencent.cloud.polaris.router.config.LoadBalancerConfiguration; import com.tencent.cloud.rpc.enhancement.transformer.InstanceTransformer; +import com.tencent.cloud.rpc.enhancement.transformer.RegistrationTransformer; import org.springframework.boot.autoconfigure.AutoConfigureBefore; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; @@ -47,4 +49,11 @@ public class NacosDiscoveryAdapterAutoConfiguration { return new NacosInstanceTransformer(); } + @Bean + @ConditionalOnMissingBean + @ConditionalOnClass(name = "com.alibaba.cloud.nacos.registry.NacosRegistration") + public RegistrationTransformer registrationTransformer() { + return new NacosRegistrationTransformer(); + } + } diff --git a/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-discovery-adapter-plugin/src/main/java/com/tencent/cloud/plugin/discovery/adapter/transformer/NacosInstanceTransformer.java b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-discovery-adapter-plugin/src/main/java/com/tencent/cloud/plugin/discovery/adapter/transformer/NacosInstanceTransformer.java index 2959e86df..7bb90d194 100644 --- a/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-discovery-adapter-plugin/src/main/java/com/tencent/cloud/plugin/discovery/adapter/transformer/NacosInstanceTransformer.java +++ b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-discovery-adapter-plugin/src/main/java/com/tencent/cloud/plugin/discovery/adapter/transformer/NacosInstanceTransformer.java @@ -44,6 +44,7 @@ public class NacosInstanceTransformer implements InstanceTransformer { ); String nacosInstanceId = serviceInstance.getMetadata().get("nacos.instanceId"); instance.setId(nacosInstanceId); + } } diff --git a/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-discovery-adapter-plugin/src/main/java/com/tencent/cloud/plugin/discovery/adapter/transformer/NacosRegistrationTransformer.java b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-discovery-adapter-plugin/src/main/java/com/tencent/cloud/plugin/discovery/adapter/transformer/NacosRegistrationTransformer.java new file mode 100644 index 000000000..c90d2b388 --- /dev/null +++ b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-discovery-adapter-plugin/src/main/java/com/tencent/cloud/plugin/discovery/adapter/transformer/NacosRegistrationTransformer.java @@ -0,0 +1,43 @@ +/* + * 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.plugin.discovery.adapter.transformer; + +import com.alibaba.cloud.nacos.NacosDiscoveryProperties; +import com.alibaba.cloud.nacos.registry.NacosRegistration; +import com.tencent.cloud.rpc.enhancement.transformer.RegistrationTransformer; +import com.tencent.polaris.api.pojo.DefaultInstance; +import com.tencent.polaris.api.utils.StringUtils; + +import org.springframework.cloud.client.serviceregistry.Registration; + +public class NacosRegistrationTransformer implements RegistrationTransformer { + + @Override + public void transformCustom(DefaultInstance instance, Registration registration) { + if (registration instanceof NacosRegistration) { + NacosDiscoveryProperties nacosDiscoveryProperties = ((NacosRegistration) registration).getNacosDiscoveryProperties(); + String namespace = nacosDiscoveryProperties.getNamespace(); + if (StringUtils.isBlank(namespace)) { + namespace = "default"; + } + instance.setNamespace(namespace); + } + } + +} diff --git a/spring-cloud-tencent-plugin-starters/spring-cloud-tencent-lossless-plugin/pom.xml b/spring-cloud-tencent-plugin-starters/spring-cloud-tencent-lossless-plugin/pom.xml new file mode 100644 index 000000000..59a313be9 --- /dev/null +++ b/spring-cloud-tencent-plugin-starters/spring-cloud-tencent-lossless-plugin/pom.xml @@ -0,0 +1,75 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <parent> + <artifactId>spring-cloud-tencent-plugin-starters</artifactId> + <groupId>com.tencent.cloud</groupId> + <version>${revision}</version> + <relativePath>../pom.xml</relativePath> + </parent> + <modelVersion>4.0.0</modelVersion> + + <artifactId>spring-cloud-tencent-lossless-plugin</artifactId> + <name>Spring Cloud Tencent Lossless Plugin</name> + + + <dependencies> + <dependency> + <groupId>com.tencent.cloud</groupId> + <artifactId>spring-cloud-tencent-polaris-context</artifactId> + </dependency> + + <dependency> + <groupId>com.tencent.cloud</groupId> + <artifactId>spring-cloud-tencent-commons</artifactId> + </dependency> + + <dependency> + <groupId>com.tencent.polaris</groupId> + <artifactId>lossless-register</artifactId> + </dependency> + + <dependency> + <groupId>com.tencent.polaris</groupId> + <artifactId>lossless-deregister</artifactId> + </dependency> + + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-aop</artifactId> + </dependency> + + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-test</artifactId> + <scope>test</scope> + </dependency> + + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-web</artifactId> + <scope>test</scope> + </dependency> + + <dependency> + <groupId>com.tencent.cloud</groupId> + <artifactId>spring-cloud-starter-tencent-polaris-discovery</artifactId> + <optional>true</optional> + </dependency> + + <dependency> + <groupId>com.tencent.polaris</groupId> + <artifactId>polaris-test-mock-discovery</artifactId> + <scope>test</scope> + <exclusions> + <exclusion> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + </exclusion> + </exclusions> + </dependency> + + </dependencies> + +</project> diff --git a/spring-cloud-tencent-plugin-starters/spring-cloud-tencent-lossless-plugin/src/main/java/com/tencent/cloud/plugin/lossless/LosslessRegistryAspect.java b/spring-cloud-tencent-plugin-starters/spring-cloud-tencent-lossless-plugin/src/main/java/com/tencent/cloud/plugin/lossless/LosslessRegistryAspect.java new file mode 100644 index 000000000..c9af94576 --- /dev/null +++ b/spring-cloud-tencent-plugin-starters/spring-cloud-tencent-lossless-plugin/src/main/java/com/tencent/cloud/plugin/lossless/LosslessRegistryAspect.java @@ -0,0 +1,104 @@ +/* + * 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.plugin.lossless; + +import com.tencent.cloud.plugin.lossless.config.LosslessProperties; +import com.tencent.cloud.polaris.context.PolarisSDKContextManager; +import com.tencent.cloud.polaris.context.config.PolarisContextProperties; +import com.tencent.cloud.rpc.enhancement.transformer.RegistrationTransformer; +import com.tencent.polaris.api.pojo.BaseInstance; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; + +import org.springframework.cloud.client.serviceregistry.Registration; +import org.springframework.cloud.client.serviceregistry.ServiceRegistry; + +/** + * Intercept for of register and deregister. + * + * @author Shedfree Wu + */ +@Aspect +public class LosslessRegistryAspect { + + private ServiceRegistry<Registration> serviceRegistry; + + private Registration registration; + + private LosslessProperties losslessProperties; + + private PolarisSDKContextManager polarisSDKContextManager; + + private RegistrationTransformer registrationTransformer; + + private PolarisContextProperties properties; + + public LosslessRegistryAspect(ServiceRegistry<Registration> serviceRegistry, Registration registration, + PolarisContextProperties properties, LosslessProperties losslessProperties, + PolarisSDKContextManager polarisSDKContextManager, RegistrationTransformer registrationTransformer) { + this.serviceRegistry = serviceRegistry; + this.registration = registration; + this.losslessProperties = losslessProperties; + this.polarisSDKContextManager = polarisSDKContextManager; + this.registrationTransformer = registrationTransformer; + this.properties = properties; + } + + @Pointcut("execution(public * org.springframework.cloud.client.serviceregistry.ServiceRegistry.register(..))") + public void registerPointcut() { + + } + + @Pointcut("execution(public * org.springframework.cloud.client.serviceregistry.ServiceRegistry.deregister(..))") + public void deregisterPointcut() { + + } + + @Around("registerPointcut()") + public Object invokeRegister(ProceedingJoinPoint joinPoint) throws Throwable { + + // web started, get port from registration + BaseInstance instance = SpringCloudLosslessActionProvider.getBaseInstance(registration, registrationTransformer); + + Runnable registerAction = () -> executeJoinPoint(joinPoint); + + SpringCloudLosslessActionProvider losslessActionProvider = + new SpringCloudLosslessActionProvider(serviceRegistry, registration, losslessProperties, registerAction); + + polarisSDKContextManager.getLosslessAPI().setLosslessActionProvider(instance, losslessActionProvider); + polarisSDKContextManager.getLosslessAPI().losslessRegister(instance); + // return void + return null; + } + + @Around("deregisterPointcut()") + public Object invokeDeregister(ProceedingJoinPoint joinPoint) throws Throwable { + return joinPoint.proceed(); + } + + public void executeJoinPoint(ProceedingJoinPoint joinPoint) { + try { + joinPoint.proceed(); + } + catch (Throwable e) { + throw new RuntimeException(e); + } + } +} diff --git a/spring-cloud-tencent-plugin-starters/spring-cloud-tencent-lossless-plugin/src/main/java/com/tencent/cloud/plugin/lossless/SpringCloudLosslessActionProvider.java b/spring-cloud-tencent-plugin-starters/spring-cloud-tencent-lossless-plugin/src/main/java/com/tencent/cloud/plugin/lossless/SpringCloudLosslessActionProvider.java new file mode 100644 index 000000000..a97df5960 --- /dev/null +++ b/spring-cloud-tencent-plugin-starters/spring-cloud-tencent-lossless-plugin/src/main/java/com/tencent/cloud/plugin/lossless/SpringCloudLosslessActionProvider.java @@ -0,0 +1,95 @@ +/* + * 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.plugin.lossless; + +import java.util.HashMap; +import java.util.Map; + +import com.tencent.cloud.common.util.OkHttpUtil; +import com.tencent.cloud.plugin.lossless.config.LosslessProperties; +import com.tencent.cloud.rpc.enhancement.transformer.RegistrationTransformer; +import com.tencent.polaris.api.plugin.lossless.InstanceProperties; +import com.tencent.polaris.api.plugin.lossless.LosslessActionProvider; +import com.tencent.polaris.api.pojo.BaseInstance; +import com.tencent.polaris.api.utils.StringUtils; + +import org.springframework.cloud.client.serviceregistry.Registration; +import org.springframework.cloud.client.serviceregistry.ServiceRegistry; +import org.springframework.http.HttpHeaders; + +/** + * LosslessActionProvider for Spring Cloud. + * + * @author Shedfree Wu + */ +public class SpringCloudLosslessActionProvider implements LosslessActionProvider { + private ServiceRegistry<Registration> serviceRegistry; + + private LosslessProperties losslessProperties; + + private Runnable originalRegisterAction; + + private Registration registration; + + public SpringCloudLosslessActionProvider(ServiceRegistry<Registration> serviceRegistry, Registration registration, + LosslessProperties losslessProperties, Runnable originalRegisterAction) { + this.serviceRegistry = serviceRegistry; + this.registration = registration; + this.losslessProperties = losslessProperties; + this.originalRegisterAction = originalRegisterAction; + } + + @Override + public String getName() { + return "spring-cloud"; + } + + @Override + public void doRegister(InstanceProperties instanceProperties) { + // use lambda to do original register + originalRegisterAction.run(); + } + + @Override + public void doDeregister() { + serviceRegistry.deregister(registration); + } + + /** + * Check whether health check is enable. + * @return true: register after passing doHealthCheck, false: register after delayRegisterInterval. + */ + @Override + public boolean isEnableHealthCheck() { + return StringUtils.isNotBlank(losslessProperties.getHealthCheckPath()); + } + + @Override + public boolean doHealthCheck() { + Map<String, String> headers = new HashMap<>(1); + headers.put(HttpHeaders.USER_AGENT, "polaris"); + + return OkHttpUtil.checkUrl("localhost", registration.getPort(), + losslessProperties.getHealthCheckPath(), headers); + } + + public static BaseInstance getBaseInstance(Registration registration, RegistrationTransformer registrationTransformer) { + return registrationTransformer.transform(registration); + } + +} diff --git a/spring-cloud-tencent-plugin-starters/spring-cloud-tencent-lossless-plugin/src/main/java/com/tencent/cloud/plugin/lossless/config/LosslessAutoConfiguration.java b/spring-cloud-tencent-plugin-starters/spring-cloud-tencent-lossless-plugin/src/main/java/com/tencent/cloud/plugin/lossless/config/LosslessAutoConfiguration.java new file mode 100644 index 000000000..8b2cffe49 --- /dev/null +++ b/spring-cloud-tencent-plugin-starters/spring-cloud-tencent-lossless-plugin/src/main/java/com/tencent/cloud/plugin/lossless/config/LosslessAutoConfiguration.java @@ -0,0 +1,54 @@ +/* + * 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.plugin.lossless.config; + +import com.tencent.cloud.plugin.lossless.LosslessRegistryAspect; +import com.tencent.cloud.polaris.context.ConditionalOnPolarisEnabled; +import com.tencent.cloud.polaris.context.PolarisSDKContextManager; +import com.tencent.cloud.polaris.context.config.PolarisContextProperties; +import com.tencent.cloud.rpc.enhancement.transformer.RegistrationTransformer; + +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.cloud.client.serviceregistry.Registration; +import org.springframework.cloud.client.serviceregistry.ServiceRegistry; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; + +/** + * Autoconfiguration of lossless. + * + * @author Shedfree Wu + */ +@Configuration(proxyBeanMethods = false) +@ConditionalOnPolarisEnabled +@Import(LosslessPropertiesAutoConfiguration.class) +public class LosslessAutoConfiguration { + + @Bean + @ConditionalOnMissingBean + public LosslessRegistryAspect losslessRegistryAspect( + ServiceRegistry serviceRegistry, Registration registration, PolarisContextProperties properties, + LosslessProperties losslessProperties, PolarisSDKContextManager polarisSDKContextManager, + RegistrationTransformer registrationTransformer) { + return new LosslessRegistryAspect(serviceRegistry, registration, properties, losslessProperties, + polarisSDKContextManager, registrationTransformer); + } + +} diff --git a/spring-cloud-tencent-plugin-starters/spring-cloud-tencent-lossless-plugin/src/main/java/com/tencent/cloud/plugin/lossless/config/LosslessConfigModifier.java b/spring-cloud-tencent-plugin-starters/spring-cloud-tencent-lossless-plugin/src/main/java/com/tencent/cloud/plugin/lossless/config/LosslessConfigModifier.java new file mode 100644 index 000000000..f5049df76 --- /dev/null +++ b/spring-cloud-tencent-plugin-starters/spring-cloud-tencent-lossless-plugin/src/main/java/com/tencent/cloud/plugin/lossless/config/LosslessConfigModifier.java @@ -0,0 +1,59 @@ +/* + * 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.plugin.lossless.config; + +import java.util.Objects; + +import com.tencent.cloud.common.constant.OrderConstant.Modifier; +import com.tencent.cloud.polaris.context.PolarisConfigModifier; +import com.tencent.polaris.factory.config.ConfigurationImpl; +import com.tencent.polaris.factory.config.provider.LosslessConfigImpl; + +/** + * Config modifier for lossless. + * + * @author Shedfree Wu + */ +public class LosslessConfigModifier implements PolarisConfigModifier { + + private final LosslessProperties losslessProperties; + + public LosslessConfigModifier(LosslessProperties losslessProperties) { + this.losslessProperties = losslessProperties; + } + + @Override + public void modify(ConfigurationImpl configuration) { + if (losslessProperties.isEnabled()) { + LosslessConfigImpl losslessConfig = (LosslessConfigImpl) configuration.getProvider().getLossless(); + losslessConfig.setEnable(true); + losslessConfig.setPort(losslessProperties.getPort()); + if (Objects.nonNull(losslessProperties.getDelayRegisterInterval())) { + losslessConfig.setDelayRegisterInterval(losslessProperties.getDelayRegisterInterval()); + } + if (Objects.nonNull(losslessProperties.getHealthCheckInterval())) { + losslessConfig.setHealthCheckInterval(losslessProperties.getHealthCheckInterval()); + } + } + } + + @Override + public int getOrder() { + return Modifier.LOSSLESS_ORDER; + } +} diff --git a/spring-cloud-tencent-plugin-starters/spring-cloud-tencent-lossless-plugin/src/main/java/com/tencent/cloud/plugin/lossless/config/LosslessProperties.java b/spring-cloud-tencent-plugin-starters/spring-cloud-tencent-lossless-plugin/src/main/java/com/tencent/cloud/plugin/lossless/config/LosslessProperties.java new file mode 100644 index 000000000..3f2960883 --- /dev/null +++ b/spring-cloud-tencent-plugin-starters/spring-cloud-tencent-lossless-plugin/src/main/java/com/tencent/cloud/plugin/lossless/config/LosslessProperties.java @@ -0,0 +1,75 @@ +/* + * 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.plugin.lossless.config; + +import org.springframework.boot.context.properties.ConfigurationProperties; + +@ConfigurationProperties("spring.cloud.polaris.lossless") +public class LosslessProperties { + + private boolean enabled = true; + + private int port = 28080; + + private String healthCheckPath; + + private Long delayRegisterInterval; + + private Long healthCheckInterval; + + public boolean isEnabled() { + return enabled; + } + + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } + + public int getPort() { + return port; + } + + public void setPort(int port) { + this.port = port; + } + + public String getHealthCheckPath() { + return healthCheckPath; + } + + public void setHealthCheckPath(String healthCheckPath) { + this.healthCheckPath = healthCheckPath; + } + + public Long getDelayRegisterInterval() { + return delayRegisterInterval; + } + + public void setDelayRegisterInterval(Long delayRegisterInterval) { + this.delayRegisterInterval = delayRegisterInterval; + } + + public Long getHealthCheckInterval() { + return healthCheckInterval; + } + + public void setHealthCheckInterval(Long healthCheckInterval) { + this.healthCheckInterval = healthCheckInterval; + } +} diff --git a/spring-cloud-tencent-plugin-starters/spring-cloud-tencent-lossless-plugin/src/main/java/com/tencent/cloud/plugin/lossless/config/LosslessPropertiesAutoConfiguration.java b/spring-cloud-tencent-plugin-starters/spring-cloud-tencent-lossless-plugin/src/main/java/com/tencent/cloud/plugin/lossless/config/LosslessPropertiesAutoConfiguration.java new file mode 100644 index 000000000..23826a37c --- /dev/null +++ b/spring-cloud-tencent-plugin-starters/spring-cloud-tencent-lossless-plugin/src/main/java/com/tencent/cloud/plugin/lossless/config/LosslessPropertiesAutoConfiguration.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.plugin.lossless.config; + +import com.tencent.cloud.polaris.context.ConditionalOnPolarisEnabled; + +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * Autoconfiguration of lossless properties. + * + * @author Shedfree Wu + */ +@Configuration(proxyBeanMethods = false) +@ConditionalOnPolarisEnabled +@EnableConfigurationProperties(LosslessProperties.class) +public class LosslessPropertiesAutoConfiguration { + + @Bean + @ConditionalOnMissingBean + public LosslessConfigModifier losslessConfigModifier(LosslessProperties losslessProperties) { + return new LosslessConfigModifier(losslessProperties); + } + +} diff --git a/spring-cloud-tencent-plugin-starters/spring-cloud-tencent-lossless-plugin/src/main/java/com/tencent/cloud/plugin/lossless/config/LosslessPropertiesBootstrapConfiguration.java b/spring-cloud-tencent-plugin-starters/spring-cloud-tencent-lossless-plugin/src/main/java/com/tencent/cloud/plugin/lossless/config/LosslessPropertiesBootstrapConfiguration.java new file mode 100644 index 000000000..dd047cabc --- /dev/null +++ b/spring-cloud-tencent-plugin-starters/spring-cloud-tencent-lossless-plugin/src/main/java/com/tencent/cloud/plugin/lossless/config/LosslessPropertiesBootstrapConfiguration.java @@ -0,0 +1,35 @@ +/* + * Tencent is pleased to support the open source community by making Spring Cloud Tencent available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * Unless required by applicable law or agreed to in writing, software distributed + * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package com.tencent.cloud.plugin.lossless.config; + +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; + + +/** + * BootstrapConfiguration of lossless properties. + * + * @author Shedfree Wu + */ +@Configuration(proxyBeanMethods = false) +@ConditionalOnProperty("spring.cloud.polaris.enabled") +@Import(LosslessPropertiesAutoConfiguration.class) +public class LosslessPropertiesBootstrapConfiguration { + +} diff --git a/spring-cloud-tencent-plugin-starters/spring-cloud-tencent-lossless-plugin/src/main/resources/META-INF/additional-spring-configuration-metadata.json b/spring-cloud-tencent-plugin-starters/spring-cloud-tencent-lossless-plugin/src/main/resources/META-INF/additional-spring-configuration-metadata.json new file mode 100644 index 000000000..48a31c1cd --- /dev/null +++ b/spring-cloud-tencent-plugin-starters/spring-cloud-tencent-lossless-plugin/src/main/resources/META-INF/additional-spring-configuration-metadata.json @@ -0,0 +1,10 @@ +{ + "properties": [ + { + "name": "spring.cloud.polaris.lossless.enabled", + "type": "java.lang.Boolean", + "defaultValue": true, + "description": "the switch for lossless plugin." + } + ] +} diff --git a/spring-cloud-tencent-plugin-starters/spring-cloud-tencent-lossless-plugin/src/main/resources/META-INF/spring.factories b/spring-cloud-tencent-plugin-starters/spring-cloud-tencent-lossless-plugin/src/main/resources/META-INF/spring.factories new file mode 100644 index 000000000..1308d2ebb --- /dev/null +++ b/spring-cloud-tencent-plugin-starters/spring-cloud-tencent-lossless-plugin/src/main/resources/META-INF/spring.factories @@ -0,0 +1,2 @@ +org.springframework.cloud.bootstrap.BootstrapConfiguration=\ + com.tencent.cloud.plugin.lossless.config.LosslessPropertiesBootstrapConfiguration diff --git a/spring-cloud-tencent-plugin-starters/spring-cloud-tencent-lossless-plugin/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/spring-cloud-tencent-plugin-starters/spring-cloud-tencent-lossless-plugin/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 000000000..b1326e228 --- /dev/null +++ b/spring-cloud-tencent-plugin-starters/spring-cloud-tencent-lossless-plugin/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1 @@ +com.tencent.cloud.plugin.lossless.config.LosslessAutoConfiguration \ No newline at end of file diff --git a/spring-cloud-tencent-plugin-starters/spring-cloud-tencent-lossless-plugin/src/test/java/com/tencent/cloud/plugin/lossless/LosslessConfigModifierTest.java b/spring-cloud-tencent-plugin-starters/spring-cloud-tencent-lossless-plugin/src/test/java/com/tencent/cloud/plugin/lossless/LosslessConfigModifierTest.java new file mode 100644 index 000000000..0b0d847ff --- /dev/null +++ b/spring-cloud-tencent-plugin-starters/spring-cloud-tencent-lossless-plugin/src/test/java/com/tencent/cloud/plugin/lossless/LosslessConfigModifierTest.java @@ -0,0 +1,91 @@ +/* + * 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.plugin.lossless; + +import com.tencent.cloud.plugin.lossless.config.LosslessConfigModifier; +import com.tencent.cloud.polaris.context.PolarisSDKContextManager; +import com.tencent.polaris.api.config.provider.LosslessConfig; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import org.springframework.boot.autoconfigure.AutoConfigurations; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.test.context.runner.ApplicationContextRunner; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Test for {@link LosslessConfigModifier}. + * + * @author Shedfree Wu + */ +public class LosslessConfigModifierTest { + + private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() + .withConfiguration(AutoConfigurations.of(TestApplication.class)) + .withPropertyValues("spring.cloud.nacos.discovery.enabled=false") + .withPropertyValues("spring.cloud.polaris.enabled=true") + .withPropertyValues("spring.cloud.polaris.lossless.enabled=true") + .withPropertyValues("spring.cloud.polaris.lossless.port=20000") + .withPropertyValues("spring.cloud.polaris.lossless.healthCheckPath=/xxx") + .withPropertyValues("spring.cloud.polaris.lossless.delayRegisterInterval=10") + .withPropertyValues("spring.cloud.polaris.lossless.healthCheckInterval=5") + .withPropertyValues("spring.application.name=test") + .withPropertyValues("spring.cloud.gateway.enabled=false"); + private final ApplicationContextRunner disabledContextRunner = new ApplicationContextRunner() + .withConfiguration(AutoConfigurations.of(TestApplication.class)) + .withPropertyValues("spring.cloud.nacos.discovery.enabled=false") + .withPropertyValues("spring.cloud.polaris.enabled=true") + .withPropertyValues("spring.cloud.polaris.lossless.enabled=false") + .withPropertyValues("spring.application.name=test") + .withPropertyValues("spring.cloud.gateway.enabled=false"); + + @BeforeEach + void setUp() { + PolarisSDKContextManager.innerDestroy(); + } + + @Test + void testModify() { + contextRunner.run(context -> { + PolarisSDKContextManager polarisSDKContextManager = context.getBean(PolarisSDKContextManager.class); + LosslessConfig losslessConfig = polarisSDKContextManager.getSDKContext(). + getConfig().getProvider().getLossless(); + assertThat(losslessConfig.getHost()).isEqualTo("0.0.0.0"); + assertThat(losslessConfig.getPort()).isEqualTo(20000); + assertThat(losslessConfig.getDelayRegisterInterval()).isEqualTo(10); + assertThat(losslessConfig.getHealthCheckInterval()).isEqualTo(5); + }); + } + + + @Test + void testDisabled() { + disabledContextRunner.run(context -> { + PolarisSDKContextManager polarisSDKContextManager = context.getBean(PolarisSDKContextManager.class); + LosslessConfig losslessConfig = polarisSDKContextManager.getSDKContext(). + getConfig().getProvider().getLossless(); + assertThat(losslessConfig.isEnable()).isFalse(); + }); + } + + @SpringBootApplication + protected static class TestApplication { + + } +} diff --git a/spring-cloud-tencent-plugin-starters/spring-cloud-tencent-lossless-plugin/src/test/java/com/tencent/cloud/plugin/lossless/LosslessPropertiesTest.java b/spring-cloud-tencent-plugin-starters/spring-cloud-tencent-lossless-plugin/src/test/java/com/tencent/cloud/plugin/lossless/LosslessPropertiesTest.java new file mode 100644 index 000000000..02e6f4087 --- /dev/null +++ b/spring-cloud-tencent-plugin-starters/spring-cloud-tencent-lossless-plugin/src/test/java/com/tencent/cloud/plugin/lossless/LosslessPropertiesTest.java @@ -0,0 +1,40 @@ +/* + * 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.plugin.lossless; + +import com.tencent.cloud.plugin.lossless.config.LosslessProperties; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Test for {@link LosslessProperties}. + * + * @author Shedfree Wu + */ +public class LosslessPropertiesTest { + + @Test + void testGetAndSet() { + LosslessProperties polarisStatProperties = new LosslessProperties(); + + // healthCheckPath + polarisStatProperties.setHealthCheckPath("/xxx"); + assertThat(polarisStatProperties.getHealthCheckPath()).isEqualTo("/xxx"); + } +} diff --git a/spring-cloud-tencent-plugin-starters/spring-cloud-tencent-lossless-plugin/src/test/java/com/tencent/cloud/plugin/lossless/LosslessRegistryAspectTest.java b/spring-cloud-tencent-plugin-starters/spring-cloud-tencent-lossless-plugin/src/test/java/com/tencent/cloud/plugin/lossless/LosslessRegistryAspectTest.java new file mode 100644 index 000000000..45f656529 --- /dev/null +++ b/spring-cloud-tencent-plugin-starters/spring-cloud-tencent-lossless-plugin/src/test/java/com/tencent/cloud/plugin/lossless/LosslessRegistryAspectTest.java @@ -0,0 +1,191 @@ +/* + * 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.plugin.lossless; + +import java.util.Collections; + +import com.tencent.cloud.common.util.OkHttpUtil; +import com.tencent.cloud.plugin.lossless.config.LosslessAutoConfiguration; +import com.tencent.cloud.plugin.lossless.config.LosslessPropertiesBootstrapConfiguration; +import com.tencent.cloud.polaris.context.PolarisSDKContextManager; +import com.tencent.cloud.polaris.context.config.PolarisContextAutoConfiguration; +import com.tencent.cloud.polaris.discovery.PolarisDiscoveryAutoConfiguration; +import com.tencent.cloud.polaris.discovery.PolarisDiscoveryClientConfiguration; +import com.tencent.cloud.polaris.registry.PolarisRegistration; +import com.tencent.cloud.polaris.registry.PolarisServiceRegistry; +import com.tencent.polaris.api.pojo.ServiceKey; +import com.tencent.polaris.test.mock.discovery.NamingServer; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import org.springframework.boot.autoconfigure.AutoConfigurations; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.test.context.runner.WebApplicationContextRunner; +import org.springframework.cloud.client.serviceregistry.AbstractAutoServiceRegistration; +import org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationUtils; +import org.springframework.context.annotation.Configuration; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatCode; + +/** + * Test for {@link LosslessRegistryAspect}. + * + * @author Shedfree Wu + */ +public class LosslessRegistryAspectTest { + + private static String NAMESPACE_TEST = "Test"; + + private static String SERVICE_PROVIDER = "java_provider_test"; + + private static String HOST = "127.0.0.1"; + + private static int APPLICATION_PORT = 19091; + + private static int LOSSLESS_PORT_1 = 28083; + + private static NamingServer namingServer; + + private final WebApplicationContextRunner contextRunner = new WebApplicationContextRunner() + .withConfiguration(AutoConfigurations.of( + LosslessAutoConfiguration.class, + LosslessPropertiesBootstrapConfiguration.class, + PolarisContextAutoConfiguration.class, + PolarisPropertiesConfiguration.class, + PolarisDiscoveryClientConfiguration.class, + PolarisDiscoveryAutoConfiguration.class)) + .withPropertyValues("spring.cloud.nacos.discovery.enabled=false") + .withPropertyValues("spring.cloud.polaris.lossless.delayRegisterInterval=5000") + .withPropertyValues("spring.cloud.polaris.lossless.healthCheckPath=") + .withPropertyValues("spring.cloud.polaris.lossless.port=" + LOSSLESS_PORT_1) + .withPropertyValues("spring.application.name=" + SERVICE_PROVIDER) + .withPropertyValues("server.port=" + APPLICATION_PORT) + .withPropertyValues("spring.cloud.polaris.localIpAddress=" + HOST) + .withPropertyValues("spring.cloud.polaris.localPort=" + APPLICATION_PORT) + .withPropertyValues("spring.cloud.polaris.address=grpc://127.0.0.1:10081") + .withPropertyValues("spring.cloud.polaris.discovery.namespace=" + NAMESPACE_TEST) + .withPropertyValues("spring.cloud.polaris.discovery.token=xxxxxx"); + + private final WebApplicationContextRunner contextRunner2 = new WebApplicationContextRunner() + .withConfiguration(AutoConfigurations.of( + LosslessAutoConfiguration.class, + LosslessPropertiesBootstrapConfiguration.class, + PolarisContextAutoConfiguration.class, + PolarisPropertiesConfiguration.class, + PolarisDiscoveryClientConfiguration.class, + PolarisDiscoveryAutoConfiguration.class)) + .withPropertyValues("spring.cloud.nacos.discovery.enabled=false") + .withPropertyValues("spring.cloud.polaris.lossless.healthCheckInterval=1000") + .withPropertyValues("spring.cloud.polaris.lossless.healthCheckPath=/test") + .withPropertyValues("spring.cloud.polaris.lossless.port=28082") + .withPropertyValues("spring.application.name=" + SERVICE_PROVIDER) + .withPropertyValues("server.port=" + APPLICATION_PORT) + .withPropertyValues("spring.cloud.polaris.localIpAddress=" + HOST) + .withPropertyValues("spring.cloud.polaris.localPort=" + APPLICATION_PORT) + .withPropertyValues("spring.cloud.polaris.address=grpc://127.0.0.1:10081") + .withPropertyValues("spring.cloud.polaris.discovery.namespace=" + NAMESPACE_TEST) + .withPropertyValues("spring.cloud.polaris.discovery.token=xxxxxx"); + + @BeforeAll + static void beforeAll() throws Exception { + namingServer = NamingServer.startNamingServer(10081); + + // add service + namingServer.getNamingService().addService(new ServiceKey(NAMESPACE_TEST, SERVICE_PROVIDER)); + } + + @AfterAll + static void afterAll() { + if (null != namingServer) { + namingServer.terminate(); + } + } + + @BeforeEach + void setUp() { + PolarisSDKContextManager.innerDestroy(); + } + + @Test + public void testRegister() { + this.contextRunner.run(context -> { + + AbstractAutoServiceRegistration autoServiceRegistration = context.getBean(AbstractAutoServiceRegistration.class); + + assertThatCode(() -> { + AutoServiceRegistrationUtils.register(autoServiceRegistration); + }).doesNotThrowAnyException(); + Thread.sleep(1000); + // before register online status is false + assertThatCode(() -> { + assertThat(OkHttpUtil.checkUrl(HOST, LOSSLESS_PORT_1, "/online", Collections.EMPTY_MAP)).isFalse(); + }).doesNotThrowAnyException(); + // delay register after 5s + Thread.sleep(5000); + PolarisServiceRegistry registry = context.getBean(PolarisServiceRegistry.class); + PolarisRegistration registration = context.getBean(PolarisRegistration.class); + + assertThatCode(() -> { + assertThat(registry.getStatus(registration)).isEqualTo("DOWN"); + }).doesNotThrowAnyException(); + + assertThatCode(() -> { + assertThat(OkHttpUtil.checkUrl(HOST, LOSSLESS_PORT_1, "/online", Collections.EMPTY_MAP)).isTrue(); + }).doesNotThrowAnyException(); + + assertThatCode(() -> { + assertThat(OkHttpUtil.checkUrl(HOST, LOSSLESS_PORT_1, "/offline", Collections.EMPTY_MAP)).isTrue(); + }).doesNotThrowAnyException(); + + assertThatCode(() -> { + AutoServiceRegistrationUtils.deRegister(autoServiceRegistration); + }).doesNotThrowAnyException(); + + assertThatCode(() -> { + assertThat(registry.getStatus(registration)).isEqualTo("DOWN"); + }).doesNotThrowAnyException(); + }); + } + + @Test + public void testRegister2() { + this.contextRunner2.run(context -> { + + AbstractAutoServiceRegistration autoServiceRegistration = context.getBean(AbstractAutoServiceRegistration.class); + + assertThatCode(() -> { + AutoServiceRegistrationUtils.register(autoServiceRegistration); + }).doesNotThrowAnyException(); + + Thread.sleep(2000); + + assertThatCode(() -> { + AutoServiceRegistrationUtils.deRegister(autoServiceRegistration); + }).doesNotThrowAnyException(); + }); + } + + @Configuration + @EnableAutoConfiguration + static class PolarisPropertiesConfiguration { + + } +} diff --git a/spring-cloud-tencent-plugin-starters/spring-cloud-tencent-lossless-plugin/src/test/java/org/springframework/cloud/client/serviceregistry/AutoServiceRegistrationUtils.java b/spring-cloud-tencent-plugin-starters/spring-cloud-tencent-lossless-plugin/src/test/java/org/springframework/cloud/client/serviceregistry/AutoServiceRegistrationUtils.java new file mode 100644 index 000000000..1c8e09f91 --- /dev/null +++ b/spring-cloud-tencent-plugin-starters/spring-cloud-tencent-lossless-plugin/src/test/java/org/springframework/cloud/client/serviceregistry/AutoServiceRegistrationUtils.java @@ -0,0 +1,29 @@ +/* + * 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 org.springframework.cloud.client.serviceregistry; + +public class AutoServiceRegistrationUtils { + + public static void register(AbstractAutoServiceRegistration autoServiceRegistration) { + autoServiceRegistration.register(); + } + + public static void deRegister(AbstractAutoServiceRegistration autoServiceRegistration) { + autoServiceRegistration.deregister(); + } +} diff --git a/spring-cloud-tencent-polaris-context/src/main/java/com/tencent/cloud/polaris/context/PolarisSDKContextManager.java b/spring-cloud-tencent-polaris-context/src/main/java/com/tencent/cloud/polaris/context/PolarisSDKContextManager.java index e28a60770..143b6fbb7 100644 --- a/spring-cloud-tencent-polaris-context/src/main/java/com/tencent/cloud/polaris/context/PolarisSDKContextManager.java +++ b/spring-cloud-tencent-polaris-context/src/main/java/com/tencent/cloud/polaris/context/PolarisSDKContextManager.java @@ -23,6 +23,7 @@ import java.util.Objects; import com.tencent.cloud.polaris.context.config.PolarisContextProperties; import com.tencent.polaris.api.control.Destroyable; import com.tencent.polaris.api.core.ConsumerAPI; +import com.tencent.polaris.api.core.LosslessAPI; import com.tencent.polaris.api.core.ProviderAPI; import com.tencent.polaris.assembly.api.AssemblyAPI; import com.tencent.polaris.assembly.factory.AssemblyAPIFactory; @@ -55,6 +56,7 @@ public class PolarisSDKContextManager { private volatile static SDKContext sdkContext; private volatile static ProviderAPI providerAPI; private volatile static ConsumerAPI consumerAPI; + private volatile static LosslessAPI losslessAPI; private volatile static RouterAPI routerAPI; private volatile static CircuitBreakAPI circuitBreakAPI; private volatile static LimitAPI limitAPI; @@ -81,6 +83,12 @@ public class PolarisSDKContextManager { providerAPI = null; } + // destroy LosslessAPI + if (Objects.nonNull(losslessAPI)) { + ((AutoCloseable) losslessAPI).close(); + losslessAPI = null; + } + // destroy ConsumerAPI if (Objects.nonNull(consumerAPI)) { ((AutoCloseable) consumerAPI).close(); @@ -135,6 +143,9 @@ public class PolarisSDKContextManager { // init ProviderAPI providerAPI = DiscoveryAPIFactory.createProviderAPIByContext(sdkContext); + // init losslessAPI + losslessAPI = DiscoveryAPIFactory.createLosslessAPIByContext(sdkContext); + // init ConsumerAPI consumerAPI = DiscoveryAPIFactory.createConsumerAPIByContext(sdkContext); @@ -183,6 +194,11 @@ public class PolarisSDKContextManager { return providerAPI; } + public LosslessAPI getLosslessAPI() { + init(); + return losslessAPI; + } + public ConsumerAPI getConsumerAPI() { init(); return consumerAPI; diff --git a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/config/RpcEnhancementAutoConfiguration.java b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/config/RpcEnhancementAutoConfiguration.java index 3f458676c..e333451bd 100644 --- a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/config/RpcEnhancementAutoConfiguration.java +++ b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/config/RpcEnhancementAutoConfiguration.java @@ -37,6 +37,8 @@ import com.tencent.cloud.rpc.enhancement.resttemplate.PolarisLoadBalancerRequest import com.tencent.cloud.rpc.enhancement.scg.EnhancedGatewayGlobalFilter; import com.tencent.cloud.rpc.enhancement.transformer.InstanceTransformer; import com.tencent.cloud.rpc.enhancement.transformer.PolarisInstanceTransformer; +import com.tencent.cloud.rpc.enhancement.transformer.PolarisRegistrationTransformer; +import com.tencent.cloud.rpc.enhancement.transformer.RegistrationTransformer; import com.tencent.cloud.rpc.enhancement.webclient.EnhancedWebClientExchangeFilterFunction; import com.tencent.cloud.rpc.enhancement.webclient.PolarisLoadBalancerClientRequestTransformer; @@ -47,7 +49,6 @@ import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.AutoConfigureBefore; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; import org.springframework.boot.context.properties.EnableConfigurationProperties; @@ -82,11 +83,18 @@ public class RpcEnhancementAutoConfiguration { @Bean @ConditionalOnMissingBean - @ConditionalOnMissingClass("com.alibaba.cloud.nacos.NacosServiceInstance") + @ConditionalOnClass(name = "com.tencent.cloud.common.pojo.PolarisServiceInstance") public InstanceTransformer instanceTransformer() { return new PolarisInstanceTransformer(); } + @Bean + @ConditionalOnMissingBean + @ConditionalOnClass(name = "com.tencent.cloud.polaris.registry.PolarisRegistration") + public RegistrationTransformer registrationTransformer() { + return new PolarisRegistrationTransformer(); + } + @Bean @Lazy public EnhancedPluginRunner enhancedFeignPluginRunner( diff --git a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/transformer/PolarisRegistrationTransformer.java b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/transformer/PolarisRegistrationTransformer.java new file mode 100644 index 000000000..8c4000a76 --- /dev/null +++ b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/transformer/PolarisRegistrationTransformer.java @@ -0,0 +1,25 @@ +/* + * 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.rpc.enhancement.transformer; + +public class PolarisRegistrationTransformer implements RegistrationTransformer { + + + +} diff --git a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/transformer/RegistrationTransformer.java b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/transformer/RegistrationTransformer.java new file mode 100644 index 000000000..c79fe3401 --- /dev/null +++ b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/transformer/RegistrationTransformer.java @@ -0,0 +1,55 @@ +/* + * 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.rpc.enhancement.transformer; + +import com.tencent.cloud.common.metadata.MetadataContext; +import com.tencent.polaris.api.pojo.DefaultInstance; +import com.tencent.polaris.api.pojo.Instance; + +import org.springframework.cloud.client.serviceregistry.Registration; + + +/** + * RegistrationTransformer extensions to adapt 3rd registration to polaris instance. + * + * @author andrew shan + */ +public interface RegistrationTransformer { + + default Instance transform(Registration registration) { + DefaultInstance instance = new DefaultInstance(); + transformDefault(instance, registration); + transformCustom(instance, registration); + return instance; + } + + default void transformDefault(DefaultInstance instance, Registration registration) { + instance.setNamespace(MetadataContext.LOCAL_NAMESPACE); + instance.setService(registration.getServiceId()); + instance.setProtocol(registration.getScheme()); + instance.setId(registration.getInstanceId()); + instance.setHost(registration.getHost()); + instance.setPort(registration.getPort()); + instance.setMetadata(registration.getMetadata()); + } + + default void transformCustom(DefaultInstance instance, Registration registration) { + + } +}