Merge branch '2021.0' into 2021_shade

pull/694/head
Haotian Zhang 3 years ago committed by GitHub
commit 250e9cda85
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -3,10 +3,17 @@
- [Optimize:optimize SpringValueProcessor.](https://github.com/Tencent/spring-cloud-tencent/pull/655)
- [Optimize/optimize annotation.](https://github.com/Tencent/spring-cloud-tencent/pull/672)
- [enhancement: revert default value when the field is deleted in @ConfigurationProperties bean](https://github.com/Tencent/spring-cloud-tencent/issues/681)
- [Optimize: Register the service with the ProviderAPI#registerInstance method.](https://github.com/Tencent/spring-cloud-tencent/pull/686)
- [docs:update PR template.](https://github.com/Tencent/spring-cloud-tencent/pull/690)
- [Feature:support multi register and discovery both to nacos and polaris.](https://github.com/Tencent/spring-cloud-tencent/pull/693)
- [Optimize: update spring-cloud-starter-tencent-all pom to jar](https://github.com/Tencent/spring-cloud-tencent/pull/694)
- [Optimize: remote deprecated method](https://github.com/Tencent/spring-cloud-tencent/pull/697)
- [Test:support environment variable metadata test](https://github.com/Tencent/spring-cloud-tencent/pull/698)
- [Code optimize & add junit tests.](https://github.com/Tencent/spring-cloud-tencent/pull/701)
- [Test: remote deprecated method in test](https://github.com/Tencent/spring-cloud-tencent/pull/706)
- [Test: remote deprecated method in test](https://github.com/Tencent/spring-cloud-tencent/pull/706)
- [upgrade protobuf-java.version to 3.21.7](https://github.com/Tencent/spring-cloud-tencent/pull/715)
- [docs:update README.](https://github.com/Tencent/spring-cloud-tencent/pull/718)
- [Fix:fix javadoc.](https://github.com/Tencent/spring-cloud-tencent/pull/721)
- [Code optimization & correct comment](https://github.com/Tencent/spring-cloud-tencent/pull/722)
- [fix:fix discovery junit.](https://github.com/Tencent/spring-cloud-tencent/pull/725)

@ -7,7 +7,6 @@
[![Build Status](https://github.com/Tencent/spring-cloud-tencent/actions/workflows/junit_test.yml/badge.svg)](https://github.com/Tencent/spring-cloud-tencent/actions/workflows/junit_test.yml)
[![codecov.io](https://codecov.io/gh/Tencent/spring-cloud-tencent/branch/2021.0/graph/badge.svg)](https://codecov.io/gh/Tencent/spring-cloud-tencent?branch=2021.0)
[![Language grade: Java](https://img.shields.io/lgtm/grade/java/g/Tencent/spring-cloud-tencent.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/Tencent/spring-cloud-tencent/context:java)
[English](./README.md) | 简体中文
@ -108,23 +107,26 @@ You can build this project with command:
## 文档
- 使用文档
- [Spring Cloud Tencent Version Management](https://github.com/Tencent/spring-cloud-tencent/wiki/Spring-Cloud-Tencent-%E7%89%88%E6%9C%AC%E7%AE%A1%E7%90%86)
- [Spring Cloud Tencent Discovery](https://github.com/Tencent/spring-cloud-tencent/wiki/Spring-Cloud-Tencent-Discovery-%E4%BD%BF%E7%94%A8%E6%96%87%E6%A1%A3)
- [Spring Cloud Tencent Config](https://github.com/Tencent/spring-cloud-tencent/wiki/Spring-Cloud-Tencent-Config-%E4%BD%BF%E7%94%A8%E6%96%87%E6%A1%A3)
- [Spring Cloud Tencent Rate Limit](https://github.com/Tencent/spring-cloud-tencent/wiki/Spring-Cloud-Tencent-Rate-Limit-%E4%BD%BF%E7%94%A8%E6%96%87%E6%A1%A3)
- [Spring Cloud Tencent CircuitBreaker](https://github.com/Tencent/spring-cloud-tencent/wiki/Spring-Cloud-Tencent-Circuitbreaker-%E4%BD%BF%E7%94%A8%E6%96%87%E6%A1%A3)
- [Spring Cloud Tencent Router](https://github.com/Tencent/spring-cloud-tencent/wiki/Spring-Cloud-Tencent-Router-%E4%BD%BF%E7%94%A8%E6%96%87%E6%A1%A3)
- [Spring Cloud Starter Tencent RPC Enhancement](https://github.com/Tencent/spring-cloud-tencent/wiki/RPC%E5%A2%9E%E5%BC%BA)
- [Spring Cloud Tencent Metadata Transfer](https://github.com/Tencent/spring-cloud-tencent/wiki/Spring-Cloud-Tencent-Metadata-Transfer-%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97)
- [Actuator Endpoint Extension](https://github.com/Tencent/spring-cloud-tencent/wiki/Actuator-Endpoint-%E6%89%A9%E5%B1%95)
- [Spring Cloud Tencent 版本管理](https://github.com/Tencent/spring-cloud-tencent/wiki/Spring-Cloud-Tencent-%E7%89%88%E6%9C%AC%E7%AE%A1%E7%90%86)
- [服务注册与发现](https://github.com/Tencent/spring-cloud-tencent/wiki/Spring-Cloud-Tencent-Discovery-%E4%BD%BF%E7%94%A8%E6%96%87%E6%A1%A3)
- [配置中心](https://github.com/Tencent/spring-cloud-tencent/wiki/Spring-Cloud-Tencent-Config-%E4%BD%BF%E7%94%A8%E6%96%87%E6%A1%A3)
- [服务限流](https://github.com/Tencent/spring-cloud-tencent/wiki/Spring-Cloud-Tencent-Rate-Limit-%E4%BD%BF%E7%94%A8%E6%96%87%E6%A1%A3)
- [服务熔断](https://github.com/Tencent/spring-cloud-tencent/wiki/Spring-Cloud-Tencent-Circuitbreaker-%E4%BD%BF%E7%94%A8%E6%96%87%E6%A1%A3)
- [服务路由](https://github.com/Tencent/spring-cloud-tencent/wiki/Spring-Cloud-Tencent-Router-%E4%BD%BF%E7%94%A8%E6%96%87%E6%A1%A3)
- [RPC增强](https://github.com/Tencent/spring-cloud-tencent/wiki/RPC%E5%A2%9E%E5%BC%BA)
- [元数据传递](https://github.com/Tencent/spring-cloud-tencent/wiki/Spring-Cloud-Tencent-Metadata-Transfer-%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97)
- [场景化插件](https://github.com/Tencent/spring-cloud-tencent/wiki/场景化插件)
- [Actuator Endpoint 扩展](https://github.com/Tencent/spring-cloud-tencent/wiki/Actuator-Endpoint-%E6%89%A9%E5%B1%95)
- 最佳实践
- [Multi-feature environment](https://github.com/Tencent/spring-cloud-tencent/wiki/%E5%A4%9A%E7%89%B9%E6%80%A7%E7%8E%AF%E5%A2%83)
- [Multi-registration and multi-discovery](https://github.com/Tencent/spring-cloud-tencent/wiki/Multi-registration-and-multi-discovery)
- [可观测性实践](https://github.com/Tencent/spring-cloud-tencent/wiki/可观测性实践)
- [测试环境路由](https://github.com/Tencent/spring-cloud-tencent/wiki/%E6%B5%8B%E8%AF%95%E7%8E%AF%E5%A2%83%E8%B7%AF%E7%94%B1)
- [Spring Cloud Gateway 流量染色](https://github.com/Tencent/spring-cloud-tencent/wiki/Spring-Cloud-Gateway-%E6%B5%81%E9%87%8F%E6%9F%93%E8%89%B2)
- [多注册与多发现](https://github.com/Tencent/spring-cloud-tencent/wiki/Multi-registration-and-multi-discovery)
- 开发文档
- [Project Structure Overview](https://github.com/Tencent/spring-cloud-tencent/wiki/%E9%A1%B9%E7%9B%AE%E6%A6%82%E8%A7%88)
- [Participate in co-construction](https://github.com/Tencent/spring-cloud-tencent/wiki/%E5%8F%82%E4%B8%8E%E5%85%B1%E5%BB%BA)
- [项目概览](https://github.com/Tencent/spring-cloud-tencent/wiki/%E9%A1%B9%E7%9B%AE%E6%A6%82%E8%A7%88)
- [参与共建](https://github.com/Tencent/spring-cloud-tencent/wiki/%E5%8F%82%E4%B8%8E%E5%85%B1%E5%BB%BA)
## 交流群

@ -8,7 +8,6 @@
[![Build Status](https://github.com/Tencent/spring-cloud-tencent/actions/workflows/junit_test.yml/badge.svg)](https://github.com/Tencent/spring-cloud-tencent/actions/workflows/junit_test.yml)
[![codecov.io](https://codecov.io/gh/Tencent/spring-cloud-tencent/branch/2021.0/graph/badge.svg)](https://codecov.io/gh/Tencent/spring-cloud-tencent?branch=2021.0)
[![Language grade: Java](https://img.shields.io/lgtm/grade/java/g/Tencent/spring-cloud-tencent.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/Tencent/spring-cloud-tencent/context:java)
English | [简体中文](./README-zh.md)
@ -115,10 +114,13 @@ You can build this project with command:
- [Spring Cloud Tencent Router](https://github.com/Tencent/spring-cloud-tencent/wiki/Spring-Cloud-Tencent-Router-%E4%BD%BF%E7%94%A8%E6%96%87%E6%A1%A3)
- [Spring Cloud Starter Tencent RPC Enhancement](https://github.com/Tencent/spring-cloud-tencent/wiki/RPC%E5%A2%9E%E5%BC%BA)
- [Spring Cloud Tencent Metadata Transfer](https://github.com/Tencent/spring-cloud-tencent/wiki/Spring-Cloud-Tencent-Metadata-Transfer-%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97)
- [Spring Cloud Tencent Plugins](https://github.com/Tencent/spring-cloud-tencent/wiki/%E5%9C%BA%E6%99%AF%E5%8C%96%E6%8F%92%E4%BB%B6)
- [Actuator Endpoint Extension](https://github.com/Tencent/spring-cloud-tencent/wiki/Actuator-Endpoint-%E6%89%A9%E5%B1%95)
- Best Practices
- [Observability Practice](https://github.com/Tencent/spring-cloud-tencent/wiki/%E5%8F%AF%E8%A7%82%E6%B5%8B%E6%80%A7%E5%AE%9E%E8%B7%B5)
- [Multi-feature environment](https://github.com/Tencent/spring-cloud-tencent/wiki/%E5%A4%9A%E7%89%B9%E6%80%A7%E7%8E%AF%E5%A2%83)
- [Spring Cloud Gateway Traffic Staining](https://github.com/Tencent/spring-cloud-tencent/wiki/Spring-Cloud-Gateway-%E6%B5%81%E9%87%8F%E6%9F%93%E8%89%B2)
- [Multi-registration and multi-discovery](https://github.com/Tencent/spring-cloud-tencent/wiki/Multi-registration-and-multi-discovery)
- Development documentation

@ -59,7 +59,7 @@ public class PolarisCircuitBreakerAutoConfiguration {
// Turn on circuitbreaker configuration
configuration.getConsumer().getCircuitBreaker().setEnable(true);
// Set excludeCircuitBreakInstances to false
// Set excludeCircuitBreakInstances to true
RecoverRouterConfig recoverRouterConfig = configuration.getConsumer().getServiceRouter()
.getPluginConfig(ServiceRouterConfig.DEFAULT_ROUTER_RECOVER, RecoverRouterConfig.class);

@ -18,10 +18,18 @@
package com.tencent.cloud.polaris.config.adapter;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import com.tencent.cloud.common.util.ReflectionUtils;
import com.tencent.polaris.api.utils.MapUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.boot.context.properties.ConfigurationPropertiesBean;
@ -31,6 +39,7 @@ import org.springframework.cloud.context.properties.ConfigurationPropertiesRebin
import org.springframework.context.ApplicationContext;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
/**
* Optimize {@link ConfigurationPropertiesRebinder}, only rebuild affected beans.
@ -39,9 +48,13 @@ import org.springframework.util.CollectionUtils;
*/
public class AffectedConfigurationPropertiesRebinder extends ConfigurationPropertiesRebinder {
private static final Logger LOGGER = LoggerFactory.getLogger(AffectedConfigurationPropertiesRebinder.class);
private ApplicationContext applicationContext;
private Map<String, ConfigurationPropertiesBean> propertiesBeans = new HashMap<>();
private final Map<String, Map<String, Object>> propertiesBeanDefaultValues = new ConcurrentHashMap<>();
public AffectedConfigurationPropertiesRebinder(ConfigurationPropertiesBeans beans) {
super(beans);
}
@ -53,6 +66,7 @@ public class AffectedConfigurationPropertiesRebinder extends ConfigurationProper
this.applicationContext = applicationContext;
propertiesBeans = ConfigurationPropertiesBean.getAll(applicationContext);
initPropertiesBeanDefaultValues(propertiesBeans);
}
@Override
@ -75,8 +89,62 @@ public class AffectedConfigurationPropertiesRebinder extends ConfigurationProper
.toString();
if (key.startsWith(propertiesPrefix)) {
rebind(name);
rebindDefaultValue(name, key);
}
});
});
}
private void rebindDefaultValue(String beanName, String key) {
String changeValue = applicationContext.getEnvironment().getProperty(key);
if (StringUtils.hasLength(changeValue)) {
return;
}
Map<String, Object> defaultValues = propertiesBeanDefaultValues.get(beanName);
if (MapUtils.isEmpty(defaultValues)) {
return;
}
try {
String fieldName = key.substring(key.lastIndexOf(".") + 1);
Object bean = applicationContext.getBean(beanName);
Field field = ReflectionUtils.findField(bean.getClass(), fieldName);
if (field != null) {
field.setAccessible(true);
field.set(bean, defaultValues.get(fieldName));
}
}
catch (Exception e) {
LOGGER.error("[SCT Config] rebind default value error, bean = {}, key = {}", beanName, key);
}
}
private void initPropertiesBeanDefaultValues(Map<String, ConfigurationPropertiesBean> propertiesBeans) {
if (MapUtils.isEmpty(propertiesBeans)) {
return;
}
for (ConfigurationPropertiesBean propertiesBean : propertiesBeans.values()) {
Map<String, Object> defaultValues = new HashMap<>();
try {
Object instance = propertiesBean.getInstance().getClass().getDeclaredConstructor((Class<?>[]) null).newInstance();
ReflectionUtils.doWithFields(instance.getClass(), field -> {
try {
field.setAccessible(true);
defaultValues.put(field.getName(), field.get(instance));
}
catch (Exception ignored) {
}
}, field -> {
int modifiers = field.getModifiers();
return !Modifier.isFinal(modifiers) && !Modifier.isStatic(modifiers) && ReflectionUtils.writableBeanField(field);
});
}
catch (Exception ignored) {
}
propertiesBeanDefaultValues.put(propertiesBean.getName(), defaultValues);
}
}
}

@ -81,6 +81,7 @@ public final class PolarisConfigFilePuller {
*
* @param compositePropertySource compositePropertySource
* @param activeProfiles activeProfiles
* @param defaultProfiles defaultProfiles
* @param serviceName serviceName
*/
public void initInternalConfigFiles(CompositePropertySource compositePropertySource, String[] activeProfiles,

@ -52,7 +52,6 @@ import static org.springframework.boot.context.config.ConfigData.Option.PROFILE_
* Load {@link ConfigData} via {@link PolarisConfigDataLoader}
*
* @author wlx
* @date 2022/7/5 11:14 PM
*/
public class PolarisConfigDataLoader implements ConfigDataLoader<PolarisConfigDataResource> {

@ -30,7 +30,6 @@ import org.springframework.boot.context.config.Profiles;
* A polaris configData resource from which {@link ConfigData} can be loaded.
*
* @author wlx
* @date 2022/7/5 11:13 PM
*/
public class PolarisConfigDataResource extends ConfigDataResource {

@ -52,7 +52,7 @@ public class PlaceholderHelper {
* @param beanFactory beanFactory
* @param beanName beanName
* @param placeholder placeholder
* @return "${somePropertyValue}" -> "the actual property value"
* @return "${somePropertyValue}" -&gt; "the actual property value"
*/
public Object resolvePropertyValue(ConfigurableBeanFactory beanFactory, String beanName, String placeholder) {
// resolve string value
@ -77,16 +77,16 @@ public class PlaceholderHelper {
}
/**
*
* @param propertyString propertyString
* @return
* Extract keys from placeholder, e.g.
* <li>${some.key} => "some.key"</li>
* <li>${some.key:${some.other.key:100}} => "some.key", "some.other.key"</li>
* <li>${${some.key}} => "some.key"</li>
* <li>${${some.key:other.key}} => "some.key"</li>
* <li>${${some.key}:${another.key}} => "some.key", "another.key"</li>
* <li>#{new java.text.SimpleDateFormat('${some.key}').parse('${another.key}')} => "some.key", "another.key"</li>
* @return Extract keys from placeholder, e.g.
* <ul>
* <li>${some.key} =&gt; "some.key"</li>
* <li>${some.key:${some.other.key:100}} =&gt; "some.key", "some.other.key"</li>
* <li>${${some.key}} =&gt; "some.key"</li>
* <li>${${some.key:other.key}} =&gt; "some.key"</li>
* <li>${${some.key}:${another.key}} =&gt; "some.key", "another.key"</li>
* <li>#{new java.text.SimpleDateFormat('${some.key}').parse('${another.key}')} =&gt; "some.key", "another.key"</li>
* </ul>
*/
public Set<String> extractPlaceholderKeys(String propertyString) {
Set<String> placeholderKeys = Sets.newHashSet();

@ -21,6 +21,7 @@ import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
@ -33,6 +34,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.DisposableBean;
/**
* Spring value auto registry.
@ -43,13 +45,14 @@ import org.springframework.beans.factory.BeanFactory;
*
* @author weihubeats 2022-7-10
*/
public class SpringValueRegistry {
public class SpringValueRegistry implements DisposableBean {
private static final Logger logger = LoggerFactory.getLogger(SpringValueRegistry.class);
private static final long CLEAN_INTERVAL_IN_SECONDS = 5;
private final Map<BeanFactory, Multimap<String, SpringValue>> registry = Maps.newConcurrentMap();
private final AtomicBoolean initialized = new AtomicBoolean(false);
private final Object LOCK = new Object();
private ScheduledExecutorService executor;
public void register(BeanFactory beanFactory, String key, SpringValue springValue) {
if (!registry.containsKey(beanFactory)) {
@ -77,8 +80,9 @@ public class SpringValueRegistry {
}
private void initialize() {
Executors.newSingleThreadScheduledExecutor(
new NamedThreadFactory("polaris-spring-value-registry")).scheduleAtFixedRate(
executor = Executors.newSingleThreadScheduledExecutor(
new NamedThreadFactory("polaris-spring-value-registry"));
executor.scheduleAtFixedRate(
() -> {
try {
scanAndClean();
@ -97,4 +101,9 @@ public class SpringValueRegistry {
springValues.entries().removeIf(springValue -> !springValue.getValue().isTargetBeanValid());
}
}
@Override
public void destroy() throws Exception {
executor.shutdown();
}
}

@ -21,6 +21,8 @@ import com.tencent.cloud.polaris.context.ConditionalOnPolarisEnabled;
import com.tencent.cloud.polaris.discovery.PolarisDiscoveryHandler;
import com.tencent.cloud.polaris.extend.consul.ConsulConfigModifier;
import com.tencent.cloud.polaris.extend.consul.ConsulContextProperties;
import com.tencent.cloud.polaris.extend.nacos.NacosConfigModifier;
import com.tencent.cloud.polaris.extend.nacos.NacosContextProperties;
import com.tencent.polaris.api.core.ConsumerAPI;
import com.tencent.polaris.api.core.ProviderAPI;
import com.tencent.polaris.client.api.SDKContext;
@ -38,7 +40,7 @@ import org.springframework.context.annotation.Import;
*/
@Configuration(proxyBeanMethods = false)
@ConditionalOnPolarisEnabled
@Import({PolarisDiscoveryProperties.class, ConsulContextProperties.class})
@Import({PolarisDiscoveryProperties.class, ConsulContextProperties.class, NacosContextProperties.class})
public class DiscoveryPropertiesAutoConfiguration {
@Bean
@ -66,4 +68,10 @@ public class DiscoveryPropertiesAutoConfiguration {
public PolarisDiscoveryConfigModifier polarisDiscoveryConfigModifier(PolarisDiscoveryProperties polarisDiscoveryProperties) {
return new PolarisDiscoveryConfigModifier(polarisDiscoveryProperties);
}
@Bean
@ConditionalOnMissingBean
public NacosConfigModifier nacosConfigModifier(@Autowired(required = false) NacosContextProperties nacosContextProperties) {
return new NacosConfigModifier(nacosContextProperties);
}
}

@ -0,0 +1,114 @@
/*
* 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.extend.nacos;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Map;
import java.util.Objects;
import com.tencent.cloud.common.constant.ContextConstant;
import com.tencent.cloud.polaris.context.PolarisConfigModifier;
import com.tencent.polaris.api.config.plugin.DefaultPlugins;
import com.tencent.polaris.factory.config.ConfigurationImpl;
import com.tencent.polaris.factory.config.consumer.DiscoveryConfigImpl;
import com.tencent.polaris.factory.config.global.ServerConnectorConfigImpl;
import com.tencent.polaris.factory.config.provider.RegisterConfigImpl;
import org.apache.commons.lang.StringUtils;
import org.springframework.util.CollectionUtils;
/**
* {@link PolarisConfigModifier} impl of Nacos.
*
* @author lingxiao.wlx
*/
public class NacosConfigModifier implements PolarisConfigModifier {
private static final String ID = "nacos";
/**
* nacos username.
*/
public static final String USERNAME = "username";
/**
* nacos password.
*/
public static final String PASSWORD = "password";
/**
* nacos contextPath.
*/
public static final String CONTEXT_PATH = "contextPath";
private final NacosContextProperties nacosContextProperties;
public NacosConfigModifier(NacosContextProperties nacosContextProperties) {
this.nacosContextProperties = nacosContextProperties;
}
@Override
public void modify(ConfigurationImpl configuration) {
if (Objects.isNull(nacosContextProperties) || !nacosContextProperties.isEnabled()) {
return;
}
if (CollectionUtils.isEmpty(configuration.getGlobal().getServerConnectors())) {
configuration.getGlobal().setServerConnectors(new ArrayList<>());
}
if (CollectionUtils.isEmpty(configuration.getGlobal().getServerConnectors())
&& null != configuration.getGlobal().getServerConnector()) {
configuration.getGlobal().getServerConnectors().add(configuration.getGlobal().getServerConnector());
}
ServerConnectorConfigImpl serverConnectorConfig = new ServerConnectorConfigImpl();
serverConnectorConfig.setId(ID);
if (StringUtils.isBlank(nacosContextProperties.getServerAddr())) {
throw new IllegalArgumentException("nacos server addr must not be empty, please set it by" +
"spring.cloud.nacos.discovery.server-addr");
}
serverConnectorConfig.setAddresses(
Collections.singletonList(nacosContextProperties.getServerAddr()));
serverConnectorConfig.setProtocol(DefaultPlugins.SERVER_CONNECTOR_NACOS);
Map<String, String> metadata = serverConnectorConfig.getMetadata();
if (StringUtils.isNotBlank(nacosContextProperties.getUsername())) {
metadata.put(USERNAME, nacosContextProperties.getUsername());
}
if (StringUtils.isNotBlank(nacosContextProperties.getPassword())) {
metadata.put(PASSWORD, nacosContextProperties.getPassword());
}
if (StringUtils.isNotBlank(nacosContextProperties.getContextPath())) {
metadata.put(CONTEXT_PATH, nacosContextProperties.getContextPath());
}
configuration.getGlobal().getServerConnectors().add(serverConnectorConfig);
DiscoveryConfigImpl discoveryConfig = new DiscoveryConfigImpl();
discoveryConfig.setServerConnectorId(ID);
discoveryConfig.setEnable(nacosContextProperties.isDiscoveryEnabled());
configuration.getConsumer().getDiscoveries().add(discoveryConfig);
RegisterConfigImpl registerConfig = new RegisterConfigImpl();
registerConfig.setServerConnectorId(ID);
registerConfig.setEnable(nacosContextProperties.isRegisterEnabled());
configuration.getProvider().getRegisters().add(registerConfig);
}
@Override
public int getOrder() {
return ContextConstant.ModifierOrder.LAST;
}
}

@ -0,0 +1,172 @@
/*
* 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.extend.nacos;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
* Discovery configuration of Nacos.
*
* @author lingxiao.wlx
*/
@ConfigurationProperties("spring.cloud.nacos")
public class NacosContextProperties {
/**
* Nacos default group name.
*/
public static final String DEFAULT_GROUP = "DEFAULT_GROUP";
/**
* Nacos default cluster name.
*/
public static final String DEFAULT_CLUSTER = "DEFAULT";
private boolean enabled = false;
@Value("${spring.cloud.nacos.discovery.enabled:#{'true'}}")
private boolean discoveryEnabled;
/**
* if you just want to subscribe on nacos , but don't want to register your service, set it to
* false.
*/
@Value("${spring.cloud.nacos.discovery.register-enabled:#{'true'}}")
private boolean registerEnabled;
/**
* nacos discovery server address.
*/
@Value("${spring.cloud.nacos.discovery.server-addr:}")
private String serverAddr;
/**
* the nacos authentication username.
*/
@Value("${spring.cloud.nacos.discovery.username:}")
private String username;
/**
* the nacos authentication password.
*/
@Value("${spring.cloud.nacos.discovery.password:}")
private String password;
/**
* cluster name for nacos .
*/
@Value("${spring.cloud.nacos.discovery.cluster-name:DEFAULT}")
private String clusterName = DEFAULT_CLUSTER;
/**
* group name for nacos.
*/
@Value("${spring.cloud.nacos.discovery.group:DEFAULT_GROUP}")
private String group = DEFAULT_GROUP;
private String contextPath;
public boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
public boolean isRegisterEnabled() {
return registerEnabled;
}
public void setRegisterEnabled(boolean registerEnabled) {
this.registerEnabled = registerEnabled;
}
public boolean isDiscoveryEnabled() {
return discoveryEnabled;
}
public void setDiscoveryEnabled(boolean discoveryEnabled) {
this.discoveryEnabled = discoveryEnabled;
}
public String getServerAddr() {
return serverAddr;
}
public void setServerAddr(String serverAddr) {
this.serverAddr = serverAddr;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getClusterName() {
return clusterName;
}
public void setClusterName(String clusterName) {
this.clusterName = clusterName;
}
public String getGroup() {
return group;
}
public void setGroup(String group) {
this.group = group;
}
public String getContextPath() {
return contextPath;
}
public void setContextPath(String contextPath) {
this.contextPath = contextPath;
}
@Override
public String toString() {
return "NacosContextProperties{" +
"enabled=" + enabled +
", discoveryEnabled=" + discoveryEnabled +
", registerEnabled=" + registerEnabled +
", serverAddr='" + serverAddr + '\'' +
", username='" + username + '\'' +
", password='" + password + '\'' +
", clusterName='" + clusterName + '\'' +
", group='" + group + '\'' +
", contextPath='" + contextPath + '\'' +
'}';
}
}

@ -21,10 +21,12 @@ package com.tencent.cloud.polaris.registry;
import java.net.URI;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import com.tencent.cloud.common.metadata.StaticMetadataManager;
import com.tencent.cloud.polaris.PolarisDiscoveryProperties;
import com.tencent.cloud.polaris.extend.consul.ConsulContextProperties;
import com.tencent.cloud.polaris.extend.nacos.NacosContextProperties;
import com.tencent.polaris.client.api.SDKContext;
import org.apache.commons.lang.StringUtils;
@ -33,6 +35,9 @@ import org.springframework.cloud.client.serviceregistry.Registration;
import org.springframework.lang.Nullable;
import org.springframework.util.CollectionUtils;
import static com.tencent.cloud.polaris.extend.nacos.NacosContextProperties.DEFAULT_CLUSTER;
import static com.tencent.cloud.polaris.extend.nacos.NacosContextProperties.DEFAULT_GROUP;
/**
* Registration object of Polaris.
*
@ -42,6 +47,8 @@ public class PolarisRegistration implements Registration {
private static final String METADATA_KEY_IP = "internal-ip";
private static final String METADATA_KEY_ADDRESS = "internal-address";
private static final String GROUP_SERVER_ID_FORMAT = "%s__%s";
private static final String NACOS_CLUSTER = "nacos.cluster";
private final PolarisDiscoveryProperties polarisDiscoveryProperties;
@ -51,6 +58,8 @@ public class PolarisRegistration implements Registration {
private final StaticMetadataManager staticMetadataManager;
private final NacosContextProperties nacosContextProperties;
private Map<String, String> metadata;
private String host;
@ -60,18 +69,30 @@ public class PolarisRegistration implements Registration {
public PolarisRegistration(
PolarisDiscoveryProperties polarisDiscoveryProperties,
@Nullable ConsulContextProperties consulContextProperties,
SDKContext context, StaticMetadataManager staticMetadataManager) {
SDKContext context, StaticMetadataManager staticMetadataManager,
@Nullable NacosContextProperties nacosContextProperties) {
this.polarisDiscoveryProperties = polarisDiscoveryProperties;
this.consulContextProperties = consulContextProperties;
this.polarisContext = context;
this.staticMetadataManager = staticMetadataManager;
this.nacosContextProperties = nacosContextProperties;
host = polarisContext.getConfig().getGlobal().getAPI().getBindIP();
}
@Override
public String getServiceId() {
return polarisDiscoveryProperties.getService();
if (Objects.isNull(nacosContextProperties)) {
return polarisDiscoveryProperties.getService();
}
else {
String group = nacosContextProperties.getGroup();
if (StringUtils.isNotBlank(group) && !DEFAULT_GROUP.equals(group)) {
return String.format(GROUP_SERVER_ID_FORMAT, group, polarisDiscoveryProperties.getService());
}
else {
return polarisDiscoveryProperties.getService();
}
}
}
@Override
@ -111,6 +132,12 @@ public class PolarisRegistration implements Registration {
instanceMetadata.put(METADATA_KEY_IP, host);
instanceMetadata.put(METADATA_KEY_ADDRESS, host + ":" + polarisDiscoveryProperties.getPort());
// put internal-nacos-cluster if necessary
String clusterName = nacosContextProperties.getClusterName();
if (StringUtils.isNotBlank(clusterName) && !DEFAULT_CLUSTER.equals(clusterName)) {
instanceMetadata.put(NACOS_CLUSTER, clusterName);
}
instanceMetadata.putAll(staticMetadataManager.getMergedStaticMetadata());
this.metadata = instanceMetadata;
@ -136,12 +163,14 @@ public class PolarisRegistration implements Registration {
boolean registerEnabled = false;
if (null != polarisDiscoveryProperties) {
registerEnabled |= polarisDiscoveryProperties.isRegisterEnabled();
registerEnabled = polarisDiscoveryProperties.isRegisterEnabled();
}
if (null != consulContextProperties && consulContextProperties.isEnabled()) {
registerEnabled |= consulContextProperties.isRegister();
}
if (null != nacosContextProperties && nacosContextProperties.isEnabled()) {
registerEnabled |= nacosContextProperties.isRegisterEnabled();
}
return registerEnabled;
}

@ -23,6 +23,7 @@ import com.tencent.cloud.polaris.PolarisDiscoveryProperties;
import com.tencent.cloud.polaris.discovery.PolarisDiscoveryAutoConfiguration;
import com.tencent.cloud.polaris.discovery.PolarisDiscoveryHandler;
import com.tencent.cloud.polaris.extend.consul.ConsulContextProperties;
import com.tencent.cloud.polaris.extend.nacos.NacosContextProperties;
import com.tencent.polaris.client.api.SDKContext;
import org.springframework.beans.factory.annotation.Autowired;
@ -61,8 +62,8 @@ public class PolarisServiceRegistryAutoConfiguration {
public PolarisRegistration polarisRegistration(
PolarisDiscoveryProperties polarisDiscoveryProperties,
@Autowired(required = false) ConsulContextProperties consulContextProperties,
SDKContext context, StaticMetadataManager staticMetadataManager) {
return new PolarisRegistration(polarisDiscoveryProperties, consulContextProperties, context, staticMetadataManager);
SDKContext context, StaticMetadataManager staticMetadataManager, NacosContextProperties nacosContextProperties) {
return new PolarisRegistration(polarisDiscoveryProperties, consulContextProperties, context, staticMetadataManager, nacosContextProperties);
}
@Bean

@ -65,6 +65,50 @@
"type": "java.lang.Long",
"defaultValue": 60000,
"description": "Millis interval of refresh of service info list. Default: 60000."
},
{
"name": "spring.cloud.nacos.discovery.enabled",
"type": "java.lang.Boolean",
"sourceType": "com.tencent.cloud.polaris.extend.nacos.NacosContextProperties",
"defaultValue": false
},
{
"name": "spring.cloud.nacos.discovery.group",
"type": "java.lang.String",
"description": "group name for nacos.",
"sourceType": "com.tencent.cloud.polaris.extend.nacos.NacosContextProperties",
"defaultValue": "DEFAULT_GROUP"
},
{
"name": "spring.cloud.nacos.discovery.password",
"type": "java.lang.String",
"description": "the nacos authentication password.",
"sourceType": "com.tencent.cloud.polaris.extend.nacos.NacosContextProperties"
},
{
"name": "spring.cloud.nacos.discovery.register-enabled",
"type": "java.lang.Boolean",
"description": "if you just want to subscribe on nacos , but don't want to register your service, set it to false.",
"sourceType": "com.tencent.cloud.polaris.extend.nacos.NacosContextProperties",
"defaultValue": false
},
{
"name": "spring.cloud.nacos.discovery.server-addr",
"type": "java.lang.String",
"description": "nacos discovery server address.",
"sourceType": "com.tencent.cloud.polaris.extend.nacos.NacosContextProperties"
},
{
"name": "spring.cloud.nacos.discovery.username",
"type": "java.lang.String",
"description": "the nacos authentication username.",
"sourceType": "com.tencent.cloud.polaris.extend.nacos.NacosContextProperties"
},
{
"name": "spring.cloud.nacos.discovery.cluster-name",
"type": "java.lang.String",
"description": "the nacos authentication cluster-name.",
"sourceType": "com.tencent.cloud.polaris.extend.nacos.NacosContextProperties"
}
]
}

@ -62,13 +62,12 @@ public class PolarisDiscoveryClientTest {
@Test
public void testGetServices() {
when(polarisServiceDiscovery.getServices()).thenReturn(singletonList(SERVICE_PROVIDER));
List<String> services = client.getServices();
assertThat(services).contains(SERVICE_PROVIDER).size().isEqualTo(1);
assertThat(services).size().isEqualTo(1);
assertThat(services.contains(SERVICE_PROVIDER)).isTrue();
}
@Test

@ -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.polaris.extend.nacos;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import com.tencent.polaris.api.config.plugin.DefaultPlugins;
import com.tencent.polaris.client.api.SDKContext;
import com.tencent.polaris.factory.config.global.ServerConnectorConfigImpl;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.util.CollectionUtils;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Test for {@link NacosContextProperties}.
*
* @author lingxiao.wlx
*/
@RunWith(SpringRunner.class)
@SpringBootTest(classes = NacosContextPropertiesTest.TestApplication.class)
@ActiveProfiles("test")
public class NacosContextPropertiesTest {
@Autowired
private NacosContextProperties nacosContextProperties;
@Autowired
private SDKContext sdkContext;
@Test
public void testDefaultInitialization() {
assertThat(nacosContextProperties).isNotNull();
assertThat(nacosContextProperties.isEnabled()).isTrue();
assertThat(nacosContextProperties.getServerAddr()).isEqualTo("127.0.0.1:8848");
assertThat(nacosContextProperties.isRegisterEnabled()).isTrue();
assertThat(nacosContextProperties.isDiscoveryEnabled()).isTrue();
assertThat(nacosContextProperties.getGroup()).isNotBlank();
assertThat(nacosContextProperties.getClusterName()).isNotBlank();
}
@Test
public void testModify() {
assertThat(sdkContext).isNotNull();
com.tencent.polaris.api.config.Configuration configuration = sdkContext.getConfig();
List<ServerConnectorConfigImpl> serverConnectorConfigs = configuration.getGlobal().getServerConnectors();
Optional<ServerConnectorConfigImpl> optionalServerConnectorConfig = serverConnectorConfigs.stream().filter(
item -> "nacos".equals(item.getId())
).findAny();
assertThat(optionalServerConnectorConfig.isPresent()).isTrue();
ServerConnectorConfigImpl serverConnectorConfig = optionalServerConnectorConfig.get();
if (!CollectionUtils.isEmpty(serverConnectorConfig.getAddresses())) {
assertThat(nacosContextProperties.getServerAddr().equals(serverConnectorConfig.getAddresses().get(0))).isTrue();
}
assertThat(DefaultPlugins.SERVER_CONNECTOR_NACOS.equals(serverConnectorConfig.getProtocol())).isTrue();
Map<String, String> metadata = serverConnectorConfig.getMetadata();
assertThat(metadata.get(NacosConfigModifier.USERNAME)).isEqualTo(nacosContextProperties.getUsername());
assertThat(metadata.get(NacosConfigModifier.PASSWORD)).isEqualTo(nacosContextProperties.getPassword());
assertThat(metadata.get(NacosConfigModifier.CONTEXT_PATH)).isEqualTo(nacosContextProperties.getContextPath());
}
@SpringBootApplication
protected static class TestApplication {
}
}

@ -23,6 +23,7 @@ import java.util.Map;
import com.tencent.cloud.common.metadata.StaticMetadataManager;
import com.tencent.cloud.polaris.PolarisDiscoveryProperties;
import com.tencent.cloud.polaris.extend.consul.ConsulContextProperties;
import com.tencent.cloud.polaris.extend.nacos.NacosContextProperties;
import com.tencent.polaris.api.config.Configuration;
import com.tencent.polaris.api.config.global.APIConfig;
import com.tencent.polaris.api.config.global.GlobalConfig;
@ -38,6 +39,7 @@ import static com.tencent.polaris.test.common.Consts.SERVICE_PROVIDER;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
/**
* Test for {@link PolarisRegistration}.
@ -49,6 +51,8 @@ public class PolarisRegistrationTest {
private PolarisRegistration polarisRegistration;
NacosContextProperties nacosContextProperties = mock(NacosContextProperties.class);
@Before
public void setUp() {
// mock PolarisDiscoveryProperties
@ -76,7 +80,7 @@ public class PolarisRegistrationTest {
doReturn(Collections.singletonMap("key1", "value1")).when(staticMetadataManager).getMergedStaticMetadata();
polarisRegistration = new PolarisRegistration(polarisDiscoveryProperties, consulContextProperties,
polarisContext, staticMetadataManager);
polarisContext, staticMetadataManager, nacosContextProperties);
}
@Test
@ -127,4 +131,24 @@ public class PolarisRegistrationTest {
public void testToString() {
System.out.println(polarisRegistration);
}
@Test
public void testGetNacosServiceId() {
String groupName = "group";
String format = "%s__%s";
when(nacosContextProperties.getGroup()).thenReturn(groupName);
String serviceId = polarisRegistration.getServiceId();
assertThat(String.format(format, groupName, SERVICE_PROVIDER).equals(serviceId));
}
@Test
public void testGetNacosMetadata() {
String clusterName = "cluster";
when(nacosContextProperties.getClusterName()).thenReturn(clusterName);
Map<String, String> metadata = polarisRegistration.getMetadata();
assertThat(metadata).isNotNull();
assertThat(metadata).isNotEmpty();
assertThat(metadata.size()).isEqualTo(4);
assertThat(metadata.get("nacos.cluster")).isEqualTo(clusterName);
}
}

@ -22,3 +22,14 @@ spring:
service-name: ${spring.application.name}
ip-address: 127.0.0.1
prefer-ip-address: true
nacos:
enabled: true
context-path: /nacos
discovery:
enabled: true
register-enabled: true
group: polaris
server-addr: 127.0.0.1:8848
username: nacos
password: nacos
cluster-name: polaris

@ -181,6 +181,7 @@ public class PolarisReactiveLoadBalancerClientFilter extends ReactiveLoadBalance
new ResponseData(exchange.getResponse(), new RequestData(exchange.getRequest()))))));
}
@Override
protected URI reconstructURI(ServiceInstance serviceInstance, URI original) {
return LoadBalancerUriTools.reconstructURI(serviceInstance, original);
}

@ -19,16 +19,34 @@ package com.tencent.cloud.common.util;
import java.lang.reflect.Field;
import org.springframework.util.ClassUtils;
import static java.util.Locale.ENGLISH;
/**
* Reflection Utils.
*
* @author Haotian Zhang
*/
public final class ReflectionUtils {
public final class ReflectionUtils extends org.springframework.util.ReflectionUtils {
private final static String SET_PREFIX = "set";
private ReflectionUtils() {
}
public static boolean writableBeanField(Field field) {
String fieldName = field.getName();
String setMethodName = SET_PREFIX + capitalize(fieldName);
return ClassUtils.hasMethod(field.getDeclaringClass(), setMethodName, field.getType());
}
public static String capitalize(String name) {
if (name == null || name.length() == 0) {
return name;
}
return name.substring(0, 1).toUpperCase(ENGLISH) + name.substring(1);
}
public static Object getFieldValue(Object instance, String fieldName) {
Field field = org.springframework.util.ReflectionUtils.findField(instance.getClass(), fieldName);
if (field == null) {

@ -78,7 +78,7 @@
<logback.version>1.2.11</logback.version>
<mocktio.version>4.5.1</mocktio.version>
<byte-buddy.version>1.12.10</byte-buddy.version>
<protobuf-java.version>3.16.1</protobuf-java.version>
<protobuf-java.version>3.21.7</protobuf-java.version>
<bcprov-jdk15on.version>1.69</bcprov-jdk15on.version>
<system-stubs-junit4.version>2.0.1</system-stubs-junit4.version>

@ -5,7 +5,6 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* @author wlx
* @date 2022/7/6 9:15 PM
*/
@SpringBootApplication
public class PolarisConfigDataExampleApplication {

@ -34,6 +34,8 @@ public class Person {
private int age;
private boolean isDirector;
public String getName() {
return name;
}
@ -50,8 +52,17 @@ public class Person {
this.age = age;
}
public boolean isDirector() {
return isDirector;
}
public void setIsDirector(boolean isDirector) {
this.isDirector = isDirector;
}
@Override
public String toString() {
return "User{" + "name='" + name + '\'' + ", age=" + age + '}';
return "User{" + "name='" + name + '\'' + ", age=" + age + ", isDirector=" + isDirector + '\'' + '}';
}
}

@ -41,6 +41,17 @@ spring:
# service-name: ${spring.application.name}
# ip-address: localhost
# prefer-ip-address: true
# nacos:
# enabled: true
# context-path: /nacos
# discovery:
# enabled: true
# register-enabled: true
# group: polaris
# server-addr: 127.0.0.1:8848
# username: nacos
# password: nacos
# cluster-name: polaris
#eureka:
# client:
# serviceUrl:

@ -69,6 +69,11 @@
<artifactId>connector-consul</artifactId>
</dependency>
<dependency>
<groupId>com.tencent.polaris</groupId>
<artifactId>connector-nacos</artifactId>
</dependency>
<dependency>
<groupId>com.tencent.polaris</groupId>
<artifactId>connector-composite</artifactId>

Loading…
Cancel
Save