#745 Support multiple server modes
This commit is contained in:
parent
4fe7c3d3b8
commit
194387b583
@ -29,4 +29,6 @@ public class CommonParams {
|
|||||||
|
|
||||||
public static final String NAMESPACE_ID = "namespaceId";
|
public static final String NAMESPACE_ID = "namespaceId";
|
||||||
|
|
||||||
|
public static final String GROUP_NAME = "groupName";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,7 @@ import com.alibaba.nacos.api.exception.NacosException;
|
|||||||
/**
|
/**
|
||||||
* Naming Factory
|
* Naming Factory
|
||||||
*
|
*
|
||||||
* @author dungu.zpf
|
* @author nkorange
|
||||||
*/
|
*/
|
||||||
public class NamingFactory {
|
public class NamingFactory {
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@ import java.util.List;
|
|||||||
/**
|
/**
|
||||||
* Naming Service
|
* Naming Service
|
||||||
*
|
*
|
||||||
* @author dungu.zpf
|
* @author nkorange
|
||||||
*/
|
*/
|
||||||
public interface NamingService {
|
public interface NamingService {
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ package com.alibaba.nacos.api.naming.listener;
|
|||||||
/**
|
/**
|
||||||
* Event Interface
|
* Event Interface
|
||||||
*
|
*
|
||||||
* @author dungu.zpf
|
* @author nkorange
|
||||||
*/
|
*/
|
||||||
public interface Event {
|
public interface Event {
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@ import com.alibaba.nacos.api.naming.pojo.Instance;
|
|||||||
/**
|
/**
|
||||||
* Naming Event
|
* Naming Event
|
||||||
*
|
*
|
||||||
* @author dungu.zpf
|
* @author nkorange
|
||||||
*/
|
*/
|
||||||
public class NamingEvent implements Event {
|
public class NamingEvent implements Event {
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ import java.util.Map;
|
|||||||
/**
|
/**
|
||||||
* Cluster
|
* Cluster
|
||||||
*
|
*
|
||||||
* @author dungu.zpf
|
* @author nkorange
|
||||||
*/
|
*/
|
||||||
public class Cluster {
|
public class Cluster {
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ import java.util.List;
|
|||||||
/**
|
/**
|
||||||
* ListView
|
* ListView
|
||||||
*
|
*
|
||||||
* @author dungu.zpf
|
* @author nkorange
|
||||||
*/
|
*/
|
||||||
public class ListView<T> {
|
public class ListView<T> {
|
||||||
|
|
||||||
|
@ -19,9 +19,14 @@ import java.util.HashMap;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Service
|
* Service of Nacos
|
||||||
|
* <p>
|
||||||
|
* We introduce a 'service --> cluster --> instance' model, in which service stores a list of clusters,
|
||||||
|
* which contains a list of instances.
|
||||||
|
* <p>
|
||||||
|
* Typically we put some unique properties between instances to service level.
|
||||||
*
|
*
|
||||||
* @author dungu.zpf
|
* @author nkorange
|
||||||
*/
|
*/
|
||||||
public class Service {
|
public class Service {
|
||||||
|
|
||||||
@ -43,7 +48,7 @@ public class Service {
|
|||||||
private String app;
|
private String app;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Service group which is meant to classify services into different sets.
|
* Service group to classify services into different sets.
|
||||||
*/
|
*/
|
||||||
private String group;
|
private String group;
|
||||||
|
|
||||||
|
@ -26,7 +26,7 @@ import java.util.List;
|
|||||||
/**
|
/**
|
||||||
* ServiceInfo
|
* ServiceInfo
|
||||||
*
|
*
|
||||||
* @author dungu.zpf
|
* @author nkorange
|
||||||
*/
|
*/
|
||||||
public class ServiceInfo {
|
public class ServiceInfo {
|
||||||
|
|
||||||
|
@ -16,7 +16,6 @@
|
|||||||
package com.alibaba.nacos.naming.boot;
|
package com.alibaba.nacos.naming.boot;
|
||||||
|
|
||||||
import org.springframework.beans.BeansException;
|
import org.springframework.beans.BeansException;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.context.ApplicationContext;
|
import org.springframework.context.ApplicationContext;
|
||||||
import org.springframework.context.ApplicationContextAware;
|
import org.springframework.context.ApplicationContextAware;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
@ -0,0 +1,48 @@
|
|||||||
|
/*
|
||||||
|
* 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.naming.cluster;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Server running mode
|
||||||
|
* <p>
|
||||||
|
* We use CAP theory to set the server mode, users can select their preferred mode in running time.
|
||||||
|
* <p>
|
||||||
|
* CP mode provides strong consistency, data persistence but network partition tolerance.
|
||||||
|
* <p>
|
||||||
|
* AP mode provides eventual consistency and network partition tolerance but data persistence.
|
||||||
|
* <p>
|
||||||
|
* Mixed mode provides CP for some data and AP for some other data.
|
||||||
|
* <p>
|
||||||
|
* Service level information and cluster level information are always operated via CP protocol, so
|
||||||
|
* in AP mode they cannot be edited.
|
||||||
|
*
|
||||||
|
* @author nkorange
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
public enum ServerMode {
|
||||||
|
/**
|
||||||
|
* AP mode
|
||||||
|
*/
|
||||||
|
AP,
|
||||||
|
/**
|
||||||
|
* CP mode
|
||||||
|
*/
|
||||||
|
CP,
|
||||||
|
/**
|
||||||
|
* Mixed mode
|
||||||
|
*/
|
||||||
|
MIXED
|
||||||
|
}
|
@ -23,6 +23,7 @@ import org.springframework.beans.factory.annotation.Autowired;
|
|||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import javax.annotation.PostConstruct;
|
import javax.annotation.PostConstruct;
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Detect and control the working status of local server
|
* Detect and control the working status of local server
|
||||||
@ -33,7 +34,7 @@ import javax.annotation.PostConstruct;
|
|||||||
@Service
|
@Service
|
||||||
public class ServerStatusManager {
|
public class ServerStatusManager {
|
||||||
|
|
||||||
@Autowired
|
@Resource(name = "consistencyDelegate")
|
||||||
private ConsistencyService consistencyService;
|
private ConsistencyService consistencyService;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
@ -41,8 +42,6 @@ public class ServerStatusManager {
|
|||||||
|
|
||||||
private ServerStatus serverStatus = ServerStatus.STARTING;
|
private ServerStatus serverStatus = ServerStatus.STARTING;
|
||||||
|
|
||||||
private boolean serverStatusLocked = false;
|
|
||||||
|
|
||||||
@PostConstruct
|
@PostConstruct
|
||||||
public void init() {
|
public void init() {
|
||||||
GlobalExecutor.registerServerStatusUpdater(new ServerStatusUpdater());
|
GlobalExecutor.registerServerStatusUpdater(new ServerStatusUpdater());
|
||||||
|
@ -18,7 +18,10 @@ package com.alibaba.nacos.naming.consistency.ephemeral.partition;
|
|||||||
import com.alibaba.nacos.naming.consistency.Datum;
|
import com.alibaba.nacos.naming.consistency.Datum;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -49,14 +49,9 @@ public class RaftStore {
|
|||||||
|
|
||||||
private Properties meta = new Properties();
|
private Properties meta = new Properties();
|
||||||
|
|
||||||
private String metaFileName;
|
private String metaFileName = UtilsAndCommons.DATA_BASE_DIR + File.separator + "meta.properties";
|
||||||
|
|
||||||
private String cacheDir;
|
private String cacheDir = UtilsAndCommons.DATA_BASE_DIR + File.separator + "data";
|
||||||
|
|
||||||
public RaftStore() {
|
|
||||||
metaFileName = UtilsAndCommons.DATA_BASE_DIR + File.separator + "meta.properties";
|
|
||||||
cacheDir = UtilsAndCommons.DATA_BASE_DIR + File.separator + "data";
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized ConcurrentHashMap<String, Datum<?>> loadDatums(RaftCore.Notifier notifier) throws Exception {
|
public synchronized ConcurrentHashMap<String, Datum<?>> loadDatums(RaftCore.Notifier notifier) throws Exception {
|
||||||
|
|
||||||
@ -116,7 +111,7 @@ public class RaftStore {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized static Datum readDatum(File file, String namespaceId) throws IOException {
|
public synchronized Datum readDatum(File file, String namespaceId) throws IOException {
|
||||||
|
|
||||||
ByteBuffer buffer;
|
ByteBuffer buffer;
|
||||||
FileChannel fc = null;
|
FileChannel fc = null;
|
||||||
|
@ -26,11 +26,7 @@ import com.alibaba.nacos.naming.core.ServiceManager;
|
|||||||
import com.alibaba.nacos.naming.exception.NacosException;
|
import com.alibaba.nacos.naming.exception.NacosException;
|
||||||
import com.alibaba.nacos.naming.healthcheck.HealthCheckTask;
|
import com.alibaba.nacos.naming.healthcheck.HealthCheckTask;
|
||||||
import com.alibaba.nacos.naming.misc.UtilsAndCommons;
|
import com.alibaba.nacos.naming.misc.UtilsAndCommons;
|
||||||
import com.alibaba.nacos.naming.pojo.ClusterInfo;
|
import com.alibaba.nacos.naming.pojo.*;
|
||||||
import com.alibaba.nacos.naming.pojo.IpAddressInfo;
|
|
||||||
import com.alibaba.nacos.naming.pojo.ServiceDetailInfo;
|
|
||||||
import com.alibaba.nacos.naming.pojo.ServiceDetailView;
|
|
||||||
import com.alibaba.nacos.naming.pojo.ServiceView;
|
|
||||||
import org.apache.commons.collections.CollectionUtils;
|
import org.apache.commons.collections.CollectionUtils;
|
||||||
import org.apache.commons.collections.map.HashedMap;
|
import org.apache.commons.collections.map.HashedMap;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
@ -21,8 +21,8 @@ import com.alibaba.nacos.api.naming.CommonParams;
|
|||||||
import com.alibaba.nacos.api.naming.pojo.AbstractHealthChecker;
|
import com.alibaba.nacos.api.naming.pojo.AbstractHealthChecker;
|
||||||
import com.alibaba.nacos.core.utils.WebUtils;
|
import com.alibaba.nacos.core.utils.WebUtils;
|
||||||
import com.alibaba.nacos.naming.core.Cluster;
|
import com.alibaba.nacos.naming.core.Cluster;
|
||||||
import com.alibaba.nacos.naming.core.ServiceManager;
|
|
||||||
import com.alibaba.nacos.naming.core.Service;
|
import com.alibaba.nacos.naming.core.Service;
|
||||||
|
import com.alibaba.nacos.naming.core.ServiceManager;
|
||||||
import com.alibaba.nacos.naming.exception.NacosException;
|
import com.alibaba.nacos.naming.exception.NacosException;
|
||||||
import com.alibaba.nacos.naming.misc.Loggers;
|
import com.alibaba.nacos.naming.misc.Loggers;
|
||||||
import com.alibaba.nacos.naming.misc.UtilsAndCommons;
|
import com.alibaba.nacos.naming.misc.UtilsAndCommons;
|
||||||
|
@ -21,6 +21,7 @@ import com.alibaba.fastjson.JSONObject;
|
|||||||
import com.alibaba.nacos.api.naming.CommonParams;
|
import com.alibaba.nacos.api.naming.CommonParams;
|
||||||
import com.alibaba.nacos.core.utils.WebUtils;
|
import com.alibaba.nacos.core.utils.WebUtils;
|
||||||
import com.alibaba.nacos.naming.boot.RunningConfig;
|
import com.alibaba.nacos.naming.boot.RunningConfig;
|
||||||
|
import com.alibaba.nacos.naming.cluster.ServerMode;
|
||||||
import com.alibaba.nacos.naming.core.DistroMapper;
|
import com.alibaba.nacos.naming.core.DistroMapper;
|
||||||
import com.alibaba.nacos.naming.core.Instance;
|
import com.alibaba.nacos.naming.core.Instance;
|
||||||
import com.alibaba.nacos.naming.core.Service;
|
import com.alibaba.nacos.naming.core.Service;
|
||||||
@ -90,7 +91,7 @@ public class InstanceController {
|
|||||||
|
|
||||||
@RequestMapping(value = "/instance", method = RequestMethod.POST)
|
@RequestMapping(value = "/instance", method = RequestMethod.POST)
|
||||||
public String register(HttpServletRequest request) throws Exception {
|
public String register(HttpServletRequest request) throws Exception {
|
||||||
return regService(request);
|
return registerInstance(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
@RequestMapping(value = "/instance", method = RequestMethod.DELETE)
|
@RequestMapping(value = "/instance", method = RequestMethod.DELETE)
|
||||||
@ -112,7 +113,7 @@ public class InstanceController {
|
|||||||
|
|
||||||
@RequestMapping(value = {"/instance/update", "instance"}, method = RequestMethod.PUT)
|
@RequestMapping(value = {"/instance/update", "instance"}, method = RequestMethod.PUT)
|
||||||
public String update(HttpServletRequest request) throws Exception {
|
public String update(HttpServletRequest request) throws Exception {
|
||||||
return regService(request);
|
return registerInstance(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
@RequestMapping(value = {"/instances", "/instance/list"}, method = RequestMethod.GET)
|
@RequestMapping(value = {"/instances", "/instance/list"}, method = RequestMethod.GET)
|
||||||
@ -184,6 +185,16 @@ public class InstanceController {
|
|||||||
|
|
||||||
@RequestMapping(value = "/instance/beat", method = RequestMethod.PUT)
|
@RequestMapping(value = "/instance/beat", method = RequestMethod.PUT)
|
||||||
public JSONObject beat(HttpServletRequest request) throws Exception {
|
public JSONObject beat(HttpServletRequest request) throws Exception {
|
||||||
|
|
||||||
|
JSONObject result = new JSONObject();
|
||||||
|
|
||||||
|
result.put("clientBeatInterval", switchDomain.getClientBeatInterval());
|
||||||
|
|
||||||
|
// ignore client beat in CP mode:
|
||||||
|
if (ServerMode.CP.name().equals(switchDomain.getServerMode())) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
String namespaceId = WebUtils.optional(request, CommonParams.NAMESPACE_ID,
|
String namespaceId = WebUtils.optional(request, CommonParams.NAMESPACE_ID,
|
||||||
UtilsAndCommons.DEFAULT_NAMESPACE_ID);
|
UtilsAndCommons.DEFAULT_NAMESPACE_ID);
|
||||||
String beat = WebUtils.required(request, "beat");
|
String beat = WebUtils.required(request, "beat");
|
||||||
@ -218,7 +229,13 @@ public class InstanceController {
|
|||||||
instance.setClusterName(clusterName);
|
instance.setClusterName(clusterName);
|
||||||
instance.setServiceName(serviceName);
|
instance.setServiceName(serviceName);
|
||||||
instance.setInstanceId(instance.generateInstanceId());
|
instance.setInstanceId(instance.generateInstanceId());
|
||||||
serviceManager.registerInstance(namespaceId, serviceName, clusterName, instance);
|
instance.setEphemeral(clientBeat.isEphemeral());
|
||||||
|
|
||||||
|
if (ServerMode.AP.name().equals(switchDomain.getServerMode())) {
|
||||||
|
serviceManager.registerInstance(namespaceId, serviceName, clusterName, instance);
|
||||||
|
} else {
|
||||||
|
serviceManager.addInstance(namespaceId, serviceName, clusterName, true, instance);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Service service = serviceManager.getService(namespaceId, serviceName);
|
Service service = serviceManager.getService(namespaceId, serviceName);
|
||||||
@ -252,10 +269,6 @@ public class InstanceController {
|
|||||||
service.processClientBeat(clientBeat);
|
service.processClientBeat(clientBeat);
|
||||||
}
|
}
|
||||||
|
|
||||||
JSONObject result = new JSONObject();
|
|
||||||
|
|
||||||
result.put("clientBeatInterval", switchDomain.getClientBeatInterval());
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -295,7 +308,7 @@ public class InstanceController {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private String regService(HttpServletRequest request) throws Exception {
|
private String registerInstance(HttpServletRequest request) throws Exception {
|
||||||
|
|
||||||
String serviceName = WebUtils.required(request, CommonParams.SERVICE_NAME);
|
String serviceName = WebUtils.required(request, CommonParams.SERVICE_NAME);
|
||||||
String clusterName = WebUtils.optional(request, CommonParams.CLUSTER_NAME, UtilsAndCommons.DEFAULT_CLUSTER_NAME);
|
String clusterName = WebUtils.optional(request, CommonParams.CLUSTER_NAME, UtilsAndCommons.DEFAULT_CLUSTER_NAME);
|
||||||
@ -325,7 +338,9 @@ public class InstanceController {
|
|||||||
String weight = WebUtils.optional(request, "weight", "1");
|
String weight = WebUtils.optional(request, "weight", "1");
|
||||||
String cluster = WebUtils.optional(request, CommonParams.CLUSTER_NAME, UtilsAndCommons.DEFAULT_CLUSTER_NAME);
|
String cluster = WebUtils.optional(request, CommonParams.CLUSTER_NAME, UtilsAndCommons.DEFAULT_CLUSTER_NAME);
|
||||||
boolean enabled = BooleanUtils.toBoolean(WebUtils.optional(request, "enable", "true"));
|
boolean enabled = BooleanUtils.toBoolean(WebUtils.optional(request, "enable", "true"));
|
||||||
boolean ephemeral = BooleanUtils.toBoolean(WebUtils.optional(request, "ephemeral", "true"));
|
// If server running in CP mode, we set this flag to false:
|
||||||
|
boolean ephemeral = BooleanUtils.toBoolean(WebUtils.optional(request, "ephemeral",
|
||||||
|
String.valueOf(!ServerMode.CP.name().equals(switchDomain.getServerMode()))));
|
||||||
|
|
||||||
Instance instance = new Instance();
|
Instance instance = new Instance();
|
||||||
instance.setPort(Integer.parseInt(port));
|
instance.setPort(Integer.parseInt(port));
|
||||||
|
@ -16,14 +16,11 @@
|
|||||||
package com.alibaba.nacos.naming.controllers;
|
package com.alibaba.nacos.naming.controllers;
|
||||||
|
|
||||||
import com.alibaba.fastjson.TypeReference;
|
import com.alibaba.fastjson.TypeReference;
|
||||||
import com.alibaba.nacos.api.common.Constants;
|
|
||||||
import com.alibaba.nacos.api.naming.pojo.Instance;
|
|
||||||
import com.alibaba.nacos.common.util.IoUtils;
|
|
||||||
import com.alibaba.nacos.core.utils.WebUtils;
|
import com.alibaba.nacos.core.utils.WebUtils;
|
||||||
|
import com.alibaba.nacos.naming.cluster.transport.Serializer;
|
||||||
import com.alibaba.nacos.naming.consistency.Datum;
|
import com.alibaba.nacos.naming.consistency.Datum;
|
||||||
import com.alibaba.nacos.naming.consistency.KeyBuilder;
|
import com.alibaba.nacos.naming.consistency.KeyBuilder;
|
||||||
import com.alibaba.nacos.naming.consistency.ephemeral.partition.PartitionConsistencyServiceImpl;
|
import com.alibaba.nacos.naming.consistency.ephemeral.partition.PartitionConsistencyServiceImpl;
|
||||||
import com.alibaba.nacos.naming.cluster.transport.Serializer;
|
|
||||||
import com.alibaba.nacos.naming.core.Instances;
|
import com.alibaba.nacos.naming.core.Instances;
|
||||||
import com.alibaba.nacos.naming.exception.NacosException;
|
import com.alibaba.nacos.naming.exception.NacosException;
|
||||||
import com.alibaba.nacos.naming.misc.Loggers;
|
import com.alibaba.nacos.naming.misc.Loggers;
|
||||||
@ -37,7 +34,6 @@ import org.springframework.web.bind.annotation.RestController;
|
|||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -24,7 +24,9 @@ import com.alibaba.nacos.core.utils.WebUtils;
|
|||||||
import com.alibaba.nacos.naming.consistency.DataListener;
|
import com.alibaba.nacos.naming.consistency.DataListener;
|
||||||
import com.alibaba.nacos.naming.consistency.Datum;
|
import com.alibaba.nacos.naming.consistency.Datum;
|
||||||
import com.alibaba.nacos.naming.consistency.KeyBuilder;
|
import com.alibaba.nacos.naming.consistency.KeyBuilder;
|
||||||
import com.alibaba.nacos.naming.consistency.persistent.raft.*;
|
import com.alibaba.nacos.naming.consistency.persistent.raft.RaftConsistencyServiceImpl;
|
||||||
|
import com.alibaba.nacos.naming.consistency.persistent.raft.RaftCore;
|
||||||
|
import com.alibaba.nacos.naming.consistency.persistent.raft.RaftPeer;
|
||||||
import com.alibaba.nacos.naming.core.Instances;
|
import com.alibaba.nacos.naming.core.Instances;
|
||||||
import com.alibaba.nacos.naming.core.Service;
|
import com.alibaba.nacos.naming.core.Service;
|
||||||
import com.alibaba.nacos.naming.core.ServiceManager;
|
import com.alibaba.nacos.naming.core.ServiceManager;
|
||||||
|
@ -25,7 +25,6 @@ import com.alibaba.nacos.naming.cluster.ServerListManager;
|
|||||||
import com.alibaba.nacos.naming.core.*;
|
import com.alibaba.nacos.naming.core.*;
|
||||||
import com.alibaba.nacos.naming.exception.NacosException;
|
import com.alibaba.nacos.naming.exception.NacosException;
|
||||||
import com.alibaba.nacos.naming.misc.Loggers;
|
import com.alibaba.nacos.naming.misc.Loggers;
|
||||||
import com.alibaba.nacos.naming.misc.SwitchDomain;
|
|
||||||
import com.alibaba.nacos.naming.misc.UtilsAndCommons;
|
import com.alibaba.nacos.naming.misc.UtilsAndCommons;
|
||||||
import com.alibaba.nacos.naming.selector.LabelSelector;
|
import com.alibaba.nacos.naming.selector.LabelSelector;
|
||||||
import com.alibaba.nacos.naming.selector.NoneSelector;
|
import com.alibaba.nacos.naming.selector.NoneSelector;
|
||||||
@ -53,9 +52,6 @@ public class ServiceController {
|
|||||||
@Autowired
|
@Autowired
|
||||||
protected ServiceManager serviceManager;
|
protected ServiceManager serviceManager;
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private SwitchDomain switchDomain;
|
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private DistroMapper distroMapper;
|
private DistroMapper distroMapper;
|
||||||
|
|
||||||
|
@ -16,7 +16,6 @@
|
|||||||
package com.alibaba.nacos.naming.core;
|
package com.alibaba.nacos.naming.core;
|
||||||
|
|
||||||
import com.alibaba.fastjson.annotation.JSONField;
|
import com.alibaba.fastjson.annotation.JSONField;
|
||||||
import com.alibaba.nacos.api.naming.pojo.AbstractHealthChecker;
|
|
||||||
import com.alibaba.nacos.naming.healthcheck.HealthCheckReactor;
|
import com.alibaba.nacos.naming.healthcheck.HealthCheckReactor;
|
||||||
import com.alibaba.nacos.naming.healthcheck.HealthCheckStatus;
|
import com.alibaba.nacos.naming.healthcheck.HealthCheckStatus;
|
||||||
import com.alibaba.nacos.naming.healthcheck.HealthCheckTask;
|
import com.alibaba.nacos.naming.healthcheck.HealthCheckTask;
|
||||||
|
@ -40,12 +40,12 @@ import java.security.MessageDigest;
|
|||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Service of Nacos
|
* Service of Nacos server side
|
||||||
* <p>
|
* <p>
|
||||||
* We introduce a 'service --> cluster --> instance' model, in which service stores a list of clusters,
|
* We introduce a 'service --> cluster --> instance' model, in which service stores a list of clusters,
|
||||||
* which contains a list of instances.
|
* which contains a list of instances.
|
||||||
* <p>
|
* <p>
|
||||||
* Typically we put some common properties between instances to service level.
|
* This class inherits from Service in API module and stores some fields that do not expose to client.
|
||||||
*
|
*
|
||||||
* @author nkorange
|
* @author nkorange
|
||||||
*/
|
*/
|
||||||
|
@ -21,7 +21,6 @@ import com.alibaba.fastjson.JSONObject;
|
|||||||
import com.alibaba.nacos.api.exception.NacosException;
|
import com.alibaba.nacos.api.exception.NacosException;
|
||||||
import com.alibaba.nacos.naming.cluster.ServerListManager;
|
import com.alibaba.nacos.naming.cluster.ServerListManager;
|
||||||
import com.alibaba.nacos.naming.cluster.servers.Server;
|
import com.alibaba.nacos.naming.cluster.servers.Server;
|
||||||
import com.alibaba.nacos.naming.cluster.transport.Serializer;
|
|
||||||
import com.alibaba.nacos.naming.consistency.ConsistencyService;
|
import com.alibaba.nacos.naming.consistency.ConsistencyService;
|
||||||
import com.alibaba.nacos.naming.consistency.DataListener;
|
import com.alibaba.nacos.naming.consistency.DataListener;
|
||||||
import com.alibaba.nacos.naming.consistency.Datum;
|
import com.alibaba.nacos.naming.consistency.Datum;
|
||||||
@ -37,12 +36,15 @@ import org.springframework.stereotype.Component;
|
|||||||
import javax.annotation.PostConstruct;
|
import javax.annotation.PostConstruct;
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.*;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.locks.Condition;
|
import java.util.concurrent.LinkedBlockingDeque;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.concurrent.locks.Lock;
|
import java.util.concurrent.locks.Lock;
|
||||||
import java.util.concurrent.locks.ReentrantLock;
|
import java.util.concurrent.locks.ReentrantLock;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Core manager storing all services in Nacos
|
||||||
|
*
|
||||||
* @author nkorange
|
* @author nkorange
|
||||||
*/
|
*/
|
||||||
@Component
|
@Component
|
||||||
@ -54,21 +56,12 @@ public class ServiceManager implements DataListener<Service> {
|
|||||||
*/
|
*/
|
||||||
private Map<String, Map<String, Service>> serviceMap = new ConcurrentHashMap<>();
|
private Map<String, Map<String, Service>> serviceMap = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
private LinkedBlockingDeque<ServiceKey> toBeUpdatedDomsQueue = new LinkedBlockingDeque<>(1024 * 1024);
|
private LinkedBlockingDeque<ServiceKey> toBeUpdatedServicesQueue = new LinkedBlockingDeque<>(1024 * 1024);
|
||||||
|
|
||||||
private Synchronizer synchronizer = new DomainStatusSynchronizer();
|
private Synchronizer synchronizer = new DomainStatusSynchronizer();
|
||||||
|
|
||||||
/**
|
|
||||||
* thread pool core size
|
|
||||||
*/
|
|
||||||
private final static int DOMAIN_UPDATE_EXECUTOR_NUM = 2;
|
|
||||||
|
|
||||||
private final Lock lock = new ReentrantLock();
|
private final Lock lock = new ReentrantLock();
|
||||||
|
|
||||||
private Map<String, Condition> service2ConditionMap = new ConcurrentHashMap<>();
|
|
||||||
|
|
||||||
private Map<String, Lock> service2LockMap = new ConcurrentHashMap<>();
|
|
||||||
|
|
||||||
@Resource(name = "consistencyDelegate")
|
@Resource(name = "consistencyDelegate")
|
||||||
private ConsistencyService consistencyService;
|
private ConsistencyService consistencyService;
|
||||||
|
|
||||||
@ -84,29 +77,12 @@ public class ServiceManager implements DataListener<Service> {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private PushService pushService;
|
private PushService pushService;
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private Serializer serializer;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* thread pool that processes getting service detail from other server asynchronously
|
|
||||||
*/
|
|
||||||
private ExecutorService serviceUpdateExecutor
|
|
||||||
= Executors.newFixedThreadPool(DOMAIN_UPDATE_EXECUTOR_NUM, new ThreadFactory() {
|
|
||||||
@Override
|
|
||||||
public Thread newThread(Runnable r) {
|
|
||||||
Thread t = new Thread(r);
|
|
||||||
t.setName("com.alibaba.nacos.naming.service.update.http.handler");
|
|
||||||
t.setDaemon(true);
|
|
||||||
return t;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
@PostConstruct
|
@PostConstruct
|
||||||
public void init() {
|
public void init() {
|
||||||
|
|
||||||
UtilsAndCommons.DOMAIN_SYNCHRONIZATION_EXECUTOR.schedule(new ServiceReporter(), 60000, TimeUnit.MILLISECONDS);
|
UtilsAndCommons.DOMAIN_SYNCHRONIZATION_EXECUTOR.schedule(new ServiceReporter(), 60000, TimeUnit.MILLISECONDS);
|
||||||
|
|
||||||
UtilsAndCommons.DOMAIN_UPDATE_EXECUTOR.submit(new UpdatedDomainProcessor());
|
UtilsAndCommons.DOMAIN_UPDATE_EXECUTOR.submit(new UpdatedServiceProcessor());
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Loggers.SRV_LOG.info("listen for service meta change");
|
Loggers.SRV_LOG.info("listen for service meta change");
|
||||||
@ -123,10 +99,10 @@ public class ServiceManager implements DataListener<Service> {
|
|||||||
public void addUpdatedService2Queue(String namespaceId, String serviceName, String serverIP, String checksum) {
|
public void addUpdatedService2Queue(String namespaceId, String serviceName, String serverIP, String checksum) {
|
||||||
lock.lock();
|
lock.lock();
|
||||||
try {
|
try {
|
||||||
toBeUpdatedDomsQueue.offer(new ServiceKey(namespaceId, serviceName, serverIP, checksum), 5, TimeUnit.MILLISECONDS);
|
toBeUpdatedServicesQueue.offer(new ServiceKey(namespaceId, serviceName, serverIP, checksum), 5, TimeUnit.MILLISECONDS);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
toBeUpdatedDomsQueue.poll();
|
toBeUpdatedServicesQueue.poll();
|
||||||
toBeUpdatedDomsQueue.add(new ServiceKey(namespaceId, serviceName, serverIP, checksum));
|
toBeUpdatedServicesQueue.add(new ServiceKey(namespaceId, serviceName, serverIP, checksum));
|
||||||
Loggers.SRV_LOG.error("[DOMAIN-STATUS] Failed to add service to be updatd to queue.", e);
|
Loggers.SRV_LOG.error("[DOMAIN-STATUS] Failed to add service to be updatd to queue.", e);
|
||||||
} finally {
|
} finally {
|
||||||
lock.unlock();
|
lock.unlock();
|
||||||
@ -162,16 +138,12 @@ public class ServiceManager implements DataListener<Service> {
|
|||||||
if (oldDom != null) {
|
if (oldDom != null) {
|
||||||
oldDom.update(service);
|
oldDom.update(service);
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
addLockIfAbsent(UtilsAndCommons.assembleFullServiceName(service.getNamespaceId(), service.getName()));
|
|
||||||
putService(service);
|
putService(service);
|
||||||
service.init();
|
service.init();
|
||||||
consistencyService.listen(KeyBuilder.buildInstanceListKey(service.getNamespaceId(), service.getName(), true), service);
|
consistencyService.listen(KeyBuilder.buildInstanceListKey(service.getNamespaceId(), service.getName(), true), service);
|
||||||
consistencyService.listen(KeyBuilder.buildInstanceListKey(service.getNamespaceId(), service.getName(), false), service);
|
consistencyService.listen(KeyBuilder.buildInstanceListKey(service.getNamespaceId(), service.getName(), false), service);
|
||||||
Loggers.SRV_LOG.info("[NEW-SERVICE] {}", service.toJSON());
|
Loggers.SRV_LOG.info("[NEW-SERVICE] {}", service.toJSON());
|
||||||
}
|
}
|
||||||
wakeUp(UtilsAndCommons.assembleFullServiceName(service.getNamespaceId(), service.getName()));
|
|
||||||
|
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
Loggers.SRV_LOG.error("[NACOS-SERVICE] error while processing service update", e);
|
Loggers.SRV_LOG.error("[NACOS-SERVICE] error while processing service update", e);
|
||||||
}
|
}
|
||||||
@ -189,23 +161,20 @@ public class ServiceManager implements DataListener<Service> {
|
|||||||
consistencyService.remove(KeyBuilder.buildInstanceListKey(namespace, name, true));
|
consistencyService.remove(KeyBuilder.buildInstanceListKey(namespace, name, true));
|
||||||
consistencyService.remove(KeyBuilder.buildInstanceListKey(namespace, name, false));
|
consistencyService.remove(KeyBuilder.buildInstanceListKey(namespace, name, false));
|
||||||
consistencyService.unlisten(KeyBuilder.buildServiceMetaKey(namespace, name), service);
|
consistencyService.unlisten(KeyBuilder.buildServiceMetaKey(namespace, name), service);
|
||||||
Loggers.SRV_LOG.info("[DEAD-DOM] {}", service.toJSON());
|
Loggers.SRV_LOG.info("[DEAD-SERVICE] {}", service.toJSON());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class UpdatedDomainProcessor implements Runnable {
|
private class UpdatedServiceProcessor implements Runnable {
|
||||||
//get changed service from other server asynchronously
|
//get changed service from other server asynchronously
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
String serviceName = null;
|
ServiceKey serviceKey = null;
|
||||||
String serverIP = null;
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
while (true) {
|
while (true) {
|
||||||
ServiceKey serviceKey = null;
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
serviceKey = toBeUpdatedDomsQueue.take();
|
serviceKey = toBeUpdatedServicesQueue.take();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Loggers.EVT_LOG.error("[UPDATE-DOMAIN] Exception while taking item from LinkedBlockingDeque.");
|
Loggers.EVT_LOG.error("[UPDATE-DOMAIN] Exception while taking item from LinkedBlockingDeque.");
|
||||||
}
|
}
|
||||||
@ -213,14 +182,10 @@ public class ServiceManager implements DataListener<Service> {
|
|||||||
if (serviceKey == null) {
|
if (serviceKey == null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
GlobalExecutor.sumbitServiceUpdate(new ServiceUpdater(serviceKey));
|
||||||
serviceName = serviceKey.getServiceName();
|
|
||||||
serverIP = serviceKey.getServerIP();
|
|
||||||
|
|
||||||
serviceUpdateExecutor.execute(new ServiceUpdater(serviceKey.getNamespaceId(), serviceName, serverIP));
|
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Loggers.EVT_LOG.error("[UPDATE-DOMAIN] Exception while update service: {} from {}, error: {}", serviceName, serverIP, e);
|
Loggers.EVT_LOG.error("[UPDATE-DOMAIN] Exception while update service: {}", serviceKey, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -231,10 +196,10 @@ public class ServiceManager implements DataListener<Service> {
|
|||||||
String serviceName;
|
String serviceName;
|
||||||
String serverIP;
|
String serverIP;
|
||||||
|
|
||||||
public ServiceUpdater(String namespaceId, String serviceName, String serverIP) {
|
public ServiceUpdater(ServiceKey serviceKey) {
|
||||||
this.namespaceId = namespaceId;
|
this.namespaceId = serviceKey.getNamespaceId();
|
||||||
this.serviceName = serviceName;
|
this.serviceName = serviceKey.getServiceName();
|
||||||
this.serverIP = serverIP;
|
this.serverIP = serviceKey.getServerIP();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -357,7 +322,7 @@ public class ServiceManager implements DataListener<Service> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register an instance to a service.
|
* Register an instance to a service in AP mode.
|
||||||
* <p>
|
* <p>
|
||||||
* This method creates service or cluster silently if they don't exist.
|
* This method creates service or cluster silently if they don't exist.
|
||||||
*
|
*
|
||||||
@ -400,28 +365,9 @@ public class ServiceManager implements DataListener<Service> {
|
|||||||
serviceUpdated = true;
|
serviceUpdated = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// only local memory is updated:
|
||||||
if (serviceUpdated) {
|
if (serviceUpdated) {
|
||||||
Lock lock = addLockIfAbsent(UtilsAndCommons.assembleFullServiceName(namespaceId, serviceName));
|
putService(service);
|
||||||
Condition condition = addCondtion(UtilsAndCommons.assembleFullServiceName(namespaceId, serviceName));
|
|
||||||
|
|
||||||
final Service finalService = service;
|
|
||||||
GlobalExecutor.submit(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
try {
|
|
||||||
addOrReplaceService(finalService);
|
|
||||||
} catch (Exception e) {
|
|
||||||
Loggers.SRV_LOG.error("register or update service failed, service: {}", finalService, e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
try {
|
|
||||||
lock.lock();
|
|
||||||
condition.await(5000, TimeUnit.MILLISECONDS);
|
|
||||||
} finally {
|
|
||||||
lock.unlock();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (service.allIPs().contains(instance)) {
|
if (service.allIPs().contains(instance)) {
|
||||||
@ -437,6 +383,11 @@ public class ServiceManager implements DataListener<Service> {
|
|||||||
|
|
||||||
Service service = getService(namespaceId, serviceName);
|
Service service = getService(namespaceId, serviceName);
|
||||||
|
|
||||||
|
if (service == null) {
|
||||||
|
throw new NacosException(NacosException.INVALID_PARAM,
|
||||||
|
"service not found, namespace: " + namespaceId + ", service: " + serviceName);
|
||||||
|
}
|
||||||
|
|
||||||
Map<String, Instance> instanceMap = addIpAddresses(service, ephemeral, ips);
|
Map<String, Instance> instanceMap = addIpAddresses(service, ephemeral, ips);
|
||||||
|
|
||||||
Instances instances = new Instances();
|
Instances instances = new Instances();
|
||||||
@ -564,7 +515,6 @@ public class ServiceManager implements DataListener<Service> {
|
|||||||
serviceMap.get(service.getNamespaceId()).put(service.getName(), service);
|
serviceMap.get(service.getNamespaceId()).put(service.getName(), service);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public List<Service> searchServices(String namespaceId, String regex) {
|
public List<Service> searchServices(String namespaceId, String regex) {
|
||||||
List<Service> result = new ArrayList<>();
|
List<Service> result = new ArrayList<>();
|
||||||
for (Map.Entry<String, Service> entry : chooseServiceMap(namespaceId).entrySet()) {
|
for (Map.Entry<String, Service> entry : chooseServiceMap(namespaceId).entrySet()) {
|
||||||
@ -716,40 +666,11 @@ public class ServiceManager implements DataListener<Service> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void wakeUp(String key) {
|
|
||||||
|
|
||||||
Lock lock = service2LockMap.get(key);
|
|
||||||
Condition condition = service2ConditionMap.get(key);
|
|
||||||
|
|
||||||
try {
|
|
||||||
lock.lock();
|
|
||||||
condition.signalAll();
|
|
||||||
} catch (Exception ignore) {
|
|
||||||
} finally {
|
|
||||||
lock.unlock();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Lock addLockIfAbsent(String key) {
|
|
||||||
|
|
||||||
if (service2LockMap.containsKey(key)) {
|
|
||||||
return service2LockMap.get(key);
|
|
||||||
}
|
|
||||||
Lock lock = new ReentrantLock();
|
|
||||||
service2LockMap.put(key, lock);
|
|
||||||
return lock;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Condition addCondtion(String key) {
|
|
||||||
Condition condition = service2LockMap.get(key).newCondition();
|
|
||||||
service2ConditionMap.put(key, condition);
|
|
||||||
return condition;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class ServiceKey {
|
private static class ServiceKey {
|
||||||
private String namespaceId;
|
private String namespaceId;
|
||||||
private String serviceName;
|
private String serviceName;
|
||||||
private String serverIP;
|
private String serverIP;
|
||||||
|
private String checksum;
|
||||||
|
|
||||||
public String getChecksum() {
|
public String getChecksum() {
|
||||||
return checksum;
|
return checksum;
|
||||||
@ -767,13 +688,16 @@ public class ServiceManager implements DataListener<Service> {
|
|||||||
return namespaceId;
|
return namespaceId;
|
||||||
}
|
}
|
||||||
|
|
||||||
private String checksum;
|
|
||||||
|
|
||||||
public ServiceKey(String namespaceId, String serviceName, String serverIP, String checksum) {
|
public ServiceKey(String namespaceId, String serviceName, String serverIP, String checksum) {
|
||||||
this.namespaceId = namespaceId;
|
this.namespaceId = namespaceId;
|
||||||
this.serviceName = serviceName;
|
this.serviceName = serviceName;
|
||||||
this.serverIP = serverIP;
|
this.serverIP = serverIP;
|
||||||
this.checksum = checksum;
|
this.checksum = checksum;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return JSON.toJSONString(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,9 @@ package com.alibaba.nacos.naming.healthcheck;
|
|||||||
|
|
||||||
import com.alibaba.fastjson.annotation.JSONField;
|
import com.alibaba.fastjson.annotation.JSONField;
|
||||||
import com.alibaba.nacos.naming.boot.SpringContext;
|
import com.alibaba.nacos.naming.boot.SpringContext;
|
||||||
import com.alibaba.nacos.naming.core.*;
|
import com.alibaba.nacos.naming.core.Cluster;
|
||||||
|
import com.alibaba.nacos.naming.core.Instance;
|
||||||
|
import com.alibaba.nacos.naming.core.Service;
|
||||||
import com.alibaba.nacos.naming.misc.Loggers;
|
import com.alibaba.nacos.naming.misc.Loggers;
|
||||||
import com.alibaba.nacos.naming.misc.UtilsAndCommons;
|
import com.alibaba.nacos.naming.misc.UtilsAndCommons;
|
||||||
import com.alibaba.nacos.naming.push.PushService;
|
import com.alibaba.nacos.naming.push.PushService;
|
||||||
|
@ -18,7 +18,6 @@ package com.alibaba.nacos.naming.healthcheck;
|
|||||||
import com.alibaba.nacos.api.naming.pojo.AbstractHealthChecker;
|
import com.alibaba.nacos.api.naming.pojo.AbstractHealthChecker;
|
||||||
import com.alibaba.nacos.naming.core.Cluster;
|
import com.alibaba.nacos.naming.core.Cluster;
|
||||||
import com.alibaba.nacos.naming.core.Instance;
|
import com.alibaba.nacos.naming.core.Instance;
|
||||||
import com.alibaba.nacos.naming.core.Service;
|
|
||||||
import com.alibaba.nacos.naming.misc.SwitchDomain;
|
import com.alibaba.nacos.naming.misc.SwitchDomain;
|
||||||
import com.alibaba.nacos.naming.monitor.MetricsMonitor;
|
import com.alibaba.nacos.naming.monitor.MetricsMonitor;
|
||||||
import com.ning.http.client.AsyncCompletionHandler;
|
import com.ning.http.client.AsyncCompletionHandler;
|
||||||
|
@ -18,7 +18,6 @@ package com.alibaba.nacos.naming.healthcheck;
|
|||||||
import com.alibaba.nacos.api.naming.pojo.AbstractHealthChecker;
|
import com.alibaba.nacos.api.naming.pojo.AbstractHealthChecker;
|
||||||
import com.alibaba.nacos.naming.core.Cluster;
|
import com.alibaba.nacos.naming.core.Cluster;
|
||||||
import com.alibaba.nacos.naming.core.Instance;
|
import com.alibaba.nacos.naming.core.Instance;
|
||||||
import com.alibaba.nacos.naming.core.Service;
|
|
||||||
import com.alibaba.nacos.naming.misc.Loggers;
|
import com.alibaba.nacos.naming.misc.Loggers;
|
||||||
import com.alibaba.nacos.naming.misc.SwitchDomain;
|
import com.alibaba.nacos.naming.misc.SwitchDomain;
|
||||||
import com.alibaba.nacos.naming.monitor.MetricsMonitor;
|
import com.alibaba.nacos.naming.monitor.MetricsMonitor;
|
||||||
|
@ -36,6 +36,7 @@ public class RsInfo {
|
|||||||
private String ak;
|
private String ak;
|
||||||
private String cluster;
|
private String cluster;
|
||||||
private double weight;
|
private double weight;
|
||||||
|
private boolean ephemeral = true;
|
||||||
private Map<String, String> metadata;
|
private Map<String, String> metadata;
|
||||||
|
|
||||||
public String getServiceName() {
|
public String getServiceName() {
|
||||||
@ -126,6 +127,14 @@ public class RsInfo {
|
|||||||
this.weight = weight;
|
this.weight = weight;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isEphemeral() {
|
||||||
|
return ephemeral;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEphemeral(boolean ephemeral) {
|
||||||
|
this.ephemeral = ephemeral;
|
||||||
|
}
|
||||||
|
|
||||||
public Map<String, String> getMetadata() {
|
public Map<String, String> getMetadata() {
|
||||||
return metadata;
|
return metadata;
|
||||||
}
|
}
|
||||||
|
@ -19,8 +19,8 @@ import com.alibaba.nacos.naming.core.Cluster;
|
|||||||
import com.alibaba.nacos.naming.core.Instance;
|
import com.alibaba.nacos.naming.core.Instance;
|
||||||
import com.alibaba.nacos.naming.core.Service;
|
import com.alibaba.nacos.naming.core.Service;
|
||||||
import com.alibaba.nacos.naming.misc.Loggers;
|
import com.alibaba.nacos.naming.misc.Loggers;
|
||||||
import com.alibaba.nacos.naming.monitor.MetricsMonitor;
|
|
||||||
import com.alibaba.nacos.naming.misc.SwitchDomain;
|
import com.alibaba.nacos.naming.misc.SwitchDomain;
|
||||||
|
import com.alibaba.nacos.naming.monitor.MetricsMonitor;
|
||||||
import org.apache.commons.collections.CollectionUtils;
|
import org.apache.commons.collections.CollectionUtils;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
@ -15,10 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package com.alibaba.nacos.naming.misc;
|
package com.alibaba.nacos.naming.misc;
|
||||||
|
|
||||||
import java.util.concurrent.ScheduledExecutorService;
|
import java.util.concurrent.*;
|
||||||
import java.util.concurrent.ScheduledThreadPoolExecutor;
|
|
||||||
import java.util.concurrent.ThreadFactory;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author nacos
|
* @author nacos
|
||||||
@ -103,6 +100,20 @@ public class GlobalExecutor {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* thread pool that processes getting service detail from other server asynchronously
|
||||||
|
*/
|
||||||
|
private static ExecutorService serviceUpdateExecutor
|
||||||
|
= Executors.newFixedThreadPool(2, new ThreadFactory() {
|
||||||
|
@Override
|
||||||
|
public Thread newThread(Runnable r) {
|
||||||
|
Thread t = new Thread(r);
|
||||||
|
t.setName("com.alibaba.nacos.naming.service.update.http.handler");
|
||||||
|
t.setDaemon(true);
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
public static void submitDataSync(Runnable runnable) {
|
public static void submitDataSync(Runnable runnable) {
|
||||||
dataSyncExecutor.submit(runnable);
|
dataSyncExecutor.submit(runnable);
|
||||||
}
|
}
|
||||||
@ -147,4 +158,8 @@ public class GlobalExecutor {
|
|||||||
public static void submit(Runnable runnable) {
|
public static void submit(Runnable runnable) {
|
||||||
executorService.submit(runnable);
|
executorService.submit(runnable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void sumbitServiceUpdate(Runnable runnable) {
|
||||||
|
serviceUpdateExecutor.execute(runnable);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,6 @@ import org.apache.http.client.config.RequestConfig;
|
|||||||
import org.apache.http.client.entity.UrlEncodedFormEntity;
|
import org.apache.http.client.entity.UrlEncodedFormEntity;
|
||||||
import org.apache.http.client.methods.HttpPost;
|
import org.apache.http.client.methods.HttpPost;
|
||||||
import org.apache.http.client.methods.HttpPut;
|
import org.apache.http.client.methods.HttpPut;
|
||||||
import org.apache.http.entity.ByteArrayEntity;
|
|
||||||
import org.apache.http.entity.ContentType;
|
import org.apache.http.entity.ContentType;
|
||||||
import org.apache.http.entity.StringEntity;
|
import org.apache.http.entity.StringEntity;
|
||||||
import org.apache.http.impl.client.CloseableHttpClient;
|
import org.apache.http.impl.client.CloseableHttpClient;
|
||||||
|
@ -93,7 +93,9 @@ public class SwitchDomain implements DataListener<SwitchDomain> {
|
|||||||
|
|
||||||
public boolean enableAuthentication = false;
|
public boolean enableAuthentication = false;
|
||||||
|
|
||||||
public String overriddenServerStatus = null;
|
private String overriddenServerStatus = null;
|
||||||
|
|
||||||
|
private String serverMode = "MIXED";
|
||||||
|
|
||||||
public boolean isEnableAuthentication() {
|
public boolean isEnableAuthentication() {
|
||||||
return enableAuthentication;
|
return enableAuthentication;
|
||||||
@ -361,6 +363,14 @@ public class SwitchDomain implements DataListener<SwitchDomain> {
|
|||||||
this.overriddenServerStatus = overriddenServerStatus;
|
this.overriddenServerStatus = overriddenServerStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getServerMode() {
|
||||||
|
return serverMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setServerMode(String serverMode) {
|
||||||
|
this.serverMode = serverMode;
|
||||||
|
}
|
||||||
|
|
||||||
public void replace(SwitchDomain newSwitchDomain) {
|
public void replace(SwitchDomain newSwitchDomain) {
|
||||||
// TODO
|
// TODO
|
||||||
}
|
}
|
||||||
|
@ -66,4 +66,5 @@ public class SwitchEntry {
|
|||||||
|
|
||||||
public static final String READ_ENABLED = "readEnabled";
|
public static final String READ_ENABLED = "readEnabled";
|
||||||
public static final String OVERRIDDEN_SERVER_STATUS = "overriddenServerStatus";
|
public static final String OVERRIDDEN_SERVER_STATUS = "overriddenServerStatus";
|
||||||
|
public static final String SERVER_MODE = "serverMode";
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@ package com.alibaba.nacos.naming.misc;
|
|||||||
|
|
||||||
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.JSON;
|
||||||
import com.alibaba.nacos.api.exception.NacosException;
|
import com.alibaba.nacos.api.exception.NacosException;
|
||||||
|
import com.alibaba.nacos.naming.cluster.ServerMode;
|
||||||
import com.alibaba.nacos.naming.consistency.ConsistencyService;
|
import com.alibaba.nacos.naming.consistency.ConsistencyService;
|
||||||
import com.alibaba.nacos.naming.consistency.Datum;
|
import com.alibaba.nacos.naming.consistency.Datum;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
@ -356,6 +357,17 @@ public class SwitchManager {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (entry.equals(SwitchEntry.SERVER_MODE)) {
|
||||||
|
String mode = value;
|
||||||
|
switchDomain.setServerMode(ServerMode.valueOf(mode).name());
|
||||||
|
|
||||||
|
if (!debug) {
|
||||||
|
consistencyService.put(UtilsAndCommons.getSwitchDomainKey(), JSON.toJSONString(switchDomain));
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
throw new IllegalArgumentException("update entry not found: " + entry);
|
throw new IllegalArgumentException("update entry not found: " + entry);
|
||||||
} finally {
|
} finally {
|
||||||
lock.unlock();
|
lock.unlock();
|
||||||
|
@ -34,7 +34,6 @@ import java.util.Map;
|
|||||||
import java.util.concurrent.*;
|
import java.util.concurrent.*;
|
||||||
|
|
||||||
import static com.alibaba.nacos.common.util.SystemUtils.NACOS_HOME;
|
import static com.alibaba.nacos.common.util.SystemUtils.NACOS_HOME;
|
||||||
import static com.alibaba.nacos.common.util.SystemUtils.NACOS_HOME_KEY;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author nacos
|
* @author nacos
|
||||||
@ -119,6 +118,8 @@ public class UtilsAndCommons {
|
|||||||
|
|
||||||
public static final String DEFAULT_NAMESPACE_ID = "public";
|
public static final String DEFAULT_NAMESPACE_ID = "public";
|
||||||
|
|
||||||
|
public static final String DEFAULT_GROUP_NAME = "DEFAULT_GROUP";
|
||||||
|
|
||||||
public static final String DATA_BASE_DIR = NACOS_HOME + File.separator + "data" + File.separator + "naming";
|
public static final String DATA_BASE_DIR = NACOS_HOME + File.separator + "data" + File.separator + "naming";
|
||||||
|
|
||||||
public static final ScheduledExecutorService DOMAIN_SYNCHRONIZATION_EXECUTOR;
|
public static final ScheduledExecutorService DOMAIN_SYNCHRONIZATION_EXECUTOR;
|
||||||
|
@ -22,8 +22,8 @@ import com.alibaba.nacos.naming.misc.Loggers;
|
|||||||
import com.alibaba.nacos.naming.misc.SwitchDomain;
|
import com.alibaba.nacos.naming.misc.SwitchDomain;
|
||||||
import com.alibaba.nacos.naming.push.PushService;
|
import com.alibaba.nacos.naming.push.PushService;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
import org.springframework.scheduling.annotation.Scheduled;
|
import org.springframework.scheduling.annotation.Scheduled;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import javax.annotation.PostConstruct;
|
import javax.annotation.PostConstruct;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
@ -100,35 +100,35 @@ public class AuthFilter implements Filter {
|
|||||||
|
|
||||||
private Class<?> mapClass(String path) throws NacosException {
|
private Class<?> mapClass(String path) throws NacosException {
|
||||||
|
|
||||||
if (path.contains(UtilsAndCommons.NACOS_NAMING_INSTANCE_CONTEXT)) {
|
if (path.startsWith(UtilsAndCommons.NACOS_NAMING_CONTEXT + UtilsAndCommons.NACOS_NAMING_INSTANCE_CONTEXT)) {
|
||||||
return InstanceController.class;
|
return InstanceController.class;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (path.contains(UtilsAndCommons.NACOS_NAMING_SERVICE_CONTEXT)) {
|
if (path.startsWith(UtilsAndCommons.NACOS_NAMING_CONTEXT + UtilsAndCommons.NACOS_NAMING_SERVICE_CONTEXT)) {
|
||||||
return ServiceController.class;
|
return ServiceController.class;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (path.contains(UtilsAndCommons.NACOS_NAMING_CLUSTER_CONTEXT)) {
|
if (path.startsWith(UtilsAndCommons.NACOS_NAMING_CONTEXT + UtilsAndCommons.NACOS_NAMING_CLUSTER_CONTEXT)) {
|
||||||
return ClusterController.class;
|
return ClusterController.class;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (path.contains(UtilsAndCommons.NACOS_NAMING_OPERATOR_CONTEXT)) {
|
if (path.startsWith(UtilsAndCommons.NACOS_NAMING_CONTEXT + UtilsAndCommons.NACOS_NAMING_OPERATOR_CONTEXT)) {
|
||||||
return OperatorController.class;
|
return OperatorController.class;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (path.contains(UtilsAndCommons.NACOS_NAMING_CATALOG_CONTEXT)) {
|
if (path.startsWith(UtilsAndCommons.NACOS_NAMING_CONTEXT + UtilsAndCommons.NACOS_NAMING_CATALOG_CONTEXT)) {
|
||||||
return CatalogController.class;
|
return CatalogController.class;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (path.contains(UtilsAndCommons.NACOS_NAMING_HEALTH_CONTEXT)) {
|
if (path.startsWith(UtilsAndCommons.NACOS_NAMING_CONTEXT + UtilsAndCommons.NACOS_NAMING_HEALTH_CONTEXT)) {
|
||||||
return HealthController.class;
|
return HealthController.class;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (path.contains(UtilsAndCommons.NACOS_NAMING_RAFT_CONTEXT)) {
|
if (path.startsWith(UtilsAndCommons.NACOS_NAMING_CONTEXT + UtilsAndCommons.NACOS_NAMING_RAFT_CONTEXT)) {
|
||||||
return RaftController.class;
|
return RaftController.class;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (path.contains(UtilsAndCommons.NACOS_NAMING_PARTITION_CONTEXT)) {
|
if (path.startsWith(UtilsAndCommons.NACOS_NAMING_CONTEXT + UtilsAndCommons.NACOS_NAMING_PARTITION_CONTEXT)) {
|
||||||
return PartitionController.class;
|
return PartitionController.class;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,8 +19,6 @@ import org.springframework.boot.web.servlet.FilterRegistrationBean;
|
|||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
import javax.servlet.Filter;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author nkorange
|
* @author nkorange
|
||||||
*/
|
*/
|
||||||
|
@ -16,8 +16,10 @@
|
|||||||
package com.alibaba.nacos.naming.web;
|
package com.alibaba.nacos.naming.web;
|
||||||
|
|
||||||
import com.alibaba.nacos.common.util.HttpMethod;
|
import com.alibaba.nacos.common.util.HttpMethod;
|
||||||
|
import com.alibaba.nacos.naming.cluster.ServerMode;
|
||||||
import com.alibaba.nacos.naming.cluster.ServerStatus;
|
import com.alibaba.nacos.naming.cluster.ServerStatus;
|
||||||
import com.alibaba.nacos.naming.cluster.ServerStatusManager;
|
import com.alibaba.nacos.naming.cluster.ServerStatusManager;
|
||||||
|
import com.alibaba.nacos.naming.misc.SwitchDomain;
|
||||||
import com.alibaba.nacos.naming.misc.UtilsAndCommons;
|
import com.alibaba.nacos.naming.misc.UtilsAndCommons;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
@ -26,6 +28,8 @@ import javax.servlet.*;
|
|||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.net.URISyntaxException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Filter incoming traffic to refuse or revise unexpected requests
|
* Filter incoming traffic to refuse or revise unexpected requests
|
||||||
@ -38,12 +42,33 @@ public class TrafficReviseFilter implements Filter {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private ServerStatusManager serverStatusManager;
|
private ServerStatusManager serverStatusManager;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private SwitchDomain switchDomain;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {
|
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {
|
||||||
|
|
||||||
HttpServletRequest req = (HttpServletRequest) request;
|
HttpServletRequest req = (HttpServletRequest) request;
|
||||||
HttpServletResponse resp = (HttpServletResponse) response;
|
HttpServletResponse resp = (HttpServletResponse) response;
|
||||||
|
|
||||||
|
// in AP mode, service and cluster cannot be edited:
|
||||||
|
try {
|
||||||
|
String path = new URI(req.getRequestURI()).getPath();
|
||||||
|
if (ServerMode.AP.name().equals(switchDomain.getServerMode()) && !HttpMethod.GET.equals(req.getMethod())) {
|
||||||
|
if (path.startsWith(UtilsAndCommons.NACOS_NAMING_CONTEXT + UtilsAndCommons.NACOS_NAMING_SERVICE_CONTEXT)
|
||||||
|
|| path.startsWith(UtilsAndCommons.NACOS_NAMING_CONTEXT + UtilsAndCommons.NACOS_NAMING_CLUSTER_CONTEXT)) {
|
||||||
|
resp.getWriter().write("server in AP mode, request: " + req.getMethod() + " " + path + " not permitted");
|
||||||
|
resp.setStatus(HttpServletResponse.SC_FORBIDDEN);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (URISyntaxException e) {
|
||||||
|
resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
|
||||||
|
"Server parse url failed," + UtilsAndCommons.getAllExceptionMsg(e));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// if server is UP:
|
// if server is UP:
|
||||||
if (serverStatusManager.getServerStatus() == ServerStatus.UP) {
|
if (serverStatusManager.getServerStatus() == ServerStatus.UP) {
|
||||||
filterChain.doFilter(req, resp);
|
filterChain.doFilter(req, resp);
|
||||||
|
@ -15,9 +15,9 @@
|
|||||||
*/
|
*/
|
||||||
package com.alibaba.nacos.naming;
|
package com.alibaba.nacos.naming;
|
||||||
|
|
||||||
import com.alibaba.nacos.naming.consistency.persistent.raft.RaftPeerSet;
|
|
||||||
import com.alibaba.nacos.naming.consistency.persistent.raft.RaftCore;
|
import com.alibaba.nacos.naming.consistency.persistent.raft.RaftCore;
|
||||||
import com.alibaba.nacos.naming.consistency.persistent.raft.RaftPeer;
|
import com.alibaba.nacos.naming.consistency.persistent.raft.RaftPeer;
|
||||||
|
import com.alibaba.nacos.naming.consistency.persistent.raft.RaftPeerSet;
|
||||||
import com.alibaba.nacos.naming.core.ServiceManager;
|
import com.alibaba.nacos.naming.core.ServiceManager;
|
||||||
import com.alibaba.nacos.naming.misc.NetUtils;
|
import com.alibaba.nacos.naming.misc.NetUtils;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
|
@ -43,7 +43,6 @@ import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.locks.ReentrantLock;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author nkorange
|
* @author nkorange
|
||||||
@ -87,10 +86,6 @@ public class InstanceControllerTest extends BaseTest {
|
|||||||
|
|
||||||
Mockito.when(domainsManager.getService(UtilsAndCommons.DEFAULT_NAMESPACE_ID, "nacos.test.1")).thenReturn(domain);
|
Mockito.when(domainsManager.getService(UtilsAndCommons.DEFAULT_NAMESPACE_ID, "nacos.test.1")).thenReturn(domain);
|
||||||
|
|
||||||
Mockito.when(domainsManager.addLockIfAbsent(
|
|
||||||
UtilsAndCommons.assembleFullServiceName(UtilsAndCommons.DEFAULT_NAMESPACE_ID, "nacos.test.1")))
|
|
||||||
.thenReturn(new ReentrantLock());
|
|
||||||
|
|
||||||
MockHttpServletRequestBuilder builder =
|
MockHttpServletRequestBuilder builder =
|
||||||
MockMvcRequestBuilders.put("/naming/instance")
|
MockMvcRequestBuilders.put("/naming/instance")
|
||||||
.param("serviceName", "nacos.test.1")
|
.param("serviceName", "nacos.test.1")
|
||||||
|
Loading…
Reference in New Issue
Block a user