commit
6963301441
@ -16,7 +16,7 @@
|
||||
<parent>
|
||||
<groupId>com.alibaba.nacos</groupId>
|
||||
<artifactId>nacos-all</artifactId>
|
||||
<version>0.7.0</version>
|
||||
<version>0.8.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
@ -39,5 +39,7 @@ public class PropertyKeyConst {
|
||||
public final static String ENCODE = "encode";
|
||||
|
||||
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>
|
||||
* @since 0.7.0
|
||||
*/
|
||||
public class Entity {
|
||||
|
||||
|
@ -17,6 +17,7 @@ package com.alibaba.nacos.api.cmdb.pojo;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:zpf.073@gmail.com">nkorange</a>
|
||||
* @since 0.7.0
|
||||
*/
|
||||
public class EntityEvent {
|
||||
|
||||
|
@ -17,6 +17,7 @@ package com.alibaba.nacos.api.cmdb.pojo;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:zpf.073@gmail.com">nkorange</a>
|
||||
* @since 0.7.0
|
||||
*/
|
||||
public enum EntityEventType {
|
||||
/**
|
||||
|
@ -19,6 +19,7 @@ import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:zpf.073@gmail.com">nkorange</a>
|
||||
* @since 0.7.0
|
||||
*/
|
||||
public class Label {
|
||||
|
||||
|
@ -17,6 +17,7 @@ package com.alibaba.nacos.api.cmdb.pojo;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:zpf.073@gmail.com">nkorange</a>
|
||||
* @since 0.7.0
|
||||
*/
|
||||
public enum PreservedEntityTypes {
|
||||
/**
|
||||
|
@ -27,6 +27,7 @@ import java.util.Set;
|
||||
* Service to visit CMDB store
|
||||
*
|
||||
* @author <a href="mailto:zpf.073@gmail.com">nkorange</a>
|
||||
* @since 0.7.0
|
||||
*/
|
||||
public interface CmdbService {
|
||||
|
||||
|
@ -122,4 +122,10 @@ public class Constants {
|
||||
public static final String NAMING_HTTP_HEADER_SPILIER = "\\|";
|
||||
|
||||
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(int errCode, String errMsg) {
|
||||
this.errCode = errCode;
|
||||
this.errMsg = errMsg;
|
||||
|
@ -92,7 +92,17 @@ public interface NamingService {
|
||||
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 clusters list of cluster
|
||||
@ -102,7 +112,18 @@ public interface NamingService {
|
||||
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 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;
|
||||
|
||||
/**
|
||||
* 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 clusters list of cluster
|
||||
@ -123,7 +155,19 @@ public interface NamingService {
|
||||
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
|
||||
* @return qualified instance
|
||||
@ -135,6 +179,16 @@ public interface NamingService {
|
||||
* select one healthy instance of service using predefined load balance strategy
|
||||
*
|
||||
* @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
|
||||
* @return qualified instance
|
||||
* @throws NacosException
|
||||
@ -142,7 +196,18 @@ public interface NamingService {
|
||||
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 listener event listener
|
||||
@ -197,6 +262,7 @@ public interface NamingService {
|
||||
* @param selector selector to filter the resource
|
||||
* @return list of service names
|
||||
* @throws NacosException
|
||||
* @since 0.7.0
|
||||
*/
|
||||
ListView<String> getServicesOfServer(int pageNo, int pageSize, AbstractSelector selector) throws NacosException;
|
||||
|
||||
|
@ -48,8 +48,6 @@ public class ServiceInfo {
|
||||
|
||||
private String checksum = "";
|
||||
|
||||
private String env = "";
|
||||
|
||||
private volatile boolean allIPs = false;
|
||||
|
||||
public ServiceInfo() {
|
||||
@ -65,48 +63,22 @@ public class ServiceInfo {
|
||||
|
||||
public ServiceInfo(String key) {
|
||||
|
||||
int maxKeySectionCount = 4;
|
||||
int allIpFlagIndex = 3;
|
||||
int envIndex = 2;
|
||||
int maxIndex = 2;
|
||||
int clusterIndex = 1;
|
||||
int serviceNameIndex = 0;
|
||||
|
||||
String[] keys = key.split(SPLITER);
|
||||
if (keys.length >= maxKeySectionCount) {
|
||||
if (keys.length >= maxIndex) {
|
||||
this.name = keys[serviceNameIndex];
|
||||
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];
|
||||
}
|
||||
|
||||
public ServiceInfo(String name, String clusters) {
|
||||
this(name, clusters, EMPTY);
|
||||
}
|
||||
|
||||
public ServiceInfo(String name, String clusters, String env) {
|
||||
this.name = name;
|
||||
this.clusters = clusters;
|
||||
this.env = env;
|
||||
}
|
||||
|
||||
public int ipCount() {
|
||||
@ -158,7 +130,6 @@ public class ServiceInfo {
|
||||
}
|
||||
|
||||
public List<Instance> getHosts() {
|
||||
|
||||
return new ArrayList<Instance>(hosts);
|
||||
}
|
||||
|
||||
@ -192,45 +163,39 @@ public class ServiceInfo {
|
||||
|
||||
@JSONField(serialize = false)
|
||||
public String getKey() {
|
||||
return getKey(name, clusters, env, isAllIPs());
|
||||
return getKey(name, clusters);
|
||||
}
|
||||
|
||||
@JSONField(serialize = false)
|
||||
public String getKeyEncoded() {
|
||||
try {
|
||||
return getKey(URLEncoder.encode(name, "UTF-8"), clusters, env, isAllIPs());
|
||||
return getKey(URLEncoder.encode(name, "UTF-8"), clusters);
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
return getKey();
|
||||
}
|
||||
}
|
||||
|
||||
@JSONField(serialize = false)
|
||||
public static String getKey(String name, String clusters, String unit) {
|
||||
return getKey(name, clusters, unit, false);
|
||||
public static ServiceInfo fromKey(String key) {
|
||||
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)
|
||||
public static String getKey(String name, String clusters, String unit, boolean isAllIPs) {
|
||||
|
||||
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;
|
||||
}
|
||||
public static String getKey(String name, String clusters) {
|
||||
|
||||
if (!isEmpty(clusters)) {
|
||||
return isAllIPs ? name + SPLITER + clusters + SPLITER + ALL_IPS : name + SPLITER + clusters;
|
||||
return name + SPLITER + clusters;
|
||||
}
|
||||
|
||||
if (!isEmpty(unit)) {
|
||||
return isAllIPs ? name + SPLITER + EMPTY + SPLITER + unit + SPLITER + ALL_IPS :
|
||||
name + SPLITER + EMPTY + SPLITER + unit;
|
||||
}
|
||||
|
||||
return isAllIPs ? name + SPLITER + ALL_IPS : name;
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -19,6 +19,7 @@ package com.alibaba.nacos.api.selector;
|
||||
* Abstract selector that only contains a type
|
||||
*
|
||||
* @author <a href="mailto:zpf.073@gmail.com">nkorange</a>
|
||||
* @since 0.7.0
|
||||
*/
|
||||
public abstract class AbstractSelector {
|
||||
|
||||
|
@ -19,6 +19,7 @@ package com.alibaba.nacos.api.selector;
|
||||
* The selector to filter resource with flexible expression.
|
||||
*
|
||||
* @author <a href="mailto:zpf.073@gmail.com">nkorange</a>
|
||||
* @since 0.7.0
|
||||
*/
|
||||
public class ExpressionSelector extends AbstractSelector {
|
||||
|
||||
|
@ -19,6 +19,7 @@ package com.alibaba.nacos.api.selector;
|
||||
* The types of selector accepted by Nacos
|
||||
*
|
||||
* @author <a href="mailto:zpf.073@gmail.com">nkorange</a>
|
||||
* @since 0.7.0
|
||||
*/
|
||||
public enum SelectorType {
|
||||
/**
|
||||
|
@ -16,7 +16,7 @@
|
||||
<parent>
|
||||
<groupId>com.alibaba.nacos</groupId>
|
||||
<artifactId>nacos-all</artifactId>
|
||||
<version>0.7.0</version>
|
||||
<version>0.8.0-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
@ -20,7 +20,6 @@ import com.alibaba.nacos.api.common.Constants;
|
||||
import com.alibaba.nacos.api.exception.NacosException;
|
||||
import com.alibaba.nacos.api.naming.NamingService;
|
||||
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.ListView;
|
||||
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.UtilAndComs;
|
||||
import org.apache.commons.lang3.BooleanUtils;
|
||||
import org.apache.commons.lang3.math.NumberUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
@ -102,7 +102,7 @@ public class NacosNamingService implements NamingService {
|
||||
eventDispatcher = new EventDispatcher();
|
||||
serverProxy = new NamingProxy(namespace, endpoint, serverList);
|
||||
beatReactor = new BeatReactor(serverProxy);
|
||||
hostReactor = new HostReactor(eventDispatcher, serverProxy, cacheDir, false);
|
||||
hostReactor = new HostReactor(eventDispatcher, serverProxy, cacheDir);
|
||||
}
|
||||
|
||||
public NacosNamingService(Properties properties) {
|
||||
@ -132,10 +132,16 @@ public class NacosNamingService implements NamingService {
|
||||
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();
|
||||
serverProxy = new NamingProxy(namespace, endpoint, serverList);
|
||||
beatReactor = new BeatReactor(serverProxy);
|
||||
hostReactor = new HostReactor(eventDispatcher, serverProxy, cacheDir, loadCacheAtStart);
|
||||
beatReactor = new BeatReactor(serverProxy, clientBeatThreadCount);
|
||||
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 {
|
||||
|
||||
BeatInfo beatInfo = new BeatInfo();
|
||||
beatInfo.setDom(serviceName);
|
||||
beatInfo.setServiceName(serviceName);
|
||||
beatInfo.setIp(instance.getIp());
|
||||
beatInfo.setPort(instance.getPort());
|
||||
beatInfo.setCluster(instance.getClusterName());
|
||||
@ -189,10 +195,24 @@ public class NacosNamingService implements NamingService {
|
||||
}
|
||||
|
||||
@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, ","),
|
||||
StringUtils.EMPTY, false);
|
||||
@Override
|
||||
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;
|
||||
if (serviceInfo == null || CollectionUtils.isEmpty(list = serviceInfo.getHosts())) {
|
||||
return new ArrayList<Instance>();
|
||||
@ -201,41 +221,58 @@ public class NacosNamingService implements NamingService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Instance> selectInstances(String serviceName, boolean healthyOnly) throws NacosException {
|
||||
return selectInstances(serviceName, new ArrayList<String>(), healthyOnly);
|
||||
public List<Instance> selectInstances(String serviceName, boolean healthy) throws NacosException {
|
||||
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
|
||||
public List<Instance> selectInstances(String serviceName, List<String> clusters, boolean healthy)
|
||||
throws NacosException {
|
||||
|
||||
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;
|
||||
return selectInstances(serviceName, clusters, healthy, true);
|
||||
}
|
||||
|
||||
@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>());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Instance selectOneHealthyInstance(String serviceName, List<String> clusters) {
|
||||
return Balancer.RandomByWeight.selectHost(
|
||||
hostReactor.getServiceInfo(serviceName, StringUtils.join(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(
|
||||
hostReactor.getServiceInfo(serviceName, StringUtils.join(clusters, ",")));
|
||||
} else {
|
||||
return Balancer.RandomByWeight.selectHost(
|
||||
hostReactor.getServiceInfoDirectlyFromServer(serviceName, StringUtils.join(clusters, ",")));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -272,7 +309,7 @@ public class NacosNamingService implements NamingService {
|
||||
|
||||
@Override
|
||||
public List<ServiceInfo> getSubscribeServices() {
|
||||
return new ArrayList<ServiceInfo>(hostReactor.getServiceInfoMap().values());
|
||||
return eventDispatcher.getSubscribeServices();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -280,6 +317,23 @@ public class NacosNamingService implements NamingService {
|
||||
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() {
|
||||
return beatReactor;
|
||||
}
|
||||
|
@ -27,7 +27,7 @@ public class BeatInfo {
|
||||
private int port;
|
||||
private String ip;
|
||||
private double weight;
|
||||
private String dom;
|
||||
private String serviceName;
|
||||
private String cluster;
|
||||
private Map<String, String> metadata;
|
||||
private boolean scheduled;
|
||||
@ -37,12 +37,12 @@ public class BeatInfo {
|
||||
return JSON.toJSONString(this);
|
||||
}
|
||||
|
||||
public String getDom() {
|
||||
return dom;
|
||||
public String getServiceName() {
|
||||
return serviceName;
|
||||
}
|
||||
|
||||
public void setDom(String dom) {
|
||||
this.dom = dom;
|
||||
public void setServiceName(String serviceName) {
|
||||
this.serviceName = serviceName;
|
||||
}
|
||||
|
||||
public String getCluster() {
|
||||
|
@ -15,15 +15,12 @@
|
||||
*/
|
||||
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.client.monitor.MetricsMonitor;
|
||||
import com.alibaba.nacos.client.naming.net.NamingProxy;
|
||||
import com.alibaba.nacos.client.naming.utils.LogUtils;
|
||||
import com.alibaba.nacos.client.naming.utils.UtilAndComs;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.*;
|
||||
|
||||
@ -32,15 +29,7 @@ import java.util.concurrent.*;
|
||||
*/
|
||||
public class BeatReactor {
|
||||
|
||||
private ScheduledExecutorService executorService = new ScheduledThreadPoolExecutor(1, new ThreadFactory() {
|
||||
@Override
|
||||
public Thread newThread(Runnable r) {
|
||||
Thread thread = new Thread(r);
|
||||
thread.setDaemon(true);
|
||||
thread.setName("com.alibaba.nacos.naming.beat.sender");
|
||||
return thread;
|
||||
}
|
||||
});
|
||||
private ScheduledExecutorService executorService;
|
||||
|
||||
private long clientBeatInterval = 5 * 1000;
|
||||
|
||||
@ -49,18 +38,33 @@ public class BeatReactor {
|
||||
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
|
||||
public Thread newThread(Runnable r) {
|
||||
Thread thread = new Thread(r);
|
||||
thread.setDaemon(true);
|
||||
thread.setName("com.alibaba.nacos.naming.beat.sender");
|
||||
return thread;
|
||||
}
|
||||
});
|
||||
|
||||
executorService.scheduleAtFixedRate(new BeatProcessor(), 0, clientBeatInterval, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
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);
|
||||
MetricsMonitor.getDom2BeatSizeMonitor().set(dom2Beat.size());
|
||||
}
|
||||
|
||||
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));
|
||||
MetricsMonitor.getDom2BeatSizeMonitor().set(dom2Beat.size());
|
||||
}
|
||||
@ -81,7 +85,6 @@ public class BeatReactor {
|
||||
}
|
||||
beatInfo.setScheduled(true);
|
||||
executorService.schedule(new BeatTask(beatInfo), 0, TimeUnit.MILLISECONDS);
|
||||
LogUtils.LOG.info("BEAT", "send beat to server: " + beatInfo.toString());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LogUtils.LOG.error("CLIENT-BEAT", "Exception while scheduling beat.", e);
|
||||
@ -99,21 +102,10 @@ public class BeatReactor {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
Map<String, String> params = new HashMap<String, String>(2);
|
||||
params.put("beat", JSON.toJSONString(beatInfo));
|
||||
params.put("dom", beatInfo.getDom());
|
||||
|
||||
try {
|
||||
beatInfo.setScheduled(false);
|
||||
String result = serverProxy.callAllServers(UtilAndComs.NACOS_URL_BASE + "/api/clientBeat", params);
|
||||
JSONObject jsonObject = JSON.parseObject(result);
|
||||
|
||||
if (jsonObject != null) {
|
||||
clientBeatInterval = jsonObject.getLong("clientBeatInterval");
|
||||
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LogUtils.LOG.error("CLIENT-BEAT", "failed to send beat: " + JSON.toJSONString(beatInfo), e);
|
||||
long result = serverProxy.sendBeat(beatInfo);
|
||||
beatInfo.setScheduled(false);
|
||||
if (result > 0) {
|
||||
clientBeatInterval = result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -21,7 +21,6 @@ import com.alibaba.nacos.api.naming.pojo.Instance;
|
||||
import com.alibaba.nacos.api.naming.pojo.ServiceInfo;
|
||||
import com.alibaba.nacos.client.naming.utils.CollectionUtils;
|
||||
import com.alibaba.nacos.client.naming.utils.LogUtils;
|
||||
import com.alibaba.nacos.client.naming.utils.StringUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
@ -57,16 +56,12 @@ public class EventDispatcher {
|
||||
}
|
||||
|
||||
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");
|
||||
List<EventListener> observers = Collections.synchronizedList(new ArrayList<EventListener>());
|
||||
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) {
|
||||
observers.add(listener);
|
||||
}
|
||||
@ -77,9 +72,8 @@ public class EventDispatcher {
|
||||
public void removeListener(String serviceName, String clusters, EventListener listener) {
|
||||
|
||||
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) {
|
||||
Iterator<EventListener> iter = observers.iterator();
|
||||
while (iter.hasNext()) {
|
||||
@ -88,9 +82,20 @@ public class EventDispatcher {
|
||||
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) {
|
||||
if (serviceInfo == null) {
|
||||
return;
|
||||
|
@ -16,6 +16,7 @@
|
||||
package com.alibaba.nacos.client.naming.core;
|
||||
|
||||
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.ServiceInfo;
|
||||
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.net.NamingProxy;
|
||||
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.UtilAndComs;
|
||||
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
|
||||
@ -56,8 +56,25 @@ public class HostReactor {
|
||||
|
||||
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,
|
||||
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.serverProxy = serverProxy;
|
||||
this.cacheDir = cacheDir;
|
||||
@ -72,16 +89,6 @@ public class HostReactor {
|
||||
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() {
|
||||
return serviceInfoMap;
|
||||
}
|
||||
@ -191,55 +198,38 @@ public class HostReactor {
|
||||
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);
|
||||
}
|
||||
|
||||
private ServiceInfo getSerivceInfo0(String serviceName, String clusters, String env, boolean allIPs) {
|
||||
|
||||
String key = ServiceInfo.getKey(serviceName, clusters, env, allIPs);
|
||||
return serviceInfoMap.get(key);
|
||||
public ServiceInfo getServiceInfoDirectlyFromServer(final String serviceName, final String clusters) throws NacosException {
|
||||
String result = serverProxy.queryList(serviceName, clusters, 0, false);
|
||||
if (StringUtils.isNotEmpty(result)) {
|
||||
return JSON.parseObject(result, ServiceInfo.class);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public ServiceInfo getServiceInfo(String serviceName, String clusters, String env) {
|
||||
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) {
|
||||
public ServiceInfo getServiceInfo(final String serviceName, final String clusters) {
|
||||
|
||||
LogUtils.LOG.debug("failover-mode: " + failoverReactor.isFailoverSwitch());
|
||||
String key = ServiceInfo.getKey(serviceName, clusters, env, allIPs);
|
||||
String key = ServiceInfo.getKey(serviceName, clusters);
|
||||
if (failoverReactor.isFailoverSwitch()) {
|
||||
return failoverReactor.getService(key);
|
||||
}
|
||||
|
||||
ServiceInfo serviceObj = getSerivceInfo0(serviceName, clusters, env, allIPs);
|
||||
ServiceInfo serviceObj = getSerivceInfo0(serviceName, clusters);
|
||||
|
||||
if (null == serviceObj) {
|
||||
serviceObj = new ServiceInfo(serviceName, clusters, env);
|
||||
|
||||
if (allIPs) {
|
||||
serviceObj.setAllIPs(allIPs);
|
||||
}
|
||||
serviceObj = new ServiceInfo(serviceName, clusters);
|
||||
|
||||
serviceInfoMap.put(serviceObj.getKey(), serviceObj);
|
||||
|
||||
updatingMap.put(serviceName, new Object());
|
||||
|
||||
if (allIPs) {
|
||||
updateService4AllIPNow(serviceName, clusters, env);
|
||||
} else {
|
||||
updateServiceNow(serviceName, clusters, env);
|
||||
}
|
||||
updateServiceNow(serviceName, clusters);
|
||||
updatingMap.remove(serviceName);
|
||||
|
||||
} else if (updatingMap.containsKey(serviceName)) {
|
||||
@ -251,100 +241,41 @@ public class HostReactor {
|
||||
serviceObj.wait(updateHoldInterval);
|
||||
} catch (InterruptedException e) {
|
||||
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());
|
||||
}
|
||||
|
||||
public void scheduleUpdateIfAbsent(String serviceName, String clusters, String env, boolean allIPs) {
|
||||
if (futureMap.get(ServiceInfo.getKey(serviceName, clusters, env, allIPs)) != null) {
|
||||
public void scheduleUpdateIfAbsent(String serviceName, String clusters) {
|
||||
if (futureMap.get(ServiceInfo.getKey(serviceName, clusters)) != null) {
|
||||
return;
|
||||
}
|
||||
|
||||
synchronized (futureMap) {
|
||||
if (futureMap.get(ServiceInfo.getKey(serviceName, clusters, env, allIPs)) != null) {
|
||||
if (futureMap.get(ServiceInfo.getKey(serviceName, clusters)) != null) {
|
||||
return;
|
||||
}
|
||||
|
||||
ScheduledFuture<?> future = addTask(new UpdateTask(serviceName, clusters, env, allIPs));
|
||||
futureMap.put(ServiceInfo.getKey(serviceName, clusters, env, allIPs), 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);
|
||||
ScheduledFuture<?> future = addTask(new UpdateTask(serviceName, clusters));
|
||||
futureMap.put(ServiceInfo.getKey(serviceName, clusters), future);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressFBWarnings("NN_NAKED_NOTIFY")
|
||||
public void updateServiceNow(String serviceName, String clusters, String env) {
|
||||
ServiceInfo oldService = getSerivceInfo0(serviceName, clusters, env);
|
||||
public void updateServiceNow(String serviceName, String clusters) {
|
||||
ServiceInfo oldService = getSerivceInfo0(serviceName, clusters);
|
||||
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();
|
||||
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);
|
||||
String result = serverProxy.queryList(serviceName, clusters, pushReceiver.getUDPPort(), false);
|
||||
if (StringUtils.isNotEmpty(result)) {
|
||||
processServiceJSON(result);
|
||||
}
|
||||
//else nothing has changed
|
||||
} catch (Exception e) {
|
||||
LogUtils.LOG.error("NA", "failed to update serviceName: " + serviceName, e);
|
||||
} 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 {
|
||||
Map<String, String> params = new HashMap<String, String>(16);
|
||||
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);
|
||||
}
|
||||
serverProxy.queryList(serviceName, clusters, pushReceiver.getUDPPort(), false);
|
||||
} catch (Exception e) {
|
||||
LogUtils.LOG.error("NA", "failed to update serviceName: " + serviceName, e);
|
||||
}
|
||||
@ -393,50 +299,30 @@ public class HostReactor {
|
||||
long lastRefTime = Long.MAX_VALUE;
|
||||
private String clusters;
|
||||
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.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
|
||||
public void run() {
|
||||
try {
|
||||
ServiceInfo serviceObj = serviceInfoMap.get(ServiceInfo.getKey(serviceName, clusters, env, allIPs));
|
||||
ServiceInfo serviceObj = serviceInfoMap.get(ServiceInfo.getKey(serviceName, clusters));
|
||||
|
||||
if (serviceObj == null) {
|
||||
if (allIPs) {
|
||||
updateService4AllIPNow(serviceName, clusters, env);
|
||||
} else {
|
||||
updateServiceNow(serviceName, clusters, env);
|
||||
executor.schedule(this, DEFAULT_DELAY, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
updateServiceNow(serviceName, clusters);
|
||||
executor.schedule(this, DEFAULT_DELAY, TimeUnit.MILLISECONDS);
|
||||
return;
|
||||
}
|
||||
|
||||
if (serviceObj.getLastRefTime() <= lastRefTime) {
|
||||
if (allIPs) {
|
||||
updateService4AllIPNow(serviceName, clusters, env);
|
||||
serviceObj = serviceInfoMap.get(ServiceInfo.getKey(serviceName, clusters, env, true));
|
||||
} else {
|
||||
updateServiceNow(serviceName, clusters, env);
|
||||
serviceObj = serviceInfoMap.get(ServiceInfo.getKey(serviceName, clusters, env));
|
||||
}
|
||||
|
||||
updateServiceNow(serviceName, clusters);
|
||||
serviceObj = serviceInfoMap.get(ServiceInfo.getKey(serviceName, clusters));
|
||||
} else {
|
||||
// if serviceName already updated by push, we should not override it
|
||||
// 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);
|
||||
|
@ -18,14 +18,17 @@ package com.alibaba.nacos.client.naming.net;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.alibaba.fastjson.TypeReference;
|
||||
import com.alibaba.nacos.api.common.Constants;
|
||||
import com.alibaba.nacos.api.exception.NacosException;
|
||||
import com.alibaba.nacos.api.naming.pojo.Instance;
|
||||
import com.alibaba.nacos.api.naming.pojo.ListView;
|
||||
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.SelectorType;
|
||||
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.common.util.HttpMethod;
|
||||
import com.alibaba.nacos.common.util.UuidUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
@ -44,7 +47,7 @@ public class NamingProxy {
|
||||
|
||||
private static final int DEFAULT_SERVER_PORT = 8848;
|
||||
|
||||
private String namespace;
|
||||
private String namespaceId;
|
||||
|
||||
private String endpoint;
|
||||
|
||||
@ -60,9 +63,9 @@ public class NamingProxy {
|
||||
|
||||
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;
|
||||
if (StringUtils.isNotEmpty(serverList)) {
|
||||
this.serverList = Arrays.asList(serverList.split(","));
|
||||
@ -97,9 +100,9 @@ public class NamingProxy {
|
||||
String urlString = "http://" + endpoint + "/nacos/serverlist";
|
||||
|
||||
List<String> headers = Arrays.asList("Client-Version", UtilAndComs.VERSION,
|
||||
"Accept-Encoding", "gzip,deflate,sdch",
|
||||
"Connection", "Keep-Alive",
|
||||
"RequestId", UuidUtils.generateUuid());
|
||||
"Accept-Encoding", "gzip,deflate,sdch",
|
||||
"Connection", "Keep-Alive",
|
||||
"RequestId", UuidUtils.generateUuid());
|
||||
|
||||
HttpClient.HttpResult result = HttpClient.httpGet(urlString, headers, null, UtilAndComs.ENCODING);
|
||||
if (HttpURLConnection.HTTP_OK != result.code) {
|
||||
@ -155,10 +158,11 @@ public class NamingProxy {
|
||||
|
||||
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);
|
||||
params.put("tenant", namespace);
|
||||
params.put(Constants.REQUEST_PARAM_NAMESPACE_ID, namespaceId);
|
||||
params.put("ip", instance.getIp());
|
||||
params.put("port", String.valueOf(instance.getPort()));
|
||||
params.put("weight", String.valueOf(instance.getWeight()));
|
||||
@ -168,33 +172,55 @@ public class NamingProxy {
|
||||
params.put("serviceName", serviceName);
|
||||
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 {
|
||||
|
||||
LogUtils.LOG.info("DEREGISTER-SERVICE", "deregistering service " + serviceName
|
||||
+ " with instance:" + ip + ":" + port + "@" + cluster);
|
||||
LogUtils.LOG.info("DEREGISTER-SERVICE", "{} deregistering service {} with instance: {}:{}@{}",
|
||||
namespaceId, serviceName, ip, port, cluster);
|
||||
|
||||
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("port", String.valueOf(port));
|
||||
params.put("serviceName", serviceName);
|
||||
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);
|
||||
params.put("tenant", namespace);
|
||||
params.put(Constants.REQUEST_PARAM_NAMESPACE_ID, namespaceId);
|
||||
params.put("serviceName", serviceName);
|
||||
params.put("clusters", clusters);
|
||||
params.put("udpPort", String.valueOf(udpPort));
|
||||
params.put("clientIP", NetUtils.localIP());
|
||||
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() {
|
||||
@ -217,6 +243,7 @@ public class NamingProxy {
|
||||
Map<String, String> params = new HashMap<String, String>(4);
|
||||
params.put("pageNo", String.valueOf(pageNo));
|
||||
params.put("pageSize", String.valueOf(pageSize));
|
||||
params.put(Constants.REQUEST_PARAM_NAMESPACE_ID, namespaceId);
|
||||
|
||||
if (selector != null) {
|
||||
switch (SelectorType.valueOf(selector.getType())) {
|
||||
@ -242,27 +269,6 @@ public class NamingProxy {
|
||||
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 {
|
||||
|
||||
|
||||
@ -285,7 +291,7 @@ public class NamingProxy {
|
||||
}
|
||||
|
||||
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)
|
||||
@ -330,11 +336,13 @@ public class NamingProxy {
|
||||
}
|
||||
|
||||
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) {
|
||||
|
||||
params.put(Constants.REQUEST_PARAM_NAMESPACE_ID, getNamespaceId());
|
||||
|
||||
if (CollectionUtils.isEmpty(servers) && StringUtils.isEmpty(nacosDomain)) {
|
||||
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 DEFAULT_NAMESPACE_ID = "default";
|
||||
public static final String DEFAULT_NAMESPACE_ID = "public";
|
||||
|
||||
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 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;
|
||||
|
||||
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.pojo.Instance;
|
||||
import com.alibaba.nacos.api.naming.pojo.ListView;
|
||||
@ -25,6 +27,7 @@ import org.junit.Test;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:zpf.073@gmail.com">nkorange</a>
|
||||
@ -35,7 +38,11 @@ public class NamingTest {
|
||||
@Ignore
|
||||
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.setIp("1.1.1.1");
|
||||
@ -48,9 +55,9 @@ public class NamingTest {
|
||||
|
||||
namingService.registerInstance("nacos.test.1", instance);
|
||||
|
||||
ExpressionSelector expressionSelector = new ExpressionSelector();
|
||||
expressionSelector.setExpression("INSTANCE.metadata.registerSource = 'dubbo'");
|
||||
ListView<String> serviceList = namingService.getServicesOfServer(1, 10, expressionSelector);
|
||||
// ExpressionSelector expressionSelector = new ExpressionSelector();
|
||||
// expressionSelector.setExpression("INSTANCE.metadata.registerSource = 'dubbo'");
|
||||
// ListView<String> serviceList = namingService.getServicesOfServer(1, 10, expressionSelector);
|
||||
|
||||
Thread.sleep(1000000000L);
|
||||
}
|
||||
|
@ -18,7 +18,7 @@
|
||||
<parent>
|
||||
<artifactId>nacos-all</artifactId>
|
||||
<groupId>com.alibaba.nacos</groupId>
|
||||
<version>0.7.0</version>
|
||||
<version>0.8.0-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<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>
|
||||
* @since 0.7.0
|
||||
*/
|
||||
@SpringBootApplication
|
||||
public class CmdbApp {
|
||||
|
@ -28,6 +28,7 @@ import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:zpf.073@gmail.com">nkorange</a>
|
||||
* @since 0.7.0
|
||||
*/
|
||||
@RestController
|
||||
@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>
|
||||
* @since 0.7.0
|
||||
*/
|
||||
public class CmdbManager {
|
||||
}
|
||||
|
@ -20,6 +20,7 @@ import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:zpf.073@gmail.com">nkorange</a>
|
||||
* @since 0.7.0
|
||||
*/
|
||||
@Component
|
||||
public class SwitchAndOptions {
|
||||
|
@ -36,6 +36,7 @@ import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:zpf.073@gmail.com">nkorange</a>
|
||||
* @since 0.7.0
|
||||
*/
|
||||
@Component
|
||||
public class CmdbProvider implements CmdbReader, CmdbWriter {
|
||||
|
@ -22,6 +22,7 @@ import java.util.List;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:zpf.073@gmail.com">nkorange</a>
|
||||
* @since 0.7.0
|
||||
*/
|
||||
public interface CmdbReader {
|
||||
|
||||
|
@ -17,6 +17,7 @@ package com.alibaba.nacos.cmdb.service;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:zpf.073@gmail.com">nkorange</a>
|
||||
* @since 0.7.0
|
||||
*/
|
||||
public interface CmdbWriter {
|
||||
}
|
||||
|
@ -20,6 +20,7 @@ import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* @author nacos
|
||||
* @since 0.7.0
|
||||
*/
|
||||
public class Loggers {
|
||||
|
||||
|
@ -21,6 +21,7 @@ import java.util.concurrent.ThreadFactory;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:zpf.073@gmail.com">nkorange</a>
|
||||
* @since 0.7.0
|
||||
*/
|
||||
public class UtilsAndCommons {
|
||||
|
||||
|
@ -18,7 +18,7 @@
|
||||
<parent>
|
||||
<groupId>com.alibaba.nacos</groupId>
|
||||
<artifactId>nacos-all</artifactId>
|
||||
<version>0.7.0</version>
|
||||
<version>0.8.0-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<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>
|
||||
<groupId>com.alibaba.nacos</groupId>
|
||||
<artifactId>nacos-all</artifactId>
|
||||
<version>0.7.0</version>
|
||||
<version>0.8.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
@ -36,8 +36,6 @@ public class ConfigKey implements Serializable {
|
||||
public ConfigKey() {
|
||||
}
|
||||
|
||||
;
|
||||
|
||||
public ConfigKey(String appName, String dataId, String group) {
|
||||
this.appName = appName;
|
||||
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 com.alibaba.nacos.config.server.model.*;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
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.TransactionTemplate;
|
||||
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.MD5;
|
||||
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 {
|
||||
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) {
|
||||
List<ConfigInfo> configs = new ArrayList<ConfigInfo>();
|
||||
for (Map<String, Object> map : list) {
|
||||
@ -3265,6 +3278,8 @@ public class PersistService {
|
||||
|
||||
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 ConfigKeyRowMapper CONFIG_KEY_ROW_MAPPER = new ConfigKeyRowMapper();
|
||||
|
@ -176,4 +176,19 @@ CREATE TABLE `tenant_info` (
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uk_tenant_info_kptenantid` (`kp`,`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 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>
|
||||
<groupId>com.alibaba.nacos</groupId>
|
||||
<artifactId>nacos-all</artifactId>
|
||||
<version>0.7.0</version>
|
||||
<version>0.8.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>nacos-console</artifactId>
|
||||
<!--<packaging>war</packaging>-->
|
||||
@ -65,6 +65,24 @@
|
||||
<artifactId>mockito-core</artifactId>
|
||||
<scope>test</scope>
|
||||
</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>
|
||||
<build>
|
||||
<finalName>nacos-server</finalName>
|
||||
@ -83,6 +101,7 @@
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<version>2.1.1.RELEASE</version>
|
||||
<configuration>
|
||||
<mainClass>com.alibaba.nacos.Nacos</mainClass>
|
||||
</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.loadDataAtStart=false
|
||||
|
||||
#management.endpoints.web.exposure.include=*
|
||||
|
||||
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.1=jdbc:mysql://11.163.152.91:3306/diamond_devtest?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true
|
||||
db.user=diamond_devtest
|
||||
db.password=4b9622f3f70c7677835ac5a6719e7caf
|
||||
|
||||
|
||||
|
||||
|
||||
enableAccessControl=false
|
||||
|
||||
#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/**
|
||||
|
@ -171,3 +171,19 @@ CREATE TABLE tenant_info (
|
||||
constraint tenant_info_id_key PRIMARY KEY (id),
|
||||
constraint uk_tenant_info_kptenantid UNIQUE (kp,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: ['/'],
|
||||
changeOrigin: true,
|
||||
secure: false,
|
||||
target: 'http://console.nacos.io',
|
||||
target: 'http://localhost:8848',
|
||||
pathRewrite: {'^/v1' : '/nacos/v1'}
|
||||
}],
|
||||
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
|
||||
* */
|
||||
changeNameSpace(ns, nsName) {
|
||||
localStorage.setItem('namespace', ns);
|
||||
this.setnamespace(ns || '');
|
||||
setParams({
|
||||
namespace: ns || '',
|
||||
@ -101,7 +102,7 @@ class NameSpaceList extends React.Component {
|
||||
|
||||
getNameSpaces() {
|
||||
const { locale = {} } = this.props;
|
||||
if (window.namespaceList) {
|
||||
if (window.namespaceList && window.namespaceList.length) {
|
||||
this.handleNameSpaces(window.namespaceList);
|
||||
} else {
|
||||
request({
|
||||
@ -140,6 +141,7 @@ class NameSpaceList extends React.Component {
|
||||
}
|
||||
window.namespaceShowName = namespaceShowName;
|
||||
setParams('namespace', nownamespace || '');
|
||||
localStorage.setItem('namespace', nownamespace);
|
||||
// setParams('namespaceShowName', namespaceShowName);
|
||||
this.props.setNowNameSpace && this.props.setNowNameSpace(namespaceShowName, nownamespace);
|
||||
this.setState({
|
||||
@ -191,8 +193,8 @@ class NameSpaceList extends React.Component {
|
||||
|
||||
return (
|
||||
<div
|
||||
className={namespaceList.length > 0 ? 'namespacewrapper' : ''}
|
||||
style={namespaceList.length > 0 ? namespacestyle : {}}
|
||||
className={namespaceList.length ? 'namespacewrapper' : ''}
|
||||
style={namespaceList.length ? namespacestyle : {}}
|
||||
>
|
||||
{}
|
||||
{title ? (
|
||||
|
@ -217,6 +217,7 @@ const aliwareIntl = (function(_global) {
|
||||
this.nowData = nowData;
|
||||
this.setMomentLocale(this.currentLanguageCode);
|
||||
}
|
||||
|
||||
let aliwareLocal = aliwareGetCookieByKeyName('aliyun_lang') || 'zh';
|
||||
let aliwareLocalSite = aliwareGetCookieByKeyName('aliyun_country') || 'cn';
|
||||
aliwareLocal = aliwareLocal.toLowerCase();
|
||||
@ -473,6 +474,7 @@ const request = (function(_global) {
|
||||
return serviceObj;
|
||||
};
|
||||
})();
|
||||
|
||||
/**
|
||||
* 添加中间件函数
|
||||
* @param {*function} callback 回调函数
|
||||
@ -485,6 +487,7 @@ const request = (function(_global) {
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理中间件
|
||||
* @param {*Object} config ajax请求配置信息
|
||||
@ -504,6 +507,7 @@ const request = (function(_global) {
|
||||
}
|
||||
return config;
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理自定义url
|
||||
* @param {*Object} config ajax请求配置信息
|
||||
@ -603,9 +607,25 @@ const request = (function(_global) {
|
||||
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.handleMiddleWare = handleMiddleWare;
|
||||
|
@ -12,7 +12,7 @@
|
||||
*/
|
||||
module.exports = {
|
||||
'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.serviceManagementVirtual': '服务管理',
|
||||
'nacos.component.ExportDialog.tags2': '标签:',
|
||||
@ -574,7 +574,7 @@ module.exports = {
|
||||
'nacos.page.ConfigEditor.submit_failed': '不能为空, 提交失败',
|
||||
},
|
||||
'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.serviceManagementVirtual': 'ServiceManagement',
|
||||
'nacos.component.CloneDialog.the_same_configuration': 'Conflict:',
|
||||
|
@ -30,6 +30,7 @@ import Layout from './layouts/MainLayout';
|
||||
import CookieHelp from './utils/cookie';
|
||||
import { LANGUAGE_KEY, REDUX_DEVTOOLS } from './constants';
|
||||
|
||||
import Login from './pages/Login';
|
||||
import Namespace from './pages/NameSpace';
|
||||
import Newconfig from './pages/ConfigurationManagement/NewConfig';
|
||||
import Configsync from './pages/ConfigurationManagement/ConfigSync';
|
||||
@ -111,13 +112,15 @@ class App extends React.Component {
|
||||
get router() {
|
||||
return (
|
||||
<HashRouter>
|
||||
<Layout navList={_menu.data}>
|
||||
<Switch>
|
||||
<Switch>
|
||||
<Route path="/login" component={Login} />
|
||||
|
||||
<Layout navList={_menu.data}>
|
||||
{MENU.map(item => (
|
||||
<Route key={item.path} {...item} />
|
||||
))}
|
||||
</Switch>
|
||||
</Layout>
|
||||
</Layout>
|
||||
</Switch>
|
||||
</HashRouter>
|
||||
);
|
||||
}
|
||||
|
@ -12,14 +12,16 @@
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { withRouter } from 'react-router-dom';
|
||||
import PropTypes from 'prop-types';
|
||||
import { connect } from 'react-redux';
|
||||
import { ConfigProvider } from '@alifd/next';
|
||||
import { ConfigProvider, Dropdown, Menu } from '@alifd/next';
|
||||
import siteConfig from '../config';
|
||||
import { changeLanguage } from '@/reducers/locale';
|
||||
|
||||
import './index.scss';
|
||||
|
||||
@withRouter
|
||||
@connect(
|
||||
state => ({ ...state.locale }),
|
||||
{ changeLanguage }
|
||||
@ -40,8 +42,29 @@ class Header extends React.Component {
|
||||
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() {
|
||||
const { locale = {}, language = 'en-US' } = this.props;
|
||||
const {
|
||||
locale = {},
|
||||
language = 'en-us',
|
||||
location: { pathname },
|
||||
} = this.props;
|
||||
const { home, docs, blog, community, languageSwitchButton } = locale;
|
||||
const BASE_URL = `https://nacos.io/${language.toLocaleLowerCase()}/`;
|
||||
const NAV_MENU = [
|
||||
@ -65,6 +88,14 @@ class Header extends React.Component {
|
||||
title={siteConfig.name}
|
||||
/>
|
||||
</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}>
|
||||
{languageSwitchButton}
|
||||
</span>
|
||||
|
@ -18,7 +18,6 @@
|
||||
width: 100%;
|
||||
z-index: 1000;
|
||||
background-color: #fff;
|
||||
border-bottom: 1px solid #eee;
|
||||
}
|
||||
.header-container-primary {
|
||||
background: #252a2f;
|
||||
@ -99,6 +98,13 @@
|
||||
font-size: 14px;
|
||||
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 {
|
||||
opacity: 1;
|
||||
}
|
||||
|
@ -26,6 +26,14 @@ window.globalConfig = {
|
||||
request.middleWare((_config = {}) => {
|
||||
let config = _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') || '';
|
||||
tenant = tenant === 'global' ? '' : tenant;
|
||||
const splitArr = url.split('?');
|
||||
|
@ -18,10 +18,20 @@ const I18N_CONF = {
|
||||
blog: 'BLOG',
|
||||
community: 'COMMUNITY',
|
||||
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: {
|
||||
nacosName: 'NACOS',
|
||||
nacosVersion: '0.7.0',
|
||||
nacosVersion: '0.8.0',
|
||||
doesNotExist: 'The page you visit does not exist',
|
||||
configurationManagementVirtual: 'ConfigManagement',
|
||||
configurationManagement: 'Configurations',
|
||||
@ -239,7 +249,7 @@ const I18N_CONF = {
|
||||
escExit: 'Publish',
|
||||
release: 'Back',
|
||||
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',
|
||||
},
|
||||
CloneDialog: {
|
||||
|
@ -18,10 +18,20 @@ const I18N_CONF = {
|
||||
blog: '博客',
|
||||
community: '社区',
|
||||
languageSwitchButton: 'En',
|
||||
logout: '登出',
|
||||
},
|
||||
Login: {
|
||||
login: '登录',
|
||||
submit: '提交',
|
||||
pleaseInputUsername: '请输入用户名',
|
||||
pleaseInputPassword: '请输入密码',
|
||||
invalidUsernameOrPassword: '用户名或密码错误',
|
||||
passwordRequired: '密码不能为空',
|
||||
usernameRequired: '用户名不能为空',
|
||||
},
|
||||
MainLayout: {
|
||||
nacosName: 'NACOS',
|
||||
nacosVersion: '0.7.0',
|
||||
nacosVersion: '0.8.0',
|
||||
doesNotExist: '您访问的页面不存在',
|
||||
configurationManagementVirtual: '配置管理',
|
||||
configurationManagement: '配置列表',
|
||||
@ -238,7 +248,7 @@ const I18N_CONF = {
|
||||
escExit: '发布',
|
||||
release: '返回',
|
||||
confirmSyanx: '配置信息可能有语法错误, 确定提交吗?',
|
||||
dataIdExists: 'Data ID 已存在',
|
||||
dataIdExists: '配置已存在, 试试别的dataid和group的组合吧',
|
||||
dataRequired: '数据不能为空, 提交失败',
|
||||
},
|
||||
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,
|
||||
} = this.state.editCluster;
|
||||
request({
|
||||
method: 'POST',
|
||||
url: 'v1/ns/cluster/update',
|
||||
method: 'PUT',
|
||||
url: 'v1/ns/cluster',
|
||||
data: {
|
||||
serviceName,
|
||||
clusterName: name,
|
||||
|
@ -58,8 +58,8 @@ class EditInstanceDialog extends React.Component {
|
||||
const { serviceName, clusterName, getInstanceList, openLoading, closeLoading } = this.props;
|
||||
const { ip, port, weight, enabled, metadataText } = this.state.editInstance;
|
||||
request({
|
||||
method: 'POST',
|
||||
url: 'v1/ns/instance/update',
|
||||
method: 'PUT',
|
||||
url: 'v1/ns/instance',
|
||||
data: { serviceName, clusterName, ip, port, weight, enable: enabled, metadata: metadataText },
|
||||
dataType: 'text',
|
||||
beforeSend: () => openLoading(),
|
||||
|
@ -57,7 +57,7 @@ class EditServiceDialog extends React.Component {
|
||||
const editService = Object.assign({}, this.state.editService);
|
||||
const { name, protectThreshold, healthCheckMode, metadataText, selector } = editService;
|
||||
request({
|
||||
method: isCreate ? 'PUT' : 'POST',
|
||||
method: isCreate ? 'POST' : 'PUT',
|
||||
url: 'v1/ns/service',
|
||||
data: {
|
||||
serviceName: name,
|
||||
|
@ -80,8 +80,8 @@ class InstanceTable extends React.Component {
|
||||
const newVal = Object.assign({}, instance);
|
||||
newVal.list[index].enabled = !enabled;
|
||||
request({
|
||||
method: 'POST',
|
||||
url: 'v1/ns/instance/update',
|
||||
method: 'PUT',
|
||||
url: 'v1/ns/instance',
|
||||
data: {
|
||||
serviceName,
|
||||
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>
|
||||
<groupId>com.alibaba.nacos</groupId>
|
||||
<artifactId>nacos-all</artifactId>
|
||||
<version>0.7.0</version>
|
||||
<version>0.8.0-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
@ -50,6 +50,10 @@ public class WebUtils {
|
||||
|
||||
String value = req.getParameter(key);
|
||||
|
||||
if (StringUtils.isBlank(value)) {
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
String encoding = req.getParameter("encoding");
|
||||
if (!StringUtils.isEmpty(encoding)) {
|
||||
try {
|
||||
|
@ -34,7 +34,7 @@ if not ""%2"" == "cluster" (
|
||||
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% -jar %BASE_DIR%\target\nacos-server.jar"
|
||||
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')
|
||||
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"
|
||||
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"
|
||||
fi
|
||||
|
||||
|
@ -25,14 +25,16 @@ management.metrics.export.influx.enabled=false
|
||||
#management.metrics.export.influx.consistency=one
|
||||
#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.pattern=%h %l %u %t "%r" %s %b %D
|
||||
# default current work dir
|
||||
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`),
|
||||
KEY `idx_tenant_id` (`tenant_id`)
|
||||
) 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 uk_tenant_info_kptenantid UNIQUE (kp,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>
|
||||
<groupId>com.alibaba.nacos</groupId>
|
||||
<artifactId>nacos-all</artifactId>
|
||||
<version>0.7.0</version>
|
||||
<version>0.8.0-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
@ -18,7 +18,7 @@
|
||||
<parent>
|
||||
<groupId>com.alibaba.nacos</groupId>
|
||||
<artifactId>nacos-all</artifactId>
|
||||
<version>0.7.0</version>
|
||||
<version>0.8.0-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
@ -18,7 +18,7 @@
|
||||
<parent>
|
||||
<groupId>com.alibaba.nacos</groupId>
|
||||
<artifactId>nacos-all</artifactId>
|
||||
<version>0.7.0</version>
|
||||
<version>0.8.0-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.alibaba.nacos.naming.acl;
|
||||
|
||||
import com.alibaba.nacos.api.common.Constants;
|
||||
import com.alibaba.nacos.core.utils.WebUtils;
|
||||
import com.alibaba.nacos.naming.core.Domain;
|
||||
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 {
|
||||
|
||||
String namespaceId = WebUtils.optional(req, Constants.REQUEST_PARAM_NAMESPACE_ID,
|
||||
UtilsAndCommons.getDefaultNamespaceId());
|
||||
String dom = WebUtils.optional(req, "name", "");
|
||||
if (StringUtils.isEmpty(dom)) {
|
||||
dom = WebUtils.optional(req, "dom", "");
|
||||
@ -71,7 +75,7 @@ public class AuthChecker {
|
||||
// we consider switch is a kind of special domain
|
||||
domObj = Switch.getDom();
|
||||
} else {
|
||||
domObj = domainsManager.getDomain(dom);
|
||||
domObj = domainsManager.getDomain(namespaceId, dom);
|
||||
}
|
||||
|
||||
if (domObj == null) {
|
||||
|
@ -42,8 +42,8 @@ public class RunningConfig implements ApplicationListener<WebServerInitializedEv
|
||||
@Override
|
||||
public void onApplicationEvent(WebServerInitializedEvent event) {
|
||||
|
||||
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 port: {}", event.getWebServer().getPort());
|
||||
Loggers.SRV_LOG.info("[SERVER-INIT] got path: {}", servletContext.getContextPath());
|
||||
|
||||
serverPort = event.getWebServer().getPort();
|
||||
contextPath = servletContext.getContextPath();
|
||||
@ -51,7 +51,7 @@ public class RunningConfig implements ApplicationListener<WebServerInitializedEv
|
||||
try {
|
||||
RaftCore.init();
|
||||
} 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.JSONObject;
|
||||
import com.alibaba.nacos.api.common.Constants;
|
||||
import com.alibaba.nacos.api.naming.pojo.Cluster;
|
||||
import com.alibaba.nacos.api.naming.pojo.Instance;
|
||||
import com.alibaba.nacos.api.naming.pojo.Service;
|
||||
@ -64,6 +65,8 @@ public class CatalogController {
|
||||
@RequestMapping(value = "/serviceList")
|
||||
public JSONObject serviceList(HttpServletRequest request) throws Exception {
|
||||
|
||||
String namespaceId = WebUtils.optional(request, Constants.REQUEST_PARAM_NAMESPACE_ID,
|
||||
UtilsAndCommons.getDefaultNamespaceId());
|
||||
JSONObject result = new JSONObject();
|
||||
|
||||
int page = Integer.parseInt(WebUtils.required(request, "startPg"));
|
||||
@ -71,7 +74,7 @@ public class CatalogController {
|
||||
String keyword = WebUtils.optional(request, "keyword", StringUtils.EMPTY);
|
||||
|
||||
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)) {
|
||||
result.put("serviceList", Collections.emptyList());
|
||||
@ -109,8 +112,10 @@ public class CatalogController {
|
||||
@RequestMapping(value = "/serviceDetail")
|
||||
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");
|
||||
VirtualClusterDomain domain = (VirtualClusterDomain) domainsManager.getDomain(serviceName);
|
||||
VirtualClusterDomain domain = (VirtualClusterDomain) domainsManager.getDomain(namespaceId, serviceName);
|
||||
if (domain == null) {
|
||||
throw new NacosException(NacosException.NOT_FOUND, "serivce " + serviceName + " is not found!");
|
||||
}
|
||||
@ -164,12 +169,14 @@ public class CatalogController {
|
||||
@RequestMapping(value = "/instanceList")
|
||||
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 clusterName = WebUtils.required(request, "clusterName");
|
||||
int page = Integer.parseInt(WebUtils.required(request, "startPg"));
|
||||
int pageSize = Integer.parseInt(WebUtils.required(request, "pgSize"));
|
||||
|
||||
VirtualClusterDomain domain = (VirtualClusterDomain) domainsManager.getDomain(serviceName);
|
||||
VirtualClusterDomain domain = (VirtualClusterDomain) domainsManager.getDomain(namespaceId, serviceName);
|
||||
if (domain == null) {
|
||||
throw new NacosException(NacosException.NOT_FOUND, "serivce " + serviceName + " is not found!");
|
||||
}
|
||||
@ -218,10 +225,12 @@ public class CatalogController {
|
||||
@RequestMapping(value = "/services", method = RequestMethod.GET)
|
||||
public List<ServiceDetailInfo> listDetail(HttpServletRequest request) {
|
||||
|
||||
String namespaceId = WebUtils.optional(request, Constants.REQUEST_PARAM_NAMESPACE_ID,
|
||||
UtilsAndCommons.getDefaultNamespaceId());
|
||||
List<ServiceDetailInfo> serviceDetailInfoList = new ArrayList<>();
|
||||
|
||||
domainsManager
|
||||
.getRaftDomMap()
|
||||
.getDomMap(namespaceId)
|
||||
.forEach(
|
||||
(serviceName, domain) -> {
|
||||
|
||||
|
@ -17,6 +17,7 @@ package com.alibaba.nacos.naming.controllers;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.alibaba.nacos.api.common.Constants;
|
||||
import com.alibaba.nacos.api.naming.pojo.AbstractHealthChecker;
|
||||
import com.alibaba.nacos.core.utils.WebUtils;
|
||||
import com.alibaba.nacos.naming.core.Cluster;
|
||||
@ -45,9 +46,11 @@ public class ClusterController {
|
||||
@Autowired
|
||||
protected DomainsManager domainsManager;
|
||||
|
||||
@RequestMapping(value = {"/update", "/add"}, method = RequestMethod.POST)
|
||||
@RequestMapping(value = {"/update", "/add"}, method = RequestMethod.PUT)
|
||||
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 serviceName = WebUtils.required(request, "serviceName");
|
||||
String healthChecker = WebUtils.required(request, "healthChecker");
|
||||
@ -55,18 +58,16 @@ public class ClusterController {
|
||||
String checkPort = WebUtils.required(request, "checkPort");
|
||||
String useInstancePort4Check = WebUtils.required(request, "useInstancePort4Check");
|
||||
|
||||
VirtualClusterDomain domain = (VirtualClusterDomain) domainsManager.getDomain(serviceName);
|
||||
VirtualClusterDomain domain = (VirtualClusterDomain) domainsManager.getDomain(namespaceId, serviceName);
|
||||
if (domain == null) {
|
||||
throw new NacosException(NacosException.INVALID_PARAM, "service not found:" + serviceName);
|
||||
}
|
||||
|
||||
Cluster cluster = domain.getClusterMap().get(clusterName);
|
||||
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.setName(clusterName);
|
||||
|
||||
// throw new NacosException(NacosException.INVALID_PARAM, "cluster not found:"+ clusterName + ", " + serviceName);
|
||||
}
|
||||
|
||||
cluster.setDefCkport(NumberUtils.toInt(checkPort));
|
||||
|
@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.alibaba.nacos.naming.controllers;
|
||||
|
||||
import com.alibaba.nacos.api.common.Constants;
|
||||
import com.alibaba.nacos.core.utils.WebUtils;
|
||||
import com.alibaba.nacos.naming.boot.RunningConfig;
|
||||
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 nanamikon
|
||||
* @since 0.8.0
|
||||
*/
|
||||
@RestController("NamingHealthController")
|
||||
@RestController("namingHealthController")
|
||||
@RequestMapping(UtilsAndCommons.NACOS_NAMING_CONTEXT + "/health")
|
||||
public class HealthController {
|
||||
@Autowired
|
||||
private DomainsManager domainsManager;
|
||||
|
||||
@RequestMapping(method = RequestMethod.POST)
|
||||
@RequestMapping(method = {RequestMethod.POST, RequestMethod.PUT})
|
||||
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 ip = WebUtils.required(request, "ip");
|
||||
int port = Integer.parseInt(WebUtils.required(request, "port"));
|
||||
@ -75,16 +81,16 @@ public class HealthController {
|
||||
throw new IllegalArgumentException("failed to proxy health update to " + server + ", dom: " + dom);
|
||||
}
|
||||
} else {
|
||||
VirtualClusterDomain virtualClusterDomain = (VirtualClusterDomain) domainsManager.getDomain(dom);
|
||||
VirtualClusterDomain virtualClusterDomain = (VirtualClusterDomain) domainsManager.getDomain(namespaceId, dom);
|
||||
// Only health check "none" need update health status with api
|
||||
if (!virtualClusterDomain.getEnableHealthCheck() && !virtualClusterDomain.getEnableClientBeat()) {
|
||||
for (IpAddress ipAddress: virtualClusterDomain.allIPs(Lists.newArrayList(clusterName))) {
|
||||
for (IpAddress ipAddress : virtualClusterDomain.allIPs(Lists.newArrayList(clusterName))) {
|
||||
if (ipAddress.getIp().equals(ip) && ipAddress.getPort() == port) {
|
||||
ipAddress.setValid(valid);
|
||||
Loggers.EVT_LOG.info((valid ? "[IP-ENABLED]" : "[IP-DISABLED]") + " ips: "
|
||||
+ ipAddress.getIp() + ":" + ipAddress.getPort() + "@" + ipAddress.getClusterName()
|
||||
+ ", dom: " + dom + ", msg: update thought HealthController api");
|
||||
PushService.domChanged(virtualClusterDomain.getName());
|
||||
PushService.domChanged(namespaceId, virtualClusterDomain.getName());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -17,14 +17,14 @@ package com.alibaba.nacos.naming.controllers;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.alibaba.nacos.api.common.Constants;
|
||||
import com.alibaba.nacos.core.utils.WebUtils;
|
||||
import com.alibaba.nacos.naming.core.IpAddress;
|
||||
import com.alibaba.nacos.naming.core.VirtualClusterDomain;
|
||||
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.web.ApiCommands;
|
||||
import com.alibaba.nacos.naming.web.MockHttpRequest;
|
||||
import com.alibaba.nacos.naming.web.OverrideParameterRequestWrapper;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
@ -32,9 +32,7 @@ import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:zpf.073@gmail.com">nkorange</a>
|
||||
@ -43,70 +41,20 @@ import java.util.Map;
|
||||
@RequestMapping(UtilsAndCommons.NACOS_NAMING_CONTEXT)
|
||||
public class InstanceController extends ApiCommands {
|
||||
|
||||
@RequestMapping(value = "/instance", method = RequestMethod.PUT)
|
||||
@RequestMapping(value = "/instance", method = RequestMethod.POST)
|
||||
public String register(HttpServletRequest request) throws Exception {
|
||||
|
||||
Map<String, String[]> params = new HashMap<>(request.getParameterMap());
|
||||
MockHttpRequest mockHttpRequest = MockHttpRequest.buildRequest(params);
|
||||
OverrideParameterRequestWrapper requestWrapper = OverrideParameterRequestWrapper.buildRequest(request);
|
||||
|
||||
String serviceJson = WebUtils.optional(request, "service", StringUtils.EMPTY);
|
||||
String clusterJson = WebUtils.optional(request, "cluster", StringUtils.EMPTY);
|
||||
|
||||
// set service info:
|
||||
if (StringUtils.isNotEmpty(serviceJson)) {
|
||||
JSONObject service = JSON.parseObject(serviceJson);
|
||||
mockHttpRequest.addParameter("dom", 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)) {
|
||||
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"));
|
||||
requestWrapper.addParameter("serviceName", service.getString("name"));
|
||||
}
|
||||
|
||||
// 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);
|
||||
return regService(requestWrapper);
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/instance", method = RequestMethod.DELETE)
|
||||
@ -114,34 +62,27 @@ public class InstanceController extends ApiCommands {
|
||||
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 {
|
||||
String serviceName = WebUtils.required(request, "serviceName");
|
||||
Map<String, String[]> params = new HashMap<>(request.getParameterMap());
|
||||
MockHttpRequest mockHttpRequest = MockHttpRequest.buildRequest(params);
|
||||
mockHttpRequest.addParameter("dom", serviceName);
|
||||
return regService(mockHttpRequest);
|
||||
return regService(request);
|
||||
}
|
||||
|
||||
@RequestMapping(value = {"/instances", "/instance/list"}, method = RequestMethod.GET)
|
||||
public JSONObject queryList(HttpServletRequest request) throws Exception {
|
||||
|
||||
Map<String, String[]> params = new HashMap<>(request.getParameterMap());
|
||||
params.put("dom", params.get("serviceName"));
|
||||
MockHttpRequest mockHttpRequest = MockHttpRequest.buildRequest(params);
|
||||
|
||||
return srvIPXT(mockHttpRequest);
|
||||
return srvIPXT(OverrideParameterRequestWrapper.buildRequest(request, "dom", WebUtils.required(request, "serviceName")));
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/instance", method = RequestMethod.GET)
|
||||
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 ip = WebUtils.required(request, "ip");
|
||||
int port = Integer.parseInt(WebUtils.required(request, "port"));
|
||||
|
||||
VirtualClusterDomain domain = (VirtualClusterDomain) domainsManager.getDomain(serviceName);
|
||||
VirtualClusterDomain domain = (VirtualClusterDomain) domainsManager.getDomain(namespaceId, serviceName);
|
||||
if (domain == null) {
|
||||
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!");
|
||||
}
|
||||
|
||||
@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.JSONObject;
|
||||
import com.alibaba.nacos.api.common.Constants;
|
||||
import com.alibaba.nacos.api.selector.SelectorType;
|
||||
import com.alibaba.nacos.core.utils.WebUtils;
|
||||
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.exception.NacosException;
|
||||
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.raft.RaftCore;
|
||||
import com.alibaba.nacos.naming.selector.LabelSelector;
|
||||
import com.alibaba.nacos.naming.selector.NoneSelector;
|
||||
import com.alibaba.nacos.naming.selector.Selector;
|
||||
@ -49,16 +50,20 @@ public class ServiceController {
|
||||
@Autowired
|
||||
protected DomainsManager domainsManager;
|
||||
|
||||
@RequestMapping(value = "", method = RequestMethod.PUT)
|
||||
@RequestMapping(value = "", method = RequestMethod.POST)
|
||||
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);
|
||||
}
|
||||
|
||||
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 selector = WebUtils.optional(request, "selector", StringUtils.EMPTY);
|
||||
Map<String, String> metadataMap = new HashMap<>(16);
|
||||
@ -74,6 +79,7 @@ public class ServiceController {
|
||||
domObj.setEnableClientBeat(HealthCheckMode.client.name().equals(healthCheckMode.toLowerCase()));
|
||||
domObj.setMetadata(metadataMap);
|
||||
domObj.setSelector(parseSelector(selector));
|
||||
domObj.setNamespaceId(namespaceId);
|
||||
|
||||
// now valid the dom. if failed, exception will be thrown
|
||||
domObj.setLastModifiedMillis(System.currentTimeMillis());
|
||||
@ -88,9 +94,11 @@ public class ServiceController {
|
||||
@RequestMapping(value = "", method = RequestMethod.DELETE)
|
||||
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) {
|
||||
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);
|
||||
}
|
||||
|
||||
domainsManager.easyRemoveDom(serviceName);
|
||||
domainsManager.easyRemoveDom(namespaceId, serviceName);
|
||||
|
||||
return "ok";
|
||||
}
|
||||
@ -107,14 +115,18 @@ public class ServiceController {
|
||||
@RequestMapping(value = "", method = RequestMethod.GET)
|
||||
public JSONObject detail(HttpServletRequest request) throws Exception {
|
||||
|
||||
String serviceName = WebUtils.required(request, "serviceName");
|
||||
VirtualClusterDomain domain = (VirtualClusterDomain) domainsManager.getDomain(serviceName);
|
||||
String namespaceId = WebUtils.optional(request, Constants.REQUEST_PARAM_NAMESPACE_ID,
|
||||
UtilsAndCommons.getDefaultNamespaceId());
|
||||
String serviceName = WebUtils.required(request, Constants.REQUEST_PARAM_SERVICE_NAME);
|
||||
|
||||
VirtualClusterDomain domain = (VirtualClusterDomain) domainsManager.getDomain(namespaceId, serviceName);
|
||||
if (domain == null) {
|
||||
throw new NacosException(NacosException.NOT_FOUND, "serivce " + serviceName + " is not found!");
|
||||
}
|
||||
|
||||
JSONObject res = new JSONObject();
|
||||
res.put("name", serviceName);
|
||||
res.put("namespaceId", domain.getNamespaceId());
|
||||
res.put("protectThreshold", domain.getProtectThreshold());
|
||||
|
||||
res.put("healthCheckMode", HealthCheckMode.none.name());
|
||||
@ -131,9 +143,6 @@ public class ServiceController {
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@ -142,9 +151,15 @@ public class ServiceController {
|
||||
|
||||
int pageNo = NumberUtils.toInt(WebUtils.required(request, "pageNo"));
|
||||
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);
|
||||
|
||||
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)) {
|
||||
|
||||
@ -163,10 +178,10 @@ public class ServiceController {
|
||||
String[] factors = terms[0].split("\\.");
|
||||
switch (factors[0]) {
|
||||
case "INSTANCE":
|
||||
doms = filterInstanceMetadata(doms, factors[factors.length - 1], terms[1].replace("'", ""));
|
||||
doms = filterInstanceMetadata(namespaceId, doms, factors[factors.length - 1], terms[1].replace("'", ""));
|
||||
break;
|
||||
case "SERVICE":
|
||||
doms = filterServiceMetadata(doms, factors[factors.length - 1], terms[1].replace("'", ""));
|
||||
doms = filterServiceMetadata(namespaceId, doms, factors[factors.length - 1], terms[1].replace("'", ""));
|
||||
break;
|
||||
default:
|
||||
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 {
|
||||
|
||||
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"));
|
||||
String healthCheckMode = WebUtils.required(request, "healthCheckMode");
|
||||
String metadata = WebUtils.optional(request, "metadata", 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) {
|
||||
throw new NacosException(NacosException.INVALID_PARAM, "service " + serviceName + " not found!");
|
||||
}
|
||||
@ -242,16 +259,16 @@ public class ServiceController {
|
||||
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<>();
|
||||
for (String service : serivces) {
|
||||
VirtualClusterDomain serviceObj = (VirtualClusterDomain) domainsManager.getDomain(service);
|
||||
VirtualClusterDomain serviceObj = (VirtualClusterDomain) domainsManager.getDomain(namespaceId, service);
|
||||
if (serviceObj == null) {
|
||||
continue;
|
||||
}
|
||||
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);
|
||||
break;
|
||||
}
|
||||
@ -260,11 +277,11 @@ public class ServiceController {
|
||||
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<>();
|
||||
for (String service : serivces) {
|
||||
VirtualClusterDomain serviceObj = (VirtualClusterDomain) domainsManager.getDomain(service);
|
||||
VirtualClusterDomain serviceObj = (VirtualClusterDomain) domainsManager.getDomain(namespaceId, service);
|
||||
if (serviceObj == null) {
|
||||
continue;
|
||||
}
|
||||
|
@ -187,24 +187,22 @@ public class Cluster extends com.alibaba.nacos.api.naming.pojo.Cluster implement
|
||||
} else {
|
||||
if (ip.isValid() != oldIP.isValid()) {
|
||||
// ip validation status updated
|
||||
Loggers.EVT_LOG.info("{" + getDom().getName() + "} {SYNC} " +
|
||||
"{IP-" + (ip.isValid() ? "ENABLED" : "DISABLED") + "} " + ip.getIp()
|
||||
+ ":" + ip.getPort() + "@" + getName());
|
||||
Loggers.EVT_LOG.info("{} {SYNC} IP-{} {}:{}@{}",
|
||||
getDom().getName(), (ip.isValid() ? "ENABLED" : "DISABLED"), ip.getIp(), ip.getPort(), getName());
|
||||
}
|
||||
}
|
||||
|
||||
if (ip.getWeight() != oldIP.getWeight()) {
|
||||
// ip validation status updated
|
||||
Loggers.EVT_LOG.info("{" + getDom().getName() + "} {SYNC} " +
|
||||
"{IP-UPDATED} " + oldIP.toString() + "->" + ip.toString());
|
||||
Loggers.EVT_LOG.info("{} {SYNC} {IP-UPDATED} {}->{}", getDom().getName(), oldIP.toString(), ip.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
List<IpAddress> newIPs = subtract(ips, oldIPMap.values());
|
||||
if (newIPs.size() > 0) {
|
||||
Loggers.EVT_LOG.info("{" + getDom().getName() + "} {SYNC} {IP-NEW} cluster: " + getName()
|
||||
+ ", new ips(" + newIPs.size() + "): " + newIPs.toString());
|
||||
Loggers.EVT_LOG.info("{} {SYNC} {IP-NEW} cluster: {}, new ips size: {}, content: {}",
|
||||
getDom().getName(), getName(), newIPs.size(), newIPs.toString());
|
||||
|
||||
for (IpAddress ip : newIPs) {
|
||||
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);
|
||||
|
||||
if (deadIPs.size() > 0) {
|
||||
Loggers.EVT_LOG.info("{" + getDom().getName() + "} {SYNC} {IP-DEAD} cluster: " + getName()
|
||||
+ ", dead ips(" + deadIPs.size() + "): " + deadIPs.toString());
|
||||
Loggers.EVT_LOG.info("{} {SYNC} {IP-DEAD} cluster: {}, dead ips size: {}, content: {}",
|
||||
getDom().getName(), getName(), deadIPs.size(), deadIPs.toString());
|
||||
|
||||
for (IpAddress ip : deadIPs) {
|
||||
HealthCheckStatus.remv(ip);
|
||||
@ -333,32 +331,38 @@ public class Cluster extends com.alibaba.nacos.api.naming.pojo.Cluster implement
|
||||
public void update(Cluster cluster) {
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
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());
|
||||
}
|
||||
|
||||
@ -387,9 +391,9 @@ public class Cluster extends com.alibaba.nacos.api.naming.pojo.Cluster implement
|
||||
|
||||
public boolean responsible(IpAddress ip) {
|
||||
return Switch.isHealthCheckEnabled(dom.getName())
|
||||
&& !getHealthCheckTask().isCancelled()
|
||||
&& DistroMapper.responsible(getDom().getName())
|
||||
&& ipContains.containsKey(ip.toIPAddr());
|
||||
&& !getHealthCheckTask().isCancelled()
|
||||
&& DistroMapper.responsible(getDom().getName())
|
||||
&& ipContains.containsKey(ip.toIPAddr());
|
||||
}
|
||||
|
||||
public void valid() {
|
||||
|
@ -21,8 +21,6 @@ import com.alibaba.nacos.naming.misc.*;
|
||||
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
@ -61,7 +59,7 @@ public class DistroMapper {
|
||||
init();
|
||||
|
||||
UtilsAndCommons.SERVER_STATUS_EXECUTOR.schedule(new ServerStatusReporter(),
|
||||
60000, TimeUnit.MILLISECONDS);
|
||||
60000, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -110,7 +108,7 @@ public class DistroMapper {
|
||||
// site:ip:lastReportTime:weight
|
||||
String[] params = config.split("#");
|
||||
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;
|
||||
}
|
||||
|
||||
@ -159,10 +157,10 @@ public class DistroMapper {
|
||||
float curRatio = (float) newHealthyList.size() / allSiteSrvs.size();
|
||||
|
||||
if (AUTO_DISABLED_HEALTH_CHECK
|
||||
&& curRatio > Switch.getDistroThreshold()
|
||||
&& System.currentTimeMillis() - LAST_HEALTH_SERVER_MILLIS > STABLE_PERIOD) {
|
||||
&& curRatio > Switch.getDistroThreshold()
|
||||
&& System.currentTimeMillis() - LAST_HEALTH_SERVER_MILLIS > STABLE_PERIOD) {
|
||||
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);
|
||||
|
||||
@ -174,7 +172,8 @@ public class DistroMapper {
|
||||
// for every change disable healthy check for some while
|
||||
if (Switch.isHealthCheckEnabled()) {
|
||||
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);
|
||||
AUTO_DISABLED_HEALTH_CHECK = true;
|
||||
@ -200,7 +199,7 @@ public class DistroMapper {
|
||||
// site:ip:lastReportTime:weight
|
||||
String[] params = config.split("#");
|
||||
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;
|
||||
}
|
||||
|
||||
@ -232,8 +231,8 @@ public class DistroMapper {
|
||||
|
||||
if (serverId.equals(newServerId)) {
|
||||
if (s.alive != server.alive || s.weight != server.weight) {
|
||||
Loggers.SRV_LOG.warn("server beat out of date, current: " + JSON.toJSONString(server)
|
||||
+ ", last: " + JSON.toJSONString(s));
|
||||
Loggers.SRV_LOG.warn("server beat out of date, current: {}, last: {}",
|
||||
JSON.toJSONString(server), JSON.toJSONString(s));
|
||||
}
|
||||
tmpServerList.add(server);
|
||||
continue;
|
||||
@ -281,10 +280,10 @@ public class DistroMapper {
|
||||
float curRatio = (float) newHealthyList.size() / allLocalSiteSrvs.size();
|
||||
|
||||
if (AUTO_DISABLED_HEALTH_CHECK
|
||||
&& curRatio > Switch.getDistroThreshold()
|
||||
&& System.currentTimeMillis() - LAST_HEALTH_SERVER_MILLIS > STABLE_PERIOD) {
|
||||
&& curRatio > Switch.getDistroThreshold()
|
||||
&& System.currentTimeMillis() - LAST_HEALTH_SERVER_MILLIS > STABLE_PERIOD) {
|
||||
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);
|
||||
|
||||
@ -296,7 +295,7 @@ public class DistroMapper {
|
||||
// for every change disable healthy check for some while
|
||||
if (Switch.isHealthCheckEnabled()) {
|
||||
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);
|
||||
AUTO_DISABLED_HEALTH_CHECK = true;
|
||||
@ -402,7 +401,7 @@ public class DistroMapper {
|
||||
try {
|
||||
NamingProxy.reqAPI("distroStatus", params, serverIP, false);
|
||||
} 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)) {
|
||||
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;
|
||||
}
|
||||
|
||||
@ -500,7 +499,7 @@ public class DistroMapper {
|
||||
}
|
||||
}
|
||||
} 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 {
|
||||
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.RaftPeer;
|
||||
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Component;
|
||||
@ -43,7 +42,10 @@ import java.util.concurrent.locks.ReentrantLock;
|
||||
@Component
|
||||
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);
|
||||
|
||||
@ -78,8 +80,8 @@ public class DomainsManager {
|
||||
}
|
||||
});
|
||||
|
||||
public Map<String, Domain> chooseDomMap() {
|
||||
return raftDomMap;
|
||||
public Map<String, Domain> chooseDomMap(String namespaceId) {
|
||||
return serviceMap.get(namespaceId);
|
||||
}
|
||||
|
||||
private void initConfig() {
|
||||
@ -90,32 +92,32 @@ public class DomainsManager {
|
||||
try {
|
||||
TimeUnit.SECONDS.sleep(5);
|
||||
} 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 {
|
||||
leader = RaftCore.getPeerSet().getLeader();
|
||||
if (leader != null) {
|
||||
Loggers.SRV_LOG.info("[AUTO-INIT] leader is: " + leader.ip);
|
||||
Loggers.SRV_LOG.info("[AUTO-INIT] leader is: {}", leader.ip);
|
||||
break;
|
||||
}
|
||||
|
||||
} 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();
|
||||
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) {
|
||||
toBeUpdatedDomsQueue.poll();
|
||||
toBeUpdatedDomsQueue.add(new DomainKey(domName, serverIP, checksum));
|
||||
Loggers.SRV_LOG.error("DOMAIN-STATUS", "Failed to add domain to be updatd to queue.", e);
|
||||
toBeUpdatedDomsQueue.add(new DomainKey(namespaceId, domName, serverIP, checksum));
|
||||
Loggers.SRV_LOG.error("[DOMAIN-STATUS] Failed to add domain to be updatd to queue.", e);
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
@ -128,7 +130,6 @@ public class DomainsManager {
|
||||
public void run() {
|
||||
String domName = null;
|
||||
String serverIP = null;
|
||||
String checksum;
|
||||
|
||||
try {
|
||||
while (true) {
|
||||
@ -137,7 +138,7 @@ public class DomainsManager {
|
||||
try {
|
||||
domainKey = toBeUpdatedDomsQueue.take();
|
||||
} 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) {
|
||||
@ -146,21 +147,23 @@ public class DomainsManager {
|
||||
|
||||
domName = domainKey.getDomName();
|
||||
serverIP = domainKey.getServerIP();
|
||||
checksum = domainKey.getChecksum();
|
||||
|
||||
domainUpdateExecutor.execute(new DomUpdater(domName, serverIP));
|
||||
domainUpdateExecutor.execute(new DomUpdater(domainKey.getNamespaceId(), domName, serverIP));
|
||||
}
|
||||
} 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 {
|
||||
|
||||
String namespaceId;
|
||||
String domName;
|
||||
String serverIP;
|
||||
|
||||
public DomUpdater(String domName, String serverIP) {
|
||||
public DomUpdater(String namespaceId, String domName, String serverIP) {
|
||||
this.namespaceId = namespaceId;
|
||||
this.domName = domName;
|
||||
this.serverIP = serverIP;
|
||||
}
|
||||
@ -168,15 +171,16 @@ public class DomainsManager {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
updatedDom2(domName, serverIP);
|
||||
updatedDom2(namespaceId, domName, serverIP);
|
||||
} 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) {
|
||||
Message msg = synchronizer.get(serverIP, domName);
|
||||
public void updatedDom2(String namespaceId, String domName, String serverIP) {
|
||||
Message msg = synchronizer.get(serverIP, UtilsAndCommons.assembleFullServiceName(namespaceId, domName));
|
||||
JSONObject dom = JSON.parseObject(msg.getData());
|
||||
|
||||
JSONArray ipList = dom.getJSONArray("ips");
|
||||
@ -188,7 +192,7 @@ public class DomainsManager {
|
||||
ipsMap.put(strings[0], strings[1]);
|
||||
}
|
||||
|
||||
VirtualClusterDomain raftVirtualClusterDomain = (VirtualClusterDomain) raftDomMap.get(domName);
|
||||
VirtualClusterDomain raftVirtualClusterDomain = (VirtualClusterDomain) getDomain(namespaceId, domName);
|
||||
|
||||
if (raftVirtualClusterDomain == null) {
|
||||
return;
|
||||
@ -200,85 +204,92 @@ public class DomainsManager {
|
||||
Boolean valid = Boolean.parseBoolean(ipsMap.get(ipAddress.toIPAddr()));
|
||||
if (valid != ipAddress.isValid()) {
|
||||
ipAddress.setValid(valid);
|
||||
Loggers.EVT_LOG.info("{" + domName + "} {SYNC} " +
|
||||
"{IP-" + (ipAddress.isValid() ? "ENABLED" : "DISABLED") + "} " + ipAddress.getIp()
|
||||
+ ":" + ipAddress.getPort() + "@" + ipAddress.getClusterName());
|
||||
Loggers.EVT_LOG.info("{} {SYNC} IP-{} : {}@{}",
|
||||
domName, (ipAddress.isValid() ? "ENABLED" : "DISABLED"),
|
||||
ipAddress.getIp(), ipAddress.getPort(), ipAddress.getClusterName());
|
||||
}
|
||||
}
|
||||
|
||||
PushService.domChanged(raftVirtualClusterDomain.getName());
|
||||
PushService.domChanged(raftVirtualClusterDomain.getNamespaceId(), raftVirtualClusterDomain.getName());
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
List<IpAddress> allIps = raftVirtualClusterDomain.allIPs();
|
||||
for (IpAddress ipAddress : allIps) {
|
||||
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() {
|
||||
return new HashSet<String>(chooseDomMap().keySet());
|
||||
public Set<String> getAllDomNames(String namespaceId) {
|
||||
return serviceMap.get(namespaceId).keySet();
|
||||
}
|
||||
|
||||
public List<String> getAllDomNamesList() {
|
||||
return new ArrayList<>(chooseDomMap().keySet());
|
||||
}
|
||||
public Map<String, Set<String>> getAllDomNames() {
|
||||
|
||||
public void setAllDomNames(List<String> allDomNames) {
|
||||
this.allDomNames = new HashSet<>(allDomNames);
|
||||
}
|
||||
|
||||
public Set<String> getAllDomNamesCache() {
|
||||
if (Switch.isAllDomNameCache()) {
|
||||
if (CollectionUtils.isNotEmpty(allDomNames)) {
|
||||
return allDomNames;
|
||||
} else {
|
||||
allDomNames = getAllDomNames();
|
||||
}
|
||||
} else {
|
||||
return getAllDomNames();
|
||||
Map<String, Set<String>> namesMap = new HashMap<>(16);
|
||||
for (String namespaceId : serviceMap.keySet()) {
|
||||
namesMap.put(namespaceId, serviceMap.get(namespaceId).keySet());
|
||||
}
|
||||
|
||||
return allDomNames;
|
||||
return namesMap;
|
||||
}
|
||||
|
||||
private Set<String> allDomNames;
|
||||
public List<String> getAllDomNamesList(String namespaceId) {
|
||||
if (chooseDomMap(namespaceId) == null) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
return new ArrayList<>(chooseDomMap(namespaceId).keySet());
|
||||
}
|
||||
|
||||
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();
|
||||
if (DistroMapper.responsible(entry.getKey())) {
|
||||
result.add(domain);
|
||||
public Map<String, Set<Domain>> getResponsibleDoms() {
|
||||
Map<String, Set<Domain>> result = new HashMap<>(16);
|
||||
for (String namespaceId : serviceMap.keySet()) {
|
||||
result.put(namespaceId, new HashSet<>());
|
||||
for (Map.Entry<String, Domain> entry : serviceMap.get(namespaceId).entrySet()) {
|
||||
Domain domain = entry.getValue();
|
||||
if (DistroMapper.responsible(entry.getKey())) {
|
||||
result.get(namespaceId).add(domain);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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() {
|
||||
List<Domain> responsibleDoms = getResponsibleDoms();
|
||||
Map<String, Set<Domain>> responsibleDoms = getResponsibleDoms();
|
||||
int count = 0;
|
||||
for (Domain domain : responsibleDoms) {
|
||||
count += domain.allIPs().size();
|
||||
for (String namespaceId : responsibleDoms.keySet()) {
|
||||
for (Domain domain : responsibleDoms.get(namespaceId)) {
|
||||
count += domain.allIPs().size();
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
RaftCore.signalDelete(UtilsAndCommons.getDomStoreKey(dom));
|
||||
}
|
||||
}
|
||||
|
||||
public void easyAddOrReplaceDom(Domain newDom) throws Exception {
|
||||
VirtualClusterDomain virtualClusterDomain = null;
|
||||
VirtualClusterDomain virtualClusterDomain;
|
||||
if (newDom instanceof VirtualClusterDomain) {
|
||||
virtualClusterDomain = (VirtualClusterDomain) newDom;
|
||||
newDom = virtualClusterDomain;
|
||||
@ -286,17 +297,17 @@ public class DomainsManager {
|
||||
RaftCore.doSignalPublish(UtilsAndCommons.getDomStoreKey(newDom), JSON.toJSONString(newDom), true);
|
||||
}
|
||||
|
||||
public void easyAddIP4Dom(String domName, List<IpAddress> ips, long term) throws Exception {
|
||||
easyUpdateIP4Dom(domName, ips, term, "add");
|
||||
public void easyAddIP4Dom(String namespaceId, String domName, List<IpAddress> ips, long term) throws Exception {
|
||||
easyUpdateIP4Dom(namespaceId, domName, ips, term, "add");
|
||||
}
|
||||
|
||||
public void easyRemvIP4Dom(String domName, List<IpAddress> ips, long term) throws Exception {
|
||||
easyUpdateIP4Dom(domName, ips, term, "remove");
|
||||
public void easyRemvIP4Dom(String namespaceId, String domName, List<IpAddress> ips, long term) throws Exception {
|
||||
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) {
|
||||
throw new IllegalArgumentException("dom doesn't exist: " + domName);
|
||||
}
|
||||
@ -335,8 +346,8 @@ public class DomainsManager {
|
||||
Cluster cluster = new Cluster(ipAddress.getClusterName());
|
||||
cluster.setDom(dom);
|
||||
dom.getClusterMap().put(ipAddress.getClusterName(), cluster);
|
||||
Loggers.SRV_LOG.warn("cluster: " + ipAddress.getClusterName() + " not found, ip: " + ipAddress.toJSON()
|
||||
+ ", will create new cluster with default configuration.");
|
||||
Loggers.SRV_LOG.warn("cluster: {} not found, ip: {}, will create new cluster with default configuration.",
|
||||
ipAddress.getClusterName(), ipAddress.toJSON());
|
||||
}
|
||||
|
||||
if (UtilsAndCommons.UPDATE_INSTANCE_ACTION_REMOVE.equals(action)) {
|
||||
@ -352,8 +363,7 @@ public class DomainsManager {
|
||||
+ JSON.toJSONString(ipAddressMap.values()));
|
||||
}
|
||||
|
||||
Loggers.EVT_LOG.info("{" + dom + "} {POS} {IP-UPDATE}" + ips +
|
||||
", action:" + action);
|
||||
Loggers.EVT_LOG.info("{} {POS} {IP-UPDATE} {}, action: {}", dom, ips, action);
|
||||
|
||||
String key = UtilsAndCommons.getIPListStoreKey(dom);
|
||||
String value = JSON.toJSONString(ipAddressMap.values());
|
||||
@ -374,7 +384,7 @@ public class DomainsManager {
|
||||
peer.leaderDueMs = RaftCore.getLeader().leaderDueMs;
|
||||
peer.state = RaftCore.getLeader().state;
|
||||
|
||||
boolean increaseTerm = !((VirtualClusterDomain) getDomain(domName)).getEnableClientBeat();
|
||||
boolean increaseTerm = !((VirtualClusterDomain) getDomain(namespaceId, domName)).getEnableClientBeat();
|
||||
|
||||
RaftCore.onPublish(datum, peer, increaseTerm);
|
||||
} finally {
|
||||
@ -399,7 +409,7 @@ public class DomainsManager {
|
||||
}
|
||||
}
|
||||
} catch (Throwable throwable) {
|
||||
Loggers.RAFT.error("NA", "error while processing json: " + oldJson, throwable);
|
||||
Loggers.RAFT.error("error while processing json: " + oldJson, throwable);
|
||||
} finally {
|
||||
if (ipAddresses == null) {
|
||||
ipAddresses = new ArrayList<>();
|
||||
@ -410,13 +420,24 @@ public class DomainsManager {
|
||||
return ipAddresses;
|
||||
}
|
||||
|
||||
public Domain getDomain(String domName) {
|
||||
return chooseDomMap().get(domName);
|
||||
public Domain getDomain(String namespaceId, String 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>();
|
||||
for (Map.Entry<String, Domain> entry : chooseDomMap().entrySet()) {
|
||||
for (Map.Entry<String, Domain> entry : chooseDomMap(namespaceId).entrySet()) {
|
||||
Domain dom = entry.getValue();
|
||||
|
||||
String key = dom.getName() + ":" + ArrayUtils.toString(dom.getOwners());
|
||||
@ -429,32 +450,39 @@ public class DomainsManager {
|
||||
}
|
||||
|
||||
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;
|
||||
List<String> doms = new ArrayList<String>(getAllDomNames());
|
||||
for (String dom : doms) {
|
||||
Domain domain = getDomain(dom);
|
||||
total += (domain.allIPs().size());
|
||||
for (String namespaceId : serviceMap.keySet()) {
|
||||
for (Domain domain : serviceMap.get(namespaceId).values()) {
|
||||
total += domain.allIPs().size();
|
||||
}
|
||||
}
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
public Map<String, Domain> getRaftDomMap() {
|
||||
return raftDomMap;
|
||||
public Map<String, Domain> getDomMap(String namespaceId) {
|
||||
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;
|
||||
|
||||
if (chooseDomMap(namespaceId) == null) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (StringUtils.isNotBlank(keyword)) {
|
||||
matchList = searchDomains(".*" + keyword + ".*");
|
||||
matchList = searchDomains(namespaceId, ".*" + keyword + ".*");
|
||||
} else {
|
||||
matchList = new ArrayList<Domain>(chooseDomMap().values());
|
||||
matchList = new ArrayList<Domain>(chooseDomMap(namespaceId).values());
|
||||
}
|
||||
|
||||
if (pageSize >= matchList.size()) {
|
||||
@ -478,11 +506,18 @@ public class DomainsManager {
|
||||
}
|
||||
|
||||
public static class DomainChecksum {
|
||||
|
||||
public String namespaceId;
|
||||
public Map<String, String> domName2Checksum = new HashMap<String, String>();
|
||||
|
||||
public DomainChecksum(String namespaceId) {
|
||||
this.namespaceId = namespaceId;
|
||||
}
|
||||
|
||||
public void addItem(String domName, String 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;
|
||||
}
|
||||
|
||||
@ -496,49 +531,52 @@ public class DomainsManager {
|
||||
public void run() {
|
||||
try {
|
||||
|
||||
DomainChecksum checksum = new DomainChecksum();
|
||||
|
||||
List<String> allDomainNames = new ArrayList<String>(getAllDomNames());
|
||||
Map<String, Set<String>> allDomainNames = getAllDomNames();
|
||||
|
||||
if (allDomainNames.size() <= 0) {
|
||||
//ignore
|
||||
return;
|
||||
}
|
||||
|
||||
for (String domName : allDomainNames) {
|
||||
if (!DistroMapper.responsible(domName)) {
|
||||
continue;
|
||||
for (String namespaceId : allDomainNames.keySet()) {
|
||||
|
||||
DomainChecksum checksum = new DomainChecksum(namespaceId);
|
||||
|
||||
for (String domName : allDomainNames.get(namespaceId)) {
|
||||
if (!DistroMapper.responsible(domName)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Domain domain = getDomain(namespaceId, domName);
|
||||
|
||||
if (domain == null || domain instanceof SwitchDomain) {
|
||||
continue;
|
||||
}
|
||||
|
||||
domain.recalculateChecksum();
|
||||
|
||||
checksum.addItem(domName, domain.getChecksum());
|
||||
}
|
||||
|
||||
Domain domain = getDomain(domName);
|
||||
Message msg = new Message();
|
||||
|
||||
if (domain == null || domain instanceof SwitchDomain) {
|
||||
continue;
|
||||
msg.setData(JSON.toJSONString(checksum));
|
||||
|
||||
List<String> sameSiteServers = NamingProxy.getSameSiteServers().get("sameSite");
|
||||
|
||||
if (sameSiteServers == null || sameSiteServers.size() <= 0 || !NamingProxy.getServers().contains(NetUtils.localServer())) {
|
||||
return;
|
||||
}
|
||||
|
||||
domain.recalculateChecksum();
|
||||
|
||||
checksum.addItem(domName, domain.getChecksum());
|
||||
}
|
||||
|
||||
Message msg = new Message();
|
||||
|
||||
msg.setData(JSON.toJSONString(checksum));
|
||||
|
||||
List<String> sameSiteServers = NamingProxy.getSameSiteServers().get("sameSite");
|
||||
|
||||
if (sameSiteServers == null || sameSiteServers.size() <= 0 || !NamingProxy.getServers().contains(NetUtils.localServer())) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (String server : sameSiteServers) {
|
||||
if (server.equals(NetUtils.localServer())) {
|
||||
continue;
|
||||
for (String server : sameSiteServers) {
|
||||
if (server.equals(NetUtils.localServer())) {
|
||||
continue;
|
||||
}
|
||||
synchronizer.send(server, msg);
|
||||
}
|
||||
synchronizer.send(server, msg);
|
||||
}
|
||||
} 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 {
|
||||
UtilsAndCommons.DOMAIN_SYNCHRONIZATION_EXECUTOR.schedule(this, Switch.getDomStatusSynchronizationPeriodMillis(), TimeUnit.MILLISECONDS);
|
||||
}
|
||||
@ -568,12 +606,12 @@ public class DomainsManager {
|
||||
final RaftListener raftListener = new RaftListener() {
|
||||
@Override
|
||||
public boolean interests(String key) {
|
||||
return StringUtils.startsWith(key, UtilsAndCommons.DOMAINS_DATA_ID);
|
||||
return StringUtils.startsWith(key, UtilsAndCommons.DOMAINS_DATA_ID_PRE);
|
||||
}
|
||||
|
||||
@Override
|
||||
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")
|
||||
@ -581,7 +619,7 @@ public class DomainsManager {
|
||||
public void onChange(String key, String value) throws Exception {
|
||||
try {
|
||||
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;
|
||||
}
|
||||
|
||||
@ -590,48 +628,43 @@ public class DomainsManager {
|
||||
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) {
|
||||
oldDom.update(dom);
|
||||
} else {
|
||||
|
||||
if (!dom2LockMap.containsKey(dom.getName())) {
|
||||
dom2LockMap.put(dom.getName(), new ReentrantLock());
|
||||
}
|
||||
addLockIfAbsent(UtilsAndCommons.assembleFullServiceName(dom.getNamespaceId(), dom.getName()));
|
||||
|
||||
raftDomMap.put(dom.getName(), dom);
|
||||
putDomain(dom);
|
||||
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());
|
||||
Condition condition = dom2ConditionMap.get(dom.getName());
|
||||
|
||||
try {
|
||||
lock.lock();
|
||||
condition.signalAll();
|
||||
} catch (Exception ignore) {
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
wakeUp(UtilsAndCommons.assembleFullServiceName(dom.getNamespaceId(), dom.getName()));
|
||||
|
||||
} catch (Throwable e) {
|
||||
Loggers.SRV_LOG.error("VIPSRV-DOM", "error while processing dom update", e);
|
||||
Loggers.SRV_LOG.error("[NACOS-DOM] error while processing dom update", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
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);
|
||||
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());
|
||||
Loggers.SRV_LOG.info("[DEAD-DOM] {}", dom.toJSON());
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -639,19 +672,38 @@ public class DomainsManager {
|
||||
|
||||
}
|
||||
|
||||
public Lock addLock(String domName) {
|
||||
public void wakeUp(String key) {
|
||||
|
||||
Lock lock = dom2LockMap.get(key);
|
||||
Condition condition = dom2ConditionMap.get(key);
|
||||
|
||||
try {
|
||||
lock.lock();
|
||||
condition.signalAll();
|
||||
} catch (Exception ignore) {
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public Lock addLockIfAbsent(String key) {
|
||||
|
||||
if (dom2LockMap.containsKey(key)) {
|
||||
return dom2LockMap.get(key);
|
||||
}
|
||||
Lock lock = new ReentrantLock();
|
||||
dom2LockMap.put(domName, lock);
|
||||
dom2LockMap.put(key, lock);
|
||||
return lock;
|
||||
}
|
||||
|
||||
public Condition addCondtion(String domName) {
|
||||
Condition condition = dom2LockMap.get(domName).newCondition();
|
||||
dom2ConditionMap.put(domName, condition);
|
||||
public Condition addCondtion(String key) {
|
||||
Condition condition = dom2LockMap.get(key).newCondition();
|
||||
dom2ConditionMap.put(key, condition);
|
||||
return condition;
|
||||
}
|
||||
|
||||
private static class DomainKey {
|
||||
private String namespaceId;
|
||||
private String domName;
|
||||
private String serverIP;
|
||||
|
||||
@ -667,9 +719,14 @@ public class DomainsManager {
|
||||
return domName;
|
||||
}
|
||||
|
||||
public String getNamespaceId() {
|
||||
return namespaceId;
|
||||
}
|
||||
|
||||
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.serverIP = serverIP;
|
||||
this.checksum = checksum;
|
||||
|
@ -301,7 +301,7 @@ public class IpAddress extends Instance implements Comparable {
|
||||
@Override
|
||||
public int compareTo(Object o) {
|
||||
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());
|
||||
}
|
||||
|
||||
|
@ -28,8 +28,8 @@ import com.alibaba.nacos.naming.misc.UtilsAndCommons;
|
||||
import com.alibaba.nacos.naming.push.PushService;
|
||||
import com.alibaba.nacos.naming.raft.RaftCore;
|
||||
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.Selector;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.commons.collections.ListUtils;
|
||||
import org.apache.commons.lang3.RandomStringUtils;
|
||||
@ -64,9 +64,10 @@ public class VirtualClusterDomain implements Domain, RaftListener {
|
||||
private Boolean enabled = true;
|
||||
private Boolean enableClientBeat = false;
|
||||
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;
|
||||
|
||||
@ -158,23 +159,23 @@ public class VirtualClusterDomain implements Domain, RaftListener {
|
||||
|
||||
@Override
|
||||
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
|
||||
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
|
||||
public void onChange(String key, String value) throws Exception {
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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>>() {
|
||||
});
|
||||
@ -214,7 +215,7 @@ public class VirtualClusterDomain implements Domain, RaftListener {
|
||||
for (IpAddress ip : ips) {
|
||||
try {
|
||||
if (ip == null) {
|
||||
Loggers.SRV_LOG.error("VIPSRV-DOM", "received malformed ip");
|
||||
Loggers.SRV_LOG.error("[NACOS-DOM] received malformed ip: null");
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -224,7 +225,7 @@ public class VirtualClusterDomain implements Domain, RaftListener {
|
||||
|
||||
// put wild ip into DEFAULT cluster
|
||||
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;
|
||||
}
|
||||
|
||||
@ -236,7 +237,7 @@ public class VirtualClusterDomain implements Domain, RaftListener {
|
||||
|
||||
clusterIPs.add(ip);
|
||||
} 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);
|
||||
}
|
||||
setLastModifiedMillis(System.currentTimeMillis());
|
||||
PushService.domChanged(name);
|
||||
PushService.domChanged(namespaceId, name);
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
|
||||
for (IpAddress ipAddress : allIPs()) {
|
||||
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;
|
||||
} 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;
|
||||
}
|
||||
}
|
||||
@ -454,6 +455,14 @@ public class VirtualClusterDomain implements Domain, RaftListener {
|
||||
this.clusterMap = clusterMap;
|
||||
}
|
||||
|
||||
public String getNamespaceId() {
|
||||
return namespaceId;
|
||||
}
|
||||
|
||||
public void setNamespaceId(String namespaceId) {
|
||||
this.namespaceId = namespaceId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(Domain dom) {
|
||||
if (!(dom instanceof VirtualClusterDomain)) {
|
||||
@ -462,42 +471,42 @@ public class VirtualClusterDomain implements Domain, RaftListener {
|
||||
|
||||
VirtualClusterDomain vDom = (VirtualClusterDomain) dom;
|
||||
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();
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
@ -544,13 +553,13 @@ public class VirtualClusterDomain implements Domain, RaftListener {
|
||||
MessageDigest md5 = MessageDigest.getInstance("MD5");
|
||||
result = new BigInteger(1, md5.digest((ipsString.toString()).getBytes(Charset.forName("UTF-8")))).toString(16);
|
||||
} 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);
|
||||
}
|
||||
|
||||
checksum = result;
|
||||
} 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);
|
||||
}
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user