diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index a56dd0d4b..f04cb49c3 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -14,7 +14,7 @@ Other... Please describe: ## Adding the issue link (#xxx) if possible. ## Note @@ -26,6 +26,7 @@ fixes # ## Checklist (Optional) -- [ ] Will pull request to branch of 2020.0. +- [ ] Will pull request to branch of 2023.0. - [ ] Will pull request to branch of 2022.0. +- [ ] Will pull request to branch of 2020.0. - [ ] Will pull request to branch of hoxton. diff --git a/.github/workflows/codecov.yml b/.github/workflows/codecov.yml index 011787bdb..f97516343 100644 --- a/.github/workflows/codecov.yml +++ b/.github/workflows/codecov.yml @@ -3,6 +3,7 @@ name: Codecov on: push: branches: + - 2023.0 - 2022.0 - 2021.0 - 2020.0 @@ -10,6 +11,7 @@ on: - greenwich pull_request: branches: + - 2023.0 - 2022.0 - 2021.0 - 2020.0 @@ -22,15 +24,17 @@ jobs: steps: - name: Checkout codes - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Set up JDK 17 - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: distribution: 'temurin' java-version: 17 - name: Test with Maven run: mvn clean test -B -U -Psonatype - name: Upload coverage to Codecov - uses: codecov/codecov-action@v3 + uses: codecov/codecov-action@v4 + env: + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} with: files: ${{ github.workspace }}/target/site/jacoco/jacoco.xml diff --git a/.github/workflows/junit_test.yml b/.github/workflows/junit_test.yml index c26f1d8be..0ecdb273b 100644 --- a/.github/workflows/junit_test.yml +++ b/.github/workflows/junit_test.yml @@ -28,14 +28,14 @@ jobs: steps: - name: Checkout codes - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Set up JDK ${{ matrix.java }} - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: distribution: 'temurin' java-version: ${{ matrix.java }} - name: Cache local Maven repository - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ~/.m2/repository key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} diff --git a/.github/workflows/license-checker.yml b/.github/workflows/license-checker.yml index e5e639135..77a3333bc 100644 --- a/.github/workflows/license-checker.yml +++ b/.github/workflows/license-checker.yml @@ -3,6 +3,7 @@ name: License checker on: push: branches: + - 2023.0 - 2022.0 - 2021.0 - 2020.0 @@ -10,6 +11,7 @@ on: - greenwich pull_request: branches: + - 2023.0 - 2022.0 - 2021.0 - 2020.0 @@ -20,6 +22,6 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout codes - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Check License Header uses: apache/skywalking-eyes@v0.4.0 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 49f492d07..602c60148 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -8,9 +8,9 @@ jobs: release: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up JDK 17 - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: java-version: '17' distribution: 'temurin' diff --git a/.github/workflows/snapshot.yml b/.github/workflows/snapshot.yml index 1809ba7c6..3a9d462a9 100644 --- a/.github/workflows/snapshot.yml +++ b/.github/workflows/snapshot.yml @@ -3,6 +3,7 @@ name: Snapshot on: push: branches: + - 2023.0 - 2022.0 - 2021.0 - 2020.0 @@ -16,7 +17,7 @@ jobs: IS_SNAPSHOT: ${{ steps.set_output_1.outputs.IS_SNAPSHOT }} steps: - name: Checkout codes - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Check deploy type id: set_output_1 run: | @@ -33,9 +34,9 @@ jobs: if: ${{ needs.check-snapshot.outputs.IS_SNAPSHOT == 'true' }} steps: - name: Checkout codes - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Set up JDK 17 - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: java-version: '17' distribution: 'temurin' diff --git a/README-zh.md b/README-zh.md index 3552f2e40..5f7f9c3d1 100644 --- a/README-zh.md +++ b/README-zh.md @@ -61,7 +61,7 @@ Spring Cloud Tencent 所有组件都已上传到 Maven 中央仓库,只需要 > 注意: > -> 支持Spring Cloud 版本:2022.0、2021.0、2020.0、Hoxton。 +> 支持Spring Cloud 版本:2023.0, 2022.0、2021.0、2020.0、Hoxton。 > > Spring Cloud Tencent > 的版本列表可以查看 diff --git a/README.md b/README.md index 37fc6fe58..0ec14dc27 100644 --- a/README.md +++ b/README.md @@ -63,7 +63,7 @@ dependencies. > Notice: > -> Support Spring Cloud 2022.0, 2021.0, 2020.0, Hoxton. +> Support Spring Cloud 2023.0, 2022.0, 2021.0, 2020.0, Hoxton. > > The version list of Spring Cloud Tencent can be found > in diff --git a/changes/changes-1.13.0.md b/changes/changes-1.13.0.md new file mode 100644 index 000000000..29813ebfe --- /dev/null +++ b/changes/changes-1.13.0.md @@ -0,0 +1,24 @@ +# Change Log +--- + +- [feat: fix the logging problem open at #1189](https://github.com/Tencent/spring-cloud-tencent/pull/1197) +- [fix:the polaris config relation non-daemon thread should stop when application fails to start.](https://github.com/Tencent/spring-cloud-tencent/pull/1110) +- [Refactoring:remove invalid @AutoConfigureAfter and @AutoConfigureBefore from discovery client automatic configuration.](https://github.com/Tencent/spring-cloud-tencent/pull/1118) +- [fix:fix feign url bug when using sleuth.](https://github.com/Tencent/spring-cloud-tencent/pull/1119) +- [refactor:optimize the order and condition matching of service registration automatic configuration.](https://github.com/Tencent/spring-cloud-tencent/pull/1133) +- [feat:support service contract reporting.](https://github.com/Tencent/spring-cloud-tencent/pull/1135) +- [feat: support log path configuration parameters.](https://github.com/Tencent/spring-cloud-tencent/pull/1143) +- [feat:add swagger exposure filters.](https://github.com/Tencent/spring-cloud-tencent/pull/1144) +- [feat:add swagger report switch.](https://github.com/Tencent/spring-cloud-tencent/pull/1147) +- [fix: dynamic routing using cookies.](https://github.com/Tencent/spring-cloud-tencent/pull/1152) +- [fix:fix retry loadbalancer not working bug.](https://github.com/Tencent/spring-cloud-tencent/pull/1157) +- [fix:fix header validation when using Chinese char.](https://github.com/Tencent/spring-cloud-tencent/pull/1167) +- [feat: add circuit breaker actuator.](https://github.com/Tencent/spring-cloud-tencent/pull/1172) +- [feat: add metadata transfer for http header via spring.cloud.tencent.metadata.headers.](https://github.com/Tencent/spring-cloud-tencent/pull/1174) +- [fix:remove bcprov-jdk15on dependency.](https://github.com/Tencent/spring-cloud-tencent/pull/1178) +- [feat:support configuration encryption.](https://github.com/Tencent/spring-cloud-tencent/pull/1182) +- [feat:optimize examples.](https://github.com/Tencent/spring-cloud-tencent/pull/1186) +- [feat: support nacos namespace mapping](https://github.com/Tencent/spring-cloud-tencent/pull/1191) +- [fix:fix sct-all wrong spring boot version obtain.](https://github.com/Tencent/spring-cloud-tencent/pull/1204) +- fix:fix restTemplateCustomizer bean conflict causing service to fail to start properly. +- fix:fix NullPointerException when properties contain kv with null value. diff --git a/spring-cloud-starter-tencent-metadata-transfer/src/test/java/com/tencent/cloud/metadata/core/DecodeTransferMetadataReactiveFilterTest.java b/spring-cloud-starter-tencent-metadata-transfer/src/test/java/com/tencent/cloud/metadata/core/DecodeTransferMetadataReactiveFilterTest.java index bbee696c9..ff27c0c4d 100644 --- a/spring-cloud-starter-tencent-metadata-transfer/src/test/java/com/tencent/cloud/metadata/core/DecodeTransferMetadataReactiveFilterTest.java +++ b/spring-cloud-starter-tencent-metadata-transfer/src/test/java/com/tencent/cloud/metadata/core/DecodeTransferMetadataReactiveFilterTest.java @@ -20,6 +20,7 @@ package com.tencent.cloud.metadata.core; import com.tencent.cloud.common.constant.MetadataConstant; import com.tencent.cloud.common.constant.OrderConstant; import com.tencent.cloud.common.metadata.config.MetadataLocalProperties; +import com.tencent.cloud.polaris.context.config.PolarisContextProperties; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -54,7 +55,7 @@ public class DecodeTransferMetadataReactiveFilterTest { @BeforeEach public void setUp() { - this.metadataReactiveFilter = new DecodeTransferMetadataReactiveFilter(); + this.metadataReactiveFilter = new DecodeTransferMetadataReactiveFilter(new PolarisContextProperties()); } @Test diff --git a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/RouterBootstrapAutoConfiguration.java b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/RouterBootstrapAutoConfiguration.java new file mode 100644 index 000000000..2d02b2a28 --- /dev/null +++ b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/RouterBootstrapAutoConfiguration.java @@ -0,0 +1,36 @@ +/* + * Tencent is pleased to support the open source community by making Spring Cloud Tencent available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * Unless required by applicable law or agreed to in writing, software distributed + * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + */ + +package com.tencent.cloud.polaris.router.config; + +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; + +/** + * RouterBootstrapAutoConfiguration. + * + * @author sean yu + */ +@Configuration(proxyBeanMethods = false) +@ConditionalOnProperty("spring.cloud.polaris.enabled") +@Import(RouterConfigModifierAutoConfiguration.class) +public class RouterBootstrapAutoConfiguration { + + +} diff --git a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/RouterConfigModifierAutoConfiguration.java b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/RouterConfigModifierAutoConfiguration.java new file mode 100644 index 000000000..e1de4a37f --- /dev/null +++ b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/RouterConfigModifierAutoConfiguration.java @@ -0,0 +1,47 @@ +/* + * Tencent is pleased to support the open source community by making Spring Cloud Tencent available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * Unless required by applicable law or agreed to in writing, software distributed + * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + */ + +package com.tencent.cloud.polaris.router.config; + +import com.tencent.cloud.polaris.router.RouterConfigModifier; +import com.tencent.cloud.polaris.router.config.properties.PolarisMetadataRouterProperties; +import com.tencent.cloud.polaris.router.config.properties.PolarisNearByRouterProperties; +import com.tencent.cloud.polaris.router.config.properties.PolarisRuleBasedRouterProperties; + +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; + +/** + * RouterConfigModifierAutoConfiguration. + * + * @author sean yu + */ +@Configuration(proxyBeanMethods = false) +@ConditionalOnPolarisRouterEnabled +@Import({PolarisNearByRouterProperties.class, PolarisMetadataRouterProperties.class, PolarisRuleBasedRouterProperties.class}) +public class RouterConfigModifierAutoConfiguration { + + @Bean + @ConditionalOnMissingBean + public RouterConfigModifier routerConfigModifier(PolarisNearByRouterProperties polarisNearByRouterProperties) { + return new RouterConfigModifier(polarisNearByRouterProperties); + } + +} diff --git a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/properties/PolarisNearByRouterProperties.java b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/properties/PolarisNearByRouterProperties.java index 226195a13..ac3e6f27b 100644 --- a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/properties/PolarisNearByRouterProperties.java +++ b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/properties/PolarisNearByRouterProperties.java @@ -31,6 +31,8 @@ public class PolarisNearByRouterProperties { private String matchLevel; + private String matchLevel; + public boolean isEnabled() { return enabled; } diff --git a/spring-cloud-starter-tencent-polaris-router/src/main/resources/META-INF/additional-spring-configuration-metadata.json b/spring-cloud-starter-tencent-polaris-router/src/main/resources/META-INF/additional-spring-configuration-metadata.json index 92251c916..b3ee9a2d1 100644 --- a/spring-cloud-starter-tencent-polaris-router/src/main/resources/META-INF/additional-spring-configuration-metadata.json +++ b/spring-cloud-starter-tencent-polaris-router/src/main/resources/META-INF/additional-spring-configuration-metadata.json @@ -18,6 +18,12 @@ "defaultValue": "ZONE", "description": "the match level for nearby router, options can be REGION/ZONE/CAMPUS." }, + { + "name": "spring.cloud.polaris.router.nearby-router.matchLevel", + "type": "java.lang.String", + "defaultValue": "zone", + "description": "the match level for nearby router, options can be region/zone/campus." + }, { "name": "spring.cloud.polaris.router.rule-router.enabled", "type": "java.lang.Boolean", diff --git a/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/config/RouterBootstrapAutoConfigurationTest.java b/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/config/RouterBootstrapAutoConfigurationTest.java new file mode 100644 index 000000000..f10d9ada4 --- /dev/null +++ b/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/config/RouterBootstrapAutoConfigurationTest.java @@ -0,0 +1,67 @@ +/* + * Tencent is pleased to support the open source community by making Spring Cloud Tencent available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * Unless required by applicable law or agreed to in writing, software distributed + * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + */ + +package com.tencent.cloud.polaris.router.config; + +import com.tencent.cloud.polaris.context.config.PolarisContextAutoConfiguration; +import com.tencent.cloud.polaris.router.RouterConfigModifier; +import com.tencent.cloud.polaris.router.config.properties.PolarisNearByRouterProperties; +import com.tencent.cloud.rpc.enhancement.config.RpcEnhancementAutoConfiguration; +import com.tencent.polaris.api.config.Configuration; +import com.tencent.polaris.api.config.consumer.ServiceRouterConfig; +import com.tencent.polaris.factory.ConfigAPIFactory; +import com.tencent.polaris.factory.config.ConfigurationImpl; +import com.tencent.polaris.plugins.router.nearby.NearbyRouterConfig; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import org.springframework.boot.autoconfigure.AutoConfigurations; +import org.springframework.boot.test.context.runner.ApplicationContextRunner; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * RouterBootstrapAutoConfigurationTest. + * + * @author sean yu + */ +public class RouterBootstrapAutoConfigurationTest { + + private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() + .withConfiguration(AutoConfigurations.of( + PolarisContextAutoConfiguration.class, + PolarisNearByRouterProperties.class, + RpcEnhancementAutoConfiguration.class, + RouterBootstrapAutoConfiguration.class)) + .withPropertyValues("spring.cloud.polaris.enabled=true") + .withPropertyValues("spring.cloud.polaris.router.nearby-router.matchLevel=campus") + .withPropertyValues("spring.cloud.polaris.circuitbreaker.enabled=true"); + + @Test + public void testDefaultInitialization() { + this.contextRunner.run(context -> { + assertThat(context).hasSingleBean(RouterConfigModifier.class); + RouterConfigModifier routerConfigModifier = (RouterConfigModifier) context.getBean("routerConfigModifier"); + Configuration configuration = ConfigAPIFactory.defaultConfig(); + routerConfigModifier.modify((ConfigurationImpl) configuration); + NearbyRouterConfig nearbyRouterConfig = configuration.getConsumer().getServiceRouter().getPluginConfig( + ServiceRouterConfig.DEFAULT_ROUTER_NEARBY, NearbyRouterConfig.class); + Assertions.assertEquals("campus", nearbyRouterConfig.getMatchLevel().name()); + }); + } +} diff --git a/spring-cloud-tencent-examples/polaris-router-grayrelease-lane-example/router-grayrelease-lane-callee-service/src/main/resources/bootstrap.yml b/spring-cloud-tencent-examples/polaris-router-grayrelease-lane-example/router-grayrelease-lane-callee-service/src/main/resources/bootstrap.yml new file mode 100644 index 000000000..29d9d9c96 --- /dev/null +++ b/spring-cloud-tencent-examples/polaris-router-grayrelease-lane-example/router-grayrelease-lane-callee-service/src/main/resources/bootstrap.yml @@ -0,0 +1,36 @@ +server: + port: 48093 +spring: + application: + name: LaneCalleeService + 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: 28083 + # pushgateway: + # enabled: true + # address: 127.0.0.1:9091 + config: + address: grpc://9.134.5.52:8093 + auto-refresh: true + groups: + - name: ${spring.application.name} + files: [ "config/callee.properties" ] +management: + endpoints: + web: + exposure: + include: + - polaris-discovery + - polaris-config \ No newline at end of file diff --git a/spring-cloud-tencent-examples/polaris-router-grayrelease-lane-example/router-grayrelease-lane-caller-service/src/main/resources/bootstrap.yml b/spring-cloud-tencent-examples/polaris-router-grayrelease-lane-example/router-grayrelease-lane-caller-service/src/main/resources/bootstrap.yml new file mode 100644 index 000000000..259358d55 --- /dev/null +++ b/spring-cloud-tencent-examples/polaris-router-grayrelease-lane-example/router-grayrelease-lane-caller-service/src/main/resources/bootstrap.yml @@ -0,0 +1,42 @@ +server: + port: 48092 +spring: + application: + name: LaneCallerService + cloud: + polaris: + address: grpc://119.91.66.223:8091 + namespace: default + enabled: true + discovery: + enabled: true + register: true + heartbeat: + enabled: true + health-check-url: /lane/caller/healthCheck + contract: + exposure: true + report: + enabled: true + circuitbreaker: + enabled: true + stat: + enabled: true + port: 28082 + # pushgateway: + # enabled: true + # address: 127.0.0.1:9091 + tencent: + rpc-enhancement: + enabled: true + reporter: + enabled: true + ignore-internal-server-error: true + series: server_error + statuses: gateway_timeout, bad_gateway, service_unavailable +management: + endpoints: + web: + exposure: + include: + - polaris-discovery \ No newline at end of file diff --git a/spring-cloud-tencent-examples/polaris-router-grayrelease-lane-example/router-grayrelease-lane-gateway/src/main/resources/bootstrap.yml b/spring-cloud-tencent-examples/polaris-router-grayrelease-lane-example/router-grayrelease-lane-gateway/src/main/resources/bootstrap.yml new file mode 100644 index 000000000..1c02136d0 --- /dev/null +++ b/spring-cloud-tencent-examples/polaris-router-grayrelease-lane-example/router-grayrelease-lane-gateway/src/main/resources/bootstrap.yml @@ -0,0 +1,39 @@ +server: + port: 48090 +spring: + application: + name: LaneRouterGatewayService + config: + import: optional:polaris + cloud: + polaris: + address: grpc://119.91.66.223:8091 + namespace: default + enabled: true + contract: + exposure: true + report: + enabled: true + stat: + enabled: true + port: 28081 + gateway: + discovery: + locator: + enabled: true + 'predicates[0]': + name: Path + args: + patterns: '''/'' + serviceId + ''/**''' + 'filters[0]': + name: RewritePath + args: + regexp: '''/'' + serviceId + ''/(?.*)''' + replacement: '''/$\{remaining}''' + routes: + - id: LaneRouterCallerService + uri: lb://LaneCallerService + predicates: + - Path=/LaneCallerService/** + filters: + - StripPrefix=1 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 db1047296..dbcc1c8bc 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 @@ -18,10 +18,11 @@ package com.tencent.cloud.plugin.discovery.adapter.transformer; -import com.alibaba.cloud.nacos.ribbon.NacosServer; -import com.netflix.loadbalancer.Server; -import com.tencent.cloud.polaris.loadbalancer.transformer.InstanceTransformer; +import com.tencent.cloud.rpc.enhancement.transformer.InstanceTransformer; import com.tencent.polaris.api.pojo.DefaultInstance; +import org.apache.commons.lang.StringUtils; + +import org.springframework.cloud.client.ServiceInstance; /** * NacosInstanceTransformer. @@ -31,12 +32,20 @@ import com.tencent.polaris.api.pojo.DefaultInstance; public class NacosInstanceTransformer implements InstanceTransformer { @Override - public void transformCustom(DefaultInstance instance, Server server) { - if ("com.alibaba.cloud.nacos.ribbon.NacosServer".equals(server.getClass().getName())) { - NacosServer nacosServer = (NacosServer) server; - instance.setWeight((int) (nacosServer.getInstance().getWeight() * 100)); - instance.setHealthy(nacosServer.getInstance().isHealthy()); - instance.setMetadata(nacosServer.getMetadata()); + public void transformCustom(DefaultInstance instance, ServiceInstance serviceInstance) { + if ("com.alibaba.cloud.nacos.NacosServiceInstance".equals(serviceInstance.getClass().getName())) { + String nacosWeight = serviceInstance.getMetadata().get("nacos.weight"); + instance.setWeight( + StringUtils.isBlank(nacosWeight) ? 100 : (int) Double.parseDouble(nacosWeight) * 100 + ); + String nacosHealthy = serviceInstance.getMetadata().get("nacos.healthy"); + instance.setHealthy( + !StringUtils.isBlank(nacosHealthy) && Boolean.parseBoolean(nacosHealthy) + ); + 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/test/java/com/tencent/cloud/plugin/discovery/adapter/config/NacosDiscoveryAdapterAutoConfigurationTest.java b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-discovery-adapter-plugin/src/test/java/com/tencent/cloud/plugin/discovery/adapter/config/NacosDiscoveryAdapterAutoConfigurationTest.java index 8689cb2f0..b2338053e 100644 --- a/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-discovery-adapter-plugin/src/test/java/com/tencent/cloud/plugin/discovery/adapter/config/NacosDiscoveryAdapterAutoConfigurationTest.java +++ b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-discovery-adapter-plugin/src/test/java/com/tencent/cloud/plugin/discovery/adapter/config/NacosDiscoveryAdapterAutoConfigurationTest.java @@ -19,6 +19,7 @@ package com.tencent.cloud.plugin.discovery.adapter.config; import com.tencent.cloud.plugin.discovery.adapter.transformer.NacosInstanceTransformer; +import com.tencent.cloud.rpc.enhancement.transformer.PolarisInstanceTransformer; import org.junit.jupiter.api.Test; import org.springframework.boot.autoconfigure.AutoConfigurations; @@ -44,6 +45,7 @@ public class NacosDiscoveryAdapterAutoConfigurationTest { public void testDefaultInitialization() { this.contextRunner.run(context -> { assertThat(context).hasSingleBean(NacosInstanceTransformer.class); + assertThat(context).doesNotHaveBean(PolarisInstanceTransformer.class); }); } } diff --git a/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-discovery-adapter-plugin/src/test/java/com/tencent/cloud/plugin/discovery/adapter/config/NacosInstanceTransformerTest.java b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-discovery-adapter-plugin/src/test/java/com/tencent/cloud/plugin/discovery/adapter/config/NacosInstanceTransformerTest.java index 00dd8be77..8320d6d90 100644 --- a/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-discovery-adapter-plugin/src/test/java/com/tencent/cloud/plugin/discovery/adapter/config/NacosInstanceTransformerTest.java +++ b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-discovery-adapter-plugin/src/test/java/com/tencent/cloud/plugin/discovery/adapter/config/NacosInstanceTransformerTest.java @@ -18,10 +18,12 @@ package com.tencent.cloud.plugin.discovery.adapter.config; -import com.alibaba.cloud.nacos.ribbon.NacosServer; +import java.util.HashMap; + +import com.alibaba.cloud.nacos.NacosServiceInstance; import com.tencent.cloud.common.util.ApplicationContextAwareUtils; import com.tencent.cloud.plugin.discovery.adapter.transformer.NacosInstanceTransformer; -import com.tencent.polaris.api.pojo.DefaultInstance; +import com.tencent.polaris.api.pojo.Instance; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import org.mockito.MockedStatic; @@ -51,14 +53,13 @@ public class NacosInstanceTransformerTest { @Test public void test() { NacosInstanceTransformer nacosInstanceTransformer = new NacosInstanceTransformer(); - - com.alibaba.nacos.api.naming.pojo.Instance nacosInstance = new com.alibaba.nacos.api.naming.pojo.Instance(); - nacosInstance.setHealthy(true); - NacosServer nacosServer = new NacosServer(nacosInstance); - - - DefaultInstance instance = new DefaultInstance(); - nacosInstanceTransformer.transformCustom(instance, nacosServer); + NacosServiceInstance nacosServiceInstance = new NacosServiceInstance(); + nacosServiceInstance.setMetadata(new HashMap() {{ + put("nacos.weight", "0.01"); + put("nacos.healthy", "true"); + put("nacos.instanceId", "xxx"); + }}); + Instance instance = nacosInstanceTransformer.transform(nacosServiceInstance); assertThat(instance.isHealthy()).isEqualTo(true); } 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 serviceRegistry; + + private LosslessProperties losslessProperties; + + private Runnable originalRegisterAction; + + private Registration registration; + + public SpringCloudLosslessActionProvider(ServiceRegistry 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 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/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/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..687041540 --- /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(10000); + 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/test/java/com/tencent/cloud/polaris/context/config/PolarisContextAutoConfigurationTest.java b/spring-cloud-tencent-polaris-context/src/test/java/com/tencent/cloud/polaris/context/config/PolarisContextAutoConfigurationTest.java index e5d05b6a3..e176b723d 100644 --- a/spring-cloud-tencent-polaris-context/src/test/java/com/tencent/cloud/polaris/context/config/PolarisContextAutoConfigurationTest.java +++ b/spring-cloud-tencent-polaris-context/src/test/java/com/tencent/cloud/polaris/context/config/PolarisContextAutoConfigurationTest.java @@ -46,4 +46,12 @@ public class PolarisContextAutoConfigurationTest { assertThat(polarisSDKContextManager).isNotNull(); }); } + + @Test + public void testLosslessAPIProperties() { + contextRunner.run(context -> { + PolarisSDKContextManager polarisSDKContextManager = context.getBean(PolarisSDKContextManager.class); + assertThat(polarisSDKContextManager.getLosslessAPI()).isNotNull(); + }); + } } diff --git a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/plugin/reporter/SuccessPolarisReporter.java b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/plugin/reporter/SuccessPolarisReporter.java index d4c7d6a1e..96d37fe13 100644 --- a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/plugin/reporter/SuccessPolarisReporter.java +++ b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/plugin/reporter/SuccessPolarisReporter.java @@ -71,6 +71,13 @@ public class SuccessPolarisReporter implements EnhancedPlugin { return; } + if (context.getThrowable() != null) { + if (LOG.isDebugEnabled()) { + LOG.debug("Success report with throwable. Don't report. {}", context, context.getThrowable()); + } + return; + } + EnhancedRequestContext request = context.getRequest(); EnhancedResponseContext response = context.getResponse(); ServiceInstance callerServiceInstance = Optional.ofNullable(context.getLocalServiceInstance()).orElse(new DefaultServiceInstance()); diff --git a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/zuul/EnhancedErrorZuulFilter.java b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/zuul/EnhancedErrorZuulFilter.java index ed981432f..d858261de 100644 --- a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/zuul/EnhancedErrorZuulFilter.java +++ b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/zuul/EnhancedErrorZuulFilter.java @@ -20,6 +20,7 @@ package com.tencent.cloud.rpc.enhancement.zuul; import java.util.ArrayList; import java.util.Collection; +import com.netflix.client.ClientException; import com.netflix.zuul.ZuulFilter; import com.netflix.zuul.context.RequestContext; import com.netflix.zuul.exception.ZuulException; @@ -30,6 +31,7 @@ import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginRunner; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedResponseContext; +import org.springframework.cloud.netflix.zuul.util.ZuulRuntimeException; import org.springframework.core.env.Environment; import org.springframework.http.HttpHeaders; import org.springframework.util.StringUtils; @@ -86,26 +88,45 @@ public class EnhancedErrorZuulFilter extends ZuulFilter { Object startTimeMilliObject = context.get(POLARIS_PRE_ROUTE_TIME); Throwable throwable = context.getThrowable(); if (throwable != null && startTimeMilliObject != null && startTimeMilliObject instanceof Long) { - HttpHeaders responseHeaders = new HttpHeaders(); - Collection names = context.getResponse().getHeaderNames(); - for (String name : names) { - responseHeaders.put(name, new ArrayList<>(context.getResponse().getHeaders(name))); + if (checkNoInstanceException(throwable)) { + enhancedPluginContext.setThrowable(throwable); + } + else { + HttpHeaders responseHeaders = new HttpHeaders(); + Collection names = context.getResponse().getHeaderNames(); + for (String name : names) { + responseHeaders.put(name, new ArrayList<>(context.getResponse().getHeaders(name))); + } + EnhancedResponseContext enhancedResponseContext = EnhancedResponseContext.builder() + .httpStatus(context.getResponse().getStatus()) + .httpHeaders(responseHeaders) + .build(); + enhancedPluginContext.setResponse(enhancedResponseContext); + Long startTimeMilli = (Long) startTimeMilliObject; + enhancedPluginContext.setDelay(System.currentTimeMillis() - startTimeMilli); + enhancedPluginContext.setThrowable(throwable); + + // Run post enhanced plugins. + pluginRunner.run(EnhancedPluginType.Client.EXCEPTION, enhancedPluginContext); + + // Run finally enhanced plugins. + pluginRunner.run(EnhancedPluginType.Client.FINALLY, enhancedPluginContext); } - EnhancedResponseContext enhancedResponseContext = EnhancedResponseContext.builder() - .httpStatus(context.getResponse().getStatus()) - .httpHeaders(responseHeaders) - .build(); - enhancedPluginContext.setResponse(enhancedResponseContext); - Long startTimeMilli = (Long) startTimeMilliObject; - enhancedPluginContext.setDelay(System.currentTimeMillis() - startTimeMilli); - enhancedPluginContext.setThrowable(throwable); - - // Run post enhanced plugins. - pluginRunner.run(EnhancedPluginType.Client.EXCEPTION, enhancedPluginContext); - - // Run finally enhanced plugins. - pluginRunner.run(EnhancedPluginType.Client.FINALLY, enhancedPluginContext); } return null; } + + protected boolean checkNoInstanceException(Throwable throwable) { + if (throwable.getCause() instanceof ZuulRuntimeException) { + Throwable cause = null; + if (throwable.getCause().getCause() != null) { + cause = throwable.getCause().getCause().getCause(); + } + if (cause instanceof ClientException && StringUtils.hasText(cause.getMessage()) && + cause.getMessage().contains("Load balancer does not have available server for client")) { + return true; + } + } + return false; + } }