commit
6963301441
@ -16,7 +16,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>com.alibaba.nacos</groupId>
|
<groupId>com.alibaba.nacos</groupId>
|
||||||
<artifactId>nacos-all</artifactId>
|
<artifactId>nacos-all</artifactId>
|
||||||
<version>0.7.0</version>
|
<version>0.8.0-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
@ -39,5 +39,7 @@ public class PropertyKeyConst {
|
|||||||
public final static String ENCODE = "encode";
|
public final static String ENCODE = "encode";
|
||||||
|
|
||||||
public final static String NAMING_LOAD_CACHE_AT_START = "namingLoadCacheAtStart";
|
public final static String NAMING_LOAD_CACHE_AT_START = "namingLoadCacheAtStart";
|
||||||
|
public final static String NAMING_CLIENT_BEAT_THREAD_COUNT = "namingClientBeatThreadCount";
|
||||||
|
public final static String NAMING_POLLING_THREAD_COUNT = "namingPollingThreadCount";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@ import java.util.Map;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:zpf.073@gmail.com">nkorange</a>
|
* @author <a href="mailto:zpf.073@gmail.com">nkorange</a>
|
||||||
|
* @since 0.7.0
|
||||||
*/
|
*/
|
||||||
public class Entity {
|
public class Entity {
|
||||||
|
|
||||||
|
@ -17,6 +17,7 @@ package com.alibaba.nacos.api.cmdb.pojo;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:zpf.073@gmail.com">nkorange</a>
|
* @author <a href="mailto:zpf.073@gmail.com">nkorange</a>
|
||||||
|
* @since 0.7.0
|
||||||
*/
|
*/
|
||||||
public class EntityEvent {
|
public class EntityEvent {
|
||||||
|
|
||||||
|
@ -17,6 +17,7 @@ package com.alibaba.nacos.api.cmdb.pojo;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:zpf.073@gmail.com">nkorange</a>
|
* @author <a href="mailto:zpf.073@gmail.com">nkorange</a>
|
||||||
|
* @since 0.7.0
|
||||||
*/
|
*/
|
||||||
public enum EntityEventType {
|
public enum EntityEventType {
|
||||||
/**
|
/**
|
||||||
|
@ -19,6 +19,7 @@ import java.util.Set;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:zpf.073@gmail.com">nkorange</a>
|
* @author <a href="mailto:zpf.073@gmail.com">nkorange</a>
|
||||||
|
* @since 0.7.0
|
||||||
*/
|
*/
|
||||||
public class Label {
|
public class Label {
|
||||||
|
|
||||||
|
@ -17,6 +17,7 @@ package com.alibaba.nacos.api.cmdb.pojo;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:zpf.073@gmail.com">nkorange</a>
|
* @author <a href="mailto:zpf.073@gmail.com">nkorange</a>
|
||||||
|
* @since 0.7.0
|
||||||
*/
|
*/
|
||||||
public enum PreservedEntityTypes {
|
public enum PreservedEntityTypes {
|
||||||
/**
|
/**
|
||||||
|
@ -27,6 +27,7 @@ import java.util.Set;
|
|||||||
* Service to visit CMDB store
|
* Service to visit CMDB store
|
||||||
*
|
*
|
||||||
* @author <a href="mailto:zpf.073@gmail.com">nkorange</a>
|
* @author <a href="mailto:zpf.073@gmail.com">nkorange</a>
|
||||||
|
* @since 0.7.0
|
||||||
*/
|
*/
|
||||||
public interface CmdbService {
|
public interface CmdbService {
|
||||||
|
|
||||||
|
@ -122,4 +122,10 @@ public class Constants {
|
|||||||
public static final String NAMING_HTTP_HEADER_SPILIER = "\\|";
|
public static final String NAMING_HTTP_HEADER_SPILIER = "\\|";
|
||||||
|
|
||||||
public static final String NAMING_DEFAULT_CLUSTER_NAME = "DEFAULT";
|
public static final String NAMING_DEFAULT_CLUSTER_NAME = "DEFAULT";
|
||||||
|
|
||||||
|
public static final String REQUEST_PARAM_NAMESPACE_ID = "namespaceId";
|
||||||
|
public static final String REQUEST_PARAM_DEFAULT_NAMESPACE_ID = "public";
|
||||||
|
public static final String REQUEST_PARAM_SERVICE_NAME = "serviceName";
|
||||||
|
public static final String REQUEST_PARAM_GROUP = "group";
|
||||||
|
public static final String REQUEST_PARAM_DEFAULT_GROUP = "DEFAULT_GROUP";
|
||||||
}
|
}
|
||||||
|
@ -34,8 +34,6 @@ public class NacosException extends Exception {
|
|||||||
public NacosException() {
|
public NacosException() {
|
||||||
}
|
}
|
||||||
|
|
||||||
;
|
|
||||||
|
|
||||||
public NacosException(int errCode, String errMsg) {
|
public NacosException(int errCode, String errMsg) {
|
||||||
this.errCode = errCode;
|
this.errCode = errCode;
|
||||||
this.errMsg = errMsg;
|
this.errMsg = errMsg;
|
||||||
|
@ -92,7 +92,17 @@ public interface NamingService {
|
|||||||
List<Instance> getAllInstances(String serviceName) throws NacosException;
|
List<Instance> getAllInstances(String serviceName) throws NacosException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* get all instances within specified clusters of a service
|
* Get all instances of a service
|
||||||
|
*
|
||||||
|
* @param serviceName name of service
|
||||||
|
* @param subscribe if subscribe the service
|
||||||
|
* @return A list of instance
|
||||||
|
* @throws NacosException
|
||||||
|
*/
|
||||||
|
List<Instance> getAllInstances(String serviceName, boolean subscribe) throws NacosException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all instances within specified clusters of a service
|
||||||
*
|
*
|
||||||
* @param serviceName name of service
|
* @param serviceName name of service
|
||||||
* @param clusters list of cluster
|
* @param clusters list of cluster
|
||||||
@ -102,7 +112,18 @@ public interface NamingService {
|
|||||||
List<Instance> getAllInstances(String serviceName, List<String> clusters) throws NacosException;
|
List<Instance> getAllInstances(String serviceName, List<String> clusters) throws NacosException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* get qualified instances of service
|
* Get all instances within specified clusters of a service
|
||||||
|
*
|
||||||
|
* @param serviceName name of service
|
||||||
|
* @param clusters list of cluster
|
||||||
|
* @param subscribe if subscribe the service
|
||||||
|
* @return A list of qualified instance
|
||||||
|
* @throws NacosException
|
||||||
|
*/
|
||||||
|
List<Instance> getAllInstances(String serviceName, List<String> clusters, boolean subscribe) throws NacosException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get qualified instances of service
|
||||||
*
|
*
|
||||||
* @param serviceName name of service
|
* @param serviceName name of service
|
||||||
* @param healthy a flag to indicate returning healthy or unhealthy instances
|
* @param healthy a flag to indicate returning healthy or unhealthy instances
|
||||||
@ -112,7 +133,18 @@ public interface NamingService {
|
|||||||
List<Instance> selectInstances(String serviceName, boolean healthy) throws NacosException;
|
List<Instance> selectInstances(String serviceName, boolean healthy) throws NacosException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* get qualified instances within specified clusters of service
|
* Get qualified instances of service
|
||||||
|
*
|
||||||
|
* @param serviceName name of service
|
||||||
|
* @param healthy a flag to indicate returning healthy or unhealthy instances
|
||||||
|
* @param subscribe if subscribe the service
|
||||||
|
* @return A qualified list of instance
|
||||||
|
* @throws NacosException
|
||||||
|
*/
|
||||||
|
List<Instance> selectInstances(String serviceName, boolean healthy, boolean subscribe) throws NacosException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get qualified instances within specified clusters of service
|
||||||
*
|
*
|
||||||
* @param serviceName name of service
|
* @param serviceName name of service
|
||||||
* @param clusters list of cluster
|
* @param clusters list of cluster
|
||||||
@ -123,7 +155,19 @@ public interface NamingService {
|
|||||||
List<Instance> selectInstances(String serviceName, List<String> clusters, boolean healthy) throws NacosException;
|
List<Instance> selectInstances(String serviceName, List<String> clusters, boolean healthy) throws NacosException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* select one healthy instance of service using predefined load balance strategy
|
* Get qualified instances within specified clusters of service
|
||||||
|
*
|
||||||
|
* @param serviceName name of service
|
||||||
|
* @param clusters list of cluster
|
||||||
|
* @param healthy a flag to indicate returning healthy or unhealthy instances
|
||||||
|
* @param subscribe if subscribe the service
|
||||||
|
* @return A qualified list of instance
|
||||||
|
* @throws NacosException
|
||||||
|
*/
|
||||||
|
List<Instance> selectInstances(String serviceName, List<String> clusters, boolean healthy, boolean subscribe) throws NacosException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Select one healthy instance of service using predefined load balance strategy
|
||||||
*
|
*
|
||||||
* @param serviceName name of service
|
* @param serviceName name of service
|
||||||
* @return qualified instance
|
* @return qualified instance
|
||||||
@ -135,6 +179,16 @@ public interface NamingService {
|
|||||||
* select one healthy instance of service using predefined load balance strategy
|
* select one healthy instance of service using predefined load balance strategy
|
||||||
*
|
*
|
||||||
* @param serviceName name of service
|
* @param serviceName name of service
|
||||||
|
* @param subscribe if subscribe the service
|
||||||
|
* @return qualified instance
|
||||||
|
* @throws NacosException
|
||||||
|
*/
|
||||||
|
Instance selectOneHealthyInstance(String serviceName, boolean subscribe) throws NacosException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Select one healthy instance of service using predefined load balance strategy
|
||||||
|
*
|
||||||
|
* @param serviceName name of service
|
||||||
* @param clusters a list of clusters should the instance belongs to
|
* @param clusters a list of clusters should the instance belongs to
|
||||||
* @return qualified instance
|
* @return qualified instance
|
||||||
* @throws NacosException
|
* @throws NacosException
|
||||||
@ -142,7 +196,18 @@ public interface NamingService {
|
|||||||
Instance selectOneHealthyInstance(String serviceName, List<String> clusters) throws NacosException;
|
Instance selectOneHealthyInstance(String serviceName, List<String> clusters) throws NacosException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* subscribe service to receive events of instances alteration
|
* Select one healthy instance of service using predefined load balance strategy
|
||||||
|
*
|
||||||
|
* @param serviceName name of service
|
||||||
|
* @param clusters a list of clusters should the instance belongs to
|
||||||
|
* @param subscribe if subscribe the service
|
||||||
|
* @return qualified instance
|
||||||
|
* @throws NacosException
|
||||||
|
*/
|
||||||
|
Instance selectOneHealthyInstance(String serviceName, List<String> clusters, boolean subscribe) throws NacosException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subscribe service to receive events of instances alteration
|
||||||
*
|
*
|
||||||
* @param serviceName name of service
|
* @param serviceName name of service
|
||||||
* @param listener event listener
|
* @param listener event listener
|
||||||
@ -197,6 +262,7 @@ public interface NamingService {
|
|||||||
* @param selector selector to filter the resource
|
* @param selector selector to filter the resource
|
||||||
* @return list of service names
|
* @return list of service names
|
||||||
* @throws NacosException
|
* @throws NacosException
|
||||||
|
* @since 0.7.0
|
||||||
*/
|
*/
|
||||||
ListView<String> getServicesOfServer(int pageNo, int pageSize, AbstractSelector selector) throws NacosException;
|
ListView<String> getServicesOfServer(int pageNo, int pageSize, AbstractSelector selector) throws NacosException;
|
||||||
|
|
||||||
|
@ -48,8 +48,6 @@ public class ServiceInfo {
|
|||||||
|
|
||||||
private String checksum = "";
|
private String checksum = "";
|
||||||
|
|
||||||
private String env = "";
|
|
||||||
|
|
||||||
private volatile boolean allIPs = false;
|
private volatile boolean allIPs = false;
|
||||||
|
|
||||||
public ServiceInfo() {
|
public ServiceInfo() {
|
||||||
@ -65,48 +63,22 @@ public class ServiceInfo {
|
|||||||
|
|
||||||
public ServiceInfo(String key) {
|
public ServiceInfo(String key) {
|
||||||
|
|
||||||
int maxKeySectionCount = 4;
|
int maxIndex = 2;
|
||||||
int allIpFlagIndex = 3;
|
|
||||||
int envIndex = 2;
|
|
||||||
int clusterIndex = 1;
|
int clusterIndex = 1;
|
||||||
int serviceNameIndex = 0;
|
int serviceNameIndex = 0;
|
||||||
|
|
||||||
String[] keys = key.split(SPLITER);
|
String[] keys = key.split(SPLITER);
|
||||||
if (keys.length >= maxKeySectionCount) {
|
if (keys.length >= maxIndex) {
|
||||||
this.name = keys[serviceNameIndex];
|
this.name = keys[serviceNameIndex];
|
||||||
this.clusters = keys[clusterIndex];
|
this.clusters = keys[clusterIndex];
|
||||||
this.env = keys[envIndex];
|
|
||||||
if (strEquals(keys[allIpFlagIndex], ALL_IPS)) {
|
|
||||||
this.setAllIPs(true);
|
|
||||||
}
|
|
||||||
} else if (keys.length >= allIpFlagIndex) {
|
|
||||||
this.name = keys[serviceNameIndex];
|
|
||||||
this.clusters = keys[clusterIndex];
|
|
||||||
if (strEquals(keys[envIndex], ALL_IPS)) {
|
|
||||||
this.setAllIPs(true);
|
|
||||||
} else {
|
|
||||||
this.env = keys[envIndex];
|
|
||||||
}
|
|
||||||
} else if (keys.length >= envIndex) {
|
|
||||||
this.name = keys[serviceNameIndex];
|
|
||||||
if (strEquals(keys[clusterIndex], ALL_IPS)) {
|
|
||||||
this.setAllIPs(true);
|
|
||||||
} else {
|
|
||||||
this.clusters = keys[clusterIndex];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.name = keys[0];
|
this.name = keys[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
public ServiceInfo(String name, String clusters) {
|
public ServiceInfo(String name, String clusters) {
|
||||||
this(name, clusters, EMPTY);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ServiceInfo(String name, String clusters, String env) {
|
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.clusters = clusters;
|
this.clusters = clusters;
|
||||||
this.env = env;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public int ipCount() {
|
public int ipCount() {
|
||||||
@ -158,7 +130,6 @@ public class ServiceInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public List<Instance> getHosts() {
|
public List<Instance> getHosts() {
|
||||||
|
|
||||||
return new ArrayList<Instance>(hosts);
|
return new ArrayList<Instance>(hosts);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -192,45 +163,39 @@ public class ServiceInfo {
|
|||||||
|
|
||||||
@JSONField(serialize = false)
|
@JSONField(serialize = false)
|
||||||
public String getKey() {
|
public String getKey() {
|
||||||
return getKey(name, clusters, env, isAllIPs());
|
return getKey(name, clusters);
|
||||||
}
|
}
|
||||||
|
|
||||||
@JSONField(serialize = false)
|
@JSONField(serialize = false)
|
||||||
public String getKeyEncoded() {
|
public String getKeyEncoded() {
|
||||||
try {
|
try {
|
||||||
return getKey(URLEncoder.encode(name, "UTF-8"), clusters, env, isAllIPs());
|
return getKey(URLEncoder.encode(name, "UTF-8"), clusters);
|
||||||
} catch (UnsupportedEncodingException e) {
|
} catch (UnsupportedEncodingException e) {
|
||||||
return getKey();
|
return getKey();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@JSONField(serialize = false)
|
@JSONField(serialize = false)
|
||||||
public static String getKey(String name, String clusters, String unit) {
|
public static ServiceInfo fromKey(String key) {
|
||||||
return getKey(name, clusters, unit, false);
|
ServiceInfo serviceInfo = new ServiceInfo();
|
||||||
|
|
||||||
|
if (key.contains(SPLITER)) {
|
||||||
|
serviceInfo.setName(key.split(SPLITER)[0]);
|
||||||
|
serviceInfo.setClusters(key.split(SPLITER)[1]);
|
||||||
|
return serviceInfo;
|
||||||
|
}
|
||||||
|
serviceInfo.setName(key);
|
||||||
|
return serviceInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
@JSONField(serialize = false)
|
@JSONField(serialize = false)
|
||||||
public static String getKey(String name, String clusters, String unit, boolean isAllIPs) {
|
public static String getKey(String name, String clusters) {
|
||||||
|
|
||||||
if (isEmpty(unit)) {
|
|
||||||
unit = EMPTY;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isEmpty(clusters) && !isEmpty(unit)) {
|
|
||||||
return isAllIPs ? name + SPLITER + clusters + SPLITER + unit + SPLITER + ALL_IPS
|
|
||||||
: name + SPLITER + clusters + SPLITER + unit;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isEmpty(clusters)) {
|
if (!isEmpty(clusters)) {
|
||||||
return isAllIPs ? name + SPLITER + clusters + SPLITER + ALL_IPS : name + SPLITER + clusters;
|
return name + SPLITER + clusters;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isEmpty(unit)) {
|
return name;
|
||||||
return isAllIPs ? name + SPLITER + EMPTY + SPLITER + unit + SPLITER + ALL_IPS :
|
|
||||||
name + SPLITER + EMPTY + SPLITER + unit;
|
|
||||||
}
|
|
||||||
|
|
||||||
return isAllIPs ? name + SPLITER + ALL_IPS : name;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -19,6 +19,7 @@ package com.alibaba.nacos.api.selector;
|
|||||||
* Abstract selector that only contains a type
|
* Abstract selector that only contains a type
|
||||||
*
|
*
|
||||||
* @author <a href="mailto:zpf.073@gmail.com">nkorange</a>
|
* @author <a href="mailto:zpf.073@gmail.com">nkorange</a>
|
||||||
|
* @since 0.7.0
|
||||||
*/
|
*/
|
||||||
public abstract class AbstractSelector {
|
public abstract class AbstractSelector {
|
||||||
|
|
||||||
|
@ -19,6 +19,7 @@ package com.alibaba.nacos.api.selector;
|
|||||||
* The selector to filter resource with flexible expression.
|
* The selector to filter resource with flexible expression.
|
||||||
*
|
*
|
||||||
* @author <a href="mailto:zpf.073@gmail.com">nkorange</a>
|
* @author <a href="mailto:zpf.073@gmail.com">nkorange</a>
|
||||||
|
* @since 0.7.0
|
||||||
*/
|
*/
|
||||||
public class ExpressionSelector extends AbstractSelector {
|
public class ExpressionSelector extends AbstractSelector {
|
||||||
|
|
||||||
|
@ -19,6 +19,7 @@ package com.alibaba.nacos.api.selector;
|
|||||||
* The types of selector accepted by Nacos
|
* The types of selector accepted by Nacos
|
||||||
*
|
*
|
||||||
* @author <a href="mailto:zpf.073@gmail.com">nkorange</a>
|
* @author <a href="mailto:zpf.073@gmail.com">nkorange</a>
|
||||||
|
* @since 0.7.0
|
||||||
*/
|
*/
|
||||||
public enum SelectorType {
|
public enum SelectorType {
|
||||||
/**
|
/**
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>com.alibaba.nacos</groupId>
|
<groupId>com.alibaba.nacos</groupId>
|
||||||
<artifactId>nacos-all</artifactId>
|
<artifactId>nacos-all</artifactId>
|
||||||
<version>0.7.0</version>
|
<version>0.8.0-SNAPSHOT</version>
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
@ -20,7 +20,6 @@ import com.alibaba.nacos.api.common.Constants;
|
|||||||
import com.alibaba.nacos.api.exception.NacosException;
|
import com.alibaba.nacos.api.exception.NacosException;
|
||||||
import com.alibaba.nacos.api.naming.NamingService;
|
import com.alibaba.nacos.api.naming.NamingService;
|
||||||
import com.alibaba.nacos.api.naming.listener.EventListener;
|
import com.alibaba.nacos.api.naming.listener.EventListener;
|
||||||
import com.alibaba.nacos.api.naming.pojo.Cluster;
|
|
||||||
import com.alibaba.nacos.api.naming.pojo.Instance;
|
import com.alibaba.nacos.api.naming.pojo.Instance;
|
||||||
import com.alibaba.nacos.api.naming.pojo.ListView;
|
import com.alibaba.nacos.api.naming.pojo.ListView;
|
||||||
import com.alibaba.nacos.api.naming.pojo.ServiceInfo;
|
import com.alibaba.nacos.api.naming.pojo.ServiceInfo;
|
||||||
@ -36,6 +35,7 @@ import com.alibaba.nacos.client.naming.utils.LogUtils;
|
|||||||
import com.alibaba.nacos.client.naming.utils.StringUtils;
|
import com.alibaba.nacos.client.naming.utils.StringUtils;
|
||||||
import com.alibaba.nacos.client.naming.utils.UtilAndComs;
|
import com.alibaba.nacos.client.naming.utils.UtilAndComs;
|
||||||
import org.apache.commons.lang3.BooleanUtils;
|
import org.apache.commons.lang3.BooleanUtils;
|
||||||
|
import org.apache.commons.lang3.math.NumberUtils;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
@ -102,7 +102,7 @@ public class NacosNamingService implements NamingService {
|
|||||||
eventDispatcher = new EventDispatcher();
|
eventDispatcher = new EventDispatcher();
|
||||||
serverProxy = new NamingProxy(namespace, endpoint, serverList);
|
serverProxy = new NamingProxy(namespace, endpoint, serverList);
|
||||||
beatReactor = new BeatReactor(serverProxy);
|
beatReactor = new BeatReactor(serverProxy);
|
||||||
hostReactor = new HostReactor(eventDispatcher, serverProxy, cacheDir, false);
|
hostReactor = new HostReactor(eventDispatcher, serverProxy, cacheDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
public NacosNamingService(Properties properties) {
|
public NacosNamingService(Properties properties) {
|
||||||
@ -132,10 +132,16 @@ public class NacosNamingService implements NamingService {
|
|||||||
properties.getProperty(PropertyKeyConst.NAMING_LOAD_CACHE_AT_START));
|
properties.getProperty(PropertyKeyConst.NAMING_LOAD_CACHE_AT_START));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int clientBeatThreadCount = NumberUtils.toInt(properties.getProperty(PropertyKeyConst.NAMING_CLIENT_BEAT_THREAD_COUNT),
|
||||||
|
UtilAndComs.DEFAULT_CLIENT_BEAT_THREAD_COUNT);
|
||||||
|
|
||||||
|
int pollingThreadCount = NumberUtils.toInt(properties.getProperty(PropertyKeyConst.NAMING_POLLING_THREAD_COUNT),
|
||||||
|
UtilAndComs.DEFAULT_POLLING_THREAD_COUNT);
|
||||||
|
|
||||||
eventDispatcher = new EventDispatcher();
|
eventDispatcher = new EventDispatcher();
|
||||||
serverProxy = new NamingProxy(namespace, endpoint, serverList);
|
serverProxy = new NamingProxy(namespace, endpoint, serverList);
|
||||||
beatReactor = new BeatReactor(serverProxy);
|
beatReactor = new BeatReactor(serverProxy, clientBeatThreadCount);
|
||||||
hostReactor = new HostReactor(eventDispatcher, serverProxy, cacheDir, loadCacheAtStart);
|
hostReactor = new HostReactor(eventDispatcher, serverProxy, cacheDir, loadCacheAtStart, pollingThreadCount);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -159,7 +165,7 @@ public class NacosNamingService implements NamingService {
|
|||||||
public void registerInstance(String serviceName, Instance instance) throws NacosException {
|
public void registerInstance(String serviceName, Instance instance) throws NacosException {
|
||||||
|
|
||||||
BeatInfo beatInfo = new BeatInfo();
|
BeatInfo beatInfo = new BeatInfo();
|
||||||
beatInfo.setDom(serviceName);
|
beatInfo.setServiceName(serviceName);
|
||||||
beatInfo.setIp(instance.getIp());
|
beatInfo.setIp(instance.getIp());
|
||||||
beatInfo.setPort(instance.getPort());
|
beatInfo.setPort(instance.getPort());
|
||||||
beatInfo.setCluster(instance.getClusterName());
|
beatInfo.setCluster(instance.getClusterName());
|
||||||
@ -189,10 +195,24 @@ public class NacosNamingService implements NamingService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Instance> getAllInstances(String serviceName, List<String> clusters) throws NacosException {
|
public List<Instance> getAllInstances(String serviceName, boolean subscribe) throws NacosException {
|
||||||
|
return getAllInstances(serviceName, new ArrayList<String>(), subscribe);
|
||||||
|
}
|
||||||
|
|
||||||
ServiceInfo serviceInfo = hostReactor.getServiceInfo(serviceName, StringUtils.join(clusters, ","),
|
@Override
|
||||||
StringUtils.EMPTY, false);
|
public List<Instance> getAllInstances(String serviceName, List<String> clusters) throws NacosException {
|
||||||
|
return getAllInstances(serviceName, clusters, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Instance> getAllInstances(String serviceName, List<String> clusters, boolean subscribe) throws NacosException {
|
||||||
|
|
||||||
|
ServiceInfo serviceInfo;
|
||||||
|
if (subscribe) {
|
||||||
|
serviceInfo = hostReactor.getServiceInfo(serviceName, StringUtils.join(clusters, ","));
|
||||||
|
} else {
|
||||||
|
serviceInfo = hostReactor.getServiceInfoDirectlyFromServer(serviceName, StringUtils.join(clusters, ","));
|
||||||
|
}
|
||||||
List<Instance> list;
|
List<Instance> list;
|
||||||
if (serviceInfo == null || CollectionUtils.isEmpty(list = serviceInfo.getHosts())) {
|
if (serviceInfo == null || CollectionUtils.isEmpty(list = serviceInfo.getHosts())) {
|
||||||
return new ArrayList<Instance>();
|
return new ArrayList<Instance>();
|
||||||
@ -201,41 +221,58 @@ public class NacosNamingService implements NamingService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Instance> selectInstances(String serviceName, boolean healthyOnly) throws NacosException {
|
public List<Instance> selectInstances(String serviceName, boolean healthy) throws NacosException {
|
||||||
return selectInstances(serviceName, new ArrayList<String>(), healthyOnly);
|
return selectInstances(serviceName, new ArrayList<String>(), healthy);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Instance> selectInstances(String serviceName, boolean healthy, boolean subscribe) throws NacosException {
|
||||||
|
return selectInstances(serviceName, new ArrayList<String>(), healthy, subscribe);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Instance> selectInstances(String serviceName, List<String> clusters, boolean healthy)
|
public List<Instance> selectInstances(String serviceName, List<String> clusters, boolean healthy)
|
||||||
throws NacosException {
|
throws NacosException {
|
||||||
|
return selectInstances(serviceName, clusters, healthy, true);
|
||||||
ServiceInfo serviceInfo = hostReactor.getServiceInfo(serviceName, StringUtils.join(clusters, ","),
|
|
||||||
StringUtils.EMPTY, false);
|
|
||||||
List<Instance> list;
|
|
||||||
if (serviceInfo == null || CollectionUtils.isEmpty(list = serviceInfo.getHosts())) {
|
|
||||||
return new ArrayList<Instance>();
|
|
||||||
}
|
|
||||||
|
|
||||||
Iterator<Instance> iterator = list.iterator();
|
|
||||||
while (iterator.hasNext()) {
|
|
||||||
Instance instance = iterator.next();
|
|
||||||
if (healthy != instance.isHealthy() || !instance.isEnabled() || instance.getWeight() <= 0) {
|
|
||||||
iterator.remove();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return list;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Instance selectOneHealthyInstance(String serviceName) {
|
public List<Instance> selectInstances(String serviceName, List<String> clusters, boolean healthy,
|
||||||
|
boolean subscribe) throws NacosException {
|
||||||
|
ServiceInfo serviceInfo;
|
||||||
|
if (subscribe) {
|
||||||
|
serviceInfo = hostReactor.getServiceInfo(serviceName, StringUtils.join(clusters, ","));
|
||||||
|
} else {
|
||||||
|
serviceInfo = hostReactor.getServiceInfoDirectlyFromServer(serviceName, StringUtils.join(clusters, ","));
|
||||||
|
}
|
||||||
|
return selectInstances(serviceInfo, healthy);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Instance selectOneHealthyInstance(String serviceName) throws NacosException {
|
||||||
return selectOneHealthyInstance(serviceName, new ArrayList<String>());
|
return selectOneHealthyInstance(serviceName, new ArrayList<String>());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Instance selectOneHealthyInstance(String serviceName, List<String> clusters) {
|
public Instance selectOneHealthyInstance(String serviceName, boolean subscribe) throws NacosException {
|
||||||
|
return selectOneHealthyInstance(serviceName, new ArrayList<String>(), subscribe);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Instance selectOneHealthyInstance(String serviceName, List<String> clusters) throws NacosException {
|
||||||
|
return selectOneHealthyInstance(serviceName, clusters, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Instance selectOneHealthyInstance(String serviceName, List<String> clusters, boolean subscribe) throws NacosException {
|
||||||
|
|
||||||
|
if (subscribe) {
|
||||||
return Balancer.RandomByWeight.selectHost(
|
return Balancer.RandomByWeight.selectHost(
|
||||||
hostReactor.getServiceInfo(serviceName, StringUtils.join(clusters, ",")));
|
hostReactor.getServiceInfo(serviceName, StringUtils.join(clusters, ",")));
|
||||||
|
} else {
|
||||||
|
return Balancer.RandomByWeight.selectHost(
|
||||||
|
hostReactor.getServiceInfoDirectlyFromServer(serviceName, StringUtils.join(clusters, ",")));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -272,7 +309,7 @@ public class NacosNamingService implements NamingService {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<ServiceInfo> getSubscribeServices() {
|
public List<ServiceInfo> getSubscribeServices() {
|
||||||
return new ArrayList<ServiceInfo>(hostReactor.getServiceInfoMap().values());
|
return eventDispatcher.getSubscribeServices();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -280,6 +317,23 @@ public class NacosNamingService implements NamingService {
|
|||||||
return serverProxy.serverHealthy() ? "UP" : "DOWN";
|
return serverProxy.serverHealthy() ? "UP" : "DOWN";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private List<Instance> selectInstances(ServiceInfo serviceInfo, boolean healthy) {
|
||||||
|
List<Instance> list;
|
||||||
|
if (serviceInfo == null || CollectionUtils.isEmpty(list = serviceInfo.getHosts())) {
|
||||||
|
return new ArrayList<Instance>();
|
||||||
|
}
|
||||||
|
|
||||||
|
Iterator<Instance> iterator = list.iterator();
|
||||||
|
while (iterator.hasNext()) {
|
||||||
|
Instance instance = iterator.next();
|
||||||
|
if (healthy != instance.isHealthy() || !instance.isEnabled() || instance.getWeight() <= 0) {
|
||||||
|
iterator.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
public BeatReactor getBeatReactor() {
|
public BeatReactor getBeatReactor() {
|
||||||
return beatReactor;
|
return beatReactor;
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,7 @@ public class BeatInfo {
|
|||||||
private int port;
|
private int port;
|
||||||
private String ip;
|
private String ip;
|
||||||
private double weight;
|
private double weight;
|
||||||
private String dom;
|
private String serviceName;
|
||||||
private String cluster;
|
private String cluster;
|
||||||
private Map<String, String> metadata;
|
private Map<String, String> metadata;
|
||||||
private boolean scheduled;
|
private boolean scheduled;
|
||||||
@ -37,12 +37,12 @@ public class BeatInfo {
|
|||||||
return JSON.toJSONString(this);
|
return JSON.toJSONString(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getDom() {
|
public String getServiceName() {
|
||||||
return dom;
|
return serviceName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setDom(String dom) {
|
public void setServiceName(String serviceName) {
|
||||||
this.dom = dom;
|
this.serviceName = serviceName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getCluster() {
|
public String getCluster() {
|
||||||
|
@ -15,15 +15,12 @@
|
|||||||
*/
|
*/
|
||||||
package com.alibaba.nacos.client.naming.beat;
|
package com.alibaba.nacos.client.naming.beat;
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSON;
|
|
||||||
import com.alibaba.fastjson.JSONObject;
|
|
||||||
import com.alibaba.nacos.api.common.Constants;
|
import com.alibaba.nacos.api.common.Constants;
|
||||||
import com.alibaba.nacos.client.monitor.MetricsMonitor;
|
import com.alibaba.nacos.client.monitor.MetricsMonitor;
|
||||||
import com.alibaba.nacos.client.naming.net.NamingProxy;
|
import com.alibaba.nacos.client.naming.net.NamingProxy;
|
||||||
import com.alibaba.nacos.client.naming.utils.LogUtils;
|
import com.alibaba.nacos.client.naming.utils.LogUtils;
|
||||||
import com.alibaba.nacos.client.naming.utils.UtilAndComs;
|
import com.alibaba.nacos.client.naming.utils.UtilAndComs;
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.*;
|
import java.util.concurrent.*;
|
||||||
|
|
||||||
@ -32,7 +29,22 @@ import java.util.concurrent.*;
|
|||||||
*/
|
*/
|
||||||
public class BeatReactor {
|
public class BeatReactor {
|
||||||
|
|
||||||
private ScheduledExecutorService executorService = new ScheduledThreadPoolExecutor(1, new ThreadFactory() {
|
private ScheduledExecutorService executorService;
|
||||||
|
|
||||||
|
private long clientBeatInterval = 5 * 1000;
|
||||||
|
|
||||||
|
private NamingProxy serverProxy;
|
||||||
|
|
||||||
|
public final Map<String, BeatInfo> dom2Beat = new ConcurrentHashMap<String, BeatInfo>();
|
||||||
|
|
||||||
|
public BeatReactor(NamingProxy serverProxy) {
|
||||||
|
this(serverProxy, UtilAndComs.DEFAULT_CLIENT_BEAT_THREAD_COUNT);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BeatReactor(NamingProxy serverProxy, int threadCount) {
|
||||||
|
this.serverProxy = serverProxy;
|
||||||
|
|
||||||
|
executorService = new ScheduledThreadPoolExecutor(threadCount, new ThreadFactory() {
|
||||||
@Override
|
@Override
|
||||||
public Thread newThread(Runnable r) {
|
public Thread newThread(Runnable r) {
|
||||||
Thread thread = new Thread(r);
|
Thread thread = new Thread(r);
|
||||||
@ -42,25 +54,17 @@ public class BeatReactor {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
private long clientBeatInterval = 5 * 1000;
|
|
||||||
|
|
||||||
private NamingProxy serverProxy;
|
|
||||||
|
|
||||||
public final Map<String, BeatInfo> dom2Beat = new ConcurrentHashMap<String, BeatInfo>();
|
|
||||||
|
|
||||||
public BeatReactor(NamingProxy serverProxy) {
|
|
||||||
this.serverProxy = serverProxy;
|
|
||||||
executorService.scheduleAtFixedRate(new BeatProcessor(), 0, clientBeatInterval, TimeUnit.MILLISECONDS);
|
executorService.scheduleAtFixedRate(new BeatProcessor(), 0, clientBeatInterval, TimeUnit.MILLISECONDS);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addBeatInfo(String dom, BeatInfo beatInfo) {
|
public void addBeatInfo(String dom, BeatInfo beatInfo) {
|
||||||
LogUtils.LOG.info("BEAT", "adding service:" + dom + " to beat map.");
|
LogUtils.LOG.info("BEAT", "adding beat: {} to beat map.", beatInfo);
|
||||||
dom2Beat.put(buildKey(dom, beatInfo.getIp(), beatInfo.getPort()), beatInfo);
|
dom2Beat.put(buildKey(dom, beatInfo.getIp(), beatInfo.getPort()), beatInfo);
|
||||||
MetricsMonitor.getDom2BeatSizeMonitor().set(dom2Beat.size());
|
MetricsMonitor.getDom2BeatSizeMonitor().set(dom2Beat.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeBeatInfo(String dom, String ip, int port) {
|
public void removeBeatInfo(String dom, String ip, int port) {
|
||||||
LogUtils.LOG.info("BEAT", "removing service:" + dom + " from beat map.");
|
LogUtils.LOG.info("BEAT", "removing beat: {}:{}:{} from beat map.", dom, ip, port);
|
||||||
dom2Beat.remove(buildKey(dom, ip, port));
|
dom2Beat.remove(buildKey(dom, ip, port));
|
||||||
MetricsMonitor.getDom2BeatSizeMonitor().set(dom2Beat.size());
|
MetricsMonitor.getDom2BeatSizeMonitor().set(dom2Beat.size());
|
||||||
}
|
}
|
||||||
@ -81,7 +85,6 @@ public class BeatReactor {
|
|||||||
}
|
}
|
||||||
beatInfo.setScheduled(true);
|
beatInfo.setScheduled(true);
|
||||||
executorService.schedule(new BeatTask(beatInfo), 0, TimeUnit.MILLISECONDS);
|
executorService.schedule(new BeatTask(beatInfo), 0, TimeUnit.MILLISECONDS);
|
||||||
LogUtils.LOG.info("BEAT", "send beat to server: " + beatInfo.toString());
|
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LogUtils.LOG.error("CLIENT-BEAT", "Exception while scheduling beat.", e);
|
LogUtils.LOG.error("CLIENT-BEAT", "Exception while scheduling beat.", e);
|
||||||
@ -99,21 +102,10 @@ public class BeatReactor {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
Map<String, String> params = new HashMap<String, String>(2);
|
long result = serverProxy.sendBeat(beatInfo);
|
||||||
params.put("beat", JSON.toJSONString(beatInfo));
|
|
||||||
params.put("dom", beatInfo.getDom());
|
|
||||||
|
|
||||||
try {
|
|
||||||
beatInfo.setScheduled(false);
|
beatInfo.setScheduled(false);
|
||||||
String result = serverProxy.callAllServers(UtilAndComs.NACOS_URL_BASE + "/api/clientBeat", params);
|
if (result > 0) {
|
||||||
JSONObject jsonObject = JSON.parseObject(result);
|
clientBeatInterval = result;
|
||||||
|
|
||||||
if (jsonObject != null) {
|
|
||||||
clientBeatInterval = jsonObject.getLong("clientBeatInterval");
|
|
||||||
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
LogUtils.LOG.error("CLIENT-BEAT", "failed to send beat: " + JSON.toJSONString(beatInfo), e);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,6 @@ import com.alibaba.nacos.api.naming.pojo.Instance;
|
|||||||
import com.alibaba.nacos.api.naming.pojo.ServiceInfo;
|
import com.alibaba.nacos.api.naming.pojo.ServiceInfo;
|
||||||
import com.alibaba.nacos.client.naming.utils.CollectionUtils;
|
import com.alibaba.nacos.client.naming.utils.CollectionUtils;
|
||||||
import com.alibaba.nacos.client.naming.utils.LogUtils;
|
import com.alibaba.nacos.client.naming.utils.LogUtils;
|
||||||
import com.alibaba.nacos.client.naming.utils.StringUtils;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
@ -57,16 +56,12 @@ public class EventDispatcher {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void addListener(ServiceInfo serviceInfo, String clusters, EventListener listener) {
|
public void addListener(ServiceInfo serviceInfo, String clusters, EventListener listener) {
|
||||||
addListener(serviceInfo, clusters, StringUtils.EMPTY, listener);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addListener(ServiceInfo serviceInfo, String clusters, String env, EventListener listener) {
|
|
||||||
|
|
||||||
LogUtils.LOG.info("LISTENER", "adding " + serviceInfo.getName() + " with " + clusters + " to listener map");
|
LogUtils.LOG.info("LISTENER", "adding " + serviceInfo.getName() + " with " + clusters + " to listener map");
|
||||||
List<EventListener> observers = Collections.synchronizedList(new ArrayList<EventListener>());
|
List<EventListener> observers = Collections.synchronizedList(new ArrayList<EventListener>());
|
||||||
observers.add(listener);
|
observers.add(listener);
|
||||||
|
|
||||||
observers = observerMap.putIfAbsent(ServiceInfo.getKey(serviceInfo.getName(), clusters, env), observers);
|
observers = observerMap.putIfAbsent(ServiceInfo.getKey(serviceInfo.getName(), clusters), observers);
|
||||||
if (observers != null) {
|
if (observers != null) {
|
||||||
observers.add(listener);
|
observers.add(listener);
|
||||||
}
|
}
|
||||||
@ -77,9 +72,8 @@ public class EventDispatcher {
|
|||||||
public void removeListener(String serviceName, String clusters, EventListener listener) {
|
public void removeListener(String serviceName, String clusters, EventListener listener) {
|
||||||
|
|
||||||
LogUtils.LOG.info("LISTENER", "removing " + serviceName + " with " + clusters + " from listener map");
|
LogUtils.LOG.info("LISTENER", "removing " + serviceName + " with " + clusters + " from listener map");
|
||||||
String unit = "";
|
|
||||||
|
|
||||||
List<EventListener> observers = observerMap.get(ServiceInfo.getKey(serviceName, clusters, unit));
|
List<EventListener> observers = observerMap.get(ServiceInfo.getKey(serviceName, clusters));
|
||||||
if (observers != null) {
|
if (observers != null) {
|
||||||
Iterator<EventListener> iter = observers.iterator();
|
Iterator<EventListener> iter = observers.iterator();
|
||||||
while (iter.hasNext()) {
|
while (iter.hasNext()) {
|
||||||
@ -88,8 +82,19 @@ public class EventDispatcher {
|
|||||||
iter.remove();
|
iter.remove();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (observers.isEmpty()) {
|
||||||
|
observerMap.remove(ServiceInfo.getKey(serviceName, clusters));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<ServiceInfo> getSubscribeServices() {
|
||||||
|
List<ServiceInfo> serviceInfos = new ArrayList<ServiceInfo>();
|
||||||
|
for (String key : observerMap.keySet()) {
|
||||||
|
serviceInfos.add(ServiceInfo.fromKey(key));
|
||||||
|
}
|
||||||
|
return serviceInfos;
|
||||||
|
}
|
||||||
|
|
||||||
public void serviceChanged(ServiceInfo serviceInfo) {
|
public void serviceChanged(ServiceInfo serviceInfo) {
|
||||||
if (serviceInfo == null) {
|
if (serviceInfo == null) {
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
package com.alibaba.nacos.client.naming.core;
|
package com.alibaba.nacos.client.naming.core;
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.JSON;
|
||||||
|
import com.alibaba.nacos.api.exception.NacosException;
|
||||||
import com.alibaba.nacos.api.naming.pojo.Instance;
|
import com.alibaba.nacos.api.naming.pojo.Instance;
|
||||||
import com.alibaba.nacos.api.naming.pojo.ServiceInfo;
|
import com.alibaba.nacos.api.naming.pojo.ServiceInfo;
|
||||||
import com.alibaba.nacos.client.monitor.MetricsMonitor;
|
import com.alibaba.nacos.client.monitor.MetricsMonitor;
|
||||||
@ -23,7 +24,6 @@ import com.alibaba.nacos.client.naming.backups.FailoverReactor;
|
|||||||
import com.alibaba.nacos.client.naming.cache.DiskCache;
|
import com.alibaba.nacos.client.naming.cache.DiskCache;
|
||||||
import com.alibaba.nacos.client.naming.net.NamingProxy;
|
import com.alibaba.nacos.client.naming.net.NamingProxy;
|
||||||
import com.alibaba.nacos.client.naming.utils.LogUtils;
|
import com.alibaba.nacos.client.naming.utils.LogUtils;
|
||||||
import com.alibaba.nacos.client.naming.utils.NetUtils;
|
|
||||||
import com.alibaba.nacos.client.naming.utils.StringUtils;
|
import com.alibaba.nacos.client.naming.utils.StringUtils;
|
||||||
import com.alibaba.nacos.client.naming.utils.UtilAndComs;
|
import com.alibaba.nacos.client.naming.utils.UtilAndComs;
|
||||||
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
|
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
|
||||||
@ -56,8 +56,25 @@ public class HostReactor {
|
|||||||
|
|
||||||
private String cacheDir;
|
private String cacheDir;
|
||||||
|
|
||||||
|
private ScheduledExecutorService executor;
|
||||||
|
|
||||||
|
public HostReactor(EventDispatcher eventDispatcher, NamingProxy serverProxy, String cacheDir) {
|
||||||
|
this(eventDispatcher, serverProxy, cacheDir, false, UtilAndComs.DEFAULT_POLLING_THREAD_COUNT);
|
||||||
|
}
|
||||||
|
|
||||||
public HostReactor(EventDispatcher eventDispatcher, NamingProxy serverProxy, String cacheDir,
|
public HostReactor(EventDispatcher eventDispatcher, NamingProxy serverProxy, String cacheDir,
|
||||||
boolean loadCacheAtStart) {
|
boolean loadCacheAtStart, int pollingThreadCount) {
|
||||||
|
|
||||||
|
executor = new ScheduledThreadPoolExecutor(pollingThreadCount, new ThreadFactory() {
|
||||||
|
@Override
|
||||||
|
public Thread newThread(Runnable r) {
|
||||||
|
Thread thread = new Thread(r);
|
||||||
|
thread.setDaemon(true);
|
||||||
|
thread.setName("com.alibaba.nacos.client.naming.updater");
|
||||||
|
return thread;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
this.eventDispatcher = eventDispatcher;
|
this.eventDispatcher = eventDispatcher;
|
||||||
this.serverProxy = serverProxy;
|
this.serverProxy = serverProxy;
|
||||||
this.cacheDir = cacheDir;
|
this.cacheDir = cacheDir;
|
||||||
@ -72,16 +89,6 @@ public class HostReactor {
|
|||||||
this.pushReceiver = new PushReceiver(this);
|
this.pushReceiver = new PushReceiver(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor(new ThreadFactory() {
|
|
||||||
@Override
|
|
||||||
public Thread newThread(Runnable r) {
|
|
||||||
Thread thread = new Thread(r, "com.alibaba.nacos.client.naming.updater");
|
|
||||||
thread.setDaemon(true);
|
|
||||||
|
|
||||||
return thread;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
public Map<String, ServiceInfo> getServiceInfoMap() {
|
public Map<String, ServiceInfo> getServiceInfoMap() {
|
||||||
return serviceInfoMap;
|
return serviceInfoMap;
|
||||||
}
|
}
|
||||||
@ -191,55 +198,38 @@ public class HostReactor {
|
|||||||
return serviceInfo;
|
return serviceInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ServiceInfo getSerivceInfo0(String serviceName, String clusters, String env) {
|
private ServiceInfo getSerivceInfo0(String serviceName, String clusters) {
|
||||||
|
|
||||||
String key = ServiceInfo.getKey(serviceName, clusters, env, false);
|
String key = ServiceInfo.getKey(serviceName, clusters);
|
||||||
|
|
||||||
return serviceInfoMap.get(key);
|
return serviceInfoMap.get(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ServiceInfo getSerivceInfo0(String serviceName, String clusters, String env, boolean allIPs) {
|
public ServiceInfo getServiceInfoDirectlyFromServer(final String serviceName, final String clusters) throws NacosException {
|
||||||
|
String result = serverProxy.queryList(serviceName, clusters, 0, false);
|
||||||
String key = ServiceInfo.getKey(serviceName, clusters, env, allIPs);
|
if (StringUtils.isNotEmpty(result)) {
|
||||||
return serviceInfoMap.get(key);
|
return JSON.parseObject(result, ServiceInfo.class);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ServiceInfo getServiceInfo(String serviceName, String clusters, String env) {
|
public ServiceInfo getServiceInfo(final String serviceName, final String clusters) {
|
||||||
return getServiceInfo(serviceName, clusters, env, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ServiceInfo getServiceInfo(String serviceName, String clusters) {
|
|
||||||
String env = StringUtils.EMPTY;
|
|
||||||
return getServiceInfo(serviceName, clusters, env, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ServiceInfo getServiceInfo(final String serviceName, final String clusters, final String env,
|
|
||||||
final boolean allIPs) {
|
|
||||||
|
|
||||||
LogUtils.LOG.debug("failover-mode: " + failoverReactor.isFailoverSwitch());
|
LogUtils.LOG.debug("failover-mode: " + failoverReactor.isFailoverSwitch());
|
||||||
String key = ServiceInfo.getKey(serviceName, clusters, env, allIPs);
|
String key = ServiceInfo.getKey(serviceName, clusters);
|
||||||
if (failoverReactor.isFailoverSwitch()) {
|
if (failoverReactor.isFailoverSwitch()) {
|
||||||
return failoverReactor.getService(key);
|
return failoverReactor.getService(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
ServiceInfo serviceObj = getSerivceInfo0(serviceName, clusters, env, allIPs);
|
ServiceInfo serviceObj = getSerivceInfo0(serviceName, clusters);
|
||||||
|
|
||||||
if (null == serviceObj) {
|
if (null == serviceObj) {
|
||||||
serviceObj = new ServiceInfo(serviceName, clusters, env);
|
serviceObj = new ServiceInfo(serviceName, clusters);
|
||||||
|
|
||||||
if (allIPs) {
|
|
||||||
serviceObj.setAllIPs(allIPs);
|
|
||||||
}
|
|
||||||
|
|
||||||
serviceInfoMap.put(serviceObj.getKey(), serviceObj);
|
serviceInfoMap.put(serviceObj.getKey(), serviceObj);
|
||||||
|
|
||||||
updatingMap.put(serviceName, new Object());
|
updatingMap.put(serviceName, new Object());
|
||||||
|
updateServiceNow(serviceName, clusters);
|
||||||
if (allIPs) {
|
|
||||||
updateService4AllIPNow(serviceName, clusters, env);
|
|
||||||
} else {
|
|
||||||
updateServiceNow(serviceName, clusters, env);
|
|
||||||
}
|
|
||||||
updatingMap.remove(serviceName);
|
updatingMap.remove(serviceName);
|
||||||
|
|
||||||
} else if (updatingMap.containsKey(serviceName)) {
|
} else if (updatingMap.containsKey(serviceName)) {
|
||||||
@ -251,100 +241,41 @@ public class HostReactor {
|
|||||||
serviceObj.wait(updateHoldInterval);
|
serviceObj.wait(updateHoldInterval);
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
LogUtils.LOG.error("[getServiceInfo]",
|
LogUtils.LOG.error("[getServiceInfo]",
|
||||||
"serviceName:" + serviceName + ", clusters:" + clusters + ", allIPs:" + allIPs, e);
|
"serviceName:" + serviceName + ", clusters:" + clusters, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
scheduleUpdateIfAbsent(serviceName, clusters, env, allIPs);
|
scheduleUpdateIfAbsent(serviceName, clusters);
|
||||||
|
|
||||||
return serviceInfoMap.get(serviceObj.getKey());
|
return serviceInfoMap.get(serviceObj.getKey());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void scheduleUpdateIfAbsent(String serviceName, String clusters, String env, boolean allIPs) {
|
public void scheduleUpdateIfAbsent(String serviceName, String clusters) {
|
||||||
if (futureMap.get(ServiceInfo.getKey(serviceName, clusters, env, allIPs)) != null) {
|
if (futureMap.get(ServiceInfo.getKey(serviceName, clusters)) != null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
synchronized (futureMap) {
|
synchronized (futureMap) {
|
||||||
if (futureMap.get(ServiceInfo.getKey(serviceName, clusters, env, allIPs)) != null) {
|
if (futureMap.get(ServiceInfo.getKey(serviceName, clusters)) != null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ScheduledFuture<?> future = addTask(new UpdateTask(serviceName, clusters, env, allIPs));
|
ScheduledFuture<?> future = addTask(new UpdateTask(serviceName, clusters));
|
||||||
futureMap.put(ServiceInfo.getKey(serviceName, clusters, env, allIPs), future);
|
futureMap.put(ServiceInfo.getKey(serviceName, clusters), future);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void updateService4AllIPNow(String serviceName, String clusters, String env) {
|
|
||||||
updateService4AllIPNow(serviceName, clusters, env, -1L);
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressFBWarnings("NN_NAKED_NOTIFY")
|
|
||||||
public void updateService4AllIPNow(String serviceName, String clusters, String env, long timeout) {
|
|
||||||
try {
|
|
||||||
Map<String, String> params = new HashMap<String, String>(8);
|
|
||||||
params.put("dom", serviceName);
|
|
||||||
params.put("clusters", clusters);
|
|
||||||
params.put("udpPort", String.valueOf(pushReceiver.getUDPPort()));
|
|
||||||
|
|
||||||
ServiceInfo oldService = getSerivceInfo0(serviceName, clusters, env, true);
|
|
||||||
if (oldService != null) {
|
|
||||||
params.put("checksum", oldService.getChecksum());
|
|
||||||
}
|
|
||||||
|
|
||||||
String result = serverProxy.reqAPI(UtilAndComs.NACOS_URL_BASE + "/api/srvAllIP", params);
|
|
||||||
if (StringUtils.isNotEmpty(result)) {
|
|
||||||
ServiceInfo serviceInfo = processServiceJSON(result);
|
|
||||||
serviceInfo.setAllIPs(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (oldService != null) {
|
|
||||||
synchronized (oldService) {
|
|
||||||
oldService.notifyAll();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//else nothing has changed
|
|
||||||
} catch (Exception e) {
|
|
||||||
LogUtils.LOG.error("NA", "failed to update serviceName: " + serviceName, e);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressFBWarnings("NN_NAKED_NOTIFY")
|
@SuppressFBWarnings("NN_NAKED_NOTIFY")
|
||||||
public void updateServiceNow(String serviceName, String clusters, String env) {
|
public void updateServiceNow(String serviceName, String clusters) {
|
||||||
ServiceInfo oldService = getSerivceInfo0(serviceName, clusters, env);
|
ServiceInfo oldService = getSerivceInfo0(serviceName, clusters);
|
||||||
try {
|
try {
|
||||||
Map<String, String> params = new HashMap<String, String>(8);
|
|
||||||
params.put("dom", serviceName);
|
|
||||||
params.put("clusters", clusters);
|
|
||||||
params.put("udpPort", String.valueOf(pushReceiver.getUDPPort()));
|
|
||||||
params.put("env", env);
|
|
||||||
params.put("clientIP", NetUtils.localIP());
|
|
||||||
|
|
||||||
StringBuilder stringBuilder = new StringBuilder();
|
String result = serverProxy.queryList(serviceName, clusters, pushReceiver.getUDPPort(), false);
|
||||||
for (String string : Balancer.UNCONSISTENT_SERVICE_WITH_ADDRESS_SERVER) {
|
|
||||||
stringBuilder.append(string).append(",");
|
|
||||||
}
|
|
||||||
|
|
||||||
Balancer.UNCONSISTENT_SERVICE_WITH_ADDRESS_SERVER.clear();
|
|
||||||
params.put("unconsistentDom", stringBuilder.toString());
|
|
||||||
|
|
||||||
String envSpliter = ",";
|
|
||||||
if (!StringUtils.isEmpty(env) && !env.contains(envSpliter)) {
|
|
||||||
params.put("useEnvId", "true");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (oldService != null) {
|
|
||||||
params.put("checksum", oldService.getChecksum());
|
|
||||||
}
|
|
||||||
|
|
||||||
String result = serverProxy.reqAPI(UtilAndComs.NACOS_URL_BASE + "/api/srvIPXT", params);
|
|
||||||
if (StringUtils.isNotEmpty(result)) {
|
if (StringUtils.isNotEmpty(result)) {
|
||||||
processServiceJSON(result);
|
processServiceJSON(result);
|
||||||
}
|
}
|
||||||
//else nothing has changed
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LogUtils.LOG.error("NA", "failed to update serviceName: " + serviceName, e);
|
LogUtils.LOG.error("NA", "failed to update serviceName: " + serviceName, e);
|
||||||
} finally {
|
} finally {
|
||||||
@ -356,34 +287,9 @@ public class HostReactor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void refreshOnly(String serviceName, String clusters, String env, boolean allIPs) {
|
public void refreshOnly(String serviceName, String clusters) {
|
||||||
try {
|
try {
|
||||||
Map<String, String> params = new HashMap<String, String>(16);
|
serverProxy.queryList(serviceName, clusters, pushReceiver.getUDPPort(), false);
|
||||||
params.put("dom", serviceName);
|
|
||||||
params.put("clusters", clusters);
|
|
||||||
params.put("udpPort", String.valueOf(pushReceiver.getUDPPort()));
|
|
||||||
params.put("unit", env);
|
|
||||||
params.put("clientIP", NetUtils.localIP());
|
|
||||||
|
|
||||||
String serviceSpliter = ",";
|
|
||||||
StringBuilder stringBuilder = new StringBuilder();
|
|
||||||
for (String string : Balancer.UNCONSISTENT_SERVICE_WITH_ADDRESS_SERVER) {
|
|
||||||
stringBuilder.append(string).append(serviceSpliter);
|
|
||||||
}
|
|
||||||
|
|
||||||
Balancer.UNCONSISTENT_SERVICE_WITH_ADDRESS_SERVER.clear();
|
|
||||||
params.put("unconsistentDom", stringBuilder.toString());
|
|
||||||
|
|
||||||
String envSpliter = ",";
|
|
||||||
if (!env.contains(envSpliter)) {
|
|
||||||
params.put("useEnvId", "true");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (allIPs) {
|
|
||||||
serverProxy.reqAPI(UtilAndComs.NACOS_URL_BASE + "/api/srvAllIP", params);
|
|
||||||
} else {
|
|
||||||
serverProxy.reqAPI(UtilAndComs.NACOS_URL_BASE + "/api/srvIPXT", params);
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LogUtils.LOG.error("NA", "failed to update serviceName: " + serviceName, e);
|
LogUtils.LOG.error("NA", "failed to update serviceName: " + serviceName, e);
|
||||||
}
|
}
|
||||||
@ -393,50 +299,30 @@ public class HostReactor {
|
|||||||
long lastRefTime = Long.MAX_VALUE;
|
long lastRefTime = Long.MAX_VALUE;
|
||||||
private String clusters;
|
private String clusters;
|
||||||
private String serviceName;
|
private String serviceName;
|
||||||
private String env;
|
|
||||||
private boolean allIPs = false;
|
|
||||||
|
|
||||||
public UpdateTask(String serviceName, String clusters, String env) {
|
public UpdateTask(String serviceName, String clusters) {
|
||||||
this.serviceName = serviceName;
|
this.serviceName = serviceName;
|
||||||
this.clusters = clusters;
|
this.clusters = clusters;
|
||||||
this.env = env;
|
|
||||||
}
|
|
||||||
|
|
||||||
public UpdateTask(String serviceName, String clusters, String env, boolean allIPs) {
|
|
||||||
this.serviceName = serviceName;
|
|
||||||
this.clusters = clusters;
|
|
||||||
this.env = env;
|
|
||||||
this.allIPs = allIPs;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
try {
|
try {
|
||||||
ServiceInfo serviceObj = serviceInfoMap.get(ServiceInfo.getKey(serviceName, clusters, env, allIPs));
|
ServiceInfo serviceObj = serviceInfoMap.get(ServiceInfo.getKey(serviceName, clusters));
|
||||||
|
|
||||||
if (serviceObj == null) {
|
if (serviceObj == null) {
|
||||||
if (allIPs) {
|
updateServiceNow(serviceName, clusters);
|
||||||
updateService4AllIPNow(serviceName, clusters, env);
|
|
||||||
} else {
|
|
||||||
updateServiceNow(serviceName, clusters, env);
|
|
||||||
executor.schedule(this, DEFAULT_DELAY, TimeUnit.MILLISECONDS);
|
executor.schedule(this, DEFAULT_DELAY, TimeUnit.MILLISECONDS);
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (serviceObj.getLastRefTime() <= lastRefTime) {
|
if (serviceObj.getLastRefTime() <= lastRefTime) {
|
||||||
if (allIPs) {
|
updateServiceNow(serviceName, clusters);
|
||||||
updateService4AllIPNow(serviceName, clusters, env);
|
serviceObj = serviceInfoMap.get(ServiceInfo.getKey(serviceName, clusters));
|
||||||
serviceObj = serviceInfoMap.get(ServiceInfo.getKey(serviceName, clusters, env, true));
|
|
||||||
} else {
|
|
||||||
updateServiceNow(serviceName, clusters, env);
|
|
||||||
serviceObj = serviceInfoMap.get(ServiceInfo.getKey(serviceName, clusters, env));
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// if serviceName already updated by push, we should not override it
|
// if serviceName already updated by push, we should not override it
|
||||||
// since the push data may be different from pull through force push
|
// since the push data may be different from pull through force push
|
||||||
refreshOnly(serviceName, clusters, env, allIPs);
|
refreshOnly(serviceName, clusters);
|
||||||
}
|
}
|
||||||
|
|
||||||
executor.schedule(this, serviceObj.getCacheMillis(), TimeUnit.MILLISECONDS);
|
executor.schedule(this, serviceObj.getCacheMillis(), TimeUnit.MILLISECONDS);
|
||||||
|
@ -18,14 +18,17 @@ package com.alibaba.nacos.client.naming.net;
|
|||||||
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.JSON;
|
||||||
import com.alibaba.fastjson.JSONObject;
|
import com.alibaba.fastjson.JSONObject;
|
||||||
import com.alibaba.fastjson.TypeReference;
|
import com.alibaba.fastjson.TypeReference;
|
||||||
|
import com.alibaba.nacos.api.common.Constants;
|
||||||
import com.alibaba.nacos.api.exception.NacosException;
|
import com.alibaba.nacos.api.exception.NacosException;
|
||||||
import com.alibaba.nacos.api.naming.pojo.Instance;
|
import com.alibaba.nacos.api.naming.pojo.Instance;
|
||||||
import com.alibaba.nacos.api.naming.pojo.ListView;
|
import com.alibaba.nacos.api.naming.pojo.ListView;
|
||||||
import com.alibaba.nacos.api.selector.AbstractSelector;
|
import com.alibaba.nacos.api.selector.AbstractSelector;
|
||||||
import com.alibaba.nacos.api.selector.SelectorType;
|
|
||||||
import com.alibaba.nacos.api.selector.ExpressionSelector;
|
import com.alibaba.nacos.api.selector.ExpressionSelector;
|
||||||
|
import com.alibaba.nacos.api.selector.SelectorType;
|
||||||
import com.alibaba.nacos.client.monitor.MetricsMonitor;
|
import com.alibaba.nacos.client.monitor.MetricsMonitor;
|
||||||
|
import com.alibaba.nacos.client.naming.beat.BeatInfo;
|
||||||
import com.alibaba.nacos.client.naming.utils.*;
|
import com.alibaba.nacos.client.naming.utils.*;
|
||||||
|
import com.alibaba.nacos.common.util.HttpMethod;
|
||||||
import com.alibaba.nacos.common.util.UuidUtils;
|
import com.alibaba.nacos.common.util.UuidUtils;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -44,7 +47,7 @@ public class NamingProxy {
|
|||||||
|
|
||||||
private static final int DEFAULT_SERVER_PORT = 8848;
|
private static final int DEFAULT_SERVER_PORT = 8848;
|
||||||
|
|
||||||
private String namespace;
|
private String namespaceId;
|
||||||
|
|
||||||
private String endpoint;
|
private String endpoint;
|
||||||
|
|
||||||
@ -60,9 +63,9 @@ public class NamingProxy {
|
|||||||
|
|
||||||
private ScheduledExecutorService executorService;
|
private ScheduledExecutorService executorService;
|
||||||
|
|
||||||
public NamingProxy(String namespace, String endpoint, String serverList) {
|
public NamingProxy(String namespaceId, String endpoint, String serverList) {
|
||||||
|
|
||||||
this.namespace = namespace;
|
this.namespaceId = namespaceId;
|
||||||
this.endpoint = endpoint;
|
this.endpoint = endpoint;
|
||||||
if (StringUtils.isNotEmpty(serverList)) {
|
if (StringUtils.isNotEmpty(serverList)) {
|
||||||
this.serverList = Arrays.asList(serverList.split(","));
|
this.serverList = Arrays.asList(serverList.split(","));
|
||||||
@ -155,10 +158,11 @@ public class NamingProxy {
|
|||||||
|
|
||||||
public void registerService(String serviceName, Instance instance) throws NacosException {
|
public void registerService(String serviceName, Instance instance) throws NacosException {
|
||||||
|
|
||||||
LogUtils.LOG.info("REGISTER-SERVICE", "registering service " + serviceName + " with instance:" + instance);
|
LogUtils.LOG.info("REGISTER-SERVICE", "{} registering service {} with instance: {}",
|
||||||
|
namespaceId, serviceName, instance);
|
||||||
|
|
||||||
final Map<String, String> params = new HashMap<String, String>(8);
|
final Map<String, String> params = new HashMap<String, String>(8);
|
||||||
params.put("tenant", namespace);
|
params.put(Constants.REQUEST_PARAM_NAMESPACE_ID, namespaceId);
|
||||||
params.put("ip", instance.getIp());
|
params.put("ip", instance.getIp());
|
||||||
params.put("port", String.valueOf(instance.getPort()));
|
params.put("port", String.valueOf(instance.getPort()));
|
||||||
params.put("weight", String.valueOf(instance.getWeight()));
|
params.put("weight", String.valueOf(instance.getWeight()));
|
||||||
@ -168,33 +172,55 @@ public class NamingProxy {
|
|||||||
params.put("serviceName", serviceName);
|
params.put("serviceName", serviceName);
|
||||||
params.put("clusterName", instance.getClusterName());
|
params.put("clusterName", instance.getClusterName());
|
||||||
|
|
||||||
reqAPI(UtilAndComs.NACOS_URL_INSTANCE, params, "PUT");
|
reqAPI(UtilAndComs.NACOS_URL_INSTANCE, params, HttpMethod.POST);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void deregisterService(String serviceName, String ip, int port, String cluster) throws NacosException {
|
public void deregisterService(String serviceName, String ip, int port, String cluster) throws NacosException {
|
||||||
|
|
||||||
LogUtils.LOG.info("DEREGISTER-SERVICE", "deregistering service " + serviceName
|
LogUtils.LOG.info("DEREGISTER-SERVICE", "{} deregistering service {} with instance: {}:{}@{}",
|
||||||
+ " with instance:" + ip + ":" + port + "@" + cluster);
|
namespaceId, serviceName, ip, port, cluster);
|
||||||
|
|
||||||
final Map<String, String> params = new HashMap<String, String>(8);
|
final Map<String, String> params = new HashMap<String, String>(8);
|
||||||
params.put("tenant", namespace);
|
params.put(Constants.REQUEST_PARAM_NAMESPACE_ID, namespaceId);
|
||||||
params.put("ip", ip);
|
params.put("ip", ip);
|
||||||
params.put("port", String.valueOf(port));
|
params.put("port", String.valueOf(port));
|
||||||
params.put("serviceName", serviceName);
|
params.put("serviceName", serviceName);
|
||||||
params.put("cluster", cluster);
|
params.put("cluster", cluster);
|
||||||
|
|
||||||
reqAPI(UtilAndComs.NACOS_URL_INSTANCE, params, "DELETE");
|
reqAPI(UtilAndComs.NACOS_URL_INSTANCE, params, HttpMethod.DELETE);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String queryList(String serviceName, String clusters, boolean healthyOnly) throws NacosException {
|
public String queryList(String serviceName, String clusters, int udpPort, boolean healthyOnly) throws NacosException {
|
||||||
|
|
||||||
final Map<String, String> params = new HashMap<String, String>(8);
|
final Map<String, String> params = new HashMap<String, String>(8);
|
||||||
params.put("tenant", namespace);
|
params.put(Constants.REQUEST_PARAM_NAMESPACE_ID, namespaceId);
|
||||||
params.put("serviceName", serviceName);
|
params.put("serviceName", serviceName);
|
||||||
params.put("clusters", clusters);
|
params.put("clusters", clusters);
|
||||||
|
params.put("udpPort", String.valueOf(udpPort));
|
||||||
|
params.put("clientIP", NetUtils.localIP());
|
||||||
params.put("healthyOnly", String.valueOf(healthyOnly));
|
params.put("healthyOnly", String.valueOf(healthyOnly));
|
||||||
|
|
||||||
return reqAPI(UtilAndComs.NACOS_URL_BASE + "/instance/list", params, "GET");
|
return reqAPI(UtilAndComs.NACOS_URL_BASE + "/instance/list", params, HttpMethod.GET);
|
||||||
|
}
|
||||||
|
|
||||||
|
public long sendBeat(BeatInfo beatInfo) {
|
||||||
|
try {
|
||||||
|
LogUtils.LOG.info("BEAT", "{} sending beat to server: {}", namespaceId, beatInfo.toString());
|
||||||
|
Map<String, String> params = new HashMap<String, String>(4);
|
||||||
|
params.put("beat", JSON.toJSONString(beatInfo));
|
||||||
|
params.put(Constants.REQUEST_PARAM_NAMESPACE_ID, namespaceId);
|
||||||
|
params.put("serviceName", beatInfo.getServiceName());
|
||||||
|
String result = reqAPI(UtilAndComs.NACOS_URL_BASE + "/instance/beat", params, HttpMethod.PUT);
|
||||||
|
JSONObject jsonObject = JSON.parseObject(result);
|
||||||
|
|
||||||
|
if (jsonObject != null) {
|
||||||
|
return jsonObject.getLong("clientBeatInterval");
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
LogUtils.LOG.error("CLIENT-BEAT", "failed to send beat: " + JSON.toJSONString(beatInfo), e);
|
||||||
|
}
|
||||||
|
return 0L;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean serverHealthy() {
|
public boolean serverHealthy() {
|
||||||
@ -217,6 +243,7 @@ public class NamingProxy {
|
|||||||
Map<String, String> params = new HashMap<String, String>(4);
|
Map<String, String> params = new HashMap<String, String>(4);
|
||||||
params.put("pageNo", String.valueOf(pageNo));
|
params.put("pageNo", String.valueOf(pageNo));
|
||||||
params.put("pageSize", String.valueOf(pageSize));
|
params.put("pageSize", String.valueOf(pageSize));
|
||||||
|
params.put(Constants.REQUEST_PARAM_NAMESPACE_ID, namespaceId);
|
||||||
|
|
||||||
if (selector != null) {
|
if (selector != null) {
|
||||||
switch (SelectorType.valueOf(selector.getType())) {
|
switch (SelectorType.valueOf(selector.getType())) {
|
||||||
@ -242,27 +269,6 @@ public class NamingProxy {
|
|||||||
return listView;
|
return listView;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String callAllServers(String api, Map<String, String> params) throws NacosException {
|
|
||||||
String result = "";
|
|
||||||
|
|
||||||
List<String> snapshot = serversFromEndpoint;
|
|
||||||
if (!CollectionUtils.isEmpty(serverList)) {
|
|
||||||
snapshot = serverList;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
result = reqAPI(api, params, snapshot);
|
|
||||||
} catch (Exception e) {
|
|
||||||
LogUtils.LOG.error("NA", "req api:" + api + " failed, servers: " + snapshot, e);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (StringUtils.isNotEmpty(result)) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new IllegalStateException("failed to req API:/api/" + api + " after all sites(" + snapshot + ") tried");
|
|
||||||
}
|
|
||||||
|
|
||||||
public String reqAPI(String api, Map<String, String> params) throws NacosException {
|
public String reqAPI(String api, Map<String, String> params) throws NacosException {
|
||||||
|
|
||||||
|
|
||||||
@ -285,7 +291,7 @@ public class NamingProxy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public String callServer(String api, Map<String, String> params, String curServer) throws NacosException {
|
public String callServer(String api, Map<String, String> params, String curServer) throws NacosException {
|
||||||
return callServer(api, params, curServer, "GET");
|
return callServer(api, params, curServer, HttpMethod.GET);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String callServer(String api, Map<String, String> params, String curServer, String method)
|
public String callServer(String api, Map<String, String> params, String curServer, String method)
|
||||||
@ -330,11 +336,13 @@ public class NamingProxy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public String reqAPI(String api, Map<String, String> params, List<String> servers) {
|
public String reqAPI(String api, Map<String, String> params, List<String> servers) {
|
||||||
return reqAPI(api, params, servers, "GET");
|
return reqAPI(api, params, servers, HttpMethod.GET);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String reqAPI(String api, Map<String, String> params, List<String> servers, String method) {
|
public String reqAPI(String api, Map<String, String> params, List<String> servers, String method) {
|
||||||
|
|
||||||
|
params.put(Constants.REQUEST_PARAM_NAMESPACE_ID, getNamespaceId());
|
||||||
|
|
||||||
if (CollectionUtils.isEmpty(servers) && StringUtils.isEmpty(nacosDomain)) {
|
if (CollectionUtils.isEmpty(servers) && StringUtils.isEmpty(nacosDomain)) {
|
||||||
throw new IllegalArgumentException("no server available");
|
throw new IllegalArgumentException("no server available");
|
||||||
}
|
}
|
||||||
@ -370,4 +378,7 @@ public class NamingProxy {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getNamespaceId() {
|
||||||
|
return namespaceId;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,7 @@ public class UtilAndComs {
|
|||||||
|
|
||||||
public static final String NACOS_URL_INSTANCE = NACOS_URL_BASE + "/instance";
|
public static final String NACOS_URL_INSTANCE = NACOS_URL_BASE + "/instance";
|
||||||
|
|
||||||
public static final String DEFAULT_NAMESPACE_ID = "default";
|
public static final String DEFAULT_NAMESPACE_ID = "public";
|
||||||
|
|
||||||
public static final int REQUEST_DOMAIN_RETRY_COUNT = 3;
|
public static final int REQUEST_DOMAIN_RETRY_COUNT = 3;
|
||||||
|
|
||||||
@ -45,4 +45,10 @@ public class UtilAndComs {
|
|||||||
public static final String NACOS_NAMING_LOG_LEVEL = "com.alibaba.nacos.naming.log.level";
|
public static final String NACOS_NAMING_LOG_LEVEL = "com.alibaba.nacos.naming.log.level";
|
||||||
|
|
||||||
public static final String SERVER_ADDR_IP_SPLITER = ":";
|
public static final String SERVER_ADDR_IP_SPLITER = ":";
|
||||||
|
|
||||||
|
public static final int DEFAULT_CLIENT_BEAT_THREAD_COUNT = Runtime.getRuntime().availableProcessors() > 1 ?
|
||||||
|
Runtime.getRuntime().availableProcessors() / 2 : 1;
|
||||||
|
|
||||||
|
public static final int DEFAULT_POLLING_THREAD_COUNT = Runtime.getRuntime().availableProcessors() > 1 ?
|
||||||
|
Runtime.getRuntime().availableProcessors() / 2 : 1;
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,8 @@
|
|||||||
package com.alibaba.nacos.client;
|
package com.alibaba.nacos.client;
|
||||||
|
|
||||||
import com.alibaba.nacos.api.NacosFactory;
|
import com.alibaba.nacos.api.NacosFactory;
|
||||||
|
import com.alibaba.nacos.api.PropertyKeyConst;
|
||||||
|
import com.alibaba.nacos.api.common.Constants;
|
||||||
import com.alibaba.nacos.api.naming.NamingService;
|
import com.alibaba.nacos.api.naming.NamingService;
|
||||||
import com.alibaba.nacos.api.naming.pojo.Instance;
|
import com.alibaba.nacos.api.naming.pojo.Instance;
|
||||||
import com.alibaba.nacos.api.naming.pojo.ListView;
|
import com.alibaba.nacos.api.naming.pojo.ListView;
|
||||||
@ -25,6 +27,7 @@ import org.junit.Test;
|
|||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:zpf.073@gmail.com">nkorange</a>
|
* @author <a href="mailto:zpf.073@gmail.com">nkorange</a>
|
||||||
@ -35,7 +38,11 @@ public class NamingTest {
|
|||||||
@Ignore
|
@Ignore
|
||||||
public void testServiceList() throws Exception {
|
public void testServiceList() throws Exception {
|
||||||
|
|
||||||
NamingService namingService = NacosFactory.createNamingService("127.0.0.1:8848");
|
Properties properties = new Properties();
|
||||||
|
properties.put(PropertyKeyConst.SERVER_ADDR, "11.160.165.126:8848");
|
||||||
|
properties.put(PropertyKeyConst.NAMESPACE, "t1");
|
||||||
|
|
||||||
|
NamingService namingService = NacosFactory.createNamingService(properties);
|
||||||
|
|
||||||
Instance instance = new Instance();
|
Instance instance = new Instance();
|
||||||
instance.setIp("1.1.1.1");
|
instance.setIp("1.1.1.1");
|
||||||
@ -48,9 +55,9 @@ public class NamingTest {
|
|||||||
|
|
||||||
namingService.registerInstance("nacos.test.1", instance);
|
namingService.registerInstance("nacos.test.1", instance);
|
||||||
|
|
||||||
ExpressionSelector expressionSelector = new ExpressionSelector();
|
// ExpressionSelector expressionSelector = new ExpressionSelector();
|
||||||
expressionSelector.setExpression("INSTANCE.metadata.registerSource = 'dubbo'");
|
// expressionSelector.setExpression("INSTANCE.metadata.registerSource = 'dubbo'");
|
||||||
ListView<String> serviceList = namingService.getServicesOfServer(1, 10, expressionSelector);
|
// ListView<String> serviceList = namingService.getServicesOfServer(1, 10, expressionSelector);
|
||||||
|
|
||||||
Thread.sleep(1000000000L);
|
Thread.sleep(1000000000L);
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>nacos-all</artifactId>
|
<artifactId>nacos-all</artifactId>
|
||||||
<groupId>com.alibaba.nacos</groupId>
|
<groupId>com.alibaba.nacos</groupId>
|
||||||
<version>0.7.0</version>
|
<version>0.8.0-SNAPSHOT</version>
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
@ -20,6 +20,7 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:zpf.073@gmail.com">nkorange</a>
|
* @author <a href="mailto:zpf.073@gmail.com">nkorange</a>
|
||||||
|
* @since 0.7.0
|
||||||
*/
|
*/
|
||||||
@SpringBootApplication
|
@SpringBootApplication
|
||||||
public class CmdbApp {
|
public class CmdbApp {
|
||||||
|
@ -28,6 +28,7 @@ import javax.servlet.http.HttpServletRequest;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:zpf.073@gmail.com">nkorange</a>
|
* @author <a href="mailto:zpf.073@gmail.com">nkorange</a>
|
||||||
|
* @since 0.7.0
|
||||||
*/
|
*/
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping(UtilsAndCommons.NACOS_CMDB_CONTEXT + "/ops")
|
@RequestMapping(UtilsAndCommons.NACOS_CMDB_CONTEXT + "/ops")
|
||||||
|
@ -17,6 +17,7 @@ package com.alibaba.nacos.cmdb.core;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:zpf.073@gmail.com">nkorange</a>
|
* @author <a href="mailto:zpf.073@gmail.com">nkorange</a>
|
||||||
|
* @since 0.7.0
|
||||||
*/
|
*/
|
||||||
public class CmdbManager {
|
public class CmdbManager {
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,7 @@ import org.springframework.stereotype.Component;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:zpf.073@gmail.com">nkorange</a>
|
* @author <a href="mailto:zpf.073@gmail.com">nkorange</a>
|
||||||
|
* @since 0.7.0
|
||||||
*/
|
*/
|
||||||
@Component
|
@Component
|
||||||
public class SwitchAndOptions {
|
public class SwitchAndOptions {
|
||||||
|
@ -36,6 +36,7 @@ import java.util.concurrent.TimeUnit;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:zpf.073@gmail.com">nkorange</a>
|
* @author <a href="mailto:zpf.073@gmail.com">nkorange</a>
|
||||||
|
* @since 0.7.0
|
||||||
*/
|
*/
|
||||||
@Component
|
@Component
|
||||||
public class CmdbProvider implements CmdbReader, CmdbWriter {
|
public class CmdbProvider implements CmdbReader, CmdbWriter {
|
||||||
|
@ -22,6 +22,7 @@ import java.util.List;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:zpf.073@gmail.com">nkorange</a>
|
* @author <a href="mailto:zpf.073@gmail.com">nkorange</a>
|
||||||
|
* @since 0.7.0
|
||||||
*/
|
*/
|
||||||
public interface CmdbReader {
|
public interface CmdbReader {
|
||||||
|
|
||||||
|
@ -17,6 +17,7 @@ package com.alibaba.nacos.cmdb.service;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:zpf.073@gmail.com">nkorange</a>
|
* @author <a href="mailto:zpf.073@gmail.com">nkorange</a>
|
||||||
|
* @since 0.7.0
|
||||||
*/
|
*/
|
||||||
public interface CmdbWriter {
|
public interface CmdbWriter {
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,7 @@ import org.slf4j.LoggerFactory;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @author nacos
|
* @author nacos
|
||||||
|
* @since 0.7.0
|
||||||
*/
|
*/
|
||||||
public class Loggers {
|
public class Loggers {
|
||||||
|
|
||||||
|
@ -21,6 +21,7 @@ import java.util.concurrent.ThreadFactory;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:zpf.073@gmail.com">nkorange</a>
|
* @author <a href="mailto:zpf.073@gmail.com">nkorange</a>
|
||||||
|
* @since 0.7.0
|
||||||
*/
|
*/
|
||||||
public class UtilsAndCommons {
|
public class UtilsAndCommons {
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>com.alibaba.nacos</groupId>
|
<groupId>com.alibaba.nacos</groupId>
|
||||||
<artifactId>nacos-all</artifactId>
|
<artifactId>nacos-all</artifactId>
|
||||||
<version>0.7.0</version>
|
<version>0.8.0-SNAPSHOT</version>
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 1999-2018 Alibaba Group Holding Ltd.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* 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.alibaba.nacos.common.util;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:zpf.073@gmail.com">nkorange</a>
|
||||||
|
* @since 0.8.0
|
||||||
|
*/
|
||||||
|
public class HttpMethod {
|
||||||
|
|
||||||
|
public static final String GET = "GET";
|
||||||
|
|
||||||
|
public static final String HEAD = "HEAD";
|
||||||
|
|
||||||
|
public static final String POST = "POST";
|
||||||
|
|
||||||
|
public static final String PUT = "PUT";
|
||||||
|
|
||||||
|
public static final String PATCH = "PATCH";
|
||||||
|
|
||||||
|
public static final String DELETE = "DELETE";
|
||||||
|
|
||||||
|
public static final String OPTIONS = "PATCH";
|
||||||
|
|
||||||
|
public static final String TRACE = "TRACE";
|
||||||
|
}
|
@ -17,7 +17,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>com.alibaba.nacos</groupId>
|
<groupId>com.alibaba.nacos</groupId>
|
||||||
<artifactId>nacos-all</artifactId>
|
<artifactId>nacos-all</artifactId>
|
||||||
<version>0.7.0</version>
|
<version>0.8.0-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
@ -36,8 +36,6 @@ public class ConfigKey implements Serializable {
|
|||||||
public ConfigKey() {
|
public ConfigKey() {
|
||||||
}
|
}
|
||||||
|
|
||||||
;
|
|
||||||
|
|
||||||
public ConfigKey(String appName, String dataId, String group) {
|
public ConfigKey(String appName, String dataId, String group) {
|
||||||
this.appName = appName;
|
this.appName = appName;
|
||||||
this.dataId = dataId;
|
this.dataId = dataId;
|
||||||
|
@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 1999-2018 Alibaba Group Holding Ltd.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* 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.alibaba.nacos.config.server.model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* user info
|
||||||
|
*
|
||||||
|
* @author wfnuser
|
||||||
|
*/
|
||||||
|
public class User {
|
||||||
|
private String username;
|
||||||
|
private String password;
|
||||||
|
|
||||||
|
public String getPassword() {
|
||||||
|
return password;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPassword(String password) {
|
||||||
|
this.password = password;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUsername() {
|
||||||
|
return username;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUsername(String username) {
|
||||||
|
this.username = username;
|
||||||
|
}
|
||||||
|
}
|
@ -33,6 +33,7 @@ import java.util.Map.Entry;
|
|||||||
|
|
||||||
import javax.annotation.PostConstruct;
|
import javax.annotation.PostConstruct;
|
||||||
|
|
||||||
|
import com.alibaba.nacos.config.server.model.*;
|
||||||
import org.apache.commons.lang.StringUtils;
|
import org.apache.commons.lang.StringUtils;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.dao.DataAccessException;
|
import org.springframework.dao.DataAccessException;
|
||||||
@ -53,19 +54,6 @@ import org.springframework.transaction.TransactionSystemException;
|
|||||||
import org.springframework.transaction.support.TransactionCallback;
|
import org.springframework.transaction.support.TransactionCallback;
|
||||||
import org.springframework.transaction.support.TransactionTemplate;
|
import org.springframework.transaction.support.TransactionTemplate;
|
||||||
import org.springframework.util.CollectionUtils;
|
import org.springframework.util.CollectionUtils;
|
||||||
import com.alibaba.nacos.config.server.model.ConfigAdvanceInfo;
|
|
||||||
import com.alibaba.nacos.config.server.model.ConfigAllInfo;
|
|
||||||
import com.alibaba.nacos.config.server.model.ConfigHistoryInfo;
|
|
||||||
import com.alibaba.nacos.config.server.model.ConfigInfo;
|
|
||||||
import com.alibaba.nacos.config.server.model.ConfigInfo4Beta;
|
|
||||||
import com.alibaba.nacos.config.server.model.ConfigInfo4Tag;
|
|
||||||
import com.alibaba.nacos.config.server.model.ConfigInfoAggr;
|
|
||||||
import com.alibaba.nacos.config.server.model.ConfigInfoBase;
|
|
||||||
import com.alibaba.nacos.config.server.model.ConfigInfoChanged;
|
|
||||||
import com.alibaba.nacos.config.server.model.ConfigKey;
|
|
||||||
import com.alibaba.nacos.config.server.model.Page;
|
|
||||||
import com.alibaba.nacos.config.server.model.SubInfo;
|
|
||||||
import com.alibaba.nacos.config.server.model.TenantInfo;
|
|
||||||
import com.alibaba.nacos.config.server.utils.LogUtil;
|
import com.alibaba.nacos.config.server.utils.LogUtil;
|
||||||
import com.alibaba.nacos.config.server.utils.MD5;
|
import com.alibaba.nacos.config.server.utils.MD5;
|
||||||
import com.alibaba.nacos.config.server.utils.PaginationHelper;
|
import com.alibaba.nacos.config.server.utils.PaginationHelper;
|
||||||
@ -455,6 +443,15 @@ public class PersistService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static final class UserRowMapper implements RowMapper<User> {
|
||||||
|
public User mapRow(ResultSet rs, int rowNum) throws SQLException {
|
||||||
|
User user = new User();
|
||||||
|
user.setUsername(rs.getString("username"));
|
||||||
|
user.setPassword(rs.getString("password"));
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public synchronized void reload() throws IOException {
|
public synchronized void reload() throws IOException {
|
||||||
this.dataSourceService.reload();
|
this.dataSourceService.reload();
|
||||||
}
|
}
|
||||||
@ -3113,6 +3110,22 @@ public class PersistService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public User findUserByUsername(String username) {
|
||||||
|
String sql = "SELECT username,password FROM users WHERE username=? ";
|
||||||
|
try {
|
||||||
|
return this.jt.queryForObject(sql, new Object[] {username}, USER_ROW_MAPPER);
|
||||||
|
} catch (CannotGetJdbcConnectionException e) {
|
||||||
|
fatalLog.error("[db-error] " + e.toString(), e);
|
||||||
|
throw e;
|
||||||
|
} catch (EmptyResultDataAccessException e) {
|
||||||
|
return null;
|
||||||
|
} catch (Exception e) {
|
||||||
|
fatalLog.error("[db-other-error]" + e.getMessage(), e);
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private List<ConfigInfo> convertDeletedConfig(List<Map<String, Object>> list) {
|
private List<ConfigInfo> convertDeletedConfig(List<Map<String, Object>> list) {
|
||||||
List<ConfigInfo> configs = new ArrayList<ConfigInfo>();
|
List<ConfigInfo> configs = new ArrayList<ConfigInfo>();
|
||||||
for (Map<String, Object> map : list) {
|
for (Map<String, Object> map : list) {
|
||||||
@ -3265,6 +3278,8 @@ public class PersistService {
|
|||||||
|
|
||||||
static final TenantInfoRowMapper TENANT_INFO_ROW_MAPPER = new TenantInfoRowMapper();
|
static final TenantInfoRowMapper TENANT_INFO_ROW_MAPPER = new TenantInfoRowMapper();
|
||||||
|
|
||||||
|
static final UserRowMapper USER_ROW_MAPPER = new UserRowMapper();
|
||||||
|
|
||||||
static final ConfigInfoWrapperRowMapper CONFIG_INFO_WRAPPER_ROW_MAPPER = new ConfigInfoWrapperRowMapper();
|
static final ConfigInfoWrapperRowMapper CONFIG_INFO_WRAPPER_ROW_MAPPER = new ConfigInfoWrapperRowMapper();
|
||||||
|
|
||||||
static final ConfigKeyRowMapper CONFIG_KEY_ROW_MAPPER = new ConfigKeyRowMapper();
|
static final ConfigKeyRowMapper CONFIG_KEY_ROW_MAPPER = new ConfigKeyRowMapper();
|
||||||
|
@ -177,3 +177,18 @@ CREATE TABLE `tenant_info` (
|
|||||||
UNIQUE KEY `uk_tenant_info_kptenantid` (`kp`,`tenant_id`),
|
UNIQUE KEY `uk_tenant_info_kptenantid` (`kp`,`tenant_id`),
|
||||||
KEY `idx_tenant_id` (`tenant_id`)
|
KEY `idx_tenant_id` (`tenant_id`)
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='tenant_info';
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='tenant_info';
|
||||||
|
|
||||||
|
CREATE TABLE users (
|
||||||
|
username varchar(50) NOT NULL PRIMARY KEY,
|
||||||
|
password varchar(500) NOT NULL,
|
||||||
|
enabled boolean NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE roles (
|
||||||
|
username varchar(50) NOT NULL,
|
||||||
|
role varchar(50) NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
INSERT INTO users (username, password, enabled) VALUES ('admin', '$2a$10$HxtJtd59imujvbux.i55zOGewhnJiLVXX8D9AETDMV.XtBLDGOXtW', TRUE);
|
||||||
|
|
||||||
|
INSERT INTO roles (username, role) VALUES ('admin', 'ROLE_ADMIN');
|
||||||
|
@ -173,3 +173,17 @@ CREATE TABLE tenant_info (
|
|||||||
CREATE INDEX tenant_info_tenant_id_idx ON tenant_info(tenant_id);
|
CREATE INDEX tenant_info_tenant_id_idx ON tenant_info(tenant_id);
|
||||||
|
|
||||||
|
|
||||||
|
CREATE TABLE users (
|
||||||
|
username varchar(50) NOT NULL PRIMARY KEY,
|
||||||
|
password varchar(500) NOT NULL,
|
||||||
|
enabled boolean NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE roles (
|
||||||
|
username varchar(50) NOT NULL,
|
||||||
|
role varchar(50) NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
INSERT INTO users (username, password, enabled) VALUES ('admin', '$2a$10$HxtJtd59imujvbux.i55zOGewhnJiLVXX8D9AETDMV.XtBLDGOXtW', TRUE);
|
||||||
|
|
||||||
|
INSERT INTO roles (username, role) VALUES ('admin', 'ROLE_ADMIN');
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>com.alibaba.nacos</groupId>
|
<groupId>com.alibaba.nacos</groupId>
|
||||||
<artifactId>nacos-all</artifactId>
|
<artifactId>nacos-all</artifactId>
|
||||||
<version>0.7.0</version>
|
<version>0.8.0-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>nacos-console</artifactId>
|
<artifactId>nacos-console</artifactId>
|
||||||
<!--<packaging>war</packaging>-->
|
<!--<packaging>war</packaging>-->
|
||||||
@ -65,6 +65,24 @@
|
|||||||
<artifactId>mockito-core</artifactId>
|
<artifactId>mockito-core</artifactId>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-security</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.jsonwebtoken</groupId>
|
||||||
|
<artifactId>jjwt-api</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.jsonwebtoken</groupId>
|
||||||
|
<artifactId>jjwt-impl</artifactId>
|
||||||
|
<scope>runtime</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.jsonwebtoken</groupId>
|
||||||
|
<artifactId>jjwt-jackson</artifactId>
|
||||||
|
<scope>runtime</scope>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
<build>
|
<build>
|
||||||
<finalName>nacos-server</finalName>
|
<finalName>nacos-server</finalName>
|
||||||
@ -83,6 +101,7 @@
|
|||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||||
|
<version>2.1.1.RELEASE</version>
|
||||||
<configuration>
|
<configuration>
|
||||||
<mainClass>com.alibaba.nacos.Nacos</mainClass>
|
<mainClass>com.alibaba.nacos.Nacos</mainClass>
|
||||||
</configuration>
|
</configuration>
|
||||||
|
@ -0,0 +1,107 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 1999-2018 Alibaba Group Holding Ltd.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* 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.alibaba.nacos.console.config;
|
||||||
|
|
||||||
|
import com.alibaba.nacos.console.filter.JwtAuthenticationTokenFilter;
|
||||||
|
import com.alibaba.nacos.console.security.CustomUserDetailsServiceImpl;
|
||||||
|
import com.alibaba.nacos.console.security.JwtAuthenticationEntryPoint;
|
||||||
|
import com.alibaba.nacos.console.utils.JwtTokenUtils;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.core.env.Environment;
|
||||||
|
import org.springframework.security.authentication.AuthenticationManager;
|
||||||
|
import org.springframework.security.config.BeanIds;
|
||||||
|
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||||
|
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
|
||||||
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||||
|
import org.springframework.security.config.annotation.web.builders.WebSecurity;
|
||||||
|
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||||
|
import org.springframework.security.config.http.SessionCreationPolicy;
|
||||||
|
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||||
|
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||||
|
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Spring security config
|
||||||
|
*
|
||||||
|
* @author Nacos
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
@EnableGlobalMethodSecurity(prePostEnabled = true)
|
||||||
|
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
|
||||||
|
|
||||||
|
public static final String AUTHORIZATION_HEADER = "Authorization";
|
||||||
|
|
||||||
|
public static final String AUTHORIZATION_TOKEN = "access_token";
|
||||||
|
|
||||||
|
public static final String SECURITY_IGNORE_URLS_SPILT_CHAR = ",";
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private CustomUserDetailsServiceImpl userDetailsService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private JwtAuthenticationEntryPoint unauthorizedHandler;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private JwtTokenUtils tokenProvider;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private Environment env;
|
||||||
|
|
||||||
|
@Bean(name = BeanIds.AUTHENTICATION_MANAGER)
|
||||||
|
@Override
|
||||||
|
public AuthenticationManager authenticationManagerBean() throws Exception {
|
||||||
|
return super.authenticationManagerBean();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||||
|
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void configure(WebSecurity web) {
|
||||||
|
String ignoreURLs = env.getProperty("nacos.security.ignore.urls", "/**");
|
||||||
|
for (String ignoreURL : ignoreURLs.trim().split(SECURITY_IGNORE_URLS_SPILT_CHAR)) {
|
||||||
|
web.ignoring().antMatchers(ignoreURL.trim());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void configure(HttpSecurity http) throws Exception {
|
||||||
|
http
|
||||||
|
.authorizeRequests()
|
||||||
|
.anyRequest().authenticated().and()
|
||||||
|
// custom token authorize exception handler
|
||||||
|
.exceptionHandling()
|
||||||
|
.authenticationEntryPoint(unauthorizedHandler).and()
|
||||||
|
// since we use jwt, session is not necessary
|
||||||
|
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
|
||||||
|
// since we use jwt, csrf is not necessary
|
||||||
|
.csrf().disable();
|
||||||
|
http.addFilterBefore(new JwtAuthenticationTokenFilter(tokenProvider), UsernamePasswordAuthenticationFilter.class);
|
||||||
|
|
||||||
|
// disable cache
|
||||||
|
http.headers().cacheControl();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public PasswordEncoder passwordEncoder() {
|
||||||
|
return new BCryptPasswordEncoder();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,82 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 1999-2018 Alibaba Group Holding Ltd.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* 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.alibaba.nacos.console.controller;
|
||||||
|
|
||||||
|
import com.alibaba.nacos.console.config.WebSecurityConfig;
|
||||||
|
import com.alibaba.nacos.config.server.model.RestResult;
|
||||||
|
import com.alibaba.nacos.console.utils.JwtTokenUtils;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.security.authentication.AuthenticationManager;
|
||||||
|
import org.springframework.security.authentication.BadCredentialsException;
|
||||||
|
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||||
|
import org.springframework.security.core.Authentication;
|
||||||
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* auth
|
||||||
|
*
|
||||||
|
* @author wfnuser
|
||||||
|
*/
|
||||||
|
@RestController("auth")
|
||||||
|
@RequestMapping("/v1/auth")
|
||||||
|
public class AuthController {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private JwtTokenUtils jwtTokenUtils;
|
||||||
|
@Autowired
|
||||||
|
private AuthenticationManager authenticationManager;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether the Nacos is in broken states or not, and cannot recover except by being restarted
|
||||||
|
*
|
||||||
|
* @return HTTP code equal to 200 indicates that Nacos is in right states. HTTP code equal to 500 indicates that
|
||||||
|
* Nacos is in broken states.
|
||||||
|
*/
|
||||||
|
|
||||||
|
@ResponseBody
|
||||||
|
@RequestMapping(value = "login", method = RequestMethod.POST)
|
||||||
|
public RestResult<String> login(HttpServletRequest request, HttpServletResponse response) throws Exception {
|
||||||
|
String username = request.getParameter("username");
|
||||||
|
String password = request.getParameter("password");
|
||||||
|
|
||||||
|
// 通过用户名和密码创建一个 Authentication 认证对象,实现类为 UsernamePasswordAuthenticationToken
|
||||||
|
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(username, password);
|
||||||
|
RestResult<String> rr = new RestResult<String>();
|
||||||
|
|
||||||
|
try {
|
||||||
|
//通过 AuthenticationManager(默认实现为ProviderManager)的authenticate方法验证 Authentication 对象
|
||||||
|
Authentication authentication = authenticationManager.authenticate(authenticationToken);
|
||||||
|
//将 Authentication 绑定到 SecurityContext
|
||||||
|
SecurityContextHolder.getContext().setAuthentication(authentication);
|
||||||
|
//生成Token
|
||||||
|
String token = jwtTokenUtils.createToken(authentication);
|
||||||
|
//将Token写入到Http头部
|
||||||
|
response.addHeader(WebSecurityConfig.AUTHORIZATION_HEADER, "Bearer " + token);
|
||||||
|
rr.setCode(200);
|
||||||
|
rr.setData("Bearer " + token);
|
||||||
|
return rr;
|
||||||
|
} catch (BadCredentialsException authentication) {
|
||||||
|
rr.setCode(401);
|
||||||
|
rr.setMessage("Login failed");
|
||||||
|
return rr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,80 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 1999-2018 Alibaba Group Holding Ltd.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* 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.alibaba.nacos.console.filter;
|
||||||
|
|
||||||
|
import com.alibaba.nacos.console.config.WebSecurityConfig;
|
||||||
|
import com.alibaba.nacos.console.utils.JwtTokenUtils;
|
||||||
|
import org.springframework.security.core.Authentication;
|
||||||
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
import org.springframework.web.filter.OncePerRequestFilter;
|
||||||
|
|
||||||
|
import javax.servlet.FilterChain;
|
||||||
|
import javax.servlet.ServletException;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* jwt auth token filter
|
||||||
|
*
|
||||||
|
* @author wfnuser
|
||||||
|
*/
|
||||||
|
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {
|
||||||
|
|
||||||
|
private static final String TOKEN_PREFIX = "Bearer ";
|
||||||
|
|
||||||
|
private JwtTokenUtils tokenProvider;
|
||||||
|
|
||||||
|
public JwtAuthenticationTokenFilter(JwtTokenUtils tokenProvider) {
|
||||||
|
this.tokenProvider = tokenProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
|
||||||
|
String jwt = resolveToken(request);
|
||||||
|
|
||||||
|
if (jwt != null && !"".equals(jwt.trim()) && SecurityContextHolder.getContext().getAuthentication() == null) {
|
||||||
|
if (this.tokenProvider.validateToken(jwt)) {
|
||||||
|
/**
|
||||||
|
* get auth info
|
||||||
|
*/
|
||||||
|
Authentication authentication = this.tokenProvider.getAuthentication(jwt);
|
||||||
|
/**
|
||||||
|
* save user info to securityContext
|
||||||
|
*/
|
||||||
|
SecurityContextHolder.getContext().setAuthentication(authentication);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
chain.doFilter(request, response);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get token from header
|
||||||
|
*/
|
||||||
|
private String resolveToken(HttpServletRequest request) {
|
||||||
|
String bearerToken = request.getHeader(WebSecurityConfig.AUTHORIZATION_HEADER);
|
||||||
|
if (StringUtils.hasText(bearerToken) && bearerToken.startsWith(TOKEN_PREFIX)) {
|
||||||
|
return bearerToken.substring(7, bearerToken.length());
|
||||||
|
}
|
||||||
|
String jwt = request.getParameter(WebSecurityConfig.AUTHORIZATION_TOKEN);
|
||||||
|
if (StringUtils.hasText(jwt)) {
|
||||||
|
return jwt;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,55 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 1999-2018 Alibaba Group Holding Ltd.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* 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.alibaba.nacos.console.security;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.security.authentication.AuthenticationProvider;
|
||||||
|
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||||
|
import org.springframework.security.core.Authentication;
|
||||||
|
import org.springframework.security.core.AuthenticationException;
|
||||||
|
import org.springframework.security.core.userdetails.UserDetails;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* auth provider
|
||||||
|
*
|
||||||
|
* @author wfnuser
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class CustomAuthenticationProvider implements AuthenticationProvider {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private CustomUserDetailsServiceImpl userDetailsService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
|
||||||
|
|
||||||
|
String username = (String) authentication.getPrincipal();
|
||||||
|
String password = (String) authentication.getCredentials();
|
||||||
|
UserDetails userDetails = userDetailsService.loadUserByUsername(username);
|
||||||
|
|
||||||
|
if (!password.equals(userDetails.getPassword())) {
|
||||||
|
return new UsernamePasswordAuthenticationToken(username, null, null);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean supports(Class<?> aClass) {
|
||||||
|
return aClass.equals(UsernamePasswordAuthenticationToken.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,73 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 1999-2018 Alibaba Group Holding Ltd.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* 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.alibaba.nacos.console.security;
|
||||||
|
|
||||||
|
import com.alibaba.nacos.config.server.model.User;
|
||||||
|
import org.springframework.security.core.GrantedAuthority;
|
||||||
|
import org.springframework.security.core.authority.AuthorityUtils;
|
||||||
|
import org.springframework.security.core.userdetails.UserDetails;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* custem user
|
||||||
|
*
|
||||||
|
* @author wfnuser
|
||||||
|
*/
|
||||||
|
public class CustomUserDetails implements UserDetails {
|
||||||
|
|
||||||
|
private User user;
|
||||||
|
|
||||||
|
public CustomUserDetails(User user) {
|
||||||
|
this.user = user;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Collection<? extends GrantedAuthority> getAuthorities() {
|
||||||
|
// TODO: get authorities
|
||||||
|
return AuthorityUtils.commaSeparatedStringToAuthorityList("");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getPassword() {
|
||||||
|
return user.getPassword();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getUsername() {
|
||||||
|
return user.getUsername();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isAccountNonExpired() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isAccountNonLocked() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isCredentialsNonExpired() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEnabled() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 1999-2018 Alibaba Group Holding Ltd.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* 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.alibaba.nacos.console.security;
|
||||||
|
|
||||||
|
|
||||||
|
import com.alibaba.nacos.config.server.model.User;
|
||||||
|
import com.alibaba.nacos.config.server.service.PersistService;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.security.core.userdetails.UserDetails;
|
||||||
|
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||||
|
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Custem user service
|
||||||
|
*
|
||||||
|
* @author wfnuser
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
public class CustomUserDetailsServiceImpl implements UserDetailsService {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private transient PersistService persistService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException {
|
||||||
|
User user = persistService.findUserByUsername(userName);
|
||||||
|
if (user == null) {
|
||||||
|
throw new UsernameNotFoundException(userName);
|
||||||
|
}
|
||||||
|
return new CustomUserDetails(user);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 1999-2018 Alibaba Group Holding Ltd.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* 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.alibaba.nacos.console.security;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.security.core.AuthenticationException;
|
||||||
|
import org.springframework.security.web.AuthenticationEntryPoint;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import javax.servlet.ServletException;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* jwt auth fail point
|
||||||
|
*
|
||||||
|
* @author wfnuser
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint {
|
||||||
|
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(JwtAuthenticationEntryPoint.class);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void commence(HttpServletRequest httpServletRequest,
|
||||||
|
HttpServletResponse httpServletResponse,
|
||||||
|
AuthenticationException e) throws IOException, ServletException {
|
||||||
|
logger.error("Responding with unauthorized error. Message - {}", e.getMessage());
|
||||||
|
httpServletResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized");
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,139 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 1999-2018 Alibaba Group Holding Ltd.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* 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.alibaba.nacos.console.utils;
|
||||||
|
|
||||||
|
import io.jsonwebtoken.*;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||||
|
import org.springframework.security.core.Authentication;
|
||||||
|
import org.springframework.security.core.GrantedAuthority;
|
||||||
|
import org.springframework.security.core.authority.AuthorityUtils;
|
||||||
|
import org.springframework.security.core.userdetails.User;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import javax.annotation.PostConstruct;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Jwt token tool
|
||||||
|
*
|
||||||
|
* @author wfnuser
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class JwtTokenUtils {
|
||||||
|
|
||||||
|
private final Logger log = LoggerFactory.getLogger(JwtTokenUtils.class);
|
||||||
|
|
||||||
|
private static final String AUTHORITIES_KEY = "auth";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* secret key
|
||||||
|
*/
|
||||||
|
private String secretKey;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Token validity time(ms)
|
||||||
|
*/
|
||||||
|
private long tokenValidityInMilliseconds;
|
||||||
|
|
||||||
|
@PostConstruct
|
||||||
|
public void init() {
|
||||||
|
this.secretKey = "SecretKey012345678901234567890123456789012345678901234567890123456789";
|
||||||
|
this.tokenValidityInMilliseconds = 1000 * 60 * 30L;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create token
|
||||||
|
*
|
||||||
|
* @param authentication auth info
|
||||||
|
* @return token
|
||||||
|
*/
|
||||||
|
public String createToken(Authentication authentication) {
|
||||||
|
/**
|
||||||
|
* Current time
|
||||||
|
*/
|
||||||
|
long now = (new Date()).getTime();
|
||||||
|
/**
|
||||||
|
* Validity date
|
||||||
|
*/
|
||||||
|
Date validity;
|
||||||
|
validity = new Date(now + this.tokenValidityInMilliseconds);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* create token
|
||||||
|
*/
|
||||||
|
return Jwts.builder()
|
||||||
|
.setSubject(authentication.getName())
|
||||||
|
.claim(AUTHORITIES_KEY, "")
|
||||||
|
.setExpiration(validity)
|
||||||
|
.signWith(SignatureAlgorithm.HS256, secretKey)
|
||||||
|
.compact();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get auth Info
|
||||||
|
*
|
||||||
|
* @param token token
|
||||||
|
* @return auth info
|
||||||
|
*/
|
||||||
|
public Authentication getAuthentication(String token) {
|
||||||
|
/**
|
||||||
|
* parse the payload of token
|
||||||
|
*/
|
||||||
|
Claims claims = Jwts.parser()
|
||||||
|
.setSigningKey(secretKey)
|
||||||
|
.parseClaimsJws(token)
|
||||||
|
.getBody();
|
||||||
|
|
||||||
|
List<GrantedAuthority> authorities = AuthorityUtils.commaSeparatedStringToAuthorityList((String) claims.get(AUTHORITIES_KEY));
|
||||||
|
|
||||||
|
|
||||||
|
User principal = new User(claims.getSubject(), "", authorities);
|
||||||
|
return new UsernamePasswordAuthenticationToken(principal, "", authorities);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* validate token
|
||||||
|
*
|
||||||
|
* @param token token
|
||||||
|
* @return whether valid
|
||||||
|
*/
|
||||||
|
public boolean validateToken(String token) {
|
||||||
|
try {
|
||||||
|
Jwts.parser().setSigningKey(secretKey).parseClaimsJws(token);
|
||||||
|
return true;
|
||||||
|
} catch (SignatureException e) {
|
||||||
|
log.info("Invalid JWT signature.");
|
||||||
|
log.trace("Invalid JWT signature trace: {}", e);
|
||||||
|
} catch (MalformedJwtException e) {
|
||||||
|
log.info("Invalid JWT token.");
|
||||||
|
log.trace("Invalid JWT token trace: {}", e);
|
||||||
|
} catch (ExpiredJwtException e) {
|
||||||
|
log.info("Expired JWT token.");
|
||||||
|
log.trace("Expired JWT token trace: {}", e);
|
||||||
|
} catch (UnsupportedJwtException e) {
|
||||||
|
log.info("Unsupported JWT token.");
|
||||||
|
log.trace("Unsupported JWT token trace: {}", e);
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
log.info("JWT token compact of handler are invalid.");
|
||||||
|
log.trace("JWT token compact of handler are invalid trace: {}", e);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
@ -35,14 +35,16 @@ nacos.cmdb.eventTaskInterval=10
|
|||||||
nacos.cmdb.labelTaskInterval=300
|
nacos.cmdb.labelTaskInterval=300
|
||||||
nacos.cmdb.loadDataAtStart=false
|
nacos.cmdb.loadDataAtStart=false
|
||||||
|
|
||||||
|
#management.endpoints.web.exposure.include=*
|
||||||
|
|
||||||
db.num=2
|
db.num=2
|
||||||
db.url.0=jdbc:mysql://11.162.196.161:3306/diamond_devtest?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true
|
db.url.0=jdbc:mysql://11.162.196.161:3306/diamond_devtest?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true
|
||||||
db.url.1=jdbc:mysql://11.163.152.91:3306/diamond_devtest?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true
|
db.url.1=jdbc:mysql://11.163.152.91:3306/diamond_devtest?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true
|
||||||
db.user=diamond_devtest
|
db.user=diamond_devtest
|
||||||
db.password=4b9622f3f70c7677835ac5a6719e7caf
|
db.password=4b9622f3f70c7677835ac5a6719e7caf
|
||||||
|
|
||||||
|
#spring.security.enabled=false
|
||||||
|
#management.security=false
|
||||||
|
#security.basic.enabled=false
|
||||||
enableAccessControl=false
|
#nacos.security.ignore.urls=/**
|
||||||
|
nacos.security.ignore.urls=/,/**/*.css,/**/*.js,/**/*.html,/**/*.map,/**/*.svg,/**/*.png,/**/*.ico,/console-fe/public/**,/v1/auth/login,/v1/console/health,/v1/cs/**,/v1/ns/**,/v1/cmdb/**,/actuator/**
|
||||||
|
@ -171,3 +171,19 @@ CREATE TABLE tenant_info (
|
|||||||
constraint tenant_info_id_key PRIMARY KEY (id),
|
constraint tenant_info_id_key PRIMARY KEY (id),
|
||||||
constraint uk_tenant_info_kptenantid UNIQUE (kp,tenant_id));
|
constraint uk_tenant_info_kptenantid UNIQUE (kp,tenant_id));
|
||||||
CREATE INDEX tenant_info_tenant_id_idx ON tenant_info(tenant_id);
|
CREATE INDEX tenant_info_tenant_id_idx ON tenant_info(tenant_id);
|
||||||
|
|
||||||
|
|
||||||
|
CREATE TABLE users (
|
||||||
|
username varchar(50) NOT NULL PRIMARY KEY,
|
||||||
|
password varchar(500) NOT NULL,
|
||||||
|
enabled boolean NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE roles (
|
||||||
|
username varchar(50) NOT NULL,
|
||||||
|
role varchar(50) NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
INSERT INTO users (username, password, enabled) VALUES ('admin', '$2a$10$HxtJtd59imujvbux.i55zOGewhnJiLVXX8D9AETDMV.XtBLDGOXtW', TRUE);
|
||||||
|
|
||||||
|
INSERT INTO roles (username, role) VALUES ('admin', 'ROLE_ADMIN');
|
||||||
|
@ -26,7 +26,7 @@ module.exports = Object.assign({}, base, {
|
|||||||
context: ['/'],
|
context: ['/'],
|
||||||
changeOrigin: true,
|
changeOrigin: true,
|
||||||
secure: false,
|
secure: false,
|
||||||
target: 'http://console.nacos.io',
|
target: 'http://localhost:8848',
|
||||||
pathRewrite: {'^/v1' : '/nacos/v1'}
|
pathRewrite: {'^/v1' : '/nacos/v1'}
|
||||||
}],
|
}],
|
||||||
disableHostCheck: true,
|
disableHostCheck: true,
|
||||||
|
Binary file not shown.
After Width: | Height: | Size: 114 B |
Binary file not shown.
After Width: | Height: | Size: 3.5 KiB |
@ -83,6 +83,7 @@ class NameSpaceList extends React.Component {
|
|||||||
切换namespace
|
切换namespace
|
||||||
* */
|
* */
|
||||||
changeNameSpace(ns, nsName) {
|
changeNameSpace(ns, nsName) {
|
||||||
|
localStorage.setItem('namespace', ns);
|
||||||
this.setnamespace(ns || '');
|
this.setnamespace(ns || '');
|
||||||
setParams({
|
setParams({
|
||||||
namespace: ns || '',
|
namespace: ns || '',
|
||||||
@ -101,7 +102,7 @@ class NameSpaceList extends React.Component {
|
|||||||
|
|
||||||
getNameSpaces() {
|
getNameSpaces() {
|
||||||
const { locale = {} } = this.props;
|
const { locale = {} } = this.props;
|
||||||
if (window.namespaceList) {
|
if (window.namespaceList && window.namespaceList.length) {
|
||||||
this.handleNameSpaces(window.namespaceList);
|
this.handleNameSpaces(window.namespaceList);
|
||||||
} else {
|
} else {
|
||||||
request({
|
request({
|
||||||
@ -140,6 +141,7 @@ class NameSpaceList extends React.Component {
|
|||||||
}
|
}
|
||||||
window.namespaceShowName = namespaceShowName;
|
window.namespaceShowName = namespaceShowName;
|
||||||
setParams('namespace', nownamespace || '');
|
setParams('namespace', nownamespace || '');
|
||||||
|
localStorage.setItem('namespace', nownamespace);
|
||||||
// setParams('namespaceShowName', namespaceShowName);
|
// setParams('namespaceShowName', namespaceShowName);
|
||||||
this.props.setNowNameSpace && this.props.setNowNameSpace(namespaceShowName, nownamespace);
|
this.props.setNowNameSpace && this.props.setNowNameSpace(namespaceShowName, nownamespace);
|
||||||
this.setState({
|
this.setState({
|
||||||
@ -191,8 +193,8 @@ class NameSpaceList extends React.Component {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={namespaceList.length > 0 ? 'namespacewrapper' : ''}
|
className={namespaceList.length ? 'namespacewrapper' : ''}
|
||||||
style={namespaceList.length > 0 ? namespacestyle : {}}
|
style={namespaceList.length ? namespacestyle : {}}
|
||||||
>
|
>
|
||||||
{}
|
{}
|
||||||
{title ? (
|
{title ? (
|
||||||
|
@ -217,6 +217,7 @@ const aliwareIntl = (function(_global) {
|
|||||||
this.nowData = nowData;
|
this.nowData = nowData;
|
||||||
this.setMomentLocale(this.currentLanguageCode);
|
this.setMomentLocale(this.currentLanguageCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
let aliwareLocal = aliwareGetCookieByKeyName('aliyun_lang') || 'zh';
|
let aliwareLocal = aliwareGetCookieByKeyName('aliyun_lang') || 'zh';
|
||||||
let aliwareLocalSite = aliwareGetCookieByKeyName('aliyun_country') || 'cn';
|
let aliwareLocalSite = aliwareGetCookieByKeyName('aliyun_country') || 'cn';
|
||||||
aliwareLocal = aliwareLocal.toLowerCase();
|
aliwareLocal = aliwareLocal.toLowerCase();
|
||||||
@ -473,6 +474,7 @@ const request = (function(_global) {
|
|||||||
return serviceObj;
|
return serviceObj;
|
||||||
};
|
};
|
||||||
})();
|
})();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 添加中间件函数
|
* 添加中间件函数
|
||||||
* @param {*function} callback 回调函数
|
* @param {*function} callback 回调函数
|
||||||
@ -485,6 +487,7 @@ const request = (function(_global) {
|
|||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 处理中间件
|
* 处理中间件
|
||||||
* @param {*Object} config ajax请求配置信息
|
* @param {*Object} config ajax请求配置信息
|
||||||
@ -504,6 +507,7 @@ const request = (function(_global) {
|
|||||||
}
|
}
|
||||||
return config;
|
return config;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 处理自定义url
|
* 处理自定义url
|
||||||
* @param {*Object} config ajax请求配置信息
|
* @param {*Object} config ajax请求配置信息
|
||||||
@ -603,9 +607,25 @@ const request = (function(_global) {
|
|||||||
beforeSend(xhr) {
|
beforeSend(xhr) {
|
||||||
config.beforeSend && config.beforeSend(xhr);
|
config.beforeSend && config.beforeSend(xhr);
|
||||||
},
|
},
|
||||||
|
headers: {
|
||||||
|
Authorization: localStorage.getItem('token'),
|
||||||
|
},
|
||||||
})
|
})
|
||||||
|
).then(
|
||||||
|
success => {},
|
||||||
|
error => {
|
||||||
|
// 处理403 forbidden
|
||||||
|
if (error && (error.status === 403 || error.status === 401)) {
|
||||||
|
// 跳转至login页
|
||||||
|
// TODO: 用 react-router 重写,改造成本比较高,这里先hack
|
||||||
|
const url = window.location.href;
|
||||||
|
const base_url = url.split('#')[0];
|
||||||
|
window.location = `${base_url}#/login`;
|
||||||
|
}
|
||||||
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 暴露方法
|
// 暴露方法
|
||||||
Request.handleCustomService = handleCustomService;
|
Request.handleCustomService = handleCustomService;
|
||||||
Request.handleMiddleWare = handleMiddleWare;
|
Request.handleMiddleWare = handleMiddleWare;
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
*/
|
*/
|
||||||
module.exports = {
|
module.exports = {
|
||||||
'zh-cn': {
|
'zh-cn': {
|
||||||
'com.alibaba.nacos.layout.noenv.nacosversion': '0.7.0',
|
'com.alibaba.nacos.layout.noenv.nacosversion': '0.8.0',
|
||||||
'com.alibaba.nacos.page.configurationManagementVirtual': '配置管理',
|
'com.alibaba.nacos.page.configurationManagementVirtual': '配置管理',
|
||||||
'com.alibaba.nacos.page.serviceManagementVirtual': '服务管理',
|
'com.alibaba.nacos.page.serviceManagementVirtual': '服务管理',
|
||||||
'nacos.component.ExportDialog.tags2': '标签:',
|
'nacos.component.ExportDialog.tags2': '标签:',
|
||||||
@ -574,7 +574,7 @@ module.exports = {
|
|||||||
'nacos.page.ConfigEditor.submit_failed': '不能为空, 提交失败',
|
'nacos.page.ConfigEditor.submit_failed': '不能为空, 提交失败',
|
||||||
},
|
},
|
||||||
'en-us': {
|
'en-us': {
|
||||||
'com.alibaba.nacos.layout.noenv.nacosversion': '0.7.0',
|
'com.alibaba.nacos.layout.noenv.nacosversion': '0.8.0',
|
||||||
'com.alibaba.nacos.page.configurationManagementVirtual': 'ConfigManagement',
|
'com.alibaba.nacos.page.configurationManagementVirtual': 'ConfigManagement',
|
||||||
'com.alibaba.nacos.page.serviceManagementVirtual': 'ServiceManagement',
|
'com.alibaba.nacos.page.serviceManagementVirtual': 'ServiceManagement',
|
||||||
'nacos.component.CloneDialog.the_same_configuration': 'Conflict:',
|
'nacos.component.CloneDialog.the_same_configuration': 'Conflict:',
|
||||||
|
@ -30,6 +30,7 @@ import Layout from './layouts/MainLayout';
|
|||||||
import CookieHelp from './utils/cookie';
|
import CookieHelp from './utils/cookie';
|
||||||
import { LANGUAGE_KEY, REDUX_DEVTOOLS } from './constants';
|
import { LANGUAGE_KEY, REDUX_DEVTOOLS } from './constants';
|
||||||
|
|
||||||
|
import Login from './pages/Login';
|
||||||
import Namespace from './pages/NameSpace';
|
import Namespace from './pages/NameSpace';
|
||||||
import Newconfig from './pages/ConfigurationManagement/NewConfig';
|
import Newconfig from './pages/ConfigurationManagement/NewConfig';
|
||||||
import Configsync from './pages/ConfigurationManagement/ConfigSync';
|
import Configsync from './pages/ConfigurationManagement/ConfigSync';
|
||||||
@ -111,13 +112,15 @@ class App extends React.Component {
|
|||||||
get router() {
|
get router() {
|
||||||
return (
|
return (
|
||||||
<HashRouter>
|
<HashRouter>
|
||||||
<Layout navList={_menu.data}>
|
|
||||||
<Switch>
|
<Switch>
|
||||||
|
<Route path="/login" component={Login} />
|
||||||
|
|
||||||
|
<Layout navList={_menu.data}>
|
||||||
{MENU.map(item => (
|
{MENU.map(item => (
|
||||||
<Route key={item.path} {...item} />
|
<Route key={item.path} {...item} />
|
||||||
))}
|
))}
|
||||||
</Switch>
|
|
||||||
</Layout>
|
</Layout>
|
||||||
|
</Switch>
|
||||||
</HashRouter>
|
</HashRouter>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -12,14 +12,16 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import { withRouter } from 'react-router-dom';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { ConfigProvider } from '@alifd/next';
|
import { ConfigProvider, Dropdown, Menu } from '@alifd/next';
|
||||||
import siteConfig from '../config';
|
import siteConfig from '../config';
|
||||||
import { changeLanguage } from '@/reducers/locale';
|
import { changeLanguage } from '@/reducers/locale';
|
||||||
|
|
||||||
import './index.scss';
|
import './index.scss';
|
||||||
|
|
||||||
|
@withRouter
|
||||||
@connect(
|
@connect(
|
||||||
state => ({ ...state.locale }),
|
state => ({ ...state.locale }),
|
||||||
{ changeLanguage }
|
{ changeLanguage }
|
||||||
@ -40,8 +42,29 @@ class Header extends React.Component {
|
|||||||
changeLanguage(currentLanguage);
|
changeLanguage(currentLanguage);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
logout = () => {
|
||||||
|
window.localStorage.clear();
|
||||||
|
this.props.history.push('/login');
|
||||||
|
};
|
||||||
|
|
||||||
|
getUsername = () => {
|
||||||
|
const token = window.localStorage.getItem('token');
|
||||||
|
if (token) {
|
||||||
|
const base64Url = token.split('.')[1];
|
||||||
|
const base64 = base64Url.replace('-', '+').replace('_', '/');
|
||||||
|
const parsedToken = JSON.parse(window.atob(base64));
|
||||||
|
console.log(parsedToken);
|
||||||
|
return parsedToken.sub;
|
||||||
|
}
|
||||||
|
return '';
|
||||||
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { locale = {}, language = 'en-US' } = this.props;
|
const {
|
||||||
|
locale = {},
|
||||||
|
language = 'en-us',
|
||||||
|
location: { pathname },
|
||||||
|
} = this.props;
|
||||||
const { home, docs, blog, community, languageSwitchButton } = locale;
|
const { home, docs, blog, community, languageSwitchButton } = locale;
|
||||||
const BASE_URL = `https://nacos.io/${language.toLocaleLowerCase()}/`;
|
const BASE_URL = `https://nacos.io/${language.toLocaleLowerCase()}/`;
|
||||||
const NAV_MENU = [
|
const NAV_MENU = [
|
||||||
@ -65,6 +88,14 @@ class Header extends React.Component {
|
|||||||
title={siteConfig.name}
|
title={siteConfig.name}
|
||||||
/>
|
/>
|
||||||
</a>
|
</a>
|
||||||
|
{/* if is login page, we will show logout */}
|
||||||
|
{pathname !== '/login' && (
|
||||||
|
<Dropdown trigger={<div className="logout">{this.getUsername()}</div>}>
|
||||||
|
<Menu>
|
||||||
|
<Menu.Item onClick={this.logout}>{locale.logout}</Menu.Item>
|
||||||
|
</Menu>
|
||||||
|
</Dropdown>
|
||||||
|
)}
|
||||||
<span className="language-switch language-switch-primary" onClick={this.switchLang}>
|
<span className="language-switch language-switch-primary" onClick={this.switchLang}>
|
||||||
{languageSwitchButton}
|
{languageSwitchButton}
|
||||||
</span>
|
</span>
|
||||||
|
@ -18,7 +18,6 @@
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
z-index: 1000;
|
z-index: 1000;
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
border-bottom: 1px solid #eee;
|
|
||||||
}
|
}
|
||||||
.header-container-primary {
|
.header-container-primary {
|
||||||
background: #252a2f;
|
background: #252a2f;
|
||||||
@ -99,6 +98,13 @@
|
|||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
opacity: 0.6;
|
opacity: 0.6;
|
||||||
}
|
}
|
||||||
|
.header-container .header-body .logout {
|
||||||
|
float: right;
|
||||||
|
color: #fff;
|
||||||
|
opacity: 0.6;
|
||||||
|
font-family: Avenir-Medium;
|
||||||
|
margin-right: 40px;
|
||||||
|
}
|
||||||
.header-container .header-body .language-switch:hover {
|
.header-container .header-body .language-switch:hover {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
|
@ -26,6 +26,14 @@ window.globalConfig = {
|
|||||||
request.middleWare((_config = {}) => {
|
request.middleWare((_config = {}) => {
|
||||||
let config = _config;
|
let config = _config;
|
||||||
let { url = '' } = config;
|
let { url = '' } = config;
|
||||||
|
|
||||||
|
const namespace = localStorage.getItem('namespace') ? localStorage.getItem('namespace') : '';
|
||||||
|
// 如果url中已经有 namespaceId, 不在data中添加namespaceId
|
||||||
|
config.data =
|
||||||
|
url.indexOf('namespaceId=') === -1
|
||||||
|
? Object.assign({}, config.data, { namespaceId: namespace })
|
||||||
|
: config.data;
|
||||||
|
|
||||||
let tenant = window.nownamespace || getParams('namespace') || '';
|
let tenant = window.nownamespace || getParams('namespace') || '';
|
||||||
tenant = tenant === 'global' ? '' : tenant;
|
tenant = tenant === 'global' ? '' : tenant;
|
||||||
const splitArr = url.split('?');
|
const splitArr = url.split('?');
|
||||||
|
@ -18,10 +18,20 @@ const I18N_CONF = {
|
|||||||
blog: 'BLOG',
|
blog: 'BLOG',
|
||||||
community: 'COMMUNITY',
|
community: 'COMMUNITY',
|
||||||
languageSwitchButton: '中',
|
languageSwitchButton: '中',
|
||||||
|
logout: 'logout',
|
||||||
|
passwordRequired: 'password should not be empty',
|
||||||
|
usernameRequired: 'username should not be empty',
|
||||||
|
},
|
||||||
|
Login: {
|
||||||
|
login: 'Login',
|
||||||
|
submit: 'Submit',
|
||||||
|
pleaseInputUsername: 'Please input username',
|
||||||
|
pleaseInputPassword: 'Please input password',
|
||||||
|
invalidUsernameOrPassword: 'invalid username or password',
|
||||||
},
|
},
|
||||||
MainLayout: {
|
MainLayout: {
|
||||||
nacosName: 'NACOS',
|
nacosName: 'NACOS',
|
||||||
nacosVersion: '0.7.0',
|
nacosVersion: '0.8.0',
|
||||||
doesNotExist: 'The page you visit does not exist',
|
doesNotExist: 'The page you visit does not exist',
|
||||||
configurationManagementVirtual: 'ConfigManagement',
|
configurationManagementVirtual: 'ConfigManagement',
|
||||||
configurationManagement: 'Configurations',
|
configurationManagement: 'Configurations',
|
||||||
@ -239,7 +249,7 @@ const I18N_CONF = {
|
|||||||
escExit: 'Publish',
|
escExit: 'Publish',
|
||||||
release: 'Back',
|
release: 'Back',
|
||||||
confirmSyanx: 'The configuration information may has a syntax error. Are you sure to submit?',
|
confirmSyanx: 'The configuration information may has a syntax error. Are you sure to submit?',
|
||||||
dataIdExists: 'Data ID exists',
|
dataIdExists: 'Configuration already exists. Enter a new Data ID and Group name.',
|
||||||
dataRequired: 'Data cannot be empty, submission failed',
|
dataRequired: 'Data cannot be empty, submission failed',
|
||||||
},
|
},
|
||||||
CloneDialog: {
|
CloneDialog: {
|
||||||
|
@ -18,10 +18,20 @@ const I18N_CONF = {
|
|||||||
blog: '博客',
|
blog: '博客',
|
||||||
community: '社区',
|
community: '社区',
|
||||||
languageSwitchButton: 'En',
|
languageSwitchButton: 'En',
|
||||||
|
logout: '登出',
|
||||||
|
},
|
||||||
|
Login: {
|
||||||
|
login: '登录',
|
||||||
|
submit: '提交',
|
||||||
|
pleaseInputUsername: '请输入用户名',
|
||||||
|
pleaseInputPassword: '请输入密码',
|
||||||
|
invalidUsernameOrPassword: '用户名或密码错误',
|
||||||
|
passwordRequired: '密码不能为空',
|
||||||
|
usernameRequired: '用户名不能为空',
|
||||||
},
|
},
|
||||||
MainLayout: {
|
MainLayout: {
|
||||||
nacosName: 'NACOS',
|
nacosName: 'NACOS',
|
||||||
nacosVersion: '0.7.0',
|
nacosVersion: '0.8.0',
|
||||||
doesNotExist: '您访问的页面不存在',
|
doesNotExist: '您访问的页面不存在',
|
||||||
configurationManagementVirtual: '配置管理',
|
configurationManagementVirtual: '配置管理',
|
||||||
configurationManagement: '配置列表',
|
configurationManagement: '配置列表',
|
||||||
@ -238,7 +248,7 @@ const I18N_CONF = {
|
|||||||
escExit: '发布',
|
escExit: '发布',
|
||||||
release: '返回',
|
release: '返回',
|
||||||
confirmSyanx: '配置信息可能有语法错误, 确定提交吗?',
|
confirmSyanx: '配置信息可能有语法错误, 确定提交吗?',
|
||||||
dataIdExists: 'Data ID 已存在',
|
dataIdExists: '配置已存在, 试试别的dataid和group的组合吧',
|
||||||
dataRequired: '数据不能为空, 提交失败',
|
dataRequired: '数据不能为空, 提交失败',
|
||||||
},
|
},
|
||||||
CloneDialog: {
|
CloneDialog: {
|
||||||
|
@ -0,0 +1,131 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { Card, Form, Input, Message, ConfigProvider, Field } from '@alifd/next';
|
||||||
|
import { withRouter } from 'react-router-dom';
|
||||||
|
|
||||||
|
import './index.scss';
|
||||||
|
import Header from '../../layouts/Header';
|
||||||
|
import { request } from '../../globalLib';
|
||||||
|
|
||||||
|
const FormItem = Form.Item;
|
||||||
|
|
||||||
|
@withRouter
|
||||||
|
@ConfigProvider.config
|
||||||
|
class Login extends React.Component {
|
||||||
|
static displayName = 'Login';
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.field = new Field(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleSubmit = () => {
|
||||||
|
const { locale = {} } = this.props;
|
||||||
|
this.field.validate((errors, values) => {
|
||||||
|
if (errors) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
request({
|
||||||
|
type: 'post',
|
||||||
|
url: 'v1/auth/login',
|
||||||
|
data: values,
|
||||||
|
success: res => {
|
||||||
|
if (res.code === 200) {
|
||||||
|
const data = res.data;
|
||||||
|
// TODO: 封装一个方法存储、读取token
|
||||||
|
localStorage.setItem('token', data);
|
||||||
|
// TODO: 使用react router
|
||||||
|
this.props.history.push('/');
|
||||||
|
}
|
||||||
|
if (res.code === 401) {
|
||||||
|
Message.error({
|
||||||
|
content: locale.invalidUsernameOrPassword,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
error: () => {
|
||||||
|
Message.error({
|
||||||
|
content: locale.invalidUsernameOrPassword,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
onKeyDown = event => {
|
||||||
|
// 'keypress' event misbehaves on mobile so we track 'Enter' key via 'keydown' event
|
||||||
|
if (event.key === 'Enter') {
|
||||||
|
event.preventDefault();
|
||||||
|
event.stopPropagation();
|
||||||
|
this.handleSubmit();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { locale = {} } = this.props;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="home-page">
|
||||||
|
<Header />
|
||||||
|
<section
|
||||||
|
className="top-section"
|
||||||
|
style={{
|
||||||
|
background: 'url(img/black_dot.png) repeat',
|
||||||
|
backgroundSize: '14px 14px',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div className="vertical-middle product-area">
|
||||||
|
<img className="product-logo" src="img/nacos.png" />
|
||||||
|
<p className="product-desc">
|
||||||
|
an easy-to-use dynamic service discovery, configuration and service management
|
||||||
|
platform for building cloud native applications
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div className="animation animation1" />
|
||||||
|
<div className="animation animation2" />
|
||||||
|
<div className="animation animation3" />
|
||||||
|
<div className="animation animation4" />
|
||||||
|
<div className="animation animation5" />
|
||||||
|
<Card className="login-panel" contentHeight="auto">
|
||||||
|
<div className="login-header">{locale.login}</div>
|
||||||
|
<Form className="login-form" field={this.field}>
|
||||||
|
<FormItem>
|
||||||
|
<Input
|
||||||
|
{...this.field.init('username', {
|
||||||
|
rules: [
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: locale.usernameRequired,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})}
|
||||||
|
placeholder={locale.pleaseInputUsername}
|
||||||
|
onKeyDown={this.onKeyDown}
|
||||||
|
/>
|
||||||
|
</FormItem>
|
||||||
|
<FormItem>
|
||||||
|
<Input
|
||||||
|
htmlType="password"
|
||||||
|
placeholder={locale.pleaseInputPassword}
|
||||||
|
{...this.field.init('password', {
|
||||||
|
rules: [
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: locale.passwordRequired,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})}
|
||||||
|
onKeyDown={this.onKeyDown}
|
||||||
|
/>
|
||||||
|
</FormItem>
|
||||||
|
<FormItem label=" ">
|
||||||
|
<Form.Submit onClick={this.handleSubmit}>{locale.submit}</Form.Submit>
|
||||||
|
</FormItem>
|
||||||
|
</Form>
|
||||||
|
</Card>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Login;
|
@ -0,0 +1,16 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 1999-2018 Alibaba Group Holding Ltd.
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import Login from './Login';
|
||||||
|
|
||||||
|
export default Login;
|
@ -0,0 +1,113 @@
|
|||||||
|
$animationDuration: 2s;
|
||||||
|
|
||||||
|
// 品牌色
|
||||||
|
$brandColor: #2e3034;
|
||||||
|
$mobileWidth: 640px;
|
||||||
|
// 页面主体最大宽度
|
||||||
|
$contentWidth: 1280px;
|
||||||
|
|
||||||
|
@keyframes slashStar {
|
||||||
|
0% {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.home-page {
|
||||||
|
.top-section {
|
||||||
|
position: relative;
|
||||||
|
height: 100vh;
|
||||||
|
.login-panel {
|
||||||
|
position: absolute;
|
||||||
|
right: 40px;
|
||||||
|
width: 480px;
|
||||||
|
height: 540px;
|
||||||
|
top: 90px;
|
||||||
|
input,
|
||||||
|
input::-webkit-input-placeholder {
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
.login-header {
|
||||||
|
width: 100%;
|
||||||
|
line-height: 45px;
|
||||||
|
font-size: 32px;
|
||||||
|
margin-top: 58px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.login-form {
|
||||||
|
width: 360px;
|
||||||
|
margin: 80px auto auto auto;
|
||||||
|
input {
|
||||||
|
height: 60px;
|
||||||
|
}
|
||||||
|
button {
|
||||||
|
width: 100%;
|
||||||
|
height: 60px;
|
||||||
|
font-size: 16px;
|
||||||
|
background: #4190ff 100%;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.animation {
|
||||||
|
position: absolute;
|
||||||
|
width: 6px;
|
||||||
|
height: 6px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background-color: #1be1f6;
|
||||||
|
&1 {
|
||||||
|
left: 15%;
|
||||||
|
top: 70%;
|
||||||
|
animation: slashStar $animationDuration ease-in-out 0.3s infinite;
|
||||||
|
}
|
||||||
|
&2 {
|
||||||
|
left: 34%;
|
||||||
|
top: 35%;
|
||||||
|
animation: slashStar $animationDuration ease-in-out 1.2s infinite;
|
||||||
|
}
|
||||||
|
&3 {
|
||||||
|
left: 53%;
|
||||||
|
top: 20%;
|
||||||
|
animation: slashStar $animationDuration ease-in-out 0.5s infinite;
|
||||||
|
}
|
||||||
|
&4 {
|
||||||
|
left: 72%;
|
||||||
|
top: 64%;
|
||||||
|
animation: slashStar $animationDuration ease-in-out 0.8s infinite;
|
||||||
|
}
|
||||||
|
&5 {
|
||||||
|
left: 87%;
|
||||||
|
top: 30%;
|
||||||
|
animation: slashStar $animationDuration ease-in-out 1.5s infinite;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.vertical-middle {
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: 50%;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
}
|
||||||
|
.product-area {
|
||||||
|
width: 600px;
|
||||||
|
margin-left: 40px;
|
||||||
|
}
|
||||||
|
.product-logo {
|
||||||
|
display: block;
|
||||||
|
width: 257px;
|
||||||
|
height: 50px;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
.product-desc {
|
||||||
|
opacity: 0.8;
|
||||||
|
font-family: Avenir-Medium;
|
||||||
|
font-size: 24px;
|
||||||
|
color: #fff;
|
||||||
|
max-width: 780px;
|
||||||
|
margin: 12px auto 30px;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -64,8 +64,8 @@ class EditClusterDialog extends React.Component {
|
|||||||
healthChecker,
|
healthChecker,
|
||||||
} = this.state.editCluster;
|
} = this.state.editCluster;
|
||||||
request({
|
request({
|
||||||
method: 'POST',
|
method: 'PUT',
|
||||||
url: 'v1/ns/cluster/update',
|
url: 'v1/ns/cluster',
|
||||||
data: {
|
data: {
|
||||||
serviceName,
|
serviceName,
|
||||||
clusterName: name,
|
clusterName: name,
|
||||||
|
@ -58,8 +58,8 @@ class EditInstanceDialog extends React.Component {
|
|||||||
const { serviceName, clusterName, getInstanceList, openLoading, closeLoading } = this.props;
|
const { serviceName, clusterName, getInstanceList, openLoading, closeLoading } = this.props;
|
||||||
const { ip, port, weight, enabled, metadataText } = this.state.editInstance;
|
const { ip, port, weight, enabled, metadataText } = this.state.editInstance;
|
||||||
request({
|
request({
|
||||||
method: 'POST',
|
method: 'PUT',
|
||||||
url: 'v1/ns/instance/update',
|
url: 'v1/ns/instance',
|
||||||
data: { serviceName, clusterName, ip, port, weight, enable: enabled, metadata: metadataText },
|
data: { serviceName, clusterName, ip, port, weight, enable: enabled, metadata: metadataText },
|
||||||
dataType: 'text',
|
dataType: 'text',
|
||||||
beforeSend: () => openLoading(),
|
beforeSend: () => openLoading(),
|
||||||
|
@ -57,7 +57,7 @@ class EditServiceDialog extends React.Component {
|
|||||||
const editService = Object.assign({}, this.state.editService);
|
const editService = Object.assign({}, this.state.editService);
|
||||||
const { name, protectThreshold, healthCheckMode, metadataText, selector } = editService;
|
const { name, protectThreshold, healthCheckMode, metadataText, selector } = editService;
|
||||||
request({
|
request({
|
||||||
method: isCreate ? 'PUT' : 'POST',
|
method: isCreate ? 'POST' : 'PUT',
|
||||||
url: 'v1/ns/service',
|
url: 'v1/ns/service',
|
||||||
data: {
|
data: {
|
||||||
serviceName: name,
|
serviceName: name,
|
||||||
|
@ -80,8 +80,8 @@ class InstanceTable extends React.Component {
|
|||||||
const newVal = Object.assign({}, instance);
|
const newVal = Object.assign({}, instance);
|
||||||
newVal.list[index].enabled = !enabled;
|
newVal.list[index].enabled = !enabled;
|
||||||
request({
|
request({
|
||||||
method: 'POST',
|
method: 'PUT',
|
||||||
url: 'v1/ns/instance/update',
|
url: 'v1/ns/instance',
|
||||||
data: {
|
data: {
|
||||||
serviceName,
|
serviceName,
|
||||||
clusterName,
|
clusterName,
|
||||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
BIN
console/src/main/resources/static/img/black_dot.png
Normal file
BIN
console/src/main/resources/static/img/black_dot.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 114 B |
BIN
console/src/main/resources/static/img/nacos.png
Normal file
BIN
console/src/main/resources/static/img/nacos.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.5 KiB |
File diff suppressed because one or more lines are too long
27
console/src/main/resources/static/login.html
Normal file
27
console/src/main/resources/static/login.html
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>登录</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h3>登录</h3>
|
||||||
|
<form action="/nacos/login" method="post">
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<td>用户名:</td>
|
||||||
|
<td><input type="text" name="username"></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>密码:</td>
|
||||||
|
<td><input type="password" name="password"></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<button type="submit">登录</button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</form>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -18,7 +18,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>com.alibaba.nacos</groupId>
|
<groupId>com.alibaba.nacos</groupId>
|
||||||
<artifactId>nacos-all</artifactId>
|
<artifactId>nacos-all</artifactId>
|
||||||
<version>0.7.0</version>
|
<version>0.8.0-SNAPSHOT</version>
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
@ -50,6 +50,10 @@ public class WebUtils {
|
|||||||
|
|
||||||
String value = req.getParameter(key);
|
String value = req.getParameter(key);
|
||||||
|
|
||||||
|
if (StringUtils.isBlank(value)) {
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
String encoding = req.getParameter("encoding");
|
String encoding = req.getParameter("encoding");
|
||||||
if (!StringUtils.isEmpty(encoding)) {
|
if (!StringUtils.isEmpty(encoding)) {
|
||||||
try {
|
try {
|
||||||
|
@ -34,7 +34,7 @@ if not ""%2"" == "cluster" (
|
|||||||
set "JAVA_OPT=%JAVA_OPT% -XX:-UseLargePages"
|
set "JAVA_OPT=%JAVA_OPT% -XX:-UseLargePages"
|
||||||
)
|
)
|
||||||
|
|
||||||
set "JAVA_OPT=%JAVA_OPT% -Djava.ext.dirs=%BASE_DIR%\plugins\cmdb"
|
set "JAVA_OPT=%JAVA_OPT% -Xbootclasspath/a:%BASE_DIR%\plugins\cmdb"
|
||||||
set "JAVA_OPT=%JAVA_OPT% -Dnacos.home=%BASE_DIR%"
|
set "JAVA_OPT=%JAVA_OPT% -Dnacos.home=%BASE_DIR%"
|
||||||
set "JAVA_OPT=%JAVA_OPT% -jar %BASE_DIR%\target\nacos-server.jar"
|
set "JAVA_OPT=%JAVA_OPT% -jar %BASE_DIR%\target\nacos-server.jar"
|
||||||
set "JAVA_OPT=%JAVA_OPT% --spring.config.location="%CUSTOM_SEARCH_LOCATIONS%""
|
set "JAVA_OPT=%JAVA_OPT% --spring.config.location="%CUSTOM_SEARCH_LOCATIONS%""
|
||||||
|
@ -58,10 +58,10 @@ fi
|
|||||||
|
|
||||||
JAVA_MAJOR_VERSION=$($JAVA -version 2>&1 | sed -E -n 's/.* version "([0-9]*).*$/\1/p')
|
JAVA_MAJOR_VERSION=$($JAVA -version 2>&1 | sed -E -n 's/.* version "([0-9]*).*$/\1/p')
|
||||||
if [[ "$JAVA_MAJOR_VERSION" -ge "9" ]] ; then
|
if [[ "$JAVA_MAJOR_VERSION" -ge "9" ]] ; then
|
||||||
JAVA_OPT="${JAVA_OPT} -Xbootclasspath/a:${BASE_DIR}/plugins/cmdb"
|
JAVA_OPT="${JAVA_OPT} -cp .:${BASE_DIR}/plugins/cmdb/*.jar"
|
||||||
JAVA_OPT="${JAVA_OPT} -Xlog:gc*:file=${BASE_DIR}/logs/nacos_gc.log:time,tags:filecount=10,filesize=102400"
|
JAVA_OPT="${JAVA_OPT} -Xlog:gc*:file=${BASE_DIR}/logs/nacos_gc.log:time,tags:filecount=10,filesize=102400"
|
||||||
else
|
else
|
||||||
JAVA_OPT="${JAVA_OPT} -Djava.ext.dirs=${BASE_DIR}/plugins/cmdb"
|
JAVA_OPT="${JAVA_OPT} -Djava.ext.dirs=${JAVA_HOME}/jre/lib/ext:${JAVA_HOME}/lib/ext:${BASE_DIR}/plugins/cmdb"
|
||||||
JAVA_OPT="${JAVA_OPT} -Xloggc:${BASE_DIR}/logs/nacos_gc.log -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCTimeStamps -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M"
|
JAVA_OPT="${JAVA_OPT} -Xloggc:${BASE_DIR}/logs/nacos_gc.log -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCTimeStamps -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
@ -25,14 +25,16 @@ management.metrics.export.influx.enabled=false
|
|||||||
#management.metrics.export.influx.consistency=one
|
#management.metrics.export.influx.consistency=one
|
||||||
#management.metrics.export.influx.compressed=true
|
#management.metrics.export.influx.compressed=true
|
||||||
|
|
||||||
# spring.datasource.platform=mysql
|
|
||||||
#db.num=2
|
|
||||||
#db.url.0=jdbc:mysql://11.162.196.16:3306/nacos_devtest?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true
|
|
||||||
#db.url.1=jdbc:mysql://11.163.152.9:3306/nacos_devtest?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true
|
|
||||||
#db.user=nacos_devtest
|
|
||||||
#db.password=youdontknow
|
|
||||||
|
|
||||||
server.tomcat.accesslog.enabled=true
|
server.tomcat.accesslog.enabled=true
|
||||||
server.tomcat.accesslog.pattern=%h %l %u %t "%r" %s %b %D
|
server.tomcat.accesslog.pattern=%h %l %u %t "%r" %s %b %D
|
||||||
# default current work dir
|
# default current work dir
|
||||||
server.tomcat.basedir=
|
server.tomcat.basedir=
|
||||||
|
|
||||||
|
## spring security config
|
||||||
|
### turn off security
|
||||||
|
#spring.security.enabled=false
|
||||||
|
#management.security=false
|
||||||
|
#security.basic.enabled=false
|
||||||
|
#nacos.security.ignore.urls=/**
|
||||||
|
|
||||||
|
nacos.security.ignore.urls=/,/**/*.css,/**/*.js,/**/*.html,/**/*.map,/**/*.svg,/**/*.png,/**/*.ico,/console-fe/public/**,/v1/auth/login,/v1/console/health,/v1/cs/**,/v1/ns/**,/v1/cmdb/**,/actuator/**
|
||||||
|
@ -177,3 +177,18 @@ CREATE TABLE `tenant_info` (
|
|||||||
UNIQUE KEY `uk_tenant_info_kptenantid` (`kp`,`tenant_id`),
|
UNIQUE KEY `uk_tenant_info_kptenantid` (`kp`,`tenant_id`),
|
||||||
KEY `idx_tenant_id` (`tenant_id`)
|
KEY `idx_tenant_id` (`tenant_id`)
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='tenant_info';
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='tenant_info';
|
||||||
|
|
||||||
|
CREATE TABLE users (
|
||||||
|
username varchar(50) NOT NULL PRIMARY KEY,
|
||||||
|
password varchar(500) NOT NULL,
|
||||||
|
enabled boolean NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE roles (
|
||||||
|
username varchar(50) NOT NULL,
|
||||||
|
role varchar(50) NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
INSERT INTO users (username, password, enabled) VALUES ('admin', '$2a$10$HxtJtd59imujvbux.i55zOGewhnJiLVXX8D9AETDMV.XtBLDGOXtW', TRUE);
|
||||||
|
|
||||||
|
INSERT INTO roles (username, role) VALUES ('admin', 'ROLE_ADMIN');
|
||||||
|
@ -171,3 +171,18 @@ CREATE TABLE tenant_info (
|
|||||||
constraint tenant_info_id_key PRIMARY KEY (id),
|
constraint tenant_info_id_key PRIMARY KEY (id),
|
||||||
constraint uk_tenant_info_kptenantid UNIQUE (kp,tenant_id));
|
constraint uk_tenant_info_kptenantid UNIQUE (kp,tenant_id));
|
||||||
CREATE INDEX tenant_info_tenant_id_idx ON tenant_info(tenant_id);
|
CREATE INDEX tenant_info_tenant_id_idx ON tenant_info(tenant_id);
|
||||||
|
|
||||||
|
CREATE TABLE users (
|
||||||
|
username varchar(50) NOT NULL PRIMARY KEY,
|
||||||
|
password varchar(500) NOT NULL,
|
||||||
|
enabled boolean NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE roles (
|
||||||
|
username varchar(50) NOT NULL,
|
||||||
|
role varchar(50) NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
INSERT INTO users (username, password, enabled) VALUES ('admin', '$2a$10$HxtJtd59imujvbux.i55zOGewhnJiLVXX8D9AETDMV.XtBLDGOXtW', TRUE);
|
||||||
|
|
||||||
|
INSERT INTO roles (username, role) VALUES ('admin', 'ROLE_ADMIN');
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>com.alibaba.nacos</groupId>
|
<groupId>com.alibaba.nacos</groupId>
|
||||||
<artifactId>nacos-all</artifactId>
|
<artifactId>nacos-all</artifactId>
|
||||||
<version>0.7.0</version>
|
<version>0.8.0-SNAPSHOT</version>
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>com.alibaba.nacos</groupId>
|
<groupId>com.alibaba.nacos</groupId>
|
||||||
<artifactId>nacos-all</artifactId>
|
<artifactId>nacos-all</artifactId>
|
||||||
<version>0.7.0</version>
|
<version>0.8.0-SNAPSHOT</version>
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>com.alibaba.nacos</groupId>
|
<groupId>com.alibaba.nacos</groupId>
|
||||||
<artifactId>nacos-all</artifactId>
|
<artifactId>nacos-all</artifactId>
|
||||||
<version>0.7.0</version>
|
<version>0.8.0-SNAPSHOT</version>
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package com.alibaba.nacos.naming.acl;
|
package com.alibaba.nacos.naming.acl;
|
||||||
|
|
||||||
|
import com.alibaba.nacos.api.common.Constants;
|
||||||
import com.alibaba.nacos.core.utils.WebUtils;
|
import com.alibaba.nacos.core.utils.WebUtils;
|
||||||
import com.alibaba.nacos.naming.core.Domain;
|
import com.alibaba.nacos.naming.core.Domain;
|
||||||
import com.alibaba.nacos.naming.core.DomainsManager;
|
import com.alibaba.nacos.naming.core.DomainsManager;
|
||||||
@ -56,6 +57,9 @@ public class AuthChecker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void doAuth(Map<String, String[]> params, HttpServletRequest req) throws Exception {
|
public void doAuth(Map<String, String[]> params, HttpServletRequest req) throws Exception {
|
||||||
|
|
||||||
|
String namespaceId = WebUtils.optional(req, Constants.REQUEST_PARAM_NAMESPACE_ID,
|
||||||
|
UtilsAndCommons.getDefaultNamespaceId());
|
||||||
String dom = WebUtils.optional(req, "name", "");
|
String dom = WebUtils.optional(req, "name", "");
|
||||||
if (StringUtils.isEmpty(dom)) {
|
if (StringUtils.isEmpty(dom)) {
|
||||||
dom = WebUtils.optional(req, "dom", "");
|
dom = WebUtils.optional(req, "dom", "");
|
||||||
@ -71,7 +75,7 @@ public class AuthChecker {
|
|||||||
// we consider switch is a kind of special domain
|
// we consider switch is a kind of special domain
|
||||||
domObj = Switch.getDom();
|
domObj = Switch.getDom();
|
||||||
} else {
|
} else {
|
||||||
domObj = domainsManager.getDomain(dom);
|
domObj = domainsManager.getDomain(namespaceId, dom);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (domObj == null) {
|
if (domObj == null) {
|
||||||
|
@ -42,8 +42,8 @@ public class RunningConfig implements ApplicationListener<WebServerInitializedEv
|
|||||||
@Override
|
@Override
|
||||||
public void onApplicationEvent(WebServerInitializedEvent event) {
|
public void onApplicationEvent(WebServerInitializedEvent event) {
|
||||||
|
|
||||||
Loggers.SRV_LOG.info("[SERVER-INIT] got port:" + event.getWebServer().getPort());
|
Loggers.SRV_LOG.info("[SERVER-INIT] got port: {}", event.getWebServer().getPort());
|
||||||
Loggers.SRV_LOG.info("[SERVER-INIT] got path:" + servletContext.getContextPath());
|
Loggers.SRV_LOG.info("[SERVER-INIT] got path: {}", servletContext.getContextPath());
|
||||||
|
|
||||||
serverPort = event.getWebServer().getPort();
|
serverPort = event.getWebServer().getPort();
|
||||||
contextPath = servletContext.getContextPath();
|
contextPath = servletContext.getContextPath();
|
||||||
@ -51,7 +51,7 @@ public class RunningConfig implements ApplicationListener<WebServerInitializedEv
|
|||||||
try {
|
try {
|
||||||
RaftCore.init();
|
RaftCore.init();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Loggers.RAFT.error("VIPSRV-RAFT", "failed to initialize raft sub system", e);
|
Loggers.RAFT.error("[NACOS-RAFT] {} {}", "failed to initialize raft sub system", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,6 +17,7 @@ package com.alibaba.nacos.naming.controllers;
|
|||||||
|
|
||||||
import com.alibaba.fastjson.JSONArray;
|
import com.alibaba.fastjson.JSONArray;
|
||||||
import com.alibaba.fastjson.JSONObject;
|
import com.alibaba.fastjson.JSONObject;
|
||||||
|
import com.alibaba.nacos.api.common.Constants;
|
||||||
import com.alibaba.nacos.api.naming.pojo.Cluster;
|
import com.alibaba.nacos.api.naming.pojo.Cluster;
|
||||||
import com.alibaba.nacos.api.naming.pojo.Instance;
|
import com.alibaba.nacos.api.naming.pojo.Instance;
|
||||||
import com.alibaba.nacos.api.naming.pojo.Service;
|
import com.alibaba.nacos.api.naming.pojo.Service;
|
||||||
@ -64,6 +65,8 @@ public class CatalogController {
|
|||||||
@RequestMapping(value = "/serviceList")
|
@RequestMapping(value = "/serviceList")
|
||||||
public JSONObject serviceList(HttpServletRequest request) throws Exception {
|
public JSONObject serviceList(HttpServletRequest request) throws Exception {
|
||||||
|
|
||||||
|
String namespaceId = WebUtils.optional(request, Constants.REQUEST_PARAM_NAMESPACE_ID,
|
||||||
|
UtilsAndCommons.getDefaultNamespaceId());
|
||||||
JSONObject result = new JSONObject();
|
JSONObject result = new JSONObject();
|
||||||
|
|
||||||
int page = Integer.parseInt(WebUtils.required(request, "startPg"));
|
int page = Integer.parseInt(WebUtils.required(request, "startPg"));
|
||||||
@ -71,7 +74,7 @@ public class CatalogController {
|
|||||||
String keyword = WebUtils.optional(request, "keyword", StringUtils.EMPTY);
|
String keyword = WebUtils.optional(request, "keyword", StringUtils.EMPTY);
|
||||||
|
|
||||||
List<Domain> doms = new ArrayList<>();
|
List<Domain> doms = new ArrayList<>();
|
||||||
int total = domainsManager.getPagedDom(page - 1, pageSize, keyword, doms);
|
int total = domainsManager.getPagedDom(namespaceId, page - 1, pageSize, keyword, doms);
|
||||||
|
|
||||||
if (CollectionUtils.isEmpty(doms)) {
|
if (CollectionUtils.isEmpty(doms)) {
|
||||||
result.put("serviceList", Collections.emptyList());
|
result.put("serviceList", Collections.emptyList());
|
||||||
@ -109,8 +112,10 @@ public class CatalogController {
|
|||||||
@RequestMapping(value = "/serviceDetail")
|
@RequestMapping(value = "/serviceDetail")
|
||||||
public ServiceDetailView serviceDetail(HttpServletRequest request) throws Exception {
|
public ServiceDetailView serviceDetail(HttpServletRequest request) throws Exception {
|
||||||
|
|
||||||
|
String namespaceId = WebUtils.optional(request, Constants.REQUEST_PARAM_NAMESPACE_ID,
|
||||||
|
UtilsAndCommons.getDefaultNamespaceId());
|
||||||
String serviceName = WebUtils.required(request, "serviceName");
|
String serviceName = WebUtils.required(request, "serviceName");
|
||||||
VirtualClusterDomain domain = (VirtualClusterDomain) domainsManager.getDomain(serviceName);
|
VirtualClusterDomain domain = (VirtualClusterDomain) domainsManager.getDomain(namespaceId, serviceName);
|
||||||
if (domain == null) {
|
if (domain == null) {
|
||||||
throw new NacosException(NacosException.NOT_FOUND, "serivce " + serviceName + " is not found!");
|
throw new NacosException(NacosException.NOT_FOUND, "serivce " + serviceName + " is not found!");
|
||||||
}
|
}
|
||||||
@ -164,12 +169,14 @@ public class CatalogController {
|
|||||||
@RequestMapping(value = "/instanceList")
|
@RequestMapping(value = "/instanceList")
|
||||||
public JSONObject instanceList(HttpServletRequest request) throws Exception {
|
public JSONObject instanceList(HttpServletRequest request) throws Exception {
|
||||||
|
|
||||||
|
String namespaceId = WebUtils.optional(request, Constants.REQUEST_PARAM_NAMESPACE_ID,
|
||||||
|
UtilsAndCommons.getDefaultNamespaceId());
|
||||||
String serviceName = WebUtils.required(request, "serviceName");
|
String serviceName = WebUtils.required(request, "serviceName");
|
||||||
String clusterName = WebUtils.required(request, "clusterName");
|
String clusterName = WebUtils.required(request, "clusterName");
|
||||||
int page = Integer.parseInt(WebUtils.required(request, "startPg"));
|
int page = Integer.parseInt(WebUtils.required(request, "startPg"));
|
||||||
int pageSize = Integer.parseInt(WebUtils.required(request, "pgSize"));
|
int pageSize = Integer.parseInt(WebUtils.required(request, "pgSize"));
|
||||||
|
|
||||||
VirtualClusterDomain domain = (VirtualClusterDomain) domainsManager.getDomain(serviceName);
|
VirtualClusterDomain domain = (VirtualClusterDomain) domainsManager.getDomain(namespaceId, serviceName);
|
||||||
if (domain == null) {
|
if (domain == null) {
|
||||||
throw new NacosException(NacosException.NOT_FOUND, "serivce " + serviceName + " is not found!");
|
throw new NacosException(NacosException.NOT_FOUND, "serivce " + serviceName + " is not found!");
|
||||||
}
|
}
|
||||||
@ -218,10 +225,12 @@ public class CatalogController {
|
|||||||
@RequestMapping(value = "/services", method = RequestMethod.GET)
|
@RequestMapping(value = "/services", method = RequestMethod.GET)
|
||||||
public List<ServiceDetailInfo> listDetail(HttpServletRequest request) {
|
public List<ServiceDetailInfo> listDetail(HttpServletRequest request) {
|
||||||
|
|
||||||
|
String namespaceId = WebUtils.optional(request, Constants.REQUEST_PARAM_NAMESPACE_ID,
|
||||||
|
UtilsAndCommons.getDefaultNamespaceId());
|
||||||
List<ServiceDetailInfo> serviceDetailInfoList = new ArrayList<>();
|
List<ServiceDetailInfo> serviceDetailInfoList = new ArrayList<>();
|
||||||
|
|
||||||
domainsManager
|
domainsManager
|
||||||
.getRaftDomMap()
|
.getDomMap(namespaceId)
|
||||||
.forEach(
|
.forEach(
|
||||||
(serviceName, domain) -> {
|
(serviceName, domain) -> {
|
||||||
|
|
||||||
|
@ -17,6 +17,7 @@ package com.alibaba.nacos.naming.controllers;
|
|||||||
|
|
||||||
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.JSON;
|
||||||
import com.alibaba.fastjson.JSONObject;
|
import com.alibaba.fastjson.JSONObject;
|
||||||
|
import com.alibaba.nacos.api.common.Constants;
|
||||||
import com.alibaba.nacos.api.naming.pojo.AbstractHealthChecker;
|
import com.alibaba.nacos.api.naming.pojo.AbstractHealthChecker;
|
||||||
import com.alibaba.nacos.core.utils.WebUtils;
|
import com.alibaba.nacos.core.utils.WebUtils;
|
||||||
import com.alibaba.nacos.naming.core.Cluster;
|
import com.alibaba.nacos.naming.core.Cluster;
|
||||||
@ -45,9 +46,11 @@ public class ClusterController {
|
|||||||
@Autowired
|
@Autowired
|
||||||
protected DomainsManager domainsManager;
|
protected DomainsManager domainsManager;
|
||||||
|
|
||||||
@RequestMapping(value = {"/update", "/add"}, method = RequestMethod.POST)
|
@RequestMapping(value = {"/update", "/add"}, method = RequestMethod.PUT)
|
||||||
public String update(HttpServletRequest request) throws Exception {
|
public String update(HttpServletRequest request) throws Exception {
|
||||||
|
|
||||||
|
String namespaceId = WebUtils.optional(request, Constants.REQUEST_PARAM_NAMESPACE_ID,
|
||||||
|
UtilsAndCommons.getDefaultNamespaceId());
|
||||||
String clusterName = WebUtils.required(request, "clusterName");
|
String clusterName = WebUtils.required(request, "clusterName");
|
||||||
String serviceName = WebUtils.required(request, "serviceName");
|
String serviceName = WebUtils.required(request, "serviceName");
|
||||||
String healthChecker = WebUtils.required(request, "healthChecker");
|
String healthChecker = WebUtils.required(request, "healthChecker");
|
||||||
@ -55,18 +58,16 @@ public class ClusterController {
|
|||||||
String checkPort = WebUtils.required(request, "checkPort");
|
String checkPort = WebUtils.required(request, "checkPort");
|
||||||
String useInstancePort4Check = WebUtils.required(request, "useInstancePort4Check");
|
String useInstancePort4Check = WebUtils.required(request, "useInstancePort4Check");
|
||||||
|
|
||||||
VirtualClusterDomain domain = (VirtualClusterDomain) domainsManager.getDomain(serviceName);
|
VirtualClusterDomain domain = (VirtualClusterDomain) domainsManager.getDomain(namespaceId, serviceName);
|
||||||
if (domain == null) {
|
if (domain == null) {
|
||||||
throw new NacosException(NacosException.INVALID_PARAM, "service not found:" + serviceName);
|
throw new NacosException(NacosException.INVALID_PARAM, "service not found:" + serviceName);
|
||||||
}
|
}
|
||||||
|
|
||||||
Cluster cluster = domain.getClusterMap().get(clusterName);
|
Cluster cluster = domain.getClusterMap().get(clusterName);
|
||||||
if (cluster == null) {
|
if (cluster == null) {
|
||||||
Loggers.SRV_LOG.warn("UPDATE-CLUSTER", "cluster not exist, will create it: " + clusterName + ", service:" + serviceName);
|
Loggers.SRV_LOG.warn("[UPDATE-CLUSTER] cluster not exist, will create it: {}, service: {}", clusterName, serviceName);
|
||||||
cluster = new Cluster();
|
cluster = new Cluster();
|
||||||
cluster.setName(clusterName);
|
cluster.setName(clusterName);
|
||||||
|
|
||||||
// throw new NacosException(NacosException.INVALID_PARAM, "cluster not found:"+ clusterName + ", " + serviceName);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cluster.setDefCkport(NumberUtils.toInt(checkPort));
|
cluster.setDefCkport(NumberUtils.toInt(checkPort));
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package com.alibaba.nacos.naming.controllers;
|
package com.alibaba.nacos.naming.controllers;
|
||||||
|
|
||||||
|
import com.alibaba.nacos.api.common.Constants;
|
||||||
import com.alibaba.nacos.core.utils.WebUtils;
|
import com.alibaba.nacos.core.utils.WebUtils;
|
||||||
import com.alibaba.nacos.naming.boot.RunningConfig;
|
import com.alibaba.nacos.naming.boot.RunningConfig;
|
||||||
import com.alibaba.nacos.naming.core.DistroMapper;
|
import com.alibaba.nacos.naming.core.DistroMapper;
|
||||||
@ -38,15 +39,20 @@ import java.util.Map;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:zpf.073@gmail.com">nkorange</a>
|
* @author <a href="mailto:zpf.073@gmail.com">nkorange</a>
|
||||||
|
* @author nanamikon
|
||||||
|
* @since 0.8.0
|
||||||
*/
|
*/
|
||||||
@RestController("NamingHealthController")
|
@RestController("namingHealthController")
|
||||||
@RequestMapping(UtilsAndCommons.NACOS_NAMING_CONTEXT + "/health")
|
@RequestMapping(UtilsAndCommons.NACOS_NAMING_CONTEXT + "/health")
|
||||||
public class HealthController {
|
public class HealthController {
|
||||||
@Autowired
|
@Autowired
|
||||||
private DomainsManager domainsManager;
|
private DomainsManager domainsManager;
|
||||||
|
|
||||||
@RequestMapping(method = RequestMethod.POST)
|
@RequestMapping(method = {RequestMethod.POST, RequestMethod.PUT})
|
||||||
public String update(HttpServletRequest request) throws Exception {
|
public String update(HttpServletRequest request) throws Exception {
|
||||||
|
|
||||||
|
String namespaceId = WebUtils.optional(request, Constants.REQUEST_PARAM_NAMESPACE_ID,
|
||||||
|
UtilsAndCommons.getDefaultNamespaceId());
|
||||||
String dom = WebUtils.required(request, "serviceName");
|
String dom = WebUtils.required(request, "serviceName");
|
||||||
String ip = WebUtils.required(request, "ip");
|
String ip = WebUtils.required(request, "ip");
|
||||||
int port = Integer.parseInt(WebUtils.required(request, "port"));
|
int port = Integer.parseInt(WebUtils.required(request, "port"));
|
||||||
@ -75,7 +81,7 @@ public class HealthController {
|
|||||||
throw new IllegalArgumentException("failed to proxy health update to " + server + ", dom: " + dom);
|
throw new IllegalArgumentException("failed to proxy health update to " + server + ", dom: " + dom);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
VirtualClusterDomain virtualClusterDomain = (VirtualClusterDomain) domainsManager.getDomain(dom);
|
VirtualClusterDomain virtualClusterDomain = (VirtualClusterDomain) domainsManager.getDomain(namespaceId, dom);
|
||||||
// Only health check "none" need update health status with api
|
// Only health check "none" need update health status with api
|
||||||
if (!virtualClusterDomain.getEnableHealthCheck() && !virtualClusterDomain.getEnableClientBeat()) {
|
if (!virtualClusterDomain.getEnableHealthCheck() && !virtualClusterDomain.getEnableClientBeat()) {
|
||||||
for (IpAddress ipAddress : virtualClusterDomain.allIPs(Lists.newArrayList(clusterName))) {
|
for (IpAddress ipAddress : virtualClusterDomain.allIPs(Lists.newArrayList(clusterName))) {
|
||||||
@ -84,7 +90,7 @@ public class HealthController {
|
|||||||
Loggers.EVT_LOG.info((valid ? "[IP-ENABLED]" : "[IP-DISABLED]") + " ips: "
|
Loggers.EVT_LOG.info((valid ? "[IP-ENABLED]" : "[IP-DISABLED]") + " ips: "
|
||||||
+ ipAddress.getIp() + ":" + ipAddress.getPort() + "@" + ipAddress.getClusterName()
|
+ ipAddress.getIp() + ":" + ipAddress.getPort() + "@" + ipAddress.getClusterName()
|
||||||
+ ", dom: " + dom + ", msg: update thought HealthController api");
|
+ ", dom: " + dom + ", msg: update thought HealthController api");
|
||||||
PushService.domChanged(virtualClusterDomain.getName());
|
PushService.domChanged(namespaceId, virtualClusterDomain.getName());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,14 +17,14 @@ package com.alibaba.nacos.naming.controllers;
|
|||||||
|
|
||||||
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.JSON;
|
||||||
import com.alibaba.fastjson.JSONObject;
|
import com.alibaba.fastjson.JSONObject;
|
||||||
|
import com.alibaba.nacos.api.common.Constants;
|
||||||
import com.alibaba.nacos.core.utils.WebUtils;
|
import com.alibaba.nacos.core.utils.WebUtils;
|
||||||
import com.alibaba.nacos.naming.core.IpAddress;
|
import com.alibaba.nacos.naming.core.IpAddress;
|
||||||
import com.alibaba.nacos.naming.core.VirtualClusterDomain;
|
import com.alibaba.nacos.naming.core.VirtualClusterDomain;
|
||||||
import com.alibaba.nacos.naming.exception.NacosException;
|
import com.alibaba.nacos.naming.exception.NacosException;
|
||||||
import com.alibaba.nacos.naming.healthcheck.HealthCheckMode;
|
|
||||||
import com.alibaba.nacos.naming.misc.UtilsAndCommons;
|
import com.alibaba.nacos.naming.misc.UtilsAndCommons;
|
||||||
import com.alibaba.nacos.naming.web.ApiCommands;
|
import com.alibaba.nacos.naming.web.ApiCommands;
|
||||||
import com.alibaba.nacos.naming.web.MockHttpRequest;
|
import com.alibaba.nacos.naming.web.OverrideParameterRequestWrapper;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestMethod;
|
import org.springframework.web.bind.annotation.RequestMethod;
|
||||||
@ -32,9 +32,7 @@ import org.springframework.web.bind.annotation.RestController;
|
|||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:zpf.073@gmail.com">nkorange</a>
|
* @author <a href="mailto:zpf.073@gmail.com">nkorange</a>
|
||||||
@ -43,70 +41,20 @@ import java.util.Map;
|
|||||||
@RequestMapping(UtilsAndCommons.NACOS_NAMING_CONTEXT)
|
@RequestMapping(UtilsAndCommons.NACOS_NAMING_CONTEXT)
|
||||||
public class InstanceController extends ApiCommands {
|
public class InstanceController extends ApiCommands {
|
||||||
|
|
||||||
@RequestMapping(value = "/instance", method = RequestMethod.PUT)
|
@RequestMapping(value = "/instance", method = RequestMethod.POST)
|
||||||
public String register(HttpServletRequest request) throws Exception {
|
public String register(HttpServletRequest request) throws Exception {
|
||||||
|
|
||||||
Map<String, String[]> params = new HashMap<>(request.getParameterMap());
|
OverrideParameterRequestWrapper requestWrapper = OverrideParameterRequestWrapper.buildRequest(request);
|
||||||
MockHttpRequest mockHttpRequest = MockHttpRequest.buildRequest(params);
|
|
||||||
|
|
||||||
String serviceJson = WebUtils.optional(request, "service", StringUtils.EMPTY);
|
String serviceJson = WebUtils.optional(request, "service", StringUtils.EMPTY);
|
||||||
String clusterJson = WebUtils.optional(request, "cluster", StringUtils.EMPTY);
|
|
||||||
|
|
||||||
// set service info:
|
// set service info:
|
||||||
if (StringUtils.isNotEmpty(serviceJson)) {
|
if (StringUtils.isNotEmpty(serviceJson)) {
|
||||||
JSONObject service = JSON.parseObject(serviceJson);
|
JSONObject service = JSON.parseObject(serviceJson);
|
||||||
mockHttpRequest.addParameter("dom", service.getString("name"));
|
requestWrapper.addParameter("serviceName", service.getString("name"));
|
||||||
mockHttpRequest.addParameter("app", service.getString("app"));
|
|
||||||
mockHttpRequest.addParameter("group", service.getString("group"));
|
|
||||||
mockHttpRequest.addParameter("protectThreshold", service.getString("protectThreshold"));
|
|
||||||
|
|
||||||
String healthCheckMode = service.getString("healthCheckMode");
|
|
||||||
|
|
||||||
if (HealthCheckMode.server.name().equals(healthCheckMode)) {
|
|
||||||
mockHttpRequest.addParameter("enableHealthCheck", "true");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (HealthCheckMode.client.name().equals(healthCheckMode)) {
|
return regService(requestWrapper);
|
||||||
mockHttpRequest.addParameter("enableClientBeat", "true");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (HealthCheckMode.none.name().equals(healthCheckMode)) {
|
|
||||||
mockHttpRequest.addParameter("enableHealthCheck", "false");
|
|
||||||
mockHttpRequest.addParameter("enableClientBeat", "false");
|
|
||||||
}
|
|
||||||
|
|
||||||
mockHttpRequest.addParameter("serviceMetadata", service.getString("metadata"));
|
|
||||||
} else {
|
|
||||||
mockHttpRequest.addParameter("dom", WebUtils.required(request, "serviceName"));
|
|
||||||
}
|
|
||||||
|
|
||||||
// set cluster info:
|
|
||||||
if (StringUtils.isNotEmpty(clusterJson)) {
|
|
||||||
JSONObject cluster = JSON.parseObject(clusterJson);
|
|
||||||
String clusterName = cluster.getString("name");
|
|
||||||
if (StringUtils.isEmpty(clusterName)) {
|
|
||||||
clusterName = UtilsAndCommons.DEFAULT_CLUSTER_NAME;
|
|
||||||
}
|
|
||||||
mockHttpRequest.addParameter("clusterName", clusterName);
|
|
||||||
|
|
||||||
JSONObject healthChecker = cluster.getJSONObject("healthChecker");
|
|
||||||
if (healthChecker == null) {
|
|
||||||
mockHttpRequest.addParameter("cktype", "TCP");
|
|
||||||
} else {
|
|
||||||
for (String key : healthChecker.keySet()) {
|
|
||||||
mockHttpRequest.addParameter(key, healthChecker.getString(key));
|
|
||||||
}
|
|
||||||
mockHttpRequest.addParameter("cktype", healthChecker.getString("type"));
|
|
||||||
}
|
|
||||||
|
|
||||||
mockHttpRequest.addParameter("cluster", StringUtils.EMPTY);
|
|
||||||
mockHttpRequest.addParameter("defIPPort", cluster.getString("defaultPort"));
|
|
||||||
mockHttpRequest.addParameter("defCkport", cluster.getString("defaultCheckPort"));
|
|
||||||
mockHttpRequest.addParameter("ipPort4Check", cluster.getString("useIPPort4Check"));
|
|
||||||
mockHttpRequest.addParameter("clusterMetadata", cluster.getString("metadata"));
|
|
||||||
|
|
||||||
}
|
|
||||||
return regService(mockHttpRequest);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@RequestMapping(value = "/instance", method = RequestMethod.DELETE)
|
@RequestMapping(value = "/instance", method = RequestMethod.DELETE)
|
||||||
@ -114,34 +62,27 @@ public class InstanceController extends ApiCommands {
|
|||||||
return deRegService(request);
|
return deRegService(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
@RequestMapping(value = {"/instance/update", "instance"}, method = RequestMethod.POST)
|
@RequestMapping(value = {"/instance/update", "instance"}, method = RequestMethod.PUT)
|
||||||
public String update(HttpServletRequest request) throws Exception {
|
public String update(HttpServletRequest request) throws Exception {
|
||||||
String serviceName = WebUtils.required(request, "serviceName");
|
return regService(request);
|
||||||
Map<String, String[]> params = new HashMap<>(request.getParameterMap());
|
|
||||||
MockHttpRequest mockHttpRequest = MockHttpRequest.buildRequest(params);
|
|
||||||
mockHttpRequest.addParameter("dom", serviceName);
|
|
||||||
return regService(mockHttpRequest);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@RequestMapping(value = {"/instances", "/instance/list"}, method = RequestMethod.GET)
|
@RequestMapping(value = {"/instances", "/instance/list"}, method = RequestMethod.GET)
|
||||||
public JSONObject queryList(HttpServletRequest request) throws Exception {
|
public JSONObject queryList(HttpServletRequest request) throws Exception {
|
||||||
|
return srvIPXT(OverrideParameterRequestWrapper.buildRequest(request, "dom", WebUtils.required(request, "serviceName")));
|
||||||
Map<String, String[]> params = new HashMap<>(request.getParameterMap());
|
|
||||||
params.put("dom", params.get("serviceName"));
|
|
||||||
MockHttpRequest mockHttpRequest = MockHttpRequest.buildRequest(params);
|
|
||||||
|
|
||||||
return srvIPXT(mockHttpRequest);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@RequestMapping(value = "/instance", method = RequestMethod.GET)
|
@RequestMapping(value = "/instance", method = RequestMethod.GET)
|
||||||
public JSONObject queryDetail(HttpServletRequest request) throws Exception {
|
public JSONObject queryDetail(HttpServletRequest request) throws Exception {
|
||||||
|
|
||||||
String serviceName = WebUtils.required(request, "serviceName");
|
String namespaceId = WebUtils.optional(request, Constants.REQUEST_PARAM_NAMESPACE_ID,
|
||||||
|
UtilsAndCommons.getDefaultNamespaceId());
|
||||||
|
String serviceName = WebUtils.required(request, Constants.REQUEST_PARAM_SERVICE_NAME);
|
||||||
String cluster = WebUtils.optional(request, "cluster", UtilsAndCommons.DEFAULT_CLUSTER_NAME);
|
String cluster = WebUtils.optional(request, "cluster", UtilsAndCommons.DEFAULT_CLUSTER_NAME);
|
||||||
String ip = WebUtils.required(request, "ip");
|
String ip = WebUtils.required(request, "ip");
|
||||||
int port = Integer.parseInt(WebUtils.required(request, "port"));
|
int port = Integer.parseInt(WebUtils.required(request, "port"));
|
||||||
|
|
||||||
VirtualClusterDomain domain = (VirtualClusterDomain) domainsManager.getDomain(serviceName);
|
VirtualClusterDomain domain = (VirtualClusterDomain) domainsManager.getDomain(namespaceId, serviceName);
|
||||||
if (domain == null) {
|
if (domain == null) {
|
||||||
throw new NacosException(NacosException.NOT_FOUND, "no dom " + serviceName + " found!");
|
throw new NacosException(NacosException.NOT_FOUND, "no dom " + serviceName + " found!");
|
||||||
}
|
}
|
||||||
@ -170,6 +111,10 @@ public class InstanceController extends ApiCommands {
|
|||||||
}
|
}
|
||||||
|
|
||||||
throw new IllegalStateException("no matched ip found!");
|
throw new IllegalStateException("no matched ip found!");
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequestMapping(value = "/instance/beat", method = RequestMethod.PUT)
|
||||||
|
public JSONObject sendBeat(HttpServletRequest request) throws Exception {
|
||||||
|
return clientBeat(request);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@ package com.alibaba.nacos.naming.controllers;
|
|||||||
|
|
||||||
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.JSON;
|
||||||
import com.alibaba.fastjson.JSONObject;
|
import com.alibaba.fastjson.JSONObject;
|
||||||
|
import com.alibaba.nacos.api.common.Constants;
|
||||||
import com.alibaba.nacos.api.selector.SelectorType;
|
import com.alibaba.nacos.api.selector.SelectorType;
|
||||||
import com.alibaba.nacos.core.utils.WebUtils;
|
import com.alibaba.nacos.core.utils.WebUtils;
|
||||||
import com.alibaba.nacos.naming.core.DomainsManager;
|
import com.alibaba.nacos.naming.core.DomainsManager;
|
||||||
@ -24,8 +25,8 @@ import com.alibaba.nacos.naming.core.IpAddress;
|
|||||||
import com.alibaba.nacos.naming.core.VirtualClusterDomain;
|
import com.alibaba.nacos.naming.core.VirtualClusterDomain;
|
||||||
import com.alibaba.nacos.naming.exception.NacosException;
|
import com.alibaba.nacos.naming.exception.NacosException;
|
||||||
import com.alibaba.nacos.naming.healthcheck.HealthCheckMode;
|
import com.alibaba.nacos.naming.healthcheck.HealthCheckMode;
|
||||||
|
import com.alibaba.nacos.naming.misc.Switch;
|
||||||
import com.alibaba.nacos.naming.misc.UtilsAndCommons;
|
import com.alibaba.nacos.naming.misc.UtilsAndCommons;
|
||||||
import com.alibaba.nacos.naming.raft.RaftCore;
|
|
||||||
import com.alibaba.nacos.naming.selector.LabelSelector;
|
import com.alibaba.nacos.naming.selector.LabelSelector;
|
||||||
import com.alibaba.nacos.naming.selector.NoneSelector;
|
import com.alibaba.nacos.naming.selector.NoneSelector;
|
||||||
import com.alibaba.nacos.naming.selector.Selector;
|
import com.alibaba.nacos.naming.selector.Selector;
|
||||||
@ -49,16 +50,20 @@ public class ServiceController {
|
|||||||
@Autowired
|
@Autowired
|
||||||
protected DomainsManager domainsManager;
|
protected DomainsManager domainsManager;
|
||||||
|
|
||||||
@RequestMapping(value = "", method = RequestMethod.PUT)
|
@RequestMapping(value = "", method = RequestMethod.POST)
|
||||||
public String create(HttpServletRequest request) throws Exception {
|
public String create(HttpServletRequest request) throws Exception {
|
||||||
String serviceName = WebUtils.required(request, "serviceName");
|
|
||||||
|
|
||||||
if (domainsManager.getDomain(serviceName) != null) {
|
String namespaceId = WebUtils.optional(request, Constants.REQUEST_PARAM_NAMESPACE_ID,
|
||||||
|
UtilsAndCommons.getDefaultNamespaceId());
|
||||||
|
|
||||||
|
String serviceName = WebUtils.required(request, Constants.REQUEST_PARAM_SERVICE_NAME);
|
||||||
|
|
||||||
|
if (domainsManager.getDomain(namespaceId, serviceName) != null) {
|
||||||
throw new IllegalArgumentException("specified service already exists, serviceName : " + serviceName);
|
throw new IllegalArgumentException("specified service already exists, serviceName : " + serviceName);
|
||||||
}
|
}
|
||||||
|
|
||||||
float protectThreshold = NumberUtils.toFloat(WebUtils.optional(request, "protectThreshold", "0"));
|
float protectThreshold = NumberUtils.toFloat(WebUtils.optional(request, "protectThreshold", "0"));
|
||||||
String healthCheckMode = WebUtils.optional(request, "healthCheckMode", "client");
|
String healthCheckMode = WebUtils.optional(request, "healthCheckMode", Switch.getDefaultHealthCheckMode());
|
||||||
String metadata = WebUtils.optional(request, "metadata", StringUtils.EMPTY);
|
String metadata = WebUtils.optional(request, "metadata", StringUtils.EMPTY);
|
||||||
String selector = WebUtils.optional(request, "selector", StringUtils.EMPTY);
|
String selector = WebUtils.optional(request, "selector", StringUtils.EMPTY);
|
||||||
Map<String, String> metadataMap = new HashMap<>(16);
|
Map<String, String> metadataMap = new HashMap<>(16);
|
||||||
@ -74,6 +79,7 @@ public class ServiceController {
|
|||||||
domObj.setEnableClientBeat(HealthCheckMode.client.name().equals(healthCheckMode.toLowerCase()));
|
domObj.setEnableClientBeat(HealthCheckMode.client.name().equals(healthCheckMode.toLowerCase()));
|
||||||
domObj.setMetadata(metadataMap);
|
domObj.setMetadata(metadataMap);
|
||||||
domObj.setSelector(parseSelector(selector));
|
domObj.setSelector(parseSelector(selector));
|
||||||
|
domObj.setNamespaceId(namespaceId);
|
||||||
|
|
||||||
// now valid the dom. if failed, exception will be thrown
|
// now valid the dom. if failed, exception will be thrown
|
||||||
domObj.setLastModifiedMillis(System.currentTimeMillis());
|
domObj.setLastModifiedMillis(System.currentTimeMillis());
|
||||||
@ -88,9 +94,11 @@ public class ServiceController {
|
|||||||
@RequestMapping(value = "", method = RequestMethod.DELETE)
|
@RequestMapping(value = "", method = RequestMethod.DELETE)
|
||||||
public String remove(HttpServletRequest request) throws Exception {
|
public String remove(HttpServletRequest request) throws Exception {
|
||||||
|
|
||||||
String serviceName = WebUtils.required(request, "serviceName");
|
String namespaceId = WebUtils.optional(request, Constants.REQUEST_PARAM_NAMESPACE_ID,
|
||||||
|
UtilsAndCommons.getDefaultNamespaceId());
|
||||||
|
String serviceName = WebUtils.required(request, Constants.REQUEST_PARAM_SERVICE_NAME);
|
||||||
|
|
||||||
VirtualClusterDomain service = (VirtualClusterDomain) domainsManager.getDomain(serviceName);
|
VirtualClusterDomain service = (VirtualClusterDomain) domainsManager.getDomain(namespaceId, serviceName);
|
||||||
if (service == null) {
|
if (service == null) {
|
||||||
throw new IllegalArgumentException("specified service not exist, serviceName : " + serviceName);
|
throw new IllegalArgumentException("specified service not exist, serviceName : " + serviceName);
|
||||||
}
|
}
|
||||||
@ -99,7 +107,7 @@ public class ServiceController {
|
|||||||
throw new IllegalArgumentException("specified service has instances, serviceName : " + serviceName);
|
throw new IllegalArgumentException("specified service has instances, serviceName : " + serviceName);
|
||||||
}
|
}
|
||||||
|
|
||||||
domainsManager.easyRemoveDom(serviceName);
|
domainsManager.easyRemoveDom(namespaceId, serviceName);
|
||||||
|
|
||||||
return "ok";
|
return "ok";
|
||||||
}
|
}
|
||||||
@ -107,14 +115,18 @@ public class ServiceController {
|
|||||||
@RequestMapping(value = "", method = RequestMethod.GET)
|
@RequestMapping(value = "", method = RequestMethod.GET)
|
||||||
public JSONObject detail(HttpServletRequest request) throws Exception {
|
public JSONObject detail(HttpServletRequest request) throws Exception {
|
||||||
|
|
||||||
String serviceName = WebUtils.required(request, "serviceName");
|
String namespaceId = WebUtils.optional(request, Constants.REQUEST_PARAM_NAMESPACE_ID,
|
||||||
VirtualClusterDomain domain = (VirtualClusterDomain) domainsManager.getDomain(serviceName);
|
UtilsAndCommons.getDefaultNamespaceId());
|
||||||
|
String serviceName = WebUtils.required(request, Constants.REQUEST_PARAM_SERVICE_NAME);
|
||||||
|
|
||||||
|
VirtualClusterDomain domain = (VirtualClusterDomain) domainsManager.getDomain(namespaceId, serviceName);
|
||||||
if (domain == null) {
|
if (domain == null) {
|
||||||
throw new NacosException(NacosException.NOT_FOUND, "serivce " + serviceName + " is not found!");
|
throw new NacosException(NacosException.NOT_FOUND, "serivce " + serviceName + " is not found!");
|
||||||
}
|
}
|
||||||
|
|
||||||
JSONObject res = new JSONObject();
|
JSONObject res = new JSONObject();
|
||||||
res.put("name", serviceName);
|
res.put("name", serviceName);
|
||||||
|
res.put("namespaceId", domain.getNamespaceId());
|
||||||
res.put("protectThreshold", domain.getProtectThreshold());
|
res.put("protectThreshold", domain.getProtectThreshold());
|
||||||
|
|
||||||
res.put("healthCheckMode", HealthCheckMode.none.name());
|
res.put("healthCheckMode", HealthCheckMode.none.name());
|
||||||
@ -131,9 +143,6 @@ public class ServiceController {
|
|||||||
|
|
||||||
res.put("selector", domain.getSelector());
|
res.put("selector", domain.getSelector());
|
||||||
|
|
||||||
res.put("instanceTimestamp", RaftCore.getDatum(UtilsAndCommons.getIPListStoreKey(domain)).timestamp.get());
|
|
||||||
res.put("serviceTimestamp", RaftCore.getDatum(UtilsAndCommons.getDomStoreKey(domain)).timestamp.get());
|
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -142,9 +151,15 @@ public class ServiceController {
|
|||||||
|
|
||||||
int pageNo = NumberUtils.toInt(WebUtils.required(request, "pageNo"));
|
int pageNo = NumberUtils.toInt(WebUtils.required(request, "pageNo"));
|
||||||
int pageSize = NumberUtils.toInt(WebUtils.required(request, "pageSize"));
|
int pageSize = NumberUtils.toInt(WebUtils.required(request, "pageSize"));
|
||||||
|
String namespaceId = WebUtils.optional(request, Constants.REQUEST_PARAM_NAMESPACE_ID,
|
||||||
|
UtilsAndCommons.getDefaultNamespaceId());
|
||||||
String selectorString = WebUtils.optional(request, "selector", StringUtils.EMPTY);
|
String selectorString = WebUtils.optional(request, "selector", StringUtils.EMPTY);
|
||||||
|
|
||||||
List<String> doms = domainsManager.getAllDomNamesList();
|
List<String> doms = domainsManager.getAllDomNamesList(namespaceId);
|
||||||
|
|
||||||
|
if (doms == null || doms.isEmpty()) {
|
||||||
|
throw new NacosException(NacosException.INVALID_PARAM, "No service exist in " + namespaceId);
|
||||||
|
}
|
||||||
|
|
||||||
if (StringUtils.isNotBlank(selectorString)) {
|
if (StringUtils.isNotBlank(selectorString)) {
|
||||||
|
|
||||||
@ -163,10 +178,10 @@ public class ServiceController {
|
|||||||
String[] factors = terms[0].split("\\.");
|
String[] factors = terms[0].split("\\.");
|
||||||
switch (factors[0]) {
|
switch (factors[0]) {
|
||||||
case "INSTANCE":
|
case "INSTANCE":
|
||||||
doms = filterInstanceMetadata(doms, factors[factors.length - 1], terms[1].replace("'", ""));
|
doms = filterInstanceMetadata(namespaceId, doms, factors[factors.length - 1], terms[1].replace("'", ""));
|
||||||
break;
|
break;
|
||||||
case "SERVICE":
|
case "SERVICE":
|
||||||
doms = filterServiceMetadata(doms, factors[factors.length - 1], terms[1].replace("'", ""));
|
doms = filterServiceMetadata(namespaceId, doms, factors[factors.length - 1], terms[1].replace("'", ""));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@ -197,16 +212,18 @@ public class ServiceController {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@RequestMapping(value = "", method = RequestMethod.POST)
|
@RequestMapping(value = "", method = RequestMethod.PUT)
|
||||||
public String update(HttpServletRequest request) throws Exception {
|
public String update(HttpServletRequest request) throws Exception {
|
||||||
|
|
||||||
String serviceName = WebUtils.required(request, "serviceName");
|
String namespaceId = WebUtils.optional(request, Constants.REQUEST_PARAM_NAMESPACE_ID,
|
||||||
|
UtilsAndCommons.getDefaultNamespaceId());
|
||||||
|
String serviceName = WebUtils.required(request, Constants.REQUEST_PARAM_SERVICE_NAME);
|
||||||
float protectThreshold = NumberUtils.toFloat(WebUtils.required(request, "protectThreshold"));
|
float protectThreshold = NumberUtils.toFloat(WebUtils.required(request, "protectThreshold"));
|
||||||
String healthCheckMode = WebUtils.required(request, "healthCheckMode");
|
String healthCheckMode = WebUtils.required(request, "healthCheckMode");
|
||||||
String metadata = WebUtils.optional(request, "metadata", StringUtils.EMPTY);
|
String metadata = WebUtils.optional(request, "metadata", StringUtils.EMPTY);
|
||||||
String selector = WebUtils.optional(request, "selector", StringUtils.EMPTY);
|
String selector = WebUtils.optional(request, "selector", StringUtils.EMPTY);
|
||||||
|
|
||||||
VirtualClusterDomain domain = (VirtualClusterDomain) domainsManager.getDomain(serviceName);
|
VirtualClusterDomain domain = (VirtualClusterDomain) domainsManager.getDomain(namespaceId, serviceName);
|
||||||
if (domain == null) {
|
if (domain == null) {
|
||||||
throw new NacosException(NacosException.INVALID_PARAM, "service " + serviceName + " not found!");
|
throw new NacosException(NacosException.INVALID_PARAM, "service " + serviceName + " not found!");
|
||||||
}
|
}
|
||||||
@ -242,16 +259,16 @@ public class ServiceController {
|
|||||||
return "ok";
|
return "ok";
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<String> filterInstanceMetadata(List<String> serivces, String key, String value) {
|
private List<String> filterInstanceMetadata(String namespaceId, List<String> serivces, String key, String value) {
|
||||||
|
|
||||||
List<String> filteredServices = new ArrayList<>();
|
List<String> filteredServices = new ArrayList<>();
|
||||||
for (String service : serivces) {
|
for (String service : serivces) {
|
||||||
VirtualClusterDomain serviceObj = (VirtualClusterDomain) domainsManager.getDomain(service);
|
VirtualClusterDomain serviceObj = (VirtualClusterDomain) domainsManager.getDomain(namespaceId, service);
|
||||||
if (serviceObj == null) {
|
if (serviceObj == null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
for (IpAddress address : serviceObj.allIPs()) {
|
for (IpAddress address : serviceObj.allIPs()) {
|
||||||
if (value.equals(address.getMetadata().get(key))) {
|
if (address.getMetadata() != null && value.equals(address.getMetadata().get(key))) {
|
||||||
filteredServices.add(service);
|
filteredServices.add(service);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -260,11 +277,11 @@ public class ServiceController {
|
|||||||
return filteredServices;
|
return filteredServices;
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<String> filterServiceMetadata(List<String> serivces, String key, String value) {
|
private List<String> filterServiceMetadata(String namespaceId, List<String> serivces, String key, String value) {
|
||||||
|
|
||||||
List<String> filteredServices = new ArrayList<>();
|
List<String> filteredServices = new ArrayList<>();
|
||||||
for (String service : serivces) {
|
for (String service : serivces) {
|
||||||
VirtualClusterDomain serviceObj = (VirtualClusterDomain) domainsManager.getDomain(service);
|
VirtualClusterDomain serviceObj = (VirtualClusterDomain) domainsManager.getDomain(namespaceId, service);
|
||||||
if (serviceObj == null) {
|
if (serviceObj == null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -187,24 +187,22 @@ public class Cluster extends com.alibaba.nacos.api.naming.pojo.Cluster implement
|
|||||||
} else {
|
} else {
|
||||||
if (ip.isValid() != oldIP.isValid()) {
|
if (ip.isValid() != oldIP.isValid()) {
|
||||||
// ip validation status updated
|
// ip validation status updated
|
||||||
Loggers.EVT_LOG.info("{" + getDom().getName() + "} {SYNC} " +
|
Loggers.EVT_LOG.info("{} {SYNC} IP-{} {}:{}@{}",
|
||||||
"{IP-" + (ip.isValid() ? "ENABLED" : "DISABLED") + "} " + ip.getIp()
|
getDom().getName(), (ip.isValid() ? "ENABLED" : "DISABLED"), ip.getIp(), ip.getPort(), getName());
|
||||||
+ ":" + ip.getPort() + "@" + getName());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ip.getWeight() != oldIP.getWeight()) {
|
if (ip.getWeight() != oldIP.getWeight()) {
|
||||||
// ip validation status updated
|
// ip validation status updated
|
||||||
Loggers.EVT_LOG.info("{" + getDom().getName() + "} {SYNC} " +
|
Loggers.EVT_LOG.info("{} {SYNC} {IP-UPDATED} {}->{}", getDom().getName(), oldIP.toString(), ip.toString());
|
||||||
"{IP-UPDATED} " + oldIP.toString() + "->" + ip.toString());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
List<IpAddress> newIPs = subtract(ips, oldIPMap.values());
|
List<IpAddress> newIPs = subtract(ips, oldIPMap.values());
|
||||||
if (newIPs.size() > 0) {
|
if (newIPs.size() > 0) {
|
||||||
Loggers.EVT_LOG.info("{" + getDom().getName() + "} {SYNC} {IP-NEW} cluster: " + getName()
|
Loggers.EVT_LOG.info("{} {SYNC} {IP-NEW} cluster: {}, new ips size: {}, content: {}",
|
||||||
+ ", new ips(" + newIPs.size() + "): " + newIPs.toString());
|
getDom().getName(), getName(), newIPs.size(), newIPs.toString());
|
||||||
|
|
||||||
for (IpAddress ip : newIPs) {
|
for (IpAddress ip : newIPs) {
|
||||||
HealthCheckStatus.reset(ip);
|
HealthCheckStatus.reset(ip);
|
||||||
@ -214,8 +212,8 @@ public class Cluster extends com.alibaba.nacos.api.naming.pojo.Cluster implement
|
|||||||
List<IpAddress> deadIPs = subtract(oldIPMap.values(), ips);
|
List<IpAddress> deadIPs = subtract(oldIPMap.values(), ips);
|
||||||
|
|
||||||
if (deadIPs.size() > 0) {
|
if (deadIPs.size() > 0) {
|
||||||
Loggers.EVT_LOG.info("{" + getDom().getName() + "} {SYNC} {IP-DEAD} cluster: " + getName()
|
Loggers.EVT_LOG.info("{} {SYNC} {IP-DEAD} cluster: {}, dead ips size: {}, content: {}",
|
||||||
+ ", dead ips(" + deadIPs.size() + "): " + deadIPs.toString());
|
getDom().getName(), getName(), deadIPs.size(), deadIPs.toString());
|
||||||
|
|
||||||
for (IpAddress ip : deadIPs) {
|
for (IpAddress ip : deadIPs) {
|
||||||
HealthCheckStatus.remv(ip);
|
HealthCheckStatus.remv(ip);
|
||||||
@ -333,32 +331,38 @@ public class Cluster extends com.alibaba.nacos.api.naming.pojo.Cluster implement
|
|||||||
public void update(Cluster cluster) {
|
public void update(Cluster cluster) {
|
||||||
|
|
||||||
if (!healthChecker.equals(cluster.getHealthChecker())) {
|
if (!healthChecker.equals(cluster.getHealthChecker())) {
|
||||||
Loggers.SRV_LOG.info("[CLUSTER-UPDATE] " + cluster.getDom().getName() + ":" + cluster.getName() + ", healthChecker: " + healthChecker.toString() + " -> " + cluster.getHealthChecker().toString());
|
Loggers.SRV_LOG.info("[CLUSTER-UPDATE] {}:{}:, healthChecker: {} -> {}",
|
||||||
|
cluster.getDom().getName(), cluster.getName(), healthChecker.toString(), cluster.getHealthChecker().toString());
|
||||||
healthChecker = cluster.getHealthChecker();
|
healthChecker = cluster.getHealthChecker();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (defCkport != cluster.getDefCkport()) {
|
if (defCkport != cluster.getDefCkport()) {
|
||||||
Loggers.SRV_LOG.info("[CLUSTER-UPDATE] " + cluster.getDom().getName() + ":" + cluster.getName() + ", defCkport: " + defCkport + " -> " + cluster.getDefCkport());
|
Loggers.SRV_LOG.info("[CLUSTER-UPDATE] {}:{}, defCkport: {} -> {}",
|
||||||
|
cluster.getDom().getName(), cluster.getName(), defCkport, cluster.getDefCkport());
|
||||||
defCkport = cluster.getDefCkport();
|
defCkport = cluster.getDefCkport();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (defIPPort != cluster.getDefIPPort()) {
|
if (defIPPort != cluster.getDefIPPort()) {
|
||||||
Loggers.SRV_LOG.info("[CLUSTER-UPDATE] " + cluster.getDom().getName() + ":" + cluster.getName() + ", defIPPort: " + defIPPort + " -> " + cluster.getDefIPPort());
|
Loggers.SRV_LOG.info("[CLUSTER-UPDATE] {}:{}, defIPPort: {} -> {}",
|
||||||
|
cluster.getDom().getName(), cluster.getName(), defIPPort, cluster.getDefIPPort());
|
||||||
defIPPort = cluster.getDefIPPort();
|
defIPPort = cluster.getDefIPPort();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!StringUtils.equals(submask, cluster.getSubmask())) {
|
if (!StringUtils.equals(submask, cluster.getSubmask())) {
|
||||||
Loggers.SRV_LOG.info("[CLUSTER-UPDATE] " + cluster.getDom().getName() + ":" + cluster.getName() + ", submask: " + submask + " -> " + cluster.getSubmask());
|
Loggers.SRV_LOG.info("[CLUSTER-UPDATE] {}:{}, submask: {} -> {}",
|
||||||
|
cluster.getDom().getName(), cluster.getName(), submask, cluster.getSubmask());
|
||||||
submask = cluster.getSubmask();
|
submask = cluster.getSubmask();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!StringUtils.equals(sitegroup, cluster.getSitegroup())) {
|
if (!StringUtils.equals(sitegroup, cluster.getSitegroup())) {
|
||||||
Loggers.SRV_LOG.info("[CLUSTER-UPDATE] " + cluster.getDom().getName() + ":" + cluster.getName() + ", sitegroup: " + sitegroup + " -> " + cluster.getSitegroup());
|
Loggers.SRV_LOG.info("[CLUSTER-UPDATE] {}:{}, sitegroup: {} -> {}",
|
||||||
|
cluster.getDom().getName(), cluster.getName(), sitegroup, cluster.getSitegroup());
|
||||||
sitegroup = cluster.getSitegroup();
|
sitegroup = cluster.getSitegroup();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isUseIPPort4Check() != cluster.isUseIPPort4Check()) {
|
if (isUseIPPort4Check() != cluster.isUseIPPort4Check()) {
|
||||||
Loggers.SRV_LOG.info("[CLUSTER-UPDATE] " + cluster.getDom().getName() + ":" + cluster.getName() + ", useIPPort4Check: " + isUseIPPort4Check() + " -> " + cluster.isUseIPPort4Check());
|
Loggers.SRV_LOG.info("[CLUSTER-UPDATE] {}:{}, useIPPort4Check: {} -> {}",
|
||||||
|
cluster.getDom().getName(), cluster.getName(), isUseIPPort4Check(), cluster.isUseIPPort4Check());
|
||||||
setUseIPPort4Check(cluster.isUseIPPort4Check());
|
setUseIPPort4Check(cluster.isUseIPPort4Check());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,8 +21,6 @@ import com.alibaba.nacos.naming.misc.*;
|
|||||||
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
|
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
|
||||||
import org.apache.commons.collections.CollectionUtils;
|
import org.apache.commons.collections.CollectionUtils;
|
||||||
|
|
||||||
import java.net.InetAddress;
|
|
||||||
import java.net.UnknownHostException;
|
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
@ -110,7 +108,7 @@ public class DistroMapper {
|
|||||||
// site:ip:lastReportTime:weight
|
// site:ip:lastReportTime:weight
|
||||||
String[] params = config.split("#");
|
String[] params = config.split("#");
|
||||||
if (params.length <= 3) {
|
if (params.length <= 3) {
|
||||||
Loggers.SRV_LOG.warn("received malformed distro map data: " + config);
|
Loggers.SRV_LOG.warn("received malformed distro map data: {}", config);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -162,7 +160,7 @@ public class DistroMapper {
|
|||||||
&& curRatio > Switch.getDistroThreshold()
|
&& curRatio > Switch.getDistroThreshold()
|
||||||
&& System.currentTimeMillis() - LAST_HEALTH_SERVER_MILLIS > STABLE_PERIOD) {
|
&& System.currentTimeMillis() - LAST_HEALTH_SERVER_MILLIS > STABLE_PERIOD) {
|
||||||
Loggers.SRV_LOG.info("[VIPSRV-DISTRO] distro threshold restored and " +
|
Loggers.SRV_LOG.info("[VIPSRV-DISTRO] distro threshold restored and " +
|
||||||
"stable now, enable health check. current ratio: " + curRatio);
|
"stable now, enable health check. current ratio: {}", curRatio);
|
||||||
|
|
||||||
Switch.setHeathCheckEnabled(true);
|
Switch.setHeathCheckEnabled(true);
|
||||||
|
|
||||||
@ -174,7 +172,8 @@ public class DistroMapper {
|
|||||||
// for every change disable healthy check for some while
|
// for every change disable healthy check for some while
|
||||||
if (Switch.isHealthCheckEnabled()) {
|
if (Switch.isHealthCheckEnabled()) {
|
||||||
Loggers.SRV_LOG.info("[VIPSRV-DISTRO] healthy server list changed, " +
|
Loggers.SRV_LOG.info("[VIPSRV-DISTRO] healthy server list changed, " +
|
||||||
"disable health check for " + STABLE_PERIOD + "ms from now on, healthList: " + healthyList + ",newHealthyList " + newHealthyList);
|
"disable health check for {} ms from now on, healthList: {}, newHealthyList {}",
|
||||||
|
STABLE_PERIOD, healthyList, newHealthyList);
|
||||||
|
|
||||||
Switch.setHeathCheckEnabled(false);
|
Switch.setHeathCheckEnabled(false);
|
||||||
AUTO_DISABLED_HEALTH_CHECK = true;
|
AUTO_DISABLED_HEALTH_CHECK = true;
|
||||||
@ -200,7 +199,7 @@ public class DistroMapper {
|
|||||||
// site:ip:lastReportTime:weight
|
// site:ip:lastReportTime:weight
|
||||||
String[] params = config.split("#");
|
String[] params = config.split("#");
|
||||||
if (params.length <= 3) {
|
if (params.length <= 3) {
|
||||||
Loggers.SRV_LOG.warn("received malformed distro map data: " + config);
|
Loggers.SRV_LOG.warn("received malformed distro map data: {}", config);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -232,8 +231,8 @@ public class DistroMapper {
|
|||||||
|
|
||||||
if (serverId.equals(newServerId)) {
|
if (serverId.equals(newServerId)) {
|
||||||
if (s.alive != server.alive || s.weight != server.weight) {
|
if (s.alive != server.alive || s.weight != server.weight) {
|
||||||
Loggers.SRV_LOG.warn("server beat out of date, current: " + JSON.toJSONString(server)
|
Loggers.SRV_LOG.warn("server beat out of date, current: {}, last: {}",
|
||||||
+ ", last: " + JSON.toJSONString(s));
|
JSON.toJSONString(server), JSON.toJSONString(s));
|
||||||
}
|
}
|
||||||
tmpServerList.add(server);
|
tmpServerList.add(server);
|
||||||
continue;
|
continue;
|
||||||
@ -284,7 +283,7 @@ public class DistroMapper {
|
|||||||
&& curRatio > Switch.getDistroThreshold()
|
&& curRatio > Switch.getDistroThreshold()
|
||||||
&& System.currentTimeMillis() - LAST_HEALTH_SERVER_MILLIS > STABLE_PERIOD) {
|
&& System.currentTimeMillis() - LAST_HEALTH_SERVER_MILLIS > STABLE_PERIOD) {
|
||||||
Loggers.SRV_LOG.info("[VIPSRV-DISTRO] distro threshold restored and " +
|
Loggers.SRV_LOG.info("[VIPSRV-DISTRO] distro threshold restored and " +
|
||||||
"stable now, enable health check. current ratio: " + curRatio);
|
"stable now, enable health check. current ratio: {}", curRatio);
|
||||||
|
|
||||||
Switch.setHeathCheckEnabled(true);
|
Switch.setHeathCheckEnabled(true);
|
||||||
|
|
||||||
@ -296,7 +295,7 @@ public class DistroMapper {
|
|||||||
// for every change disable healthy check for some while
|
// for every change disable healthy check for some while
|
||||||
if (Switch.isHealthCheckEnabled()) {
|
if (Switch.isHealthCheckEnabled()) {
|
||||||
Loggers.SRV_LOG.info("[VIPSRV-DISTRO] healthy server list changed, " +
|
Loggers.SRV_LOG.info("[VIPSRV-DISTRO] healthy server list changed, " +
|
||||||
"disable health check for " + STABLE_PERIOD + "ms from now on");
|
"disable health check for {} ms from now on", STABLE_PERIOD);
|
||||||
|
|
||||||
Switch.setHeathCheckEnabled(false);
|
Switch.setHeathCheckEnabled(false);
|
||||||
AUTO_DISABLED_HEALTH_CHECK = true;
|
AUTO_DISABLED_HEALTH_CHECK = true;
|
||||||
@ -402,7 +401,7 @@ public class DistroMapper {
|
|||||||
try {
|
try {
|
||||||
NamingProxy.reqAPI("distroStatus", params, serverIP, false);
|
NamingProxy.reqAPI("distroStatus", params, serverIP, false);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Loggers.SRV_LOG.warn("DISTRO-STATUS-CLEAN", "Failed to request to clean server status to " + serverIP, e);
|
Loggers.SRV_LOG.warn("[DISTRO-STATUS-CLEAN] Failed to request to clean server status to " + serverIP, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -488,7 +487,7 @@ public class DistroMapper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!allServers.contains(localhostIP)) {
|
if (!allServers.contains(localhostIP)) {
|
||||||
Loggers.SRV_LOG.error("NA", "local ip is not in serverlist, ip: " + localhostIP + ", serverlist: " + allServers);
|
Loggers.SRV_LOG.error("local ip is not in serverlist, ip: {}, serverlist: {}", localhostIP, allServers);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -500,7 +499,7 @@ public class DistroMapper {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Loggers.SRV_LOG.error("SERVER-STATUS", "Exception while sending server status: ", e);
|
Loggers.SRV_LOG.error("[SERVER-STATUS] Exception while sending server status", e);
|
||||||
} finally {
|
} finally {
|
||||||
UtilsAndCommons.SERVER_STATUS_EXECUTOR.schedule(this, Switch.getServerStatusSynchronizationPeriodMillis(), TimeUnit.MILLISECONDS);
|
UtilsAndCommons.SERVER_STATUS_EXECUTOR.schedule(this, Switch.getServerStatusSynchronizationPeriodMillis(), TimeUnit.MILLISECONDS);
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,6 @@ import com.alibaba.nacos.naming.raft.RaftCore;
|
|||||||
import com.alibaba.nacos.naming.raft.RaftListener;
|
import com.alibaba.nacos.naming.raft.RaftListener;
|
||||||
import com.alibaba.nacos.naming.raft.RaftPeer;
|
import com.alibaba.nacos.naming.raft.RaftPeer;
|
||||||
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
|
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
|
||||||
import org.apache.commons.collections.CollectionUtils;
|
|
||||||
import org.apache.commons.lang3.ArrayUtils;
|
import org.apache.commons.lang3.ArrayUtils;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
@ -43,7 +42,10 @@ import java.util.concurrent.locks.ReentrantLock;
|
|||||||
@Component
|
@Component
|
||||||
public class DomainsManager {
|
public class DomainsManager {
|
||||||
|
|
||||||
private Map<String, Domain> raftDomMap = new ConcurrentHashMap<>();
|
/**
|
||||||
|
* Map<namespace, Map<group::serviceName, Service>>
|
||||||
|
*/
|
||||||
|
private Map<String, Map<String, Domain>> serviceMap = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
private LinkedBlockingDeque<DomainKey> toBeUpdatedDomsQueue = new LinkedBlockingDeque<>(1024 * 1024);
|
private LinkedBlockingDeque<DomainKey> toBeUpdatedDomsQueue = new LinkedBlockingDeque<>(1024 * 1024);
|
||||||
|
|
||||||
@ -78,8 +80,8 @@ public class DomainsManager {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
public Map<String, Domain> chooseDomMap() {
|
public Map<String, Domain> chooseDomMap(String namespaceId) {
|
||||||
return raftDomMap;
|
return serviceMap.get(namespaceId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initConfig() {
|
private void initConfig() {
|
||||||
@ -90,32 +92,32 @@ public class DomainsManager {
|
|||||||
try {
|
try {
|
||||||
TimeUnit.SECONDS.sleep(5);
|
TimeUnit.SECONDS.sleep(5);
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
Loggers.SRV_LOG.error("AUTO-INIT", "failed to auto init", e);
|
Loggers.SRV_LOG.error("[AUTO-INIT] failed to auto init", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
leader = RaftCore.getPeerSet().getLeader();
|
leader = RaftCore.getPeerSet().getLeader();
|
||||||
if (leader != null) {
|
if (leader != null) {
|
||||||
Loggers.SRV_LOG.info("[AUTO-INIT] leader is: " + leader.ip);
|
Loggers.SRV_LOG.info("[AUTO-INIT] leader is: {}", leader.ip);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (Throwable throwable) {
|
} catch (Throwable throwable) {
|
||||||
Loggers.SRV_LOG.error("AUTO-INIT", "failed to auto init", throwable);
|
Loggers.SRV_LOG.error("[AUTO-INIT] failed to auto init", throwable);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void addUpdatedDom2Queue(String domName, String serverIP, String checksum) {
|
public void addUpdatedDom2Queue(String namespaceId, String domName, String serverIP, String checksum) {
|
||||||
lock.lock();
|
lock.lock();
|
||||||
try {
|
try {
|
||||||
toBeUpdatedDomsQueue.offer(new DomainKey(domName, serverIP, checksum), 5, TimeUnit.MILLISECONDS);
|
toBeUpdatedDomsQueue.offer(new DomainKey(namespaceId, domName, serverIP, checksum), 5, TimeUnit.MILLISECONDS);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
toBeUpdatedDomsQueue.poll();
|
toBeUpdatedDomsQueue.poll();
|
||||||
toBeUpdatedDomsQueue.add(new DomainKey(domName, serverIP, checksum));
|
toBeUpdatedDomsQueue.add(new DomainKey(namespaceId, domName, serverIP, checksum));
|
||||||
Loggers.SRV_LOG.error("DOMAIN-STATUS", "Failed to add domain to be updatd to queue.", e);
|
Loggers.SRV_LOG.error("[DOMAIN-STATUS] Failed to add domain to be updatd to queue.", e);
|
||||||
} finally {
|
} finally {
|
||||||
lock.unlock();
|
lock.unlock();
|
||||||
}
|
}
|
||||||
@ -128,7 +130,6 @@ public class DomainsManager {
|
|||||||
public void run() {
|
public void run() {
|
||||||
String domName = null;
|
String domName = null;
|
||||||
String serverIP = null;
|
String serverIP = null;
|
||||||
String checksum;
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
while (true) {
|
while (true) {
|
||||||
@ -137,7 +138,7 @@ public class DomainsManager {
|
|||||||
try {
|
try {
|
||||||
domainKey = toBeUpdatedDomsQueue.take();
|
domainKey = toBeUpdatedDomsQueue.take();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Loggers.EVT_LOG.error("UPDATE-DOMAIN", "Exception while taking item from LinkedBlockingDeque.");
|
Loggers.EVT_LOG.error("[UPDATE-DOMAIN] Exception while taking item from LinkedBlockingDeque.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (domainKey == null) {
|
if (domainKey == null) {
|
||||||
@ -146,21 +147,23 @@ public class DomainsManager {
|
|||||||
|
|
||||||
domName = domainKey.getDomName();
|
domName = domainKey.getDomName();
|
||||||
serverIP = domainKey.getServerIP();
|
serverIP = domainKey.getServerIP();
|
||||||
checksum = domainKey.getChecksum();
|
|
||||||
|
|
||||||
domainUpdateExecutor.execute(new DomUpdater(domName, serverIP));
|
domainUpdateExecutor.execute(new DomUpdater(domainKey.getNamespaceId(), domName, serverIP));
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Loggers.EVT_LOG.error("UPDATE-DOMAIN", "Exception while update dom: " + domName + "from " + serverIP, e);
|
Loggers.EVT_LOG.error("[UPDATE-DOMAIN] Exception while update dom: {} from {}, error: {}", domName, serverIP, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class DomUpdater implements Runnable {
|
private class DomUpdater implements Runnable {
|
||||||
|
|
||||||
|
String namespaceId;
|
||||||
String domName;
|
String domName;
|
||||||
String serverIP;
|
String serverIP;
|
||||||
|
|
||||||
public DomUpdater(String domName, String serverIP) {
|
public DomUpdater(String namespaceId, String domName, String serverIP) {
|
||||||
|
this.namespaceId = namespaceId;
|
||||||
this.domName = domName;
|
this.domName = domName;
|
||||||
this.serverIP = serverIP;
|
this.serverIP = serverIP;
|
||||||
}
|
}
|
||||||
@ -168,15 +171,16 @@ public class DomainsManager {
|
|||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
try {
|
try {
|
||||||
updatedDom2(domName, serverIP);
|
updatedDom2(namespaceId, domName, serverIP);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Loggers.SRV_LOG.warn("DOMAIN-UPDATER", "Exception while update dom: " + domName + "from " + serverIP, e);
|
Loggers.SRV_LOG.warn("[DOMAIN-UPDATER] Exception while update dom: {} from {}, error: {}",
|
||||||
|
domName, serverIP, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updatedDom2(String domName, String serverIP) {
|
public void updatedDom2(String namespaceId, String domName, String serverIP) {
|
||||||
Message msg = synchronizer.get(serverIP, domName);
|
Message msg = synchronizer.get(serverIP, UtilsAndCommons.assembleFullServiceName(namespaceId, domName));
|
||||||
JSONObject dom = JSON.parseObject(msg.getData());
|
JSONObject dom = JSON.parseObject(msg.getData());
|
||||||
|
|
||||||
JSONArray ipList = dom.getJSONArray("ips");
|
JSONArray ipList = dom.getJSONArray("ips");
|
||||||
@ -188,7 +192,7 @@ public class DomainsManager {
|
|||||||
ipsMap.put(strings[0], strings[1]);
|
ipsMap.put(strings[0], strings[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
VirtualClusterDomain raftVirtualClusterDomain = (VirtualClusterDomain) raftDomMap.get(domName);
|
VirtualClusterDomain raftVirtualClusterDomain = (VirtualClusterDomain) getDomain(namespaceId, domName);
|
||||||
|
|
||||||
if (raftVirtualClusterDomain == null) {
|
if (raftVirtualClusterDomain == null) {
|
||||||
return;
|
return;
|
||||||
@ -200,85 +204,92 @@ public class DomainsManager {
|
|||||||
Boolean valid = Boolean.parseBoolean(ipsMap.get(ipAddress.toIPAddr()));
|
Boolean valid = Boolean.parseBoolean(ipsMap.get(ipAddress.toIPAddr()));
|
||||||
if (valid != ipAddress.isValid()) {
|
if (valid != ipAddress.isValid()) {
|
||||||
ipAddress.setValid(valid);
|
ipAddress.setValid(valid);
|
||||||
Loggers.EVT_LOG.info("{" + domName + "} {SYNC} " +
|
Loggers.EVT_LOG.info("{} {SYNC} IP-{} : {}@{}",
|
||||||
"{IP-" + (ipAddress.isValid() ? "ENABLED" : "DISABLED") + "} " + ipAddress.getIp()
|
domName, (ipAddress.isValid() ? "ENABLED" : "DISABLED"),
|
||||||
+ ":" + ipAddress.getPort() + "@" + ipAddress.getClusterName());
|
ipAddress.getIp(), ipAddress.getPort(), ipAddress.getClusterName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PushService.domChanged(raftVirtualClusterDomain.getName());
|
PushService.domChanged(raftVirtualClusterDomain.getNamespaceId(), raftVirtualClusterDomain.getName());
|
||||||
StringBuilder stringBuilder = new StringBuilder();
|
StringBuilder stringBuilder = new StringBuilder();
|
||||||
List<IpAddress> allIps = raftVirtualClusterDomain.allIPs();
|
List<IpAddress> allIps = raftVirtualClusterDomain.allIPs();
|
||||||
for (IpAddress ipAddress : allIps) {
|
for (IpAddress ipAddress : allIps) {
|
||||||
stringBuilder.append(ipAddress.toIPAddr()).append("_").append(ipAddress.isValid()).append(",");
|
stringBuilder.append(ipAddress.toIPAddr()).append("_").append(ipAddress.isValid()).append(",");
|
||||||
}
|
}
|
||||||
|
|
||||||
Loggers.EVT_LOG.info("[IP-UPDATED] dom: " + raftVirtualClusterDomain.getName() + ", ips: " + stringBuilder.toString());
|
Loggers.EVT_LOG.info("[IP-UPDATED] dom: {}, ips: {}", raftVirtualClusterDomain.getName(), stringBuilder.toString());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Set<String> getAllDomNames() {
|
public Set<String> getAllDomNames(String namespaceId) {
|
||||||
return new HashSet<String>(chooseDomMap().keySet());
|
return serviceMap.get(namespaceId).keySet();
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<String> getAllDomNamesList() {
|
public Map<String, Set<String>> getAllDomNames() {
|
||||||
return new ArrayList<>(chooseDomMap().keySet());
|
|
||||||
|
Map<String, Set<String>> namesMap = new HashMap<>(16);
|
||||||
|
for (String namespaceId : serviceMap.keySet()) {
|
||||||
|
namesMap.put(namespaceId, serviceMap.get(namespaceId).keySet());
|
||||||
|
}
|
||||||
|
return namesMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setAllDomNames(List<String> allDomNames) {
|
public List<String> getAllDomNamesList(String namespaceId) {
|
||||||
this.allDomNames = new HashSet<>(allDomNames);
|
if (chooseDomMap(namespaceId) == null) {
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
|
return new ArrayList<>(chooseDomMap(namespaceId).keySet());
|
||||||
}
|
}
|
||||||
|
|
||||||
public Set<String> getAllDomNamesCache() {
|
public Map<String, Set<Domain>> getResponsibleDoms() {
|
||||||
if (Switch.isAllDomNameCache()) {
|
Map<String, Set<Domain>> result = new HashMap<>(16);
|
||||||
if (CollectionUtils.isNotEmpty(allDomNames)) {
|
for (String namespaceId : serviceMap.keySet()) {
|
||||||
return allDomNames;
|
result.put(namespaceId, new HashSet<>());
|
||||||
} else {
|
for (Map.Entry<String, Domain> entry : serviceMap.get(namespaceId).entrySet()) {
|
||||||
allDomNames = getAllDomNames();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return getAllDomNames();
|
|
||||||
}
|
|
||||||
|
|
||||||
return allDomNames;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Set<String> allDomNames;
|
|
||||||
|
|
||||||
public List<Domain> getResponsibleDoms() {
|
|
||||||
List<Domain> result = new ArrayList<>();
|
|
||||||
Map<String, Domain> domainMap = chooseDomMap();
|
|
||||||
|
|
||||||
for (Map.Entry<String, Domain> entry : domainMap.entrySet()) {
|
|
||||||
Domain domain = entry.getValue();
|
Domain domain = entry.getValue();
|
||||||
if (DistroMapper.responsible(entry.getKey())) {
|
if (DistroMapper.responsible(entry.getKey())) {
|
||||||
result.add(domain);
|
result.get(namespaceId).add(domain);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getResponsibleDomCount() {
|
||||||
|
int domCount = 0;
|
||||||
|
for (String namespaceId : serviceMap.keySet()) {
|
||||||
|
for (Map.Entry<String, Domain> entry : serviceMap.get(namespaceId).entrySet()) {
|
||||||
|
if (DistroMapper.responsible(entry.getKey())) {
|
||||||
|
domCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return domCount;
|
||||||
|
}
|
||||||
|
|
||||||
public int getResponsibleIPCount() {
|
public int getResponsibleIPCount() {
|
||||||
List<Domain> responsibleDoms = getResponsibleDoms();
|
Map<String, Set<Domain>> responsibleDoms = getResponsibleDoms();
|
||||||
int count = 0;
|
int count = 0;
|
||||||
for (Domain domain : responsibleDoms) {
|
for (String namespaceId : responsibleDoms.keySet()) {
|
||||||
|
for (Domain domain : responsibleDoms.get(namespaceId)) {
|
||||||
count += domain.allIPs().size();
|
count += domain.allIPs().size();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void easyRemoveDom(String domName) throws Exception {
|
public void easyRemoveDom(String namespaceId, String serviceName) throws Exception {
|
||||||
|
|
||||||
|
Domain dom = getDomain(namespaceId, serviceName);
|
||||||
|
|
||||||
Domain dom = raftDomMap.get(domName);
|
|
||||||
if (dom != null) {
|
if (dom != null) {
|
||||||
RaftCore.signalDelete(UtilsAndCommons.getDomStoreKey(dom));
|
RaftCore.signalDelete(UtilsAndCommons.getDomStoreKey(dom));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void easyAddOrReplaceDom(Domain newDom) throws Exception {
|
public void easyAddOrReplaceDom(Domain newDom) throws Exception {
|
||||||
VirtualClusterDomain virtualClusterDomain = null;
|
VirtualClusterDomain virtualClusterDomain;
|
||||||
if (newDom instanceof VirtualClusterDomain) {
|
if (newDom instanceof VirtualClusterDomain) {
|
||||||
virtualClusterDomain = (VirtualClusterDomain) newDom;
|
virtualClusterDomain = (VirtualClusterDomain) newDom;
|
||||||
newDom = virtualClusterDomain;
|
newDom = virtualClusterDomain;
|
||||||
@ -286,17 +297,17 @@ public class DomainsManager {
|
|||||||
RaftCore.doSignalPublish(UtilsAndCommons.getDomStoreKey(newDom), JSON.toJSONString(newDom), true);
|
RaftCore.doSignalPublish(UtilsAndCommons.getDomStoreKey(newDom), JSON.toJSONString(newDom), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void easyAddIP4Dom(String domName, List<IpAddress> ips, long term) throws Exception {
|
public void easyAddIP4Dom(String namespaceId, String domName, List<IpAddress> ips, long term) throws Exception {
|
||||||
easyUpdateIP4Dom(domName, ips, term, "add");
|
easyUpdateIP4Dom(namespaceId, domName, ips, term, "add");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void easyRemvIP4Dom(String domName, List<IpAddress> ips, long term) throws Exception {
|
public void easyRemvIP4Dom(String namespaceId, String domName, List<IpAddress> ips, long term) throws Exception {
|
||||||
easyUpdateIP4Dom(domName, ips, term, "remove");
|
easyUpdateIP4Dom(namespaceId, domName, ips, term, "remove");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void easyUpdateIP4Dom(String domName, List<IpAddress> ips, long term, String action) throws Exception {
|
public void easyUpdateIP4Dom(String namespaceId, String domName, List<IpAddress> ips, long term, String action) throws Exception {
|
||||||
|
|
||||||
VirtualClusterDomain dom = (VirtualClusterDomain) chooseDomMap().get(domName);
|
VirtualClusterDomain dom = (VirtualClusterDomain) chooseDomMap(namespaceId).get(domName);
|
||||||
if (dom == null) {
|
if (dom == null) {
|
||||||
throw new IllegalArgumentException("dom doesn't exist: " + domName);
|
throw new IllegalArgumentException("dom doesn't exist: " + domName);
|
||||||
}
|
}
|
||||||
@ -335,8 +346,8 @@ public class DomainsManager {
|
|||||||
Cluster cluster = new Cluster(ipAddress.getClusterName());
|
Cluster cluster = new Cluster(ipAddress.getClusterName());
|
||||||
cluster.setDom(dom);
|
cluster.setDom(dom);
|
||||||
dom.getClusterMap().put(ipAddress.getClusterName(), cluster);
|
dom.getClusterMap().put(ipAddress.getClusterName(), cluster);
|
||||||
Loggers.SRV_LOG.warn("cluster: " + ipAddress.getClusterName() + " not found, ip: " + ipAddress.toJSON()
|
Loggers.SRV_LOG.warn("cluster: {} not found, ip: {}, will create new cluster with default configuration.",
|
||||||
+ ", will create new cluster with default configuration.");
|
ipAddress.getClusterName(), ipAddress.toJSON());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (UtilsAndCommons.UPDATE_INSTANCE_ACTION_REMOVE.equals(action)) {
|
if (UtilsAndCommons.UPDATE_INSTANCE_ACTION_REMOVE.equals(action)) {
|
||||||
@ -352,8 +363,7 @@ public class DomainsManager {
|
|||||||
+ JSON.toJSONString(ipAddressMap.values()));
|
+ JSON.toJSONString(ipAddressMap.values()));
|
||||||
}
|
}
|
||||||
|
|
||||||
Loggers.EVT_LOG.info("{" + dom + "} {POS} {IP-UPDATE}" + ips +
|
Loggers.EVT_LOG.info("{} {POS} {IP-UPDATE} {}, action: {}", dom, ips, action);
|
||||||
", action:" + action);
|
|
||||||
|
|
||||||
String key = UtilsAndCommons.getIPListStoreKey(dom);
|
String key = UtilsAndCommons.getIPListStoreKey(dom);
|
||||||
String value = JSON.toJSONString(ipAddressMap.values());
|
String value = JSON.toJSONString(ipAddressMap.values());
|
||||||
@ -374,7 +384,7 @@ public class DomainsManager {
|
|||||||
peer.leaderDueMs = RaftCore.getLeader().leaderDueMs;
|
peer.leaderDueMs = RaftCore.getLeader().leaderDueMs;
|
||||||
peer.state = RaftCore.getLeader().state;
|
peer.state = RaftCore.getLeader().state;
|
||||||
|
|
||||||
boolean increaseTerm = !((VirtualClusterDomain) getDomain(domName)).getEnableClientBeat();
|
boolean increaseTerm = !((VirtualClusterDomain) getDomain(namespaceId, domName)).getEnableClientBeat();
|
||||||
|
|
||||||
RaftCore.onPublish(datum, peer, increaseTerm);
|
RaftCore.onPublish(datum, peer, increaseTerm);
|
||||||
} finally {
|
} finally {
|
||||||
@ -399,7 +409,7 @@ public class DomainsManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (Throwable throwable) {
|
} catch (Throwable throwable) {
|
||||||
Loggers.RAFT.error("NA", "error while processing json: " + oldJson, throwable);
|
Loggers.RAFT.error("error while processing json: " + oldJson, throwable);
|
||||||
} finally {
|
} finally {
|
||||||
if (ipAddresses == null) {
|
if (ipAddresses == null) {
|
||||||
ipAddresses = new ArrayList<>();
|
ipAddresses = new ArrayList<>();
|
||||||
@ -410,13 +420,24 @@ public class DomainsManager {
|
|||||||
return ipAddresses;
|
return ipAddresses;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Domain getDomain(String domName) {
|
public Domain getDomain(String namespaceId, String domName) {
|
||||||
return chooseDomMap().get(domName);
|
if (serviceMap.get(namespaceId) == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return chooseDomMap(namespaceId).get(domName);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Domain> searchDomains(String regex) {
|
public void putDomain(VirtualClusterDomain domain) {
|
||||||
|
if (!serviceMap.containsKey(domain.getNamespaceId())) {
|
||||||
|
serviceMap.put(domain.getNamespaceId(), new ConcurrentHashMap<>(16));
|
||||||
|
}
|
||||||
|
serviceMap.get(domain.getNamespaceId()).put(domain.getName(), domain);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public List<Domain> searchDomains(String namespaceId, String regex) {
|
||||||
List<Domain> result = new ArrayList<Domain>();
|
List<Domain> result = new ArrayList<Domain>();
|
||||||
for (Map.Entry<String, Domain> entry : chooseDomMap().entrySet()) {
|
for (Map.Entry<String, Domain> entry : chooseDomMap(namespaceId).entrySet()) {
|
||||||
Domain dom = entry.getValue();
|
Domain dom = entry.getValue();
|
||||||
|
|
||||||
String key = dom.getName() + ":" + ArrayUtils.toString(dom.getOwners());
|
String key = dom.getName() + ":" + ArrayUtils.toString(dom.getOwners());
|
||||||
@ -429,32 +450,39 @@ public class DomainsManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public int getDomCount() {
|
public int getDomCount() {
|
||||||
return chooseDomMap().size();
|
int domCount = 0;
|
||||||
|
for (String namespaceId : serviceMap.keySet()) {
|
||||||
|
domCount += serviceMap.get(namespaceId).size();
|
||||||
|
}
|
||||||
|
return domCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getIPCount() {
|
public int getInstanceCount() {
|
||||||
int total = 0;
|
int total = 0;
|
||||||
List<String> doms = new ArrayList<String>(getAllDomNames());
|
for (String namespaceId : serviceMap.keySet()) {
|
||||||
for (String dom : doms) {
|
for (Domain domain : serviceMap.get(namespaceId).values()) {
|
||||||
Domain domain = getDomain(dom);
|
total += domain.allIPs().size();
|
||||||
total += (domain.allIPs().size());
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return total;
|
return total;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<String, Domain> getRaftDomMap() {
|
public Map<String, Domain> getDomMap(String namespaceId) {
|
||||||
return raftDomMap;
|
return serviceMap.get(namespaceId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getPagedDom(int startPage, int pageSize, String keyword, List<Domain> domainList) {
|
public int getPagedDom(String namespaceId, int startPage, int pageSize, String keyword, List<Domain> domainList) {
|
||||||
|
|
||||||
|
|
||||||
List<Domain> matchList;
|
List<Domain> matchList;
|
||||||
|
|
||||||
|
if (chooseDomMap(namespaceId) == null) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (StringUtils.isNotBlank(keyword)) {
|
if (StringUtils.isNotBlank(keyword)) {
|
||||||
matchList = searchDomains(".*" + keyword + ".*");
|
matchList = searchDomains(namespaceId, ".*" + keyword + ".*");
|
||||||
} else {
|
} else {
|
||||||
matchList = new ArrayList<Domain>(chooseDomMap().values());
|
matchList = new ArrayList<Domain>(chooseDomMap(namespaceId).values());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pageSize >= matchList.size()) {
|
if (pageSize >= matchList.size()) {
|
||||||
@ -478,11 +506,18 @@ public class DomainsManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static class DomainChecksum {
|
public static class DomainChecksum {
|
||||||
|
|
||||||
|
public String namespaceId;
|
||||||
public Map<String, String> domName2Checksum = new HashMap<String, String>();
|
public Map<String, String> domName2Checksum = new HashMap<String, String>();
|
||||||
|
|
||||||
|
public DomainChecksum(String namespaceId) {
|
||||||
|
this.namespaceId = namespaceId;
|
||||||
|
}
|
||||||
|
|
||||||
public void addItem(String domName, String checksum) {
|
public void addItem(String domName, String checksum) {
|
||||||
if (StringUtils.isEmpty(domName) || StringUtils.isEmpty(checksum)) {
|
if (StringUtils.isEmpty(domName) || StringUtils.isEmpty(checksum)) {
|
||||||
Loggers.SRV_LOG.warn("DOMAIN-CHECKSUM", "domName or checksum is empty,domName: " + domName + " checksum: " + checksum);
|
Loggers.SRV_LOG.warn("[DOMAIN-CHECKSUM] domName or checksum is empty,domName: {}, checksum: {}",
|
||||||
|
domName, checksum);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -496,21 +531,23 @@ public class DomainsManager {
|
|||||||
public void run() {
|
public void run() {
|
||||||
try {
|
try {
|
||||||
|
|
||||||
DomainChecksum checksum = new DomainChecksum();
|
Map<String, Set<String>> allDomainNames = getAllDomNames();
|
||||||
|
|
||||||
List<String> allDomainNames = new ArrayList<String>(getAllDomNames());
|
|
||||||
|
|
||||||
if (allDomainNames.size() <= 0) {
|
if (allDomainNames.size() <= 0) {
|
||||||
//ignore
|
//ignore
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (String domName : allDomainNames) {
|
for (String namespaceId : allDomainNames.keySet()) {
|
||||||
|
|
||||||
|
DomainChecksum checksum = new DomainChecksum(namespaceId);
|
||||||
|
|
||||||
|
for (String domName : allDomainNames.get(namespaceId)) {
|
||||||
if (!DistroMapper.responsible(domName)) {
|
if (!DistroMapper.responsible(domName)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
Domain domain = getDomain(domName);
|
Domain domain = getDomain(namespaceId, domName);
|
||||||
|
|
||||||
if (domain == null || domain instanceof SwitchDomain) {
|
if (domain == null || domain instanceof SwitchDomain) {
|
||||||
continue;
|
continue;
|
||||||
@ -537,8 +574,9 @@ public class DomainsManager {
|
|||||||
}
|
}
|
||||||
synchronizer.send(server, msg);
|
synchronizer.send(server, msg);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Loggers.SRV_LOG.error("DOMAIN-STATUS", "Exception while sending domain status: ", e);
|
Loggers.SRV_LOG.error("[DOMAIN-STATUS] Exception while sending domain status", e);
|
||||||
} finally {
|
} finally {
|
||||||
UtilsAndCommons.DOMAIN_SYNCHRONIZATION_EXECUTOR.schedule(this, Switch.getDomStatusSynchronizationPeriodMillis(), TimeUnit.MILLISECONDS);
|
UtilsAndCommons.DOMAIN_SYNCHRONIZATION_EXECUTOR.schedule(this, Switch.getDomStatusSynchronizationPeriodMillis(), TimeUnit.MILLISECONDS);
|
||||||
}
|
}
|
||||||
@ -568,12 +606,12 @@ public class DomainsManager {
|
|||||||
final RaftListener raftListener = new RaftListener() {
|
final RaftListener raftListener = new RaftListener() {
|
||||||
@Override
|
@Override
|
||||||
public boolean interests(String key) {
|
public boolean interests(String key) {
|
||||||
return StringUtils.startsWith(key, UtilsAndCommons.DOMAINS_DATA_ID);
|
return StringUtils.startsWith(key, UtilsAndCommons.DOMAINS_DATA_ID_PRE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean matchUnlistenKey(String key) {
|
public boolean matchUnlistenKey(String key) {
|
||||||
return StringUtils.equals(key, UtilsAndCommons.DOMAINS_DATA_ID + ".*");
|
return StringUtils.equals(key, UtilsAndCommons.DOMAINS_DATA_ID_PRE + "*");
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressFBWarnings("JLM_JSR166_LOCK_MONITORENTER")
|
@SuppressFBWarnings("JLM_JSR166_LOCK_MONITORENTER")
|
||||||
@ -581,7 +619,7 @@ public class DomainsManager {
|
|||||||
public void onChange(String key, String value) throws Exception {
|
public void onChange(String key, String value) throws Exception {
|
||||||
try {
|
try {
|
||||||
if (StringUtils.isEmpty(value)) {
|
if (StringUtils.isEmpty(value)) {
|
||||||
Loggers.SRV_LOG.warn("received empty push from raft, key=" + key);
|
Loggers.SRV_LOG.warn("received empty push from raft, key: {}", key);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -590,25 +628,54 @@ public class DomainsManager {
|
|||||||
throw new IllegalStateException("dom parsing failed, json: " + value);
|
throw new IllegalStateException("dom parsing failed, json: " + value);
|
||||||
}
|
}
|
||||||
|
|
||||||
Loggers.RAFT.info("[RAFT-NOTIFIER] datum is changed, key:" + key + ", value:" + value);
|
if (StringUtils.isBlank(dom.getNamespaceId())) {
|
||||||
|
dom.setNamespaceId(UtilsAndCommons.getDefaultNamespaceId());
|
||||||
|
}
|
||||||
|
|
||||||
|
Loggers.RAFT.info("[RAFT-NOTIFIER] datum is changed, key: {}, value: {}", key, value);
|
||||||
|
|
||||||
|
Domain oldDom = getDomain(dom.getNamespaceId(), dom.getName());
|
||||||
|
|
||||||
Domain oldDom = raftDomMap.get(dom.getName());
|
|
||||||
if (oldDom != null) {
|
if (oldDom != null) {
|
||||||
oldDom.update(dom);
|
oldDom.update(dom);
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
if (!dom2LockMap.containsKey(dom.getName())) {
|
addLockIfAbsent(UtilsAndCommons.assembleFullServiceName(dom.getNamespaceId(), dom.getName()));
|
||||||
dom2LockMap.put(dom.getName(), new ReentrantLock());
|
|
||||||
}
|
|
||||||
|
|
||||||
raftDomMap.put(dom.getName(), dom);
|
putDomain(dom);
|
||||||
dom.init();
|
dom.init();
|
||||||
|
Loggers.SRV_LOG.info("[NEW-DOM-RAFT] {}", dom.toJSON());
|
||||||
Loggers.SRV_LOG.info("[NEW-DOM-raft] " + dom.toJSON());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Lock lock = dom2LockMap.get(dom.getName());
|
wakeUp(UtilsAndCommons.assembleFullServiceName(dom.getNamespaceId(), dom.getName()));
|
||||||
Condition condition = dom2ConditionMap.get(dom.getName());
|
|
||||||
|
} catch (Throwable e) {
|
||||||
|
Loggers.SRV_LOG.error("[NACOS-DOM] error while processing dom update", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDelete(String key, String value) throws Exception {
|
||||||
|
String domKey = StringUtils.removeStart(key, UtilsAndCommons.DOMAINS_DATA_ID_PRE);
|
||||||
|
String namespace = domKey.split(UtilsAndCommons.SERVICE_GROUP_CONNECTOR)[0];
|
||||||
|
String name = domKey.split(UtilsAndCommons.SERVICE_GROUP_CONNECTOR)[1];
|
||||||
|
Domain dom = chooseDomMap(namespace).remove(name);
|
||||||
|
Loggers.RAFT.info("[RAFT-NOTIFIER] datum is deleted, key: {}, value: {}", key, value);
|
||||||
|
|
||||||
|
if (dom != null) {
|
||||||
|
dom.destroy();
|
||||||
|
Loggers.SRV_LOG.info("[DEAD-DOM] {}", dom.toJSON());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
RaftCore.listen(raftListener);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void wakeUp(String key) {
|
||||||
|
|
||||||
|
Lock lock = dom2LockMap.get(key);
|
||||||
|
Condition condition = dom2ConditionMap.get(key);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
lock.lock();
|
lock.lock();
|
||||||
@ -617,41 +684,26 @@ public class DomainsManager {
|
|||||||
} finally {
|
} finally {
|
||||||
lock.unlock();
|
lock.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (Throwable e) {
|
|
||||||
Loggers.SRV_LOG.error("VIPSRV-DOM", "error while processing dom update", e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public Lock addLockIfAbsent(String key) {
|
||||||
public void onDelete(String key, String value) throws Exception {
|
|
||||||
String name = StringUtils.removeStart(key, UtilsAndCommons.DOMAINS_DATA_ID + ".");
|
|
||||||
Domain dom = raftDomMap.remove(name);
|
|
||||||
Loggers.RAFT.info("[RAFT-NOTIFIER] datum is deleted, key:" + key + ", value:" + value);
|
|
||||||
|
|
||||||
if (dom != null) {
|
if (dom2LockMap.containsKey(key)) {
|
||||||
dom.destroy();
|
return dom2LockMap.get(key);
|
||||||
Loggers.SRV_LOG.info("[DEAD-DOM] " + dom.toJSON());
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
};
|
|
||||||
RaftCore.listen(raftListener);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public Lock addLock(String domName) {
|
|
||||||
Lock lock = new ReentrantLock();
|
Lock lock = new ReentrantLock();
|
||||||
dom2LockMap.put(domName, lock);
|
dom2LockMap.put(key, lock);
|
||||||
return lock;
|
return lock;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Condition addCondtion(String domName) {
|
public Condition addCondtion(String key) {
|
||||||
Condition condition = dom2LockMap.get(domName).newCondition();
|
Condition condition = dom2LockMap.get(key).newCondition();
|
||||||
dom2ConditionMap.put(domName, condition);
|
dom2ConditionMap.put(key, condition);
|
||||||
return condition;
|
return condition;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class DomainKey {
|
private static class DomainKey {
|
||||||
|
private String namespaceId;
|
||||||
private String domName;
|
private String domName;
|
||||||
private String serverIP;
|
private String serverIP;
|
||||||
|
|
||||||
@ -667,9 +719,14 @@ public class DomainsManager {
|
|||||||
return domName;
|
return domName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getNamespaceId() {
|
||||||
|
return namespaceId;
|
||||||
|
}
|
||||||
|
|
||||||
private String checksum;
|
private String checksum;
|
||||||
|
|
||||||
public DomainKey(String domName, String serverIP, String checksum) {
|
public DomainKey(String namespaceId, String domName, String serverIP, String checksum) {
|
||||||
|
this.namespaceId = namespaceId;
|
||||||
this.domName = domName;
|
this.domName = domName;
|
||||||
this.serverIP = serverIP;
|
this.serverIP = serverIP;
|
||||||
this.checksum = checksum;
|
this.checksum = checksum;
|
||||||
|
@ -301,7 +301,7 @@ public class IpAddress extends Instance implements Comparable {
|
|||||||
@Override
|
@Override
|
||||||
public int compareTo(Object o) {
|
public int compareTo(Object o) {
|
||||||
if (!(o instanceof IpAddress)) {
|
if (!(o instanceof IpAddress)) {
|
||||||
Loggers.SRV_LOG.error("IPADDRESS-COMPARE", "Object is not an instance of IPAdress,object: " + o.getClass());
|
Loggers.SRV_LOG.error("[IPADDRESS-COMPARE] Object is not an instance of IPAdress, object: {}", o.getClass());
|
||||||
throw new IllegalArgumentException("Object is not an instance of IPAdress,object: " + o.getClass());
|
throw new IllegalArgumentException("Object is not an instance of IPAdress,object: " + o.getClass());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,8 +28,8 @@ import com.alibaba.nacos.naming.misc.UtilsAndCommons;
|
|||||||
import com.alibaba.nacos.naming.push.PushService;
|
import com.alibaba.nacos.naming.push.PushService;
|
||||||
import com.alibaba.nacos.naming.raft.RaftCore;
|
import com.alibaba.nacos.naming.raft.RaftCore;
|
||||||
import com.alibaba.nacos.naming.raft.RaftListener;
|
import com.alibaba.nacos.naming.raft.RaftListener;
|
||||||
import com.alibaba.nacos.naming.selector.Selector;
|
|
||||||
import com.alibaba.nacos.naming.selector.NoneSelector;
|
import com.alibaba.nacos.naming.selector.NoneSelector;
|
||||||
|
import com.alibaba.nacos.naming.selector.Selector;
|
||||||
import org.apache.commons.collections.CollectionUtils;
|
import org.apache.commons.collections.CollectionUtils;
|
||||||
import org.apache.commons.collections.ListUtils;
|
import org.apache.commons.collections.ListUtils;
|
||||||
import org.apache.commons.lang3.RandomStringUtils;
|
import org.apache.commons.lang3.RandomStringUtils;
|
||||||
@ -64,9 +64,10 @@ public class VirtualClusterDomain implements Domain, RaftListener {
|
|||||||
private Boolean enabled = true;
|
private Boolean enabled = true;
|
||||||
private Boolean enableClientBeat = false;
|
private Boolean enableClientBeat = false;
|
||||||
private Selector selector = new NoneSelector();
|
private Selector selector = new NoneSelector();
|
||||||
|
private String namespaceId;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* IP will be deleted if it has not send beat for some time, default timeout is half an hour .
|
* IP will be deleted if it has not send beat for some time, default timeout is 30 seconds.
|
||||||
*/
|
*/
|
||||||
private long ipDeleteTimeout = 30 * 1000;
|
private long ipDeleteTimeout = 30 * 1000;
|
||||||
|
|
||||||
@ -158,23 +159,23 @@ public class VirtualClusterDomain implements Domain, RaftListener {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean interests(String key) {
|
public boolean interests(String key) {
|
||||||
return StringUtils.equals(key, UtilsAndCommons.IPADDRESS_DATA_ID_PRE + name);
|
return StringUtils.equals(key, UtilsAndCommons.IPADDRESS_DATA_ID_PRE + namespaceId + UtilsAndCommons.SERVICE_GROUP_CONNECTOR + name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean matchUnlistenKey(String key) {
|
public boolean matchUnlistenKey(String key) {
|
||||||
return StringUtils.equals(key, UtilsAndCommons.IPADDRESS_DATA_ID_PRE + name);
|
return StringUtils.equals(key, UtilsAndCommons.IPADDRESS_DATA_ID_PRE + namespaceId + UtilsAndCommons.SERVICE_GROUP_CONNECTOR + name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onChange(String key, String value) throws Exception {
|
public void onChange(String key, String value) throws Exception {
|
||||||
|
|
||||||
if (StringUtils.isEmpty(value)) {
|
if (StringUtils.isEmpty(value)) {
|
||||||
Loggers.SRV_LOG.warn("[VIPSRV-DOM] received empty iplist config for dom: " + name);
|
Loggers.SRV_LOG.warn("[NACOS-DOM] received empty iplist config for dom: {}", name);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Loggers.RAFT.info("[VIPSRV-RAFT] datum is changed, key: " + key + ", value: " + value);
|
Loggers.RAFT.info("[NACOS-RAFT] datum is changed, key: {}, value: {}", key, value);
|
||||||
|
|
||||||
List<IpAddress> ips = JSON.parseObject(value, new TypeReference<List<IpAddress>>() {
|
List<IpAddress> ips = JSON.parseObject(value, new TypeReference<List<IpAddress>>() {
|
||||||
});
|
});
|
||||||
@ -214,7 +215,7 @@ public class VirtualClusterDomain implements Domain, RaftListener {
|
|||||||
for (IpAddress ip : ips) {
|
for (IpAddress ip : ips) {
|
||||||
try {
|
try {
|
||||||
if (ip == null) {
|
if (ip == null) {
|
||||||
Loggers.SRV_LOG.error("VIPSRV-DOM", "received malformed ip");
|
Loggers.SRV_LOG.error("[NACOS-DOM] received malformed ip: null");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -224,7 +225,7 @@ public class VirtualClusterDomain implements Domain, RaftListener {
|
|||||||
|
|
||||||
// put wild ip into DEFAULT cluster
|
// put wild ip into DEFAULT cluster
|
||||||
if (!clusterMap.containsKey(ip.getClusterName())) {
|
if (!clusterMap.containsKey(ip.getClusterName())) {
|
||||||
Loggers.SRV_LOG.warn("cluster of IP not found: " + ip.toJSON());
|
Loggers.SRV_LOG.warn("cluster of IP not found: {}", ip.toJSON());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -236,7 +237,7 @@ public class VirtualClusterDomain implements Domain, RaftListener {
|
|||||||
|
|
||||||
clusterIPs.add(ip);
|
clusterIPs.add(ip);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Loggers.SRV_LOG.error("VIPSRV-DOM", "failed to process ip: " + ip, e);
|
Loggers.SRV_LOG.error("[NACOS-DOM] failed to process ip: " + ip, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -246,14 +247,14 @@ public class VirtualClusterDomain implements Domain, RaftListener {
|
|||||||
clusterMap.get(entry.getKey()).updateIPs(entryIPs);
|
clusterMap.get(entry.getKey()).updateIPs(entryIPs);
|
||||||
}
|
}
|
||||||
setLastModifiedMillis(System.currentTimeMillis());
|
setLastModifiedMillis(System.currentTimeMillis());
|
||||||
PushService.domChanged(name);
|
PushService.domChanged(namespaceId, name);
|
||||||
StringBuilder stringBuilder = new StringBuilder();
|
StringBuilder stringBuilder = new StringBuilder();
|
||||||
|
|
||||||
for (IpAddress ipAddress : allIPs()) {
|
for (IpAddress ipAddress : allIPs()) {
|
||||||
stringBuilder.append(ipAddress.toIPAddr()).append("_").append(ipAddress.isValid()).append(",");
|
stringBuilder.append(ipAddress.toIPAddr()).append("_").append(ipAddress.isValid()).append(",");
|
||||||
}
|
}
|
||||||
|
|
||||||
Loggers.EVT_LOG.info("[IP-UPDATED] dom: " + getName() + ", ips: " + stringBuilder.toString());
|
Loggers.EVT_LOG.info("[IP-UPDATED] dom: {}, ips: {}", getName(), stringBuilder.toString());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -346,7 +347,7 @@ public class VirtualClusterDomain implements Domain, RaftListener {
|
|||||||
|
|
||||||
return vDom;
|
return vDom;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Loggers.SRV_LOG.error("VIPSRV-DOM", "parse cluster json error, " + e.toString() + ", content=" + json, e);
|
Loggers.SRV_LOG.error("[NACOS-DOM] parse cluster json content: {}, error: {}", json, e);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -454,6 +455,14 @@ public class VirtualClusterDomain implements Domain, RaftListener {
|
|||||||
this.clusterMap = clusterMap;
|
this.clusterMap = clusterMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getNamespaceId() {
|
||||||
|
return namespaceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNamespaceId(String namespaceId) {
|
||||||
|
this.namespaceId = namespaceId;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void update(Domain dom) {
|
public void update(Domain dom) {
|
||||||
if (!(dom instanceof VirtualClusterDomain)) {
|
if (!(dom instanceof VirtualClusterDomain)) {
|
||||||
@ -462,42 +471,42 @@ public class VirtualClusterDomain implements Domain, RaftListener {
|
|||||||
|
|
||||||
VirtualClusterDomain vDom = (VirtualClusterDomain) dom;
|
VirtualClusterDomain vDom = (VirtualClusterDomain) dom;
|
||||||
if (!StringUtils.equals(token, vDom.getToken())) {
|
if (!StringUtils.equals(token, vDom.getToken())) {
|
||||||
Loggers.SRV_LOG.info("[DOM-UPDATE] dom: " + name + ",token" + token + " -> " + vDom.getToken());
|
Loggers.SRV_LOG.info("[DOM-UPDATE] dom: {}, token: {} -> {}", name, token, vDom.getToken());
|
||||||
token = vDom.getToken();
|
token = vDom.getToken();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ListUtils.isEqualList(owners, vDom.getOwners())) {
|
if (!ListUtils.isEqualList(owners, vDom.getOwners())) {
|
||||||
Loggers.SRV_LOG.info("[DOM-UPDATE] dom: " + name + ",owners: " + owners + " -> " + vDom.getToken());
|
Loggers.SRV_LOG.info("[DOM-UPDATE] dom: {}, owners: {} -> {}", name, owners, vDom.getOwners());
|
||||||
owners = vDom.getOwners();
|
owners = vDom.getOwners();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (protectThreshold != vDom.getProtectThreshold()) {
|
if (protectThreshold != vDom.getProtectThreshold()) {
|
||||||
Loggers.SRV_LOG.info("[DOM-UPDATE] dom: " + name + ",protectThreshold: " + protectThreshold + " -> " + vDom.getProtectThreshold());
|
Loggers.SRV_LOG.info("[DOM-UPDATE] dom: {}, protectThreshold: {} -> {}", name, protectThreshold, vDom.getProtectThreshold());
|
||||||
protectThreshold = vDom.getProtectThreshold();
|
protectThreshold = vDom.getProtectThreshold();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (useSpecifiedURL != vDom.isUseSpecifiedURL()) {
|
if (useSpecifiedURL != vDom.isUseSpecifiedURL()) {
|
||||||
Loggers.SRV_LOG.info("[DOM-UPDATE] dom: " + name + ",useSpecifiedURL: " + useSpecifiedURL + " -> " + vDom.isUseSpecifiedURL());
|
Loggers.SRV_LOG.info("[DOM-UPDATE] dom: {}, useSpecifiedURL: {} -> {}", name, useSpecifiedURL, vDom.isUseSpecifiedURL());
|
||||||
useSpecifiedURL = vDom.isUseSpecifiedURL();
|
useSpecifiedURL = vDom.isUseSpecifiedURL();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (resetWeight != vDom.getResetWeight().booleanValue()) {
|
if (resetWeight != vDom.getResetWeight().booleanValue()) {
|
||||||
Loggers.SRV_LOG.info("[DOM-UPDATE] dom: " + name + ",resetWeight: " + resetWeight + " -> " + vDom.getResetWeight());
|
Loggers.SRV_LOG.info("[DOM-UPDATE] dom: {}, resetWeight: {} -> {}", name, resetWeight, vDom.getResetWeight());
|
||||||
resetWeight = vDom.getResetWeight();
|
resetWeight = vDom.getResetWeight();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (enableHealthCheck != vDom.getEnableHealthCheck().booleanValue()) {
|
if (enableHealthCheck != vDom.getEnableHealthCheck().booleanValue()) {
|
||||||
Loggers.SRV_LOG.info("[DOM-UPDATE] dom: " + name + ", enableHealthCheck: " + enableHealthCheck + " -> " + vDom.getEnableHealthCheck());
|
Loggers.SRV_LOG.info("[DOM-UPDATE] dom: {}, enableHealthCheck: {} -> {}", name, enableHealthCheck, vDom.getEnableHealthCheck());
|
||||||
enableHealthCheck = vDom.getEnableHealthCheck();
|
enableHealthCheck = vDom.getEnableHealthCheck();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (enableClientBeat != vDom.getEnableClientBeat().booleanValue()) {
|
if (enableClientBeat != vDom.getEnableClientBeat().booleanValue()) {
|
||||||
Loggers.SRV_LOG.info("[DOM-UPDATE] dom: " + name + ", enableClientBeat: " + enableClientBeat + " -> " + vDom.getEnableClientBeat());
|
Loggers.SRV_LOG.info("[DOM-UPDATE] dom: {}, enableClientBeat: {} -> {}", name, enableClientBeat, vDom.getEnableClientBeat());
|
||||||
enableClientBeat = vDom.getEnableClientBeat();
|
enableClientBeat = vDom.getEnableClientBeat();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (enabled != vDom.getEnabled().booleanValue()) {
|
if (enabled != vDom.getEnabled().booleanValue()) {
|
||||||
Loggers.SRV_LOG.info("[DOM-UPDATE] dom: " + name + ", enabled: " + enabled + " -> " + vDom.getEnabled());
|
Loggers.SRV_LOG.info("[DOM-UPDATE] dom: {}, enabled: {} -> {}", name, enabled, vDom.getEnabled());
|
||||||
enabled = vDom.getEnabled();
|
enabled = vDom.getEnabled();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -544,13 +553,13 @@ public class VirtualClusterDomain implements Domain, RaftListener {
|
|||||||
MessageDigest md5 = MessageDigest.getInstance("MD5");
|
MessageDigest md5 = MessageDigest.getInstance("MD5");
|
||||||
result = new BigInteger(1, md5.digest((ipsString.toString()).getBytes(Charset.forName("UTF-8")))).toString(16);
|
result = new BigInteger(1, md5.digest((ipsString.toString()).getBytes(Charset.forName("UTF-8")))).toString(16);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Loggers.SRV_LOG.error("VIPSRV-DOM", "error while calculating checksum(md5)", e);
|
Loggers.SRV_LOG.error("[NACOS-DOM] error while calculating checksum(md5)", e);
|
||||||
result = RandomStringUtils.randomAscii(32);
|
result = RandomStringUtils.randomAscii(32);
|
||||||
}
|
}
|
||||||
|
|
||||||
checksum = result;
|
checksum = result;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Loggers.SRV_LOG.error("VIPSRV-DOM", "error while calculating checksum(md5)", e);
|
Loggers.SRV_LOG.error("[NACOS-DOM] error while calculating checksum(md5)", e);
|
||||||
checksum = RandomStringUtils.randomAscii(32);
|
checksum = RandomStringUtils.randomAscii(32);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user