1
0
mirror of https://gitee.com/mirrors/Spring-Cloud-Alibaba.git synced 2021-06-26 13:25:11 +08:00

nacos starter 支持可自定义dataid配置以及Nacos 商业化和云上ACM 对接

This commit is contained in:
pbting 2018-12-04 09:59:55 +08:00
parent b5ad5acf10
commit ba90952880
13 changed files with 287 additions and 84 deletions

View File

@ -18,7 +18,7 @@
<properties>
<sentinel.version>1.3.0-GA</sentinel.version>
<oss.version>3.1.0</oss.version>
<nacos.version>0.4.0</nacos.version>
<nacos.version>0.5.0</nacos.version>
<acm.version>1.0.8</acm.version>
<ans.version>0.1.1</ans.version>
<aliyun.sdk.version>4.0.1</aliyun.sdk.version>

View File

@ -16,15 +16,8 @@
package org.springframework.cloud.alibaba.nacos;
import java.util.Arrays;
import java.util.Objects;
import java.util.Properties;
import javax.annotation.PostConstruct;
import com.alibaba.nacos.api.NacosFactory;
import com.alibaba.nacos.api.config.ConfigService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
@ -32,14 +25,13 @@ import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.core.env.Environment;
import static com.alibaba.nacos.api.PropertyKeyConst.ACCESS_KEY;
import static com.alibaba.nacos.api.PropertyKeyConst.CLUSTER_NAME;
import static com.alibaba.nacos.api.PropertyKeyConst.CONTEXT_PATH;
import static com.alibaba.nacos.api.PropertyKeyConst.ENCODE;
import static com.alibaba.nacos.api.PropertyKeyConst.ENDPOINT;
import static com.alibaba.nacos.api.PropertyKeyConst.NAMESPACE;
import static com.alibaba.nacos.api.PropertyKeyConst.SECRET_KEY;
import static com.alibaba.nacos.api.PropertyKeyConst.SERVER_ADDR;
import javax.annotation.PostConstruct;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.Properties;
import static com.alibaba.nacos.api.PropertyKeyConst.*;
/**
* nacos properties
@ -118,6 +110,21 @@ public class NacosConfigProperties {
private String[] activeProfiles;
/**
* the dataids for configurable multiple shared configurations , multiple separated by commas .
*/
private String sharedDataids ;
/**
* refreshable dataids , multiple separated by commas .
*/
private String refreshableDataids ;
/**
* a set of extended configurations .
*/
private List<Config> extConfig ;
private ConfigService configService;
@Autowired
@ -234,10 +241,66 @@ public class NacosConfigProperties {
return activeProfiles;
}
public String getSharedDataids() {
return sharedDataids;
}
public void setSharedDataids(String sharedDataids) {
this.sharedDataids = sharedDataids;
}
public String getRefreshableDataids() {
return refreshableDataids;
}
public void setRefreshableDataids(String refreshableDataids) {
this.refreshableDataids = refreshableDataids;
}
public List<Config> getExtConfig() {
return extConfig;
}
public void setExtConfig(List<Config> extConfig) {
this.extConfig = extConfig;
}
public static class Config{
private String dataId;
private String group = "DEFAULT_GROUP";
private boolean refresh = false;
public String getDataId() {
return dataId;
}
public void setDataId(String dataId) {
this.dataId = dataId;
}
public String getGroup() {
return group;
}
public void setGroup(String group) {
this.group = group;
}
public boolean isRefresh() {
return refresh;
}
public void setRefresh(boolean refresh) {
this.refresh = refresh;
}
}
@Override
public String toString() {
return "NacosConfigProperties{" + "serverAddr='" + serverAddr + '\''
+ ", encode='" + encode + '\'' + ", group='" + group + '\'' + ", prefix='"
+ ", encode='" + encode + '\'' + ", group='" + group + '\''
+ ", sharedDataids='" + this.sharedDataids + '\''
+ ", refreshableDataids='" + this.refreshableDataids + '\'' + ", prefix='"
+ prefix + '\'' + ", fileExtension='" + fileExtension + '\''
+ ", timeout=" + timeout + ", endpoint='" + endpoint + '\''
+ ", namespace='" + namespace + '\'' + ", accessKey='" + accessKey + '\''

View File

@ -16,16 +16,21 @@
package org.springframework.cloud.alibaba.nacos.client;
import org.springframework.core.env.MapPropertySource;
import java.util.Date;
import java.util.Map;
import org.springframework.core.env.MapPropertySource;
/**
* @author xiaojing
*/
public class NacosPropertySource extends MapPropertySource {
/**
* Nacos Group
*/
private final String group;
/**
* Nacos dataID
*/
@ -36,11 +41,21 @@ public class NacosPropertySource extends MapPropertySource {
*/
private final Date timestamp;
/**
* Whether to support dynamic refresh for this Property Source
*/
private final boolean isRefreshable ;
NacosPropertySource(String dataId, Map<String, Object> source, Date timestamp) {
NacosPropertySource(String group,String dataId, Map<String, Object> source, Date timestamp,boolean isRefreshable) {
super(dataId, source);
this.group = group;
this.dataId = dataId;
this.timestamp = timestamp;
this.isRefreshable = isRefreshable ;
}
public String getGroup(){
return this.group;
}
public String getDataId() {
@ -51,4 +66,7 @@ public class NacosPropertySource extends MapPropertySource {
return timestamp;
}
public boolean isRefreshable(){
return isRefreshable;
}
}

View File

@ -16,22 +16,17 @@
package org.springframework.cloud.alibaba.nacos.client;
import java.io.StringReader;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import com.alibaba.nacos.api.config.ConfigService;
import com.alibaba.nacos.api.exception.NacosException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.config.YamlPropertiesFactoryBean;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.util.StringUtils;
import java.io.StringReader;
import java.util.*;
/**
* @author xiaojing
*/
@ -71,12 +66,12 @@ public class NacosPropertySourceBuilder {
* @param dataId Nacos dataId
* @param group Nacos group
*/
NacosPropertySource build(String dataId, String group, String fileExtension) {
NacosPropertySource build(String dataId, String group, String fileExtension, boolean isRefreshable) {
Properties p = loadNacosData(dataId, group, fileExtension);
if (p == null) {
return null;
}
return new NacosPropertySource(dataId, propertiesToMap(p), new Date());
return new NacosPropertySource(group,dataId, propertiesToMap(p), new Date(), isRefreshable);
}
private Properties loadNacosData(String dataId, String group, String fileExtension) {

View File

@ -16,6 +16,7 @@
package org.springframework.cloud.alibaba.nacos.client;
import com.alibaba.nacos.api.config.ConfigService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
@ -26,8 +27,8 @@ import org.springframework.core.env.CompositePropertySource;
import org.springframework.core.env.Environment;
import org.springframework.core.env.PropertySource;
import org.springframework.util.StringUtils;
import com.alibaba.nacos.api.config.ConfigService;
import java.util.Arrays;
import java.util.List;
/**
* @author xiaojing
@ -40,6 +41,8 @@ public class NacosPropertySourceLocator implements PropertySourceLocator {
private static final String NACOS_PROPERTY_SOURCE_NAME = "NACOS";
private static final String SEP1 = "-";
private static final String DOT = ".";
private static final String SHARED_CONFIG_SEPRATOR_CHAR = "[,]";
private static final List<String> SUPPORT_FILE_EXTENSION = Arrays.asList("properties","yaml","yml");
@Autowired
private NacosConfigProperties nacosConfigProperties;
@ -73,29 +76,112 @@ public class NacosPropertySourceLocator implements PropertySourceLocator {
CompositePropertySource composite = new CompositePropertySource(
NACOS_PROPERTY_SOURCE_NAME);
loadSharedConfiguration(composite);
loadExtConfiguration(composite);
loadApplicationConfiguration(composite, nacosGroup, dataIdPrefix, fileExtension);
return composite;
}
private void loadSharedConfiguration(CompositePropertySource compositePropertySource){
String sharedDataIds = nacosConfigProperties.getSharedDataids();
String refreshDataIds = nacosConfigProperties.getRefreshableDataids();
if (sharedDataIds == null || sharedDataIds.trim().length() == 0){
return ;
}
String[] sharedDataIdArry = sharedDataIds.split(SHARED_CONFIG_SEPRATOR_CHAR) ;
checkDataIdFileExtension(sharedDataIdArry);
for (int i =0;i < sharedDataIdArry.length; i++){
String dataId = sharedDataIdArry[i];
String fileExtension = dataId.substring(dataId.lastIndexOf(".")+1);
boolean isRefreshable = checkDataIdIsRefreshbable(refreshDataIds,sharedDataIdArry[i]);
loadNacosDataIfPresent(compositePropertySource,dataId,"DEFAULT_GROUP",fileExtension, isRefreshable);
}
}
private void loadExtConfiguration(CompositePropertySource compositePropertySource){
if (nacosConfigProperties.getExtConfig() == null || nacosConfigProperties.getExtConfig().isEmpty()){
return;
}
List<NacosConfigProperties.Config> extConfigs = nacosConfigProperties.getExtConfig();
checkExtConfiguration(extConfigs);
for (NacosConfigProperties.Config config : extConfigs){
String dataId = config.getDataId();
String fileExtension = dataId.substring(dataId.lastIndexOf(".")+1);
loadNacosDataIfPresent(compositePropertySource,dataId,config.getGroup(),fileExtension,config.isRefresh());
}
}
private void checkExtConfiguration(List<NacosConfigProperties.Config> extConfigs) {
String[] dataIds = new String[extConfigs.size()];
for (int i=0;i<extConfigs.size(); i++){
String dataId = extConfigs.get(i).getDataId();
if (dataId == null || dataId.trim().length() == 0){
throw new IllegalStateException(String.format("the [ spring.cloud.nacos.config.ext-config[%s] ] must give a dataid", i));
}
dataIds[i] = dataId;
}
checkDataIdFileExtension(dataIds);
}
private void loadApplicationConfiguration(
CompositePropertySource compositePropertySource, String nacosGroup,
String dataIdPrefix, String fileExtension) {
loadNacosDataIfPresent(compositePropertySource,
dataIdPrefix + DOT + fileExtension, nacosGroup, fileExtension);
dataIdPrefix + DOT + fileExtension, nacosGroup, fileExtension, true);
for (String profile : nacosConfigProperties.getActiveProfiles()) {
String dataId = dataIdPrefix + SEP1 + profile + DOT + fileExtension;
loadNacosDataIfPresent(compositePropertySource, dataId, nacosGroup,
fileExtension);
fileExtension, true);
}
}
private void loadNacosDataIfPresent(final CompositePropertySource composite,
final String dataId, final String group, String fileExtension) {
final String dataId, final String group, String fileExtension, boolean isRefreshable) {
NacosPropertySource ps = nacosPropertySourceBuilder.build(dataId, group,
fileExtension);
fileExtension, isRefreshable);
if (ps != null) {
composite.addFirstPropertySource(ps);
}
}
private static void checkDataIdFileExtension(String[] sharedDataIdArry){
StringBuilder stringBuilder = new StringBuilder();
outline:for (int i=0;i < sharedDataIdArry.length; i++){
for (String fileExtension:SUPPORT_FILE_EXTENSION) {
if (sharedDataIdArry[i].indexOf(fileExtension) > 0){
continue outline;
}
}
stringBuilder.append(sharedDataIdArry[i]+",");
}
if (stringBuilder.length() > 0){
String result = stringBuilder.substring(0,stringBuilder.length()-1);
throw new IllegalStateException(String.format("[%s] must contains file extension with properties|yaml|yml", result));
}
}
private boolean checkDataIdIsRefreshbable(String refreshDataIds,String sharedDataId){
if (refreshDataIds == null || "".equals(refreshDataIds)){
return false ;
}
String[] refreshDataIdArry = refreshDataIds.split(SHARED_CONFIG_SEPRATOR_CHAR);
for (String refreshDataId : refreshDataIdArry){
if (refreshDataId.equals(sharedDataId)){
return true ;
}
}
return false ;
}
}

View File

@ -16,14 +16,9 @@
package org.springframework.cloud.alibaba.nacos.refresh;
import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executor;
import com.alibaba.nacos.api.config.ConfigService;
import com.alibaba.nacos.api.config.listener.Listener;
import com.alibaba.nacos.api.exception.NacosException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.context.event.ApplicationReadyEvent;
@ -34,9 +29,13 @@ import org.springframework.cloud.context.refresh.ContextRefresher;
import org.springframework.context.ApplicationListener;
import org.springframework.util.StringUtils;
import com.alibaba.nacos.api.config.ConfigService;
import com.alibaba.nacos.api.config.listener.Listener;
import com.alibaba.nacos.api.exception.NacosException;
import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executor;
/**
* On application start up, NacosContextRefresher add nacos listeners to all application
@ -85,13 +84,17 @@ public class NacosContextRefresher implements ApplicationListener<ApplicationRea
if (refreshProperties.isEnabled()) {
for (NacosPropertySource nacosPropertySource : nacosPropertySourceRepository
.getAll()) {
if (!nacosPropertySource.isRefreshable()){
continue;
}
String dataId = nacosPropertySource.getDataId();
registerNacosListener(dataId);
registerNacosListener(nacosPropertySource.getGroup(),dataId);
}
}
}
private void registerNacosListener(final String dataId) {
private void registerNacosListener(final String group, final String dataId) {
Listener listener = listenerMap.computeIfAbsent(dataId, i -> new Listener() {
@Override
@ -103,7 +106,7 @@ public class NacosContextRefresher implements ApplicationListener<ApplicationRea
md5 = new BigInteger(1, md.digest(configInfo.getBytes("UTF-8")))
.toString(16);
} catch (NoSuchAlgorithmException | UnsupportedEncodingException e) {
logger.warn("unable to get md5 for dataId: " + dataId, e);
logger.warn("[Nacos] unable to get md5 for dataId: " + dataId, e);
}
}
refreshHistory.add(dataId, md5);
@ -117,7 +120,7 @@ public class NacosContextRefresher implements ApplicationListener<ApplicationRea
});
try {
configService.addListener(dataId, properties.getGroup(), listener);
configService.addListener(dataId, group, listener);
} catch (NacosException e) {
e.printStackTrace();
}

View File

@ -16,6 +16,8 @@
package org.springframework.cloud.alibaba.nacos;
import com.alibaba.nacos.api.naming.pojo.Instance;
import com.alibaba.nacos.api.naming.pojo.ListView;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
@ -24,9 +26,6 @@ import org.springframework.cloud.client.discovery.DiscoveryClient;
import java.util.*;
import com.alibaba.nacos.api.naming.pojo.Instance;
import com.alibaba.nacos.api.naming.pojo.ListView;
/**
* @author xiaojing
* @author renhaojun
@ -68,7 +67,7 @@ public class NacosDiscoveryClient implements DiscoveryClient {
metadata.put("instanceId", instance.getInstanceId());
metadata.put("weight", instance.getWeight() + "");
metadata.put("healthy", instance.isHealthy() + "");
metadata.put("cluster", instance.getCluster() + "");
metadata.put("cluster", instance.getClusterName() + "");
metadata.putAll(instance.getMetadata());
nacosServiceInstance.setMetadata(metadata);
return nacosServiceInstance;

View File

@ -16,6 +16,9 @@
package org.springframework.cloud.alibaba.nacos;
import com.alibaba.nacos.api.NacosFactory;
import com.alibaba.nacos.api.naming.NamingService;
import com.alibaba.nacos.client.naming.utils.UtilAndComs;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
@ -24,29 +27,14 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cloud.commons.util.InetUtils;
import org.springframework.core.env.Environment;
import org.springframework.util.StringUtils;
import javax.annotation.PostConstruct;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.Properties;
import java.util.*;
import com.alibaba.nacos.api.NacosFactory;
import com.alibaba.nacos.api.naming.NamingService;
import com.alibaba.nacos.client.naming.utils.UtilAndComs;
import static com.alibaba.nacos.api.PropertyKeyConst.ACCESS_KEY;
import static com.alibaba.nacos.api.PropertyKeyConst.CLUSTER_NAME;
import static com.alibaba.nacos.api.PropertyKeyConst.ENDPOINT;
import static com.alibaba.nacos.api.PropertyKeyConst.NAMESPACE;
import static com.alibaba.nacos.api.PropertyKeyConst.SECRET_KEY;
import static com.alibaba.nacos.api.PropertyKeyConst.SERVER_ADDR;
import static com.alibaba.nacos.api.PropertyKeyConst.*;
/**
* @author dungu.zpf
@ -96,6 +84,11 @@ public class NacosDiscoveryProperties {
*/
private String clusterName = "DEFAULT";
/**
* naming load from local cache at application start. true is load
*/
private String namingLoadCacheAtStart = "false";
/**
* extra metadata to register.
*/
@ -313,7 +306,15 @@ public class NacosDiscoveryProperties {
this.secretKey = secretKey;
}
@Override
public String getNamingLoadCacheAtStart() {
return namingLoadCacheAtStart;
}
public void setNamingLoadCacheAtStart(String namingLoadCacheAtStart) {
this.namingLoadCacheAtStart = namingLoadCacheAtStart;
}
@Override
public String toString() {
return "NacosDiscoveryProperties{" + "serverAddr='" + serverAddr + '\''
+ ", endpoint='" + endpoint + '\'' + ", namespace='" + namespace + '\''
@ -322,7 +323,7 @@ public class NacosDiscoveryProperties {
+ ", metadata=" + metadata + ", registerEnabled=" + registerEnabled
+ ", ip='" + ip + '\'' + ", networkInterface='" + networkInterface + '\''
+ ", port=" + port + ", secure=" + secure + ", accessKey='" + accessKey
+ '\'' + ", secretKey='" + secretKey + '\'' + '}';
+ ", namingLoadCacheAtStart=" + namingLoadCacheAtStart + '\'' + ", secretKey='" + secretKey + '\'' + '}';
}
public void overrideFromEnv(Environment env) {
@ -371,6 +372,8 @@ public class NacosDiscoveryProperties {
properties.put(ACCESS_KEY, accessKey);
properties.put(SECRET_KEY, secretKey);
properties.put(CLUSTER_NAME, clusterName);
properties.put(NAMING_LOAD_CACHE_AT_START,namingLoadCacheAtStart);
try {
namingService = NacosFactory.createNamingService(properties);
return namingService;

View File

@ -16,15 +16,13 @@
package org.springframework.cloud.alibaba.nacos.registry;
import com.alibaba.nacos.api.naming.NamingService;
import com.alibaba.nacos.api.naming.pojo.Instance;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.client.serviceregistry.ServiceRegistry;
import org.springframework.util.StringUtils;
import com.alibaba.nacos.api.naming.NamingService;
import com.alibaba.nacos.api.naming.pojo.Cluster;
import com.alibaba.nacos.api.naming.pojo.Instance;
/**
* @author xiaojing
*/
@ -51,7 +49,7 @@ public class NacosServiceRegistry implements ServiceRegistry<NacosRegistration>
instance.setIp(registration.getHost());
instance.setPort(registration.getPort());
instance.setWeight(registration.getRegisterWeight());
instance.setCluster(new Cluster(registration.getCluster()));
instance.setClusterName(registration.getCluster());
instance.setMetadata(registration.getMetadata());
try {

View File

@ -16,12 +16,11 @@
package org.springframework.cloud.alibaba.nacos.ribbon;
import java.util.Map;
import com.alibaba.nacos.api.naming.pojo.Instance;
import com.netflix.loadbalancer.Server;
import java.util.Map;
/**
* @author xiaojing
*/
@ -37,7 +36,7 @@ public class NacosServer extends Server {
this.metaInfo = new MetaInfo() {
@Override
public String getAppName() {
return instance.serviceName();
return instance.getServiceName();
}
@Override

View File

@ -4,5 +4,11 @@
"type": "java.lang.String",
"defaultValue": "${spring.application.name}",
"description": "the service name to register, default value is ${spring.application.name}."
},
{
"name": "spring.cloud.nacos.discovery.namingLoadCacheAtStart",
"type": "java.lang.Boolean",
"defaultValue": "false",
"description": "naming load from local cache at application start ."
}
]}

View File

@ -0,0 +1,32 @@
package org.springframework.cloud.alicloud.context.nacos;
import com.alibaba.cloud.context.edas.EdasChangeOrderConfiguration;
import com.alibaba.cloud.context.edas.EdasChangeOrderConfigurationFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent;
import org.springframework.context.ApplicationListener;
public class NacosParameterInitListener implements ApplicationListener<ApplicationEnvironmentPreparedEvent> {
private static final Logger log = LoggerFactory.getLogger(NacosParameterInitListener.class);
@Override
public void onApplicationEvent(ApplicationEnvironmentPreparedEvent event) {
preparedNacosConfiguration();
}
private void preparedNacosConfiguration(){
EdasChangeOrderConfiguration edasChangeOrderConfiguration = EdasChangeOrderConfigurationFactory
.buildEdasChangeOrderConfiguration();
log.info("Initialize Nacos Parameter from edas change order,is edas managed {}.",edasChangeOrderConfiguration.isEdasManaged());
if (!edasChangeOrderConfiguration.isEdasManaged()) {
return ;
}
//initialize nacos configuration
System.getProperties().setProperty("spring.cloud.nacos.config.server-addr","");
System.getProperties().setProperty("spring.cloud.nacos.config.endpoint", edasChangeOrderConfiguration.getAddressServerDomain());
System.getProperties().setProperty("spring.cloud.nacos.config.namespace", edasChangeOrderConfiguration.getTenantId());
System.getProperties().setProperty("spring.cloud.nacos.config.access-key", edasChangeOrderConfiguration.getDauthAccessKey());
System.getProperties().setProperty("spring.cloud.nacos.config.secret-key", edasChangeOrderConfiguration.getDauthSecretKey());
}
}

View File

@ -6,4 +6,5 @@ org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.cloud.alicloud.context.ans.AnsContextAutoConfiguration,\
org.springframework.cloud.alicloud.context.oss.OssContextAutoConfiguration
org.springframework.context.ApplicationListener=\
org.springframework.cloud.alicloud.context.ans.AnsContextApplicationListener
org.springframework.cloud.alicloud.context.ans.AnsContextApplicationListener,\
org.springframework.cloud.alicloud.context.nacos.NacosParameterInitListener