Merge remote-tracking branch 'origin/hoxton' into dev/shedfreewu/h-2.0.0.0

# Conflicts:
#	CHANGELOG.md
#	pom.xml
#	spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/config/MetadataTransferAutoConfiguration.java
#	spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/core/DecodeTransferMetadataReactiveFilter.java
#	spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/core/DecodeTransferMetadataServletFilter.java
#	spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/core/EncodeTransferMedataFeignEnhancedPlugin.java
#	spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/core/EncodeTransferMedataRestTemplateEnhancedPlugin.java
#	spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/core/EncodeTransferMedataScgEnhancedPlugin.java
#	spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/core/EncodeTransferMedataWebClientEnhancedPlugin.java
#	spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/core/EncodeTransferMetadataZuulEnhancedPlugin.java
#	spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/provider/ReactiveMetadataProvider.java
#	spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/provider/ServletMetadataProvider.java
#	spring-cloud-starter-tencent-metadata-transfer/src/test/java/com/tencent/cloud/metadata/core/EncodeTransferMetadataZuulFilterTest.java
#	spring-cloud-starter-tencent-metadata-transfer/src/test/java/com/tencent/cloud/metadata/provider/MetadataProviderTest.java
#	spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/feign/PolarisFeignCircuitBreakerInvocationHandler.java
#	spring-cloud-starter-tencent-polaris-circuitbreaker/src/test/java/com/tencent/cloud/polaris/circuitbreaker/feign/PolarisCircuitBreakerFeignIntegrationTest.java
#	spring-cloud-starter-tencent-polaris-router/pom.xml
#	spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/RouterConfigModifier.java
#	spring-cloud-starter-tencent-polaris-router/src/main/resources/META-INF/spring.factories
#	spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/config/properties/PolarisNearByRouterPropertiesTest.java
#	spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/constant/OrderConstant.java
#	spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/metadata/MetadataContext.java
#	spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/metadata/MetadataContextHolder.java
#	spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/util/expresstion/ExpressionLabelUtils.java
#	spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/util/expresstion/SpringWebExpressionLabelUtils.java
#	spring-cloud-tencent-commons/src/test/java/com/tencent/cloud/common/metadata/MetadataContextHolderTest.java
#	spring-cloud-tencent-coverage/pom.xml
#	spring-cloud-tencent-dependencies/pom.xml
#	spring-cloud-tencent-examples/lossless-example/lossless-callee-service/pom.xml
#	spring-cloud-tencent-examples/lossless-example/lossless-callee-service/src/main/resources/bootstrap.yml
#	spring-cloud-tencent-examples/lossless-example/lossless-nacos-callee-service/pom.xml
#	spring-cloud-tencent-examples/lossless-example/lossless-nacos-callee-service/src/main/resources/bootstrap.yml
#	spring-cloud-tencent-examples/lossless-example/pom.xml
#	spring-cloud-tencent-examples/pom.xml
#	spring-cloud-tencent-examples/quickstart-example/quickstart-callee-service-a/src/main/java/com/tencent/cloud/quickstart/callee/QuickstartCalleeController.java
#	spring-cloud-tencent-plugin-starters/pom.xml
#	spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-discovery-adapter-plugin/src/main/java/com/tencent/cloud/plugin/discovery/adapter/config/NacosDiscoveryAdapterAutoConfiguration.java
#	spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-discovery-adapter-plugin/src/main/java/com/tencent/cloud/plugin/discovery/adapter/transformer/NacosRegistrationTransformer.java
#	spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-threadlocal-plugin/src/test/java/com/tencent/cloud/plugin/threadlocal/TaskExecutorWrapperTest.java
#	spring-cloud-tencent-plugin-starters/spring-cloud-tencent-lossless-plugin/pom.xml
#	spring-cloud-tencent-plugin-starters/spring-cloud-tencent-lossless-plugin/src/main/java/com/tencent/cloud/plugin/lossless/LosslessRegistryAspect.java
#	spring-cloud-tencent-plugin-starters/spring-cloud-tencent-lossless-plugin/src/main/java/com/tencent/cloud/plugin/lossless/config/LosslessConfigModifier.java
#	spring-cloud-tencent-plugin-starters/spring-cloud-tencent-lossless-plugin/src/main/java/com/tencent/cloud/plugin/lossless/config/LosslessProperties.java
#	spring-cloud-tencent-plugin-starters/spring-cloud-tencent-lossless-plugin/src/main/java/com/tencent/cloud/plugin/lossless/config/LosslessPropertiesAutoConfiguration.java
#	spring-cloud-tencent-plugin-starters/spring-cloud-tencent-lossless-plugin/src/main/resources/META-INF/additional-spring-configuration-metadata.json
#	spring-cloud-tencent-polaris-context/pom.xml
#	spring-cloud-tencent-polaris-context/src/main/java/com/tencent/cloud/polaris/context/PolarisSDKContextManager.java
#	spring-cloud-tencent-polaris-loadbalancer/src/main/java/com/tencent/cloud/polaris/loadbalancer/PolarisLoadBalancer.java
#	spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/plugin/PluginOrderConstant.java
#	spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/transformer/PolarisInstanceTransformer.java
pull/1458/head
shedfreewu 11 months ago
commit e710eae4ab

@ -14,7 +14,7 @@ Other... Please describe:
## Adding the issue link (#xxx) if possible.
<!--
fixes #
closes #
-->
## 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.

@ -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

@ -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') }}

@ -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

@ -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'

@ -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'

@ -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
> 的版本列表可以查看

@ -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

@ -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.

@ -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

@ -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 {
}

@ -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);
}
}

@ -31,6 +31,8 @@ public class PolarisNearByRouterProperties {
private String matchLevel;
private String matchLevel;
public boolean isEnabled() {
return enabled;
}

@ -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",

@ -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());
});
}
}

@ -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

@ -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

@ -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 + ''/(?<remaining>.*)'''
replacement: '''/$\{remaining}'''
routes:
- id: LaneRouterCallerService
uri: lb://LaneCallerService
predicates:
- Path=/LaneCallerService/**
filters:
- StripPrefix=1

@ -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);
}
}
}

@ -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);
});
}
}

@ -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<String, String>() {{
put("nacos.weight", "0.01");
put("nacos.healthy", "true");
put("nacos.instanceId", "xxx");
}});
Instance instance = nacosInstanceTransformer.transform(nacosServiceInstance);
assertThat(instance.isHealthy()).isEqualTo(true);
}

@ -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);
}
}

@ -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 {
}
}

@ -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 {
}
}

@ -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();
}
}

@ -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();
});
}
}

@ -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());

@ -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<String> 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<String> 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;
}
}

Loading…
Cancel
Save