#745 Support multiple server modes

This commit is contained in:
nkorange 2019-02-11 14:59:12 +08:00
parent 4fe7c3d3b8
commit 194387b583
40 changed files with 233 additions and 189 deletions

View File

@ -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";
} }

View File

@ -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 {

View File

@ -27,7 +27,7 @@ import java.util.List;
/** /**
* Naming Service * Naming Service
* *
* @author dungu.zpf * @author nkorange
*/ */
public interface NamingService { public interface NamingService {

View File

@ -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 {
} }

View File

@ -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 {

View File

@ -21,7 +21,7 @@ import java.util.Map;
/** /**
* Cluster * Cluster
* *
* @author dungu.zpf * @author nkorange
*/ */
public class Cluster { public class Cluster {

View File

@ -22,7 +22,7 @@ import java.util.List;
/** /**
* ListView * ListView
* *
* @author dungu.zpf * @author nkorange
*/ */
public class ListView<T> { public class ListView<T> {

View File

@ -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;

View File

@ -26,7 +26,7 @@ import java.util.List;
/** /**
* ServiceInfo * ServiceInfo
* *
* @author dungu.zpf * @author nkorange
*/ */
public class ServiceInfo { public class ServiceInfo {

View File

@ -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;

View File

@ -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
}

View File

@ -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());

View File

@ -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;
/** /**

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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));

View File

@ -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;
/** /**

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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
*/ */

View File

@ -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);
}
} }
} }

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;
} }

View File

@ -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;

View File

@ -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);
}
} }

View File

@ -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;

View File

@ -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
} }

View File

@ -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";
} }

View File

@ -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();

View File

@ -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;

View File

@ -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;

View File

@ -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;
} }

View File

@ -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
*/ */

View File

@ -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);

View File

@ -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;

View File

@ -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")