Merge branch 'develop' into master

This commit is contained in:
mingyixu 2019-01-15 17:00:43 +08:00 committed by GitHub
commit a689f0f694
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
230 changed files with 8959 additions and 6277 deletions

2
.gitignore vendored
View File

@ -5,7 +5,9 @@
target
.project
.idea
.vscode
.DS_Store
.factorypath
/logs
*.iml
node_modules

View File

@ -16,7 +16,7 @@
<parent>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-all</artifactId>
<version>0.7.0</version>
<version>0.8.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -31,7 +31,7 @@ import com.alibaba.nacos.api.naming.NamingService;
public class NacosFactory {
/**
* Create config
* Create config service
*
* @param properties init param
* @return config
@ -42,7 +42,7 @@ public class NacosFactory {
}
/**
* Create config
* Create config service
*
* @param serverAddr server list
* @return config
@ -53,7 +53,7 @@ public class NacosFactory {
}
/**
* Create Naming
* Create naming service
*
* @param serverAddr server list
* @return Naming
@ -64,7 +64,7 @@ public class NacosFactory {
}
/**
* Create Naming
* Create naming service
*
* @param properties init param
* @return Naming

View File

@ -16,20 +16,30 @@
package com.alibaba.nacos.api;
/**
* properties key
* Property Key Const
*
* @author Nacos
*/
public class PropertyKeyConst {
public final static String ENDPOINT = "endpoint";
public final static String NAMESPACE = "namespace";
public final static String ACCESS_KEY = "accessKey";
public final static String SECRET_KEY = "secretKey";
public final static String SERVER_ADDR = "serverAddr";
public final static String CONTEXT_PATH = "contextPath";
public final static String CLUSTER_NAME = "clusterName";
public final static String ENCODE = "encode";
public final static String NAMING_LOAD_CACHE_AT_START = "namingLoadCacheAtStart";
public final static String NAMING_CLIENT_BEAT_THREAD_COUNT = "namingClientBeatThreadCount";
public final static String NAMING_POLLING_THREAD_COUNT = "namingPollingThreadCount";
}

View File

@ -19,6 +19,7 @@ import java.util.Map;
/**
* @author <a href="mailto:zpf.073@gmail.com">nkorange</a>
* @since 0.7.0
*/
public class Entity {

View File

@ -17,6 +17,7 @@ package com.alibaba.nacos.api.cmdb.pojo;
/**
* @author <a href="mailto:zpf.073@gmail.com">nkorange</a>
* @since 0.7.0
*/
public class EntityEvent {

View File

@ -17,6 +17,7 @@ package com.alibaba.nacos.api.cmdb.pojo;
/**
* @author <a href="mailto:zpf.073@gmail.com">nkorange</a>
* @since 0.7.0
*/
public enum EntityEventType {
/**

View File

@ -19,6 +19,7 @@ import java.util.Set;
/**
* @author <a href="mailto:zpf.073@gmail.com">nkorange</a>
* @since 0.7.0
*/
public class Label {

View File

@ -17,14 +17,15 @@ package com.alibaba.nacos.api.cmdb.pojo;
/**
* @author <a href="mailto:zpf.073@gmail.com">nkorange</a>
* @since 0.7.0
*/
public enum PreservedEntityTypes {
/**
*
* Ip
*/
ip,
/**
*
* Service
*/
service
}

View File

@ -27,6 +27,7 @@ import java.util.Set;
* Service to visit CMDB store
*
* @author <a href="mailto:zpf.073@gmail.com">nkorange</a>
* @since 0.7.0
*/
public interface CmdbService {

View File

@ -85,11 +85,6 @@ public class Constants {
*/
public static final int ONCE_TIMEOUT = 2000;
/**
* millisecond
*/
public static final int CONN_TIMEOUT = 2000;
/**
* millisecond
*/
@ -114,7 +109,7 @@ public class Constants {
public static final String WORD_SEPARATOR = Character.toString((char)2);
public static final String LONGPULLING_LINE_SEPARATOR = "\r\n";
public static final String LONGPOLLING_LINE_SEPARATOR = "\r\n";
public static final String CLIENT_APPNAME_HEADER = "Client-AppName";
public static final String CLIENT_REQUEST_TS_HEADER = "Client-RequestTS";
@ -127,4 +122,10 @@ public class Constants {
public static final String NAMING_HTTP_HEADER_SPILIER = "\\|";
public static final String NAMING_DEFAULT_CLUSTER_NAME = "DEFAULT";
public static final String REQUEST_PARAM_NAMESPACE_ID = "namespaceId";
public static final String REQUEST_PARAM_DEFAULT_NAMESPACE_ID = "public";
public static final String REQUEST_PARAM_SERVICE_NAME = "serviceName";
public static final String REQUEST_PARAM_GROUP = "group";
public static final String REQUEST_PARAM_DEFAULT_GROUP = "DEFAULT_GROUP";
}

View File

@ -32,14 +32,14 @@ public class ConfigFactory {
* Create Config
*
* @param properties init param
* @return Config
* @return ConfigService
* @throws NacosException Exception
*/
public static ConfigService createConfigService(Properties properties) throws NacosException {
try {
Class<?> driverImplClass = Class.forName("com.alibaba.nacos.client.config.NacosConfigService");
Constructor constructor = driverImplClass.getConstructor(Properties.class);
ConfigService vendorImpl = (ConfigService)constructor.newInstance(properties);
ConfigService vendorImpl = (ConfigService) constructor.newInstance(properties);
return vendorImpl;
} catch (Throwable e) {
throw new NacosException(-400, e.getMessage());
@ -49,21 +49,14 @@ public class ConfigFactory {
/**
* Create Config
*
* @param ServerAddr serverlist
* @param serverAddr serverList
* @return Config
* @throws NacosException Exception
* @throws ConfigService Exception
*/
public static ConfigService createConfigService(String serverAddr) throws NacosException {
Properties properties = new Properties();
properties.put(PropertyKeyConst.SERVER_ADDR, serverAddr);
try {
Class<?> driverImplClass = Class.forName("com.alibaba.nacos.client.config.NacosConfigService");
Constructor constructor = driverImplClass.getConstructor(Properties.class);
ConfigService vendorImpl = (ConfigService)constructor.newInstance(properties);
return vendorImpl;
} catch (Throwable e) {
throw new NacosException(-400, e.getMessage());
}
return createConfigService(properties);
}
}

View File

@ -19,17 +19,17 @@ import com.alibaba.nacos.api.config.listener.Listener;
import com.alibaba.nacos.api.exception.NacosException;
/**
* Config Interface
* Config Service Interface
*
* @author Nacos
*/
public interface ConfigService {
/**
* Get Configuration
* Get config
*
* @param dataId Config ID
* @param group Config Group
* @param dataId dataId
* @param group group
* @param timeoutMs read timeout
* @return config value
* @throws NacosException NacosException
@ -37,50 +37,52 @@ public interface ConfigService {
String getConfig(String dataId, String group, long timeoutMs) throws NacosException;
/**
* Add a listener to the configuration, after the server to modify the configuration, the client will use the
* incoming listener callback. Recommended asynchronous processing, the application can implement the getExecutor
* method in the ManagerListener, provide a thread pool of execution. If provided, use the main thread callback, May
* block other configurations or be blocked by other configurations.
* Add a listener to the configuration, after the server modified the
* configuration, the client will use the incoming listener callback.
* Recommended asynchronous processing, the application can implement the
* getExecutor method in the ManagerListener, provide a thread pool of
* execution. If provided, use the main thread callback, May block other
* configurations or be blocked by other configurations.
*
* @param dataId Config ID
* @param group Config Group
* @param dataId dataId
* @param group group
* @param listener listener
* @throws NacosException NacosException
*/
void addListener(String dataId, String group, Listener listener) throws NacosException;
/**
* publish config.
* Publish config.
*
* @param dataId Config ID
* @param group Config Group
* @param content Config Content
* @param dataId dataId
* @param group group
* @param content content
* @return Whether publish
* @throws NacosException NacosException
*/
boolean publishConfig(String dataId, String group, String content) throws NacosException;
/**
* Remove Config
* Remove config
*
* @param dataId Config ID
* @param group Config Group
* @param dataId dataId
* @param group group
* @return whether remove
* @throws NacosException NacosException
*/
boolean removeConfig(String dataId, String group) throws NacosException;
/**
* Remove Listener
* Remove listener
*
* @param dataId Config ID
* @param group Config Group
* @param dataId dataId
* @param group group
* @param listener listener
*/
void removeListener(String dataId, String group, Listener listener);
/**
* server health info
* Get server status
*
* @return whether health
*/

View File

@ -16,7 +16,7 @@
package com.alibaba.nacos.api.config.convert;
/**
* Nacos Configuration content Converter
* Nacos Config Converter
*
* @param <T> the target type that wanted
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
@ -25,7 +25,7 @@ package com.alibaba.nacos.api.config.convert;
public interface NacosConfigConverter<T> {
/**
* Can convert to be target type or not
* can convert to be target type or not
*
* @param targetType the type of target
* @return If can , return <code>true</code>, or <code>false</code>
@ -33,9 +33,9 @@ public interface NacosConfigConverter<T> {
boolean canConvert(Class<T> targetType);
/**
* Convert the Naocs's configuration of type S to target type T.
* convert the Naocs's config of type S to target type T.
*
* @param config the Naocs's configuration to convert, which must be an instance of S (never {@code null})
* @param config the Naocs's config to convert, which must be an instance of S (never {@code null})
* @return the converted object, which must be an instance of T (potentially {@code null})
*/
T convert(String config);

View File

@ -22,18 +22,18 @@ package com.alibaba.nacos.api.config.filter;
*/
public interface IConfigContext {
/**
* get context by key
* Get context param by key
*
* @param key
* @return context
*/
public Object getParameter(String key);
Object getParameter(String key);
/**
* set context
* Set context param
*
* @param key key
* @param value value
*/
public void setParameter(String key, Object value);
void setParameter(String key, Object value);
}

View File

@ -24,7 +24,7 @@ import com.alibaba.nacos.api.exception.NacosException;
*/
public interface IConfigFilter {
/**
* Init Fuction
* Init
*
* @param filterConfig Filter Config
*/
@ -39,7 +39,7 @@ public interface IConfigFilter {
* @throws NacosException exception
*/
void doFilter(IConfigRequest request, IConfigResponse response, IConfigFilterChain filterChain)
throws NacosException;
throws NacosException;
/**
* deploy
@ -47,16 +47,16 @@ public interface IConfigFilter {
void deploy();
/**
* order
* Get order
*
* @return
* @return order number
*/
int getOrder();
/**
* filterName
* Get filterName
*
* @return
* @return filter name
*/
String getFilterName();

View File

@ -30,6 +30,6 @@ public interface IConfigFilterChain {
* @param response response
* @throws NacosException NacosException
*/
public void doFilter(IConfigRequest request, IConfigResponse response) throws NacosException;
void doFilter(IConfigRequest request, IConfigResponse response) throws NacosException;
}

View File

@ -27,13 +27,13 @@ public interface IConfigRequest {
* @param key key
* @return value
*/
public Object getParameter(String key);
Object getParameter(String key);
/**
* get config context
*
* @return
*/
public IConfigContext getConfigContext();
IConfigContext getConfigContext();
}

View File

@ -27,13 +27,13 @@ public interface IConfigResponse {
* @param key key
* @return value
*/
public Object getParameter(String key);
Object getParameter(String key);
/**
* get context
* Get config context
*
* @return configContext
*/
public IConfigContext getConfigContext();
IConfigContext getConfigContext();
}

View File

@ -27,14 +27,14 @@ public interface IFilterConfig {
*
* @return
*/
public String getFilterName();
String getFilterName();
/**
* get param
* Get init param
*
* @param name
* @return param
*/
public Object getInitParameter(String name);
Object getInitParameter(String name);
}

View File

@ -26,8 +26,9 @@ import java.util.concurrent.Executor;
public abstract class AbstractListener implements Listener {
/**
* use default Executor
* Use default executor
*/
@Override
public Executor getExecutor() {
return null;
}

View File

@ -18,7 +18,7 @@ package com.alibaba.nacos.api.config.listener;
import java.util.concurrent.Executor;
/**
* shared listener
* Shared Listener
*
* @author Nacos
*/

View File

@ -25,16 +25,16 @@ import java.util.concurrent.Executor;
public interface Listener {
/**
* Executor to excute this receive
* Get executor for execute this receive
*
* @return Executor
*/
public Executor getExecutor();
Executor getExecutor();
/**
* 接收配置信息
* Receive config info
*
* @param configInfo 配置值
* @param configInfo config info
*/
public void receiveConfigInfo(final String configInfo);
void receiveConfigInfo(final String configInfo);
}

View File

@ -21,7 +21,9 @@ import java.util.Properties;
import com.alibaba.nacos.api.exception.NacosException;
/**
* @author <a href="mailto:zpf.073@gmail.com">nkorange</a>
* Naming Factory
*
* @author dungu.zpf
*/
public class NamingFactory {

View File

@ -25,12 +25,14 @@ import com.alibaba.nacos.api.selector.AbstractSelector;
import java.util.List;
/**
* @author <a href="mailto:zpf.073@gmail.com">nkorange</a>
* Naming Service
*
* @author dungu.zpf
*/
public interface NamingService {
/**
* Register a instance to service
* register a instance to service
*
* @param serviceName name of service
* @param ip instance ip
@ -40,7 +42,7 @@ public interface NamingService {
void registerInstance(String serviceName, String ip, int port) throws NacosException;
/**
* Register a instance to service with specified cluster name
* register a instance to service with specified cluster name
*
* @param serviceName name of service
* @param ip instance ip
@ -51,7 +53,7 @@ public interface NamingService {
void registerInstance(String serviceName, String ip, int port, String clusterName) throws NacosException;
/**
* Register a instance to service with specified instance properties
* register a instance to service with specified instance properties
*
* @param serviceName name of service
* @param instance instance to register
@ -60,7 +62,7 @@ public interface NamingService {
void registerInstance(String serviceName, Instance instance) throws NacosException;
/**
* Deregister instance from a service
* deregister instance from a service
*
* @param serviceName name of service
* @param ip instance ip
@ -70,7 +72,7 @@ public interface NamingService {
void deregisterInstance(String serviceName, String ip, int port) throws NacosException;
/**
* Deregister instance with specified cluster name from a service
* deregister instance with specified cluster name from a service
*
* @param serviceName name of service
* @param ip instance ip
@ -81,7 +83,7 @@ public interface NamingService {
void deregisterInstance(String serviceName, String ip, int port, String clusterName) throws NacosException;
/**
* Get all instances of a service
* get all instances of a service
*
* @param serviceName name of service
* @return A list of instance
@ -89,6 +91,16 @@ public interface NamingService {
*/
List<Instance> getAllInstances(String serviceName) throws NacosException;
/**
* Get all instances of a service
*
* @param serviceName name of service
* @param subscribe if subscribe the service
* @return A list of instance
* @throws NacosException
*/
List<Instance> getAllInstances(String serviceName, boolean subscribe) throws NacosException;
/**
* Get all instances within specified clusters of a service
*
@ -99,6 +111,17 @@ public interface NamingService {
*/
List<Instance> getAllInstances(String serviceName, List<String> clusters) throws NacosException;
/**
* Get all instances within specified clusters of a service
*
* @param serviceName name of service
* @param clusters list of cluster
* @param subscribe if subscribe the service
* @return A list of qualified instance
* @throws NacosException
*/
List<Instance> getAllInstances(String serviceName, List<String> clusters, boolean subscribe) throws NacosException;
/**
* Get qualified instances of service
*
@ -109,6 +132,17 @@ public interface NamingService {
*/
List<Instance> selectInstances(String serviceName, boolean healthy) throws NacosException;
/**
* Get qualified instances of service
*
* @param serviceName name of service
* @param healthy a flag to indicate returning healthy or unhealthy instances
* @param subscribe if subscribe the service
* @return A qualified list of instance
* @throws NacosException
*/
List<Instance> selectInstances(String serviceName, boolean healthy, boolean subscribe) throws NacosException;
/**
* Get qualified instances within specified clusters of service
*
@ -120,6 +154,18 @@ public interface NamingService {
*/
List<Instance> selectInstances(String serviceName, List<String> clusters, boolean healthy) throws NacosException;
/**
* Get qualified instances within specified clusters of service
*
* @param serviceName name of service
* @param clusters list of cluster
* @param healthy a flag to indicate returning healthy or unhealthy instances
* @param subscribe if subscribe the service
* @return A qualified list of instance
* @throws NacosException
*/
List<Instance> selectInstances(String serviceName, List<String> clusters, boolean healthy, boolean subscribe) throws NacosException;
/**
* Select one healthy instance of service using predefined load balance strategy
*
@ -129,6 +175,16 @@ public interface NamingService {
*/
Instance selectOneHealthyInstance(String serviceName) throws NacosException;
/**
* select one healthy instance of service using predefined load balance strategy
*
* @param serviceName name of service
* @param subscribe if subscribe the service
* @return qualified instance
* @throws NacosException
*/
Instance selectOneHealthyInstance(String serviceName, boolean subscribe) throws NacosException;
/**
* Select one healthy instance of service using predefined load balance strategy
*
@ -139,6 +195,17 @@ public interface NamingService {
*/
Instance selectOneHealthyInstance(String serviceName, List<String> clusters) throws NacosException;
/**
* Select one healthy instance of service using predefined load balance strategy
*
* @param serviceName name of service
* @param clusters a list of clusters should the instance belongs to
* @param subscribe if subscribe the service
* @return qualified instance
* @throws NacosException
*/
Instance selectOneHealthyInstance(String serviceName, List<String> clusters, boolean subscribe) throws NacosException;
/**
* Subscribe service to receive events of instances alteration
*
@ -149,7 +216,7 @@ public interface NamingService {
void subscribe(String serviceName, EventListener listener) throws NacosException;
/**
* Subscribe service to receive events of instances alteration
* subscribe service to receive events of instances alteration
*
* @param serviceName name of service
* @param clusters list of cluster
@ -159,7 +226,7 @@ public interface NamingService {
void subscribe(String serviceName, List<String> clusters, EventListener listener) throws NacosException;
/**
* Unsubscribe event listener of service
* unsubscribe event listener of service
*
* @param serviceName name of service
* @param listener event listener
@ -168,7 +235,7 @@ public interface NamingService {
void unsubscribe(String serviceName, EventListener listener) throws NacosException;
/**
* Unsubscribe event listener of service
* unsubscribe event listener of service
*
* @param serviceName name of service
* @param clusters list of cluster
@ -178,7 +245,7 @@ public interface NamingService {
void unsubscribe(String serviceName, List<String> clusters, EventListener listener) throws NacosException;
/**
* Get all service names from server
* get all service names from server
*
* @param pageNo page index
* @param pageSize page size
@ -188,13 +255,14 @@ public interface NamingService {
ListView<String> getServicesOfServer(int pageNo, int pageSize) throws NacosException;
/**
* Get all service names from server
* Get all subscribed services of current client
*
* @param pageNo page index
* @param pageSize page size
* @param selector selector to filter the resource
* @return list of service names
* @throws NacosException
* @since 0.7.0
*/
ListView<String> getServicesOfServer(int pageNo, int pageSize, AbstractSelector selector) throws NacosException;
@ -207,7 +275,7 @@ public interface NamingService {
List<ServiceInfo> getSubscribeServices() throws NacosException;
/**
* Get server health status
* get server health status
*
* @return is server healthy
*/

View File

@ -16,8 +16,9 @@
package com.alibaba.nacos.api.naming.listener;
/**
* event interface
* @author <a href="mailto:zpf.073@gmail.com">nkorange</a>
* Event Interface
*
* @author dungu.zpf
*/
public interface Event {
}

View File

@ -16,7 +16,7 @@
package com.alibaba.nacos.api.naming.listener;
/**
* event listener
* Event Listener
*
* @author Nacos
*/

View File

@ -20,7 +20,9 @@ import java.util.List;
import com.alibaba.nacos.api.naming.pojo.Instance;
/**
* @author <a href="mailto:zpf.073@gmail.com">nkorange</a>
* Naming Event
*
* @author dungu.zpf
*/
public class NamingEvent implements Event {

View File

@ -19,7 +19,9 @@ import java.util.HashMap;
import java.util.Map;
/**
* @author <a href="mailto:zpf.073@gmail.com">nkorange</a>
* Cluster
*
* @author dungu.zpf
*/
public class Cluster {

View File

@ -22,32 +22,34 @@ import java.util.HashMap;
import java.util.Map;
/**
* @author <a href="mailto:zpf.073@gmail.com">nkorange</a>
* Instance
*
* @author dungu.zpf
*/
public class Instance {
/**
* Unique ID of this instance.
* unique id of this instance.
*/
private String instanceId;
/**
* Instance ip
* instance ip
*/
private String ip;
/**
* Instance port
* instance port
*/
private int port;
/**
* Instance weight
* instance weight
*/
private double weight = 1.0D;
/**
* Instance health status
* instance health status
*/
@JSONField(name = "valid")
private boolean healthy = true;
@ -55,17 +57,17 @@ public class Instance {
private boolean enabled = true;
/**
* Cluster information of instance
* cluster information of instance
*/
private String clusterName;
/**
* Service name of instance
* Service information of instance
*/
private String serviceName;
/**
* User extended attributes
* user extended attributes
*/
private Map<String, String> metadata = new HashMap<String, String>();

View File

@ -20,7 +20,9 @@ import com.alibaba.fastjson.JSON;
import java.util.List;
/**
* @author <a href="mailto:zpf.073@gmail.com">nkorange</a>
* ListView
*
* @author dungu.zpf
*/
public class ListView<T> {

View File

@ -21,32 +21,34 @@ import java.util.HashMap;
import java.util.Map;
/**
* @author <a href="mailto:zpf.073@gmail.com">nkorange</a>
* Service
*
* @author dungu.zpf
*/
public class Service {
/**
* Service name
* service name
*/
private String name;
/**
* Protect threshold
* protect threshold
*/
private float protectThreshold = 0.0F;
/**
* Application name of this service
* application name of this service
*/
private String app;
/**
* Service group is meant to classify services into different sets
* Service group which is meant to classify services into different sets.
*/
private String group;
/**
* Health check mode
* Health check mode.
*/
private String healthCheckMode;

View File

@ -24,7 +24,9 @@ import java.util.Collection;
import java.util.List;
/**
* @author <a href="mailto:zpf.073@gmail.com">nkorange</a>
* ServiceInfo
*
* @author dungu.zpf
*/
public class ServiceInfo {
@ -46,8 +48,6 @@ public class ServiceInfo {
private String checksum = "";
private String env = "";
private volatile boolean allIPs = false;
public ServiceInfo() {
@ -63,48 +63,22 @@ public class ServiceInfo {
public ServiceInfo(String key) {
int maxKeySectionCount = 4;
int allIpFlagIndex = 3;
int envIndex = 2;
int maxIndex = 2;
int clusterIndex = 1;
int serviceNameIndex = 0;
String[] keys = key.split(SPLITER);
if (keys.length >= maxKeySectionCount) {
if (keys.length >= maxIndex) {
this.name = keys[serviceNameIndex];
this.clusters = keys[clusterIndex];
this.env = keys[envIndex];
if (strEquals(keys[allIpFlagIndex], ALL_IPS)) {
this.setAllIPs(true);
}
} else if (keys.length >= allIpFlagIndex) {
this.name = keys[serviceNameIndex];
this.clusters = keys[clusterIndex];
if (strEquals(keys[envIndex], ALL_IPS)) {
this.setAllIPs(true);
} else {
this.env = keys[envIndex];
}
} else if (keys.length >= envIndex) {
this.name = keys[serviceNameIndex];
if (strEquals(keys[clusterIndex], ALL_IPS)) {
this.setAllIPs(true);
} else {
this.clusters = keys[clusterIndex];
}
}
this.name = keys[0];
}
public ServiceInfo(String name, String clusters) {
this(name, clusters, EMPTY);
}
public ServiceInfo(String name, String clusters, String env) {
this.name = name;
this.clusters = clusters;
this.env = env;
}
public int ipCount() {
@ -156,7 +130,6 @@ public class ServiceInfo {
}
public List<Instance> getHosts() {
return new ArrayList<Instance>(hosts);
}
@ -190,45 +163,39 @@ public class ServiceInfo {
@JSONField(serialize = false)
public String getKey() {
return getKey(name, clusters, env, isAllIPs());
return getKey(name, clusters);
}
@JSONField(serialize = false)
public String getKeyEncoded() {
try {
return getKey(URLEncoder.encode(name, "UTF-8"), clusters, env, isAllIPs());
return getKey(URLEncoder.encode(name, "UTF-8"), clusters);
} catch (UnsupportedEncodingException e) {
return getKey();
}
}
@JSONField(serialize = false)
public static String getKey(String name, String clusters, String unit) {
return getKey(name, clusters, unit, false);
public static ServiceInfo fromKey(String key) {
ServiceInfo serviceInfo = new ServiceInfo();
if (key.contains(SPLITER)) {
serviceInfo.setName(key.split(SPLITER)[0]);
serviceInfo.setClusters(key.split(SPLITER)[1]);
return serviceInfo;
}
serviceInfo.setName(key);
return serviceInfo;
}
@JSONField(serialize = false)
public static String getKey(String name, String clusters, String unit, boolean isAllIPs) {
if (isEmpty(unit)) {
unit = EMPTY;
}
if (!isEmpty(clusters) && !isEmpty(unit)) {
return isAllIPs ? name + SPLITER + clusters + SPLITER + unit + SPLITER + ALL_IPS
: name + SPLITER + clusters + SPLITER + unit;
}
public static String getKey(String name, String clusters) {
if (!isEmpty(clusters)) {
return isAllIPs ? name + SPLITER + clusters + SPLITER + ALL_IPS : name + SPLITER + clusters;
return name + SPLITER + clusters;
}
if (!isEmpty(unit)) {
return isAllIPs ? name + SPLITER + EMPTY + SPLITER + unit + SPLITER + ALL_IPS :
name + SPLITER + EMPTY + SPLITER + unit;
}
return isAllIPs ? name + SPLITER + ALL_IPS : name;
return name;
}
@Override

View File

@ -19,6 +19,7 @@ package com.alibaba.nacos.api.selector;
* Abstract selector that only contains a type
*
* @author <a href="mailto:zpf.073@gmail.com">nkorange</a>
* @since 0.7.0
*/
public abstract class AbstractSelector {

View File

@ -19,6 +19,7 @@ package com.alibaba.nacos.api.selector;
* The selector to filter resource with flexible expression.
*
* @author <a href="mailto:zpf.073@gmail.com">nkorange</a>
* @since 0.7.0
*/
public class ExpressionSelector extends AbstractSelector {

View File

@ -19,6 +19,7 @@ package com.alibaba.nacos.api.selector;
* The types of selector accepted by Nacos
*
* @author <a href="mailto:zpf.073@gmail.com">nkorange</a>
* @since 0.7.0
*/
public enum SelectorType {
/**

View File

@ -16,7 +16,7 @@
<parent>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-all</artifactId>
<version>0.7.0</version>
<version>0.8.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
@ -107,5 +107,10 @@
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-core</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -23,10 +23,12 @@ import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.client.config.filter.impl.ConfigFilterChainManager;
import com.alibaba.nacos.client.config.filter.impl.ConfigRequest;
import com.alibaba.nacos.client.config.filter.impl.ConfigResponse;
import com.alibaba.nacos.client.config.http.HttpAgent;
import com.alibaba.nacos.client.config.http.MetricsHttpAgent;
import com.alibaba.nacos.client.config.http.ServerHttpAgent;
import com.alibaba.nacos.client.config.impl.ClientWorker;
import com.alibaba.nacos.client.config.impl.HttpSimpleClient.HttpResult;
import com.alibaba.nacos.client.config.impl.LocalConfigInfoProcessor;
import com.alibaba.nacos.client.config.impl.ServerHttpAgent;
import com.alibaba.nacos.client.config.utils.ContentUtils;
import com.alibaba.nacos.client.config.utils.LogUtils;
import com.alibaba.nacos.client.config.utils.ParamUtils;
@ -55,9 +57,9 @@ public class NacosConfigService implements ConfigService {
/**
* http agent
*/
private ServerHttpAgent agent;
private HttpAgent agent;
/**
* longpulling
* longpolling
*/
private ClientWorker worker;
private String namespace;
@ -79,7 +81,7 @@ public class NacosConfigService implements ConfigService {
namespace = namespaceTmp;
properties.put(PropertyKeyConst.NAMESPACE, namespace);
}
agent = new ServerHttpAgent(properties);
agent = new MetricsHttpAgent(new ServerHttpAgent(properties));
agent.start();
worker = new ClientWorker(agent, configFilterChainManager);
}
@ -131,9 +133,11 @@ public class NacosConfigService implements ConfigService {
try {
content = worker.getServerConfig(dataId, group, tenant, timeoutMs);
cr.setContent(content);
configFilterChainManager.doFilter(null, cr);
content = cr.getContent();
return content;
} catch (NacosException ioe) {
if (NacosException.NO_RIGHT == ioe.getErrCode()) {

View File

@ -0,0 +1,98 @@
/*
* 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.client.config.http;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.client.config.impl.HttpSimpleClient.HttpResult;
import java.io.IOException;
import java.util.List;
/**
* HttpAgent
*
* @author Nacos
*/
public interface HttpAgent {
/**
* start to get nacos ip list
* @return Nothing.
* @throws NacosException on get ip list error.
*/
void start() throws NacosException;
/**
* invoke http get method
* @param path http path
* @param headers http headers
* @param paramValues http paramValues http
* @param encoding http encode
* @param readTimeoutMs http timeout
* @return HttpResult http response
* @throws IOException If an input or output exception occurred
*/
HttpResult httpGet(String path, List<String> headers, List<String> paramValues, String encoding, long readTimeoutMs) throws IOException;
/**
* invoke http post method
* @param path http path
* @param headers http headers
* @param paramValues http paramValues http
* @param encoding http encode
* @param readTimeoutMs http timeout
* @return HttpResult http response
* @throws IOException If an input or output exception occurred
*/
HttpResult httpPost(String path, List<String> headers, List<String> paramValues, String encoding, long readTimeoutMs) throws IOException;
/**
* invoke http delete method
* @param path http path
* @param headers http headers
* @param paramValues http paramValues http
* @param encoding http encode
* @param readTimeoutMs http timeout
* @return HttpResult http response
* @throws IOException If an input or output exception occurred
*/
HttpResult httpDelete(String path, List<String> headers, List<String> paramValues, String encoding, long readTimeoutMs) throws IOException;
/**
* get name
* @return String
*/
String getName();
/**
* get namespace
* @return String
*/
String getNamespace();
/**
* get tenant
* @return String
*/
String getTenant();
/**
* get encode
* @return String
*/
String getEncode();
}

View File

@ -0,0 +1,119 @@
/*
* 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.client.config.http;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.client.config.impl.HttpSimpleClient.HttpResult;
import com.alibaba.nacos.client.monitor.MetricsMonitor;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.TimeUnit;
/**
* MetricsHttpAgent
*
* @author Nacos
*/
public class MetricsHttpAgent implements HttpAgent {
private HttpAgent httpAgent;
public MetricsHttpAgent(HttpAgent httpAgent) {
this.httpAgent = httpAgent;
}
@Override
public void start() throws NacosException {
httpAgent.start();
}
@Override
public HttpResult httpGet(String path, List<String> headers, List<String> paramValues, String encoding, long readTimeoutMs) throws IOException {
long start = System.currentTimeMillis();
long end = 0;
HttpResult result = null;
try {
result = httpAgent.httpGet(path, headers, paramValues, encoding, readTimeoutMs);
} catch (IOException e) {
end = System.currentTimeMillis();
MetricsMonitor.getConfigRequestMonitor("GET", path, "NA").record(end - start, TimeUnit.MILLISECONDS);
throw e;
}
end = System.currentTimeMillis();
MetricsMonitor.getConfigRequestMonitor("GET", path, String.valueOf(result.code)).record(end - start, TimeUnit.MILLISECONDS);
return result;
}
@Override
public HttpResult httpPost(String path, List<String> headers, List<String> paramValues, String encoding, long readTimeoutMs) throws IOException {
long start = System.currentTimeMillis();
long end = 0;
HttpResult result = null;
try {
result = httpAgent.httpPost(path, headers, paramValues, encoding, readTimeoutMs);
} catch (IOException e) {
end = System.currentTimeMillis();
MetricsMonitor.getConfigRequestMonitor("POST", path, "NA").record(end - start, TimeUnit.MILLISECONDS);
throw e;
}
end = System.currentTimeMillis();
MetricsMonitor.getConfigRequestMonitor("POST", path, String.valueOf(result.code)).record(end - start, TimeUnit.MILLISECONDS);
return result;
}
@Override
public HttpResult httpDelete(String path, List<String> headers, List<String> paramValues, String encoding, long readTimeoutMs) throws IOException {
long start = System.currentTimeMillis();
long end = 0;
HttpResult result = null;
try {
result = httpAgent.httpDelete(path, headers, paramValues, encoding, readTimeoutMs);
} catch (IOException e) {
end = System.currentTimeMillis();
MetricsMonitor.getConfigRequestMonitor("DELETE", path, "NA").record(end - start, TimeUnit.MILLISECONDS);
throw e;
}
end = System.currentTimeMillis();
MetricsMonitor.getConfigRequestMonitor("DELETE", path, String.valueOf(result.code)).record(end - start, TimeUnit.MILLISECONDS);
return result;
}
@Override
public String getName() {
return httpAgent.getName();
}
@Override
public String getNamespace() {
return httpAgent.getNamespace();
}
@Override
public String getTenant() {
return httpAgent.getTenant();
}
@Override
public String getEncode() {
return httpAgent.getEncode();
}
}

View File

@ -13,17 +13,21 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.nacos.client.config.impl;
package com.alibaba.nacos.client.config.http;
import com.alibaba.nacos.api.PropertyKeyConst;
import com.alibaba.nacos.api.common.Constants;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.client.config.impl.HttpSimpleClient;
import com.alibaba.nacos.client.config.impl.HttpSimpleClient.HttpResult;
import com.alibaba.nacos.client.config.impl.ServerListManager;
import com.alibaba.nacos.client.config.impl.SpasAdapter;
import com.alibaba.nacos.client.config.utils.IOUtils;
import com.alibaba.nacos.client.config.utils.LogUtils;
import com.alibaba.nacos.client.identify.STSConfig;
import com.alibaba.nacos.client.logger.Logger;
import com.alibaba.nacos.client.logger.support.LoggerHelper;
import com.alibaba.nacos.client.monitor.MetricsMonitor;
import com.alibaba.nacos.client.utils.JSONUtils;
import com.alibaba.nacos.client.utils.ParamUtil;
import com.alibaba.nacos.client.utils.StringUtils;
@ -39,13 +43,14 @@ import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.TimeUnit;
/**
* Server Agent
*
* @author water.lyl
*/
public class ServerHttpAgent {
public class ServerHttpAgent implements HttpAgent {
final static public Logger log = LogUtils.logger(ServerHttpAgent.class);
@ -58,6 +63,7 @@ public class ServerHttpAgent {
* @return
* @throws IOException
*/
@Override
public HttpResult httpGet(String path, List<String> headers, List<String> paramValues, String encoding,
long readTimeoutMs) throws IOException {
final long endTime = System.currentTimeMillis() + readTimeoutMs;
@ -101,6 +107,7 @@ public class ServerHttpAgent {
throw new ConnectException("no available server");
}
@Override
public HttpResult httpPost(String path, List<String> headers, List<String> paramValues, String encoding,
long readTimeoutMs) throws IOException {
final long endTime = System.currentTimeMillis() + readTimeoutMs;
@ -143,6 +150,7 @@ public class ServerHttpAgent {
throw new ConnectException("no available server");
}
@Override
public HttpResult httpDelete(String path, List<String> headers, List<String> paramValues, String encoding,
long readTimeoutMs) throws IOException {
final long endTime = System.currentTimeMillis() + readTimeoutMs;
@ -241,6 +249,7 @@ public class ServerHttpAgent {
}
}
@Override
public synchronized void start() throws NacosException {
serverListMgr.start();
}
@ -324,18 +333,22 @@ public class ServerHttpAgent {
"can not get security credentials, responseCode: " + respCode + ", response: " + response);
}
@Override
public String getName() {
return serverListMgr.getName();
}
@Override
public String getNamespace() {
return serverListMgr.getNamespace();
}
@Override
public String getTenant() {
return serverListMgr.getTenant();
}
@Override
public String getEncode() {
return encode;
}

View File

@ -20,6 +20,7 @@ import com.alibaba.nacos.api.config.listener.Listener;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.client.config.common.GroupKey;
import com.alibaba.nacos.client.config.filter.impl.ConfigFilterChainManager;
import com.alibaba.nacos.client.config.http.HttpAgent;
import com.alibaba.nacos.client.config.impl.HttpSimpleClient.HttpResult;
import com.alibaba.nacos.client.config.utils.ContentUtils;
import com.alibaba.nacos.client.config.utils.LogUtils;
@ -27,6 +28,7 @@ import com.alibaba.nacos.client.config.utils.MD5;
import com.alibaba.nacos.client.config.utils.TenantUtil;
import com.alibaba.nacos.client.logger.Logger;
import com.alibaba.nacos.client.logger.support.LoggerHelper;
import com.alibaba.nacos.client.monitor.MetricsMonitor;
import com.alibaba.nacos.client.utils.ParamUtil;
import com.alibaba.nacos.client.utils.StringUtils;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
@ -43,7 +45,7 @@ import static com.alibaba.nacos.api.common.Constants.LINE_SEPARATOR;
import static com.alibaba.nacos.api.common.Constants.WORD_SEPARATOR;
/**
* Longpulling
* Longpolling
*
* @author Nacos
*/
@ -100,6 +102,8 @@ public class ClientWorker {
cacheMap.set(copy);
}
log.info(agent.getName(), "[unsubscribe] {}", groupKey);
MetricsMonitor.getListenConfigCountMonitor().set(cacheMap.get().size());
}
@SuppressFBWarnings("JLM_JSR166_UTILCONCURRENT_MONITORENTER")
@ -111,6 +115,8 @@ public class ClientWorker {
cacheMap.set(copy);
}
log.info(agent.getName(), "[unsubscribe] {}", groupKey);
MetricsMonitor.getListenConfigCountMonitor().set(cacheMap.get().size());
}
@SuppressFBWarnings("JLM_JSR166_UTILCONCURRENT_MONITORENTER")
@ -143,6 +149,8 @@ public class ClientWorker {
log.info(agent.getName(), "[subscribe] {}", key);
MetricsMonitor.getListenConfigCountMonitor().set(cacheMap.get().size());
return cache;
}
@ -170,6 +178,9 @@ public class ClientWorker {
cacheMap.set(copy);
}
log.info(agent.getName(), "[subscribe] {}", key);
MetricsMonitor.getListenConfigCountMonitor().set(cacheMap.get().size());
return cache;
}
@ -289,7 +300,7 @@ public class ClientWorker {
if (longingTaskCount > currentLongingTaskCount) {
for (int i = (int)currentLongingTaskCount; i < longingTaskCount; i++) {
// 要判断任务是否在执行 这块需要好好想想 任务列表现在是无序的变化过程可能有问题
executorService.execute(new LongPullingRunnable(i));
executorService.execute(new LongPollingRunnable(i));
}
currentLongingTaskCount = longingTaskCount;
}
@ -406,9 +417,10 @@ public class ClientWorker {
}
@SuppressWarnings("PMD.ThreadPoolCreationRule")
public ClientWorker(final ServerHttpAgent agent, final ConfigFilterChainManager configFilterChainManager) {
public ClientWorker(final HttpAgent agent, final ConfigFilterChainManager configFilterChainManager) {
this.agent = agent;
this.configFilterChainManager = configFilterChainManager;
executor = Executors.newScheduledThreadPool(1, new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
@ -423,7 +435,7 @@ public class ClientWorker {
@Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r);
t.setName("com.alibaba.nacos.client.Worker.longPulling" + agent.getName());
t.setName("com.alibaba.nacos.client.Worker.longPolling" + agent.getName());
t.setDaemon(true);
return t;
}
@ -440,10 +452,10 @@ public class ClientWorker {
}, 1L, 10L, TimeUnit.MILLISECONDS);
}
class LongPullingRunnable implements Runnable {
class LongPollingRunnable implements Runnable {
private int taskId;
public LongPullingRunnable(int taskId) {
public LongPollingRunnable(int taskId) {
this.taskId = taskId;
}
@ -498,7 +510,7 @@ public class ClientWorker {
}
inInitializingCacheList.clear();
} catch (Throwable e) {
log.error("500", "longPulling error", e);
log.error("500", "longPolling error", e);
} finally {
executorService.execute(this);
}
@ -522,9 +534,9 @@ public class ClientWorker {
*/
AtomicReference<Map<String, CacheData>> cacheMap = new AtomicReference<Map<String, CacheData>>(
new HashMap<String, CacheData>());
ServerHttpAgent agent;
HttpAgent agent;
ConfigFilterChainManager configFilterChainManager;
private boolean isHealthServer = true;
private double currentLongingTaskCount = 0;
}

View File

@ -42,13 +42,12 @@ public class Limiter {
/**
* qps 5
*/
private static final String DEFAULT_LIMIT = "5";
private static double limit = 5;
static {
try {
String limitTimeStr = System
.getProperty("limitTime", DEFAULT_LIMIT);
.getProperty("limitTime", String.valueOf(limit));
limit = Double.parseDouble(limitTimeStr);
log.info("limitTime:{}", limit);
} catch (Exception e) {

View File

@ -104,10 +104,14 @@ public class LocalConfigInfoProcessor {
}
} else {
try {
boolean isMdOk = file.getParentFile().mkdirs();
if (!isMdOk) {
log.error(envName, "NACOS-XXXX", "save snapshot error");
File parentFile = file.getParentFile();
if (!parentFile.exists()) {
boolean isMdOk = parentFile.mkdirs();
if (!isMdOk) {
log.error(envName, "NACOS-XXXX", "save snapshot error");
}
}
if (JVMUtil.isMultiInstance()) {
ConcurrentDiskUtil.writeFileContent(file, config,
Constants.ENCODE);

View File

@ -33,6 +33,7 @@ import java.util.Properties;
public abstract class PropertiesListener extends AbstractListener {
final static public Logger log = LogUtils.logger(PropertiesListener.class);
@Override
public void receiveConfigInfo(String configInfo) {
if (StringUtils.isEmpty(configInfo)) {
return;

View File

@ -0,0 +1,81 @@
/*
* 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.client.monitor;
import io.micrometer.core.instrument.ImmutableTag;
import io.micrometer.core.instrument.Metrics;
import io.micrometer.core.instrument.Tag;
import io.micrometer.core.instrument.Timer;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
/**
* Metrics Monitor
*
* @author Nacos
*/
public class MetricsMonitor {
private static AtomicInteger serviceInfoMapSize = new AtomicInteger();
private static AtomicInteger dom2BeatSize = new AtomicInteger();
private static AtomicInteger listenConfigCount = new AtomicInteger();
static {
List<Tag> tags = new ArrayList<Tag>();
tags.add(new ImmutableTag("module", "naming"));
tags.add(new ImmutableTag("name", "subServiceCount"));
Metrics.gauge("nacos_monitor", tags, serviceInfoMapSize);
tags = new ArrayList<Tag>();
tags.add(new ImmutableTag("module", "naming"));
tags.add(new ImmutableTag("name", "pubServiceCount"));
Metrics.gauge("nacos_monitor", tags, dom2BeatSize);
tags = new ArrayList<Tag>();
tags.add(new ImmutableTag("module", "config"));
tags.add(new ImmutableTag("name", "listenConfigCount"));
Metrics.gauge("nacos_monitor", tags, listenConfigCount);
}
public static AtomicInteger getServiceInfoMapSizeMonitor() {
return serviceInfoMapSize;
}
public static AtomicInteger getDom2BeatSizeMonitor() {
return dom2BeatSize;
}
public static AtomicInteger getListenConfigCountMonitor() {
return listenConfigCount;
}
public static Timer getConfigRequestMonitor(String method, String url, String code) {
return Metrics.timer("nacos_client_request",
"module", "config",
"method", method,
"url", url,
"code", code);
}
public static Timer getNamingRequestMonitor(String method, String url, String code) {
return Metrics.timer("nacos_client_request",
"module", "naming",
"method", method,
"url", url,
"code", code);
}
}

View File

@ -20,7 +20,6 @@ import com.alibaba.nacos.api.common.Constants;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.naming.NamingService;
import com.alibaba.nacos.api.naming.listener.EventListener;
import com.alibaba.nacos.api.naming.pojo.Cluster;
import com.alibaba.nacos.api.naming.pojo.Instance;
import com.alibaba.nacos.api.naming.pojo.ListView;
import com.alibaba.nacos.api.naming.pojo.ServiceInfo;
@ -36,6 +35,7 @@ import com.alibaba.nacos.client.naming.utils.LogUtils;
import com.alibaba.nacos.client.naming.utils.StringUtils;
import com.alibaba.nacos.client.naming.utils.UtilAndComs;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.math.NumberUtils;
import java.util.ArrayList;
import java.util.Iterator;
@ -102,7 +102,7 @@ public class NacosNamingService implements NamingService {
eventDispatcher = new EventDispatcher();
serverProxy = new NamingProxy(namespace, endpoint, serverList);
beatReactor = new BeatReactor(serverProxy);
hostReactor = new HostReactor(eventDispatcher, serverProxy, cacheDir, false);
hostReactor = new HostReactor(eventDispatcher, serverProxy, cacheDir);
}
public NacosNamingService(Properties properties) {
@ -132,10 +132,16 @@ public class NacosNamingService implements NamingService {
properties.getProperty(PropertyKeyConst.NAMING_LOAD_CACHE_AT_START));
}
int clientBeatThreadCount = NumberUtils.toInt(properties.getProperty(PropertyKeyConst.NAMING_CLIENT_BEAT_THREAD_COUNT),
UtilAndComs.DEFAULT_CLIENT_BEAT_THREAD_COUNT);
int pollingThreadCount = NumberUtils.toInt(properties.getProperty(PropertyKeyConst.NAMING_POLLING_THREAD_COUNT),
UtilAndComs.DEFAULT_POLLING_THREAD_COUNT);
eventDispatcher = new EventDispatcher();
serverProxy = new NamingProxy(namespace, endpoint, serverList);
beatReactor = new BeatReactor(serverProxy);
hostReactor = new HostReactor(eventDispatcher, serverProxy, cacheDir, loadCacheAtStart);
beatReactor = new BeatReactor(serverProxy, clientBeatThreadCount);
hostReactor = new HostReactor(eventDispatcher, serverProxy, cacheDir, loadCacheAtStart, pollingThreadCount);
}
@ -159,12 +165,13 @@ public class NacosNamingService implements NamingService {
public void registerInstance(String serviceName, Instance instance) throws NacosException {
BeatInfo beatInfo = new BeatInfo();
beatInfo.setDom(serviceName);
beatInfo.setServiceName(serviceName);
beatInfo.setIp(instance.getIp());
beatInfo.setPort(instance.getPort());
beatInfo.setCluster(instance.getClusterName());
beatInfo.setWeight(instance.getWeight());
beatInfo.setMetadata(instance.getMetadata());
beatInfo.setScheduled(false);
beatReactor.addBeatInfo(serviceName, beatInfo);
@ -188,10 +195,24 @@ public class NacosNamingService implements NamingService {
}
@Override
public List<Instance> getAllInstances(String serviceName, List<String> clusters) throws NacosException {
public List<Instance> getAllInstances(String serviceName, boolean subscribe) throws NacosException {
return getAllInstances(serviceName, new ArrayList<String>(), subscribe);
}
ServiceInfo serviceInfo = hostReactor.getServiceInfo(serviceName, StringUtils.join(clusters, ","),
StringUtils.EMPTY, false);
@Override
public List<Instance> getAllInstances(String serviceName, List<String> clusters) throws NacosException {
return getAllInstances(serviceName, clusters, true);
}
@Override
public List<Instance> getAllInstances(String serviceName, List<String> clusters, boolean subscribe) throws NacosException {
ServiceInfo serviceInfo;
if (subscribe) {
serviceInfo = hostReactor.getServiceInfo(serviceName, StringUtils.join(clusters, ","));
} else {
serviceInfo = hostReactor.getServiceInfoDirectlyFromServer(serviceName, StringUtils.join(clusters, ","));
}
List<Instance> list;
if (serviceInfo == null || CollectionUtils.isEmpty(list = serviceInfo.getHosts())) {
return new ArrayList<Instance>();
@ -200,41 +221,58 @@ public class NacosNamingService implements NamingService {
}
@Override
public List<Instance> selectInstances(String serviceName, boolean healthyOnly) throws NacosException {
return selectInstances(serviceName, new ArrayList<String>(), healthyOnly);
public List<Instance> selectInstances(String serviceName, boolean healthy) throws NacosException {
return selectInstances(serviceName, new ArrayList<String>(), healthy);
}
@Override
public List<Instance> selectInstances(String serviceName, boolean healthy, boolean subscribe) throws NacosException {
return selectInstances(serviceName, new ArrayList<String>(), healthy, subscribe);
}
@Override
public List<Instance> selectInstances(String serviceName, List<String> clusters, boolean healthy)
throws NacosException {
ServiceInfo serviceInfo = hostReactor.getServiceInfo(serviceName, StringUtils.join(clusters, ","),
StringUtils.EMPTY, false);
List<Instance> list;
if (serviceInfo == null || CollectionUtils.isEmpty(list = serviceInfo.getHosts())) {
return new ArrayList<Instance>();
}
Iterator<Instance> iterator = list.iterator();
while (iterator.hasNext()) {
Instance instance = iterator.next();
if (healthy != instance.isHealthy() || !instance.isEnabled() || instance.getWeight() <= 0) {
iterator.remove();
}
}
return list;
return selectInstances(serviceName, clusters, healthy, true);
}
@Override
public Instance selectOneHealthyInstance(String serviceName) {
public List<Instance> selectInstances(String serviceName, List<String> clusters, boolean healthy,
boolean subscribe) throws NacosException {
ServiceInfo serviceInfo;
if (subscribe) {
serviceInfo = hostReactor.getServiceInfo(serviceName, StringUtils.join(clusters, ","));
} else {
serviceInfo = hostReactor.getServiceInfoDirectlyFromServer(serviceName, StringUtils.join(clusters, ","));
}
return selectInstances(serviceInfo, healthy);
}
@Override
public Instance selectOneHealthyInstance(String serviceName) throws NacosException {
return selectOneHealthyInstance(serviceName, new ArrayList<String>());
}
@Override
public Instance selectOneHealthyInstance(String serviceName, List<String> clusters) {
return Balancer.RandomByWeight.selectHost(
hostReactor.getServiceInfo(serviceName, StringUtils.join(clusters, ",")));
public Instance selectOneHealthyInstance(String serviceName, boolean subscribe) throws NacosException {
return selectOneHealthyInstance(serviceName, new ArrayList<String>(), subscribe);
}
@Override
public Instance selectOneHealthyInstance(String serviceName, List<String> clusters) throws NacosException {
return selectOneHealthyInstance(serviceName, clusters, true);
}
@Override
public Instance selectOneHealthyInstance(String serviceName, List<String> clusters, boolean subscribe) throws NacosException {
if (subscribe) {
return Balancer.RandomByWeight.selectHost(
hostReactor.getServiceInfo(serviceName, StringUtils.join(clusters, ",")));
} else {
return Balancer.RandomByWeight.selectHost(
hostReactor.getServiceInfoDirectlyFromServer(serviceName, StringUtils.join(clusters, ",")));
}
}
@Override
@ -271,7 +309,7 @@ public class NacosNamingService implements NamingService {
@Override
public List<ServiceInfo> getSubscribeServices() {
return new ArrayList<ServiceInfo>(hostReactor.getServiceInfoMap().values());
return eventDispatcher.getSubscribeServices();
}
@Override
@ -279,6 +317,23 @@ public class NacosNamingService implements NamingService {
return serverProxy.serverHealthy() ? "UP" : "DOWN";
}
private List<Instance> selectInstances(ServiceInfo serviceInfo, boolean healthy) {
List<Instance> list;
if (serviceInfo == null || CollectionUtils.isEmpty(list = serviceInfo.getHosts())) {
return new ArrayList<Instance>();
}
Iterator<Instance> iterator = list.iterator();
while (iterator.hasNext()) {
Instance instance = iterator.next();
if (healthy != instance.isHealthy() || !instance.isEnabled() || instance.getWeight() <= 0) {
iterator.remove();
}
}
return list;
}
public BeatReactor getBeatReactor() {
return beatReactor;
}

View File

@ -27,21 +27,22 @@ public class BeatInfo {
private int port;
private String ip;
private double weight;
private String dom;
private String serviceName;
private String cluster;
private Map<String, String> metadata;
private boolean scheduled;
@Override
public String toString() {
return JSON.toJSONString(this);
}
public String getDom() {
return dom;
public String getServiceName() {
return serviceName;
}
public void setDom(String dom) {
this.dom = dom;
public void setServiceName(String serviceName) {
this.serviceName = serviceName;
}
public String getCluster() {
@ -83,4 +84,12 @@ public class BeatInfo {
public void setWeight(double weight) {
this.weight = weight;
}
public boolean isScheduled() {
return scheduled;
}
public void setScheduled(boolean scheduled) {
this.scheduled = scheduled;
}
}

View File

@ -15,14 +15,12 @@
*/
package com.alibaba.nacos.client.naming.beat;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.nacos.api.common.Constants;
import com.alibaba.nacos.client.monitor.MetricsMonitor;
import com.alibaba.nacos.client.naming.net.NamingProxy;
import com.alibaba.nacos.client.naming.utils.LogUtils;
import com.alibaba.nacos.client.naming.utils.UtilAndComs;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.*;
@ -31,15 +29,7 @@ import java.util.concurrent.*;
*/
public class BeatReactor {
private ScheduledExecutorService executorService = new ScheduledThreadPoolExecutor(1, new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
Thread thread = new Thread(r);
thread.setDaemon(true);
thread.setName("com.alibaba.nacos.naming.beat.sender");
return thread;
}
});
private ScheduledExecutorService executorService;
private long clientBeatInterval = 5 * 1000;
@ -48,18 +38,35 @@ public class BeatReactor {
public final Map<String, BeatInfo> dom2Beat = new ConcurrentHashMap<String, BeatInfo>();
public BeatReactor(NamingProxy serverProxy) {
this(serverProxy, UtilAndComs.DEFAULT_CLIENT_BEAT_THREAD_COUNT);
}
public BeatReactor(NamingProxy serverProxy, int threadCount) {
this.serverProxy = serverProxy;
executorService = new ScheduledThreadPoolExecutor(threadCount, new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
Thread thread = new Thread(r);
thread.setDaemon(true);
thread.setName("com.alibaba.nacos.naming.beat.sender");
return thread;
}
});
executorService.scheduleAtFixedRate(new BeatProcessor(), 0, clientBeatInterval, TimeUnit.MILLISECONDS);
}
public void addBeatInfo(String dom, BeatInfo beatInfo) {
LogUtils.LOG.info("BEAT", "adding service:" + dom + " to beat map.");
LogUtils.LOG.info("BEAT", "adding beat: {} to beat map.", beatInfo);
dom2Beat.put(buildKey(dom, beatInfo.getIp(), beatInfo.getPort()), beatInfo);
MetricsMonitor.getDom2BeatSizeMonitor().set(dom2Beat.size());
}
public void removeBeatInfo(String dom, String ip, int port) {
LogUtils.LOG.info("BEAT", "removing service:" + dom + " from beat map.");
LogUtils.LOG.info("BEAT", "removing beat: {}:{}:{} from beat map.", dom, ip, port);
dom2Beat.remove(buildKey(dom, ip, port));
MetricsMonitor.getDom2BeatSizeMonitor().set(dom2Beat.size());
}
public String buildKey(String dom, String ip, int port) {
@ -73,8 +80,11 @@ public class BeatReactor {
try {
for (Map.Entry<String, BeatInfo> entry : dom2Beat.entrySet()) {
BeatInfo beatInfo = entry.getValue();
if (beatInfo.isScheduled()) {
continue;
}
beatInfo.setScheduled(true);
executorService.schedule(new BeatTask(beatInfo), 0, TimeUnit.MILLISECONDS);
LogUtils.LOG.info("BEAT", "send beat to server: " + beatInfo.toString());
}
} catch (Exception e) {
LogUtils.LOG.error("CLIENT-BEAT", "Exception while scheduling beat.", e);
@ -83,6 +93,7 @@ public class BeatReactor {
}
class BeatTask implements Runnable {
BeatInfo beatInfo;
public BeatTask(BeatInfo beatInfo) {
@ -91,20 +102,10 @@ public class BeatReactor {
@Override
public void run() {
Map<String, String> params = new HashMap<String, String>(2);
params.put("beat", JSON.toJSONString(beatInfo));
params.put("dom", beatInfo.getDom());
try {
String result = serverProxy.callAllServers(UtilAndComs.NACOS_URL_BASE + "/api/clientBeat", params);
JSONObject jsonObject = JSON.parseObject(result);
if (jsonObject != null) {
clientBeatInterval = jsonObject.getLong("clientBeatInterval");
}
} catch (Exception e) {
LogUtils.LOG.error("CLIENT-BEAT", "failed to send beat: " + JSON.toJSONString(beatInfo), e);
long result = serverProxy.sendBeat(beatInfo);
beatInfo.setScheduled(false);
if (result > 0) {
clientBeatInterval = result;
}
}
}

View File

@ -21,7 +21,6 @@ import com.alibaba.nacos.api.naming.pojo.Instance;
import com.alibaba.nacos.api.naming.pojo.ServiceInfo;
import com.alibaba.nacos.client.naming.utils.CollectionUtils;
import com.alibaba.nacos.client.naming.utils.LogUtils;
import com.alibaba.nacos.client.naming.utils.StringUtils;
import java.util.ArrayList;
import java.util.Collections;
@ -57,16 +56,12 @@ public class EventDispatcher {
}
public void addListener(ServiceInfo serviceInfo, String clusters, EventListener listener) {
addListener(serviceInfo, clusters, StringUtils.EMPTY, listener);
}
public void addListener(ServiceInfo serviceInfo, String clusters, String env, EventListener listener) {
LogUtils.LOG.info("LISTENER", "adding " + serviceInfo.getName() + " with " + clusters + " to listener map");
List<EventListener> observers = Collections.synchronizedList(new ArrayList<EventListener>());
observers.add(listener);
observers = observerMap.putIfAbsent(ServiceInfo.getKey(serviceInfo.getName(), clusters, env), observers);
observers = observerMap.putIfAbsent(ServiceInfo.getKey(serviceInfo.getName(), clusters), observers);
if (observers != null) {
observers.add(listener);
}
@ -77,9 +72,8 @@ public class EventDispatcher {
public void removeListener(String serviceName, String clusters, EventListener listener) {
LogUtils.LOG.info("LISTENER", "removing " + serviceName + " with " + clusters + " from listener map");
String unit = "";
List<EventListener> observers = observerMap.get(ServiceInfo.getKey(serviceName, clusters, unit));
List<EventListener> observers = observerMap.get(ServiceInfo.getKey(serviceName, clusters));
if (observers != null) {
Iterator<EventListener> iter = observers.iterator();
while (iter.hasNext()) {
@ -88,9 +82,20 @@ public class EventDispatcher {
iter.remove();
}
}
if (observers.isEmpty()) {
observerMap.remove(ServiceInfo.getKey(serviceName, clusters));
}
}
}
public List<ServiceInfo> getSubscribeServices() {
List<ServiceInfo> serviceInfos = new ArrayList<ServiceInfo>();
for (String key : observerMap.keySet()) {
serviceInfos.add(ServiceInfo.fromKey(key));
}
return serviceInfos;
}
public void serviceChanged(ServiceInfo serviceInfo) {
if (serviceInfo == null) {
return;

View File

@ -16,13 +16,14 @@
package com.alibaba.nacos.client.naming.core;
import com.alibaba.fastjson.JSON;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.naming.pojo.Instance;
import com.alibaba.nacos.api.naming.pojo.ServiceInfo;
import com.alibaba.nacos.client.monitor.MetricsMonitor;
import com.alibaba.nacos.client.naming.backups.FailoverReactor;
import com.alibaba.nacos.client.naming.cache.DiskCache;
import com.alibaba.nacos.client.naming.net.NamingProxy;
import com.alibaba.nacos.client.naming.utils.LogUtils;
import com.alibaba.nacos.client.naming.utils.NetUtils;
import com.alibaba.nacos.client.naming.utils.StringUtils;
import com.alibaba.nacos.client.naming.utils.UtilAndComs;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
@ -45,7 +46,7 @@ public class HostReactor {
private Map<String, Object> updatingMap;
private PushRecver pushRecver;
private PushReceiver pushReceiver;
private EventDispatcher eventDispatcher;
@ -55,8 +56,25 @@ public class HostReactor {
private String cacheDir;
private ScheduledExecutorService executor;
public HostReactor(EventDispatcher eventDispatcher, NamingProxy serverProxy, String cacheDir) {
this(eventDispatcher, serverProxy, cacheDir, false, UtilAndComs.DEFAULT_POLLING_THREAD_COUNT);
}
public HostReactor(EventDispatcher eventDispatcher, NamingProxy serverProxy, String cacheDir,
boolean loadCacheAtStart) {
boolean loadCacheAtStart, int pollingThreadCount) {
executor = new ScheduledThreadPoolExecutor(pollingThreadCount, new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
Thread thread = new Thread(r);
thread.setDaemon(true);
thread.setName("com.alibaba.nacos.client.naming.updater");
return thread;
}
});
this.eventDispatcher = eventDispatcher;
this.serverProxy = serverProxy;
this.cacheDir = cacheDir;
@ -68,19 +86,9 @@ public class HostReactor {
this.updatingMap = new ConcurrentHashMap<String, Object>();
this.failoverReactor = new FailoverReactor(this, cacheDir);
this.pushRecver = new PushRecver(this);
this.pushReceiver = new PushReceiver(this);
}
private ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor(new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
Thread thread = new Thread(r, "com.alibaba.nacos.client.naming.updater");
thread.setDaemon(true);
return thread;
}
});
public Map<String, ServiceInfo> getServiceInfoMap() {
return serviceInfoMap;
}
@ -182,61 +190,46 @@ public class HostReactor {
DiskCache.write(serviceInfo, cacheDir);
}
MetricsMonitor.getServiceInfoMapSizeMonitor().set(serviceInfoMap.size());
LogUtils.LOG.info("current ips:(" + serviceInfo.ipCount() + ") service: " + serviceInfo.getName() +
" -> " + JSON.toJSONString(serviceInfo.getHosts()));
return serviceInfo;
}
private ServiceInfo getSerivceInfo0(String serviceName, String clusters, String env) {
private ServiceInfo getSerivceInfo0(String serviceName, String clusters) {
String key = ServiceInfo.getKey(serviceName, clusters, env, false);
String key = ServiceInfo.getKey(serviceName, clusters);
return serviceInfoMap.get(key);
}
private ServiceInfo getSerivceInfo0(String serviceName, String clusters, String env, boolean allIPs) {
String key = ServiceInfo.getKey(serviceName, clusters, env, allIPs);
return serviceInfoMap.get(key);
public ServiceInfo getServiceInfoDirectlyFromServer(final String serviceName, final String clusters) throws NacosException {
String result = serverProxy.queryList(serviceName, clusters, 0, false);
if (StringUtils.isNotEmpty(result)) {
return JSON.parseObject(result, ServiceInfo.class);
}
return null;
}
public ServiceInfo getServiceInfo(String serviceName, String clusters, String env) {
return getServiceInfo(serviceName, clusters, env, false);
}
public ServiceInfo getServiceInfo(String serviceName, String clusters) {
String env = StringUtils.EMPTY;
return getServiceInfo(serviceName, clusters, env, false);
}
public ServiceInfo getServiceInfo(final String serviceName, final String clusters, final String env,
final boolean allIPs) {
public ServiceInfo getServiceInfo(final String serviceName, final String clusters) {
LogUtils.LOG.debug("failover-mode: " + failoverReactor.isFailoverSwitch());
String key = ServiceInfo.getKey(serviceName, clusters, env, allIPs);
String key = ServiceInfo.getKey(serviceName, clusters);
if (failoverReactor.isFailoverSwitch()) {
return failoverReactor.getService(key);
}
ServiceInfo serviceObj = getSerivceInfo0(serviceName, clusters, env, allIPs);
ServiceInfo serviceObj = getSerivceInfo0(serviceName, clusters);
if (null == serviceObj) {
serviceObj = new ServiceInfo(serviceName, clusters, env);
if (allIPs) {
serviceObj.setAllIPs(allIPs);
}
serviceObj = new ServiceInfo(serviceName, clusters);
serviceInfoMap.put(serviceObj.getKey(), serviceObj);
updatingMap.put(serviceName, new Object());
if (allIPs) {
updateService4AllIPNow(serviceName, clusters, env);
} else {
updateServiceNow(serviceName, clusters, env);
}
updateServiceNow(serviceName, clusters);
updatingMap.remove(serviceName);
} else if (updatingMap.containsKey(serviceName)) {
@ -248,100 +241,41 @@ public class HostReactor {
serviceObj.wait(updateHoldInterval);
} catch (InterruptedException e) {
LogUtils.LOG.error("[getServiceInfo]",
"serviceName:" + serviceName + ", clusters:" + clusters + ", allIPs:" + allIPs, e);
"serviceName:" + serviceName + ", clusters:" + clusters, e);
}
}
}
}
scheduleUpdateIfAbsent(serviceName, clusters, env, allIPs);
scheduleUpdateIfAbsent(serviceName, clusters);
return serviceInfoMap.get(serviceObj.getKey());
}
public void scheduleUpdateIfAbsent(String serviceName, String clusters, String env, boolean allIPs) {
if (futureMap.get(ServiceInfo.getKey(serviceName, clusters, env, allIPs)) != null) {
public void scheduleUpdateIfAbsent(String serviceName, String clusters) {
if (futureMap.get(ServiceInfo.getKey(serviceName, clusters)) != null) {
return;
}
synchronized (futureMap) {
if (futureMap.get(ServiceInfo.getKey(serviceName, clusters, env, allIPs)) != null) {
if (futureMap.get(ServiceInfo.getKey(serviceName, clusters)) != null) {
return;
}
ScheduledFuture<?> future = addTask(new UpdateTask(serviceName, clusters, env, allIPs));
futureMap.put(ServiceInfo.getKey(serviceName, clusters, env, allIPs), future);
}
}
public void updateService4AllIPNow(String serviceName, String clusters, String env) {
updateService4AllIPNow(serviceName, clusters, env, -1L);
}
@SuppressFBWarnings("NN_NAKED_NOTIFY")
public void updateService4AllIPNow(String serviceName, String clusters, String env, long timeout) {
try {
Map<String, String> params = new HashMap<String, String>(8);
params.put("dom", serviceName);
params.put("clusters", clusters);
params.put("udpPort", String.valueOf(pushRecver.getUDPPort()));
ServiceInfo oldService = getSerivceInfo0(serviceName, clusters, env, true);
if (oldService != null) {
params.put("checksum", oldService.getChecksum());
}
String result = serverProxy.reqAPI(UtilAndComs.NACOS_URL_BASE + "/api/srvAllIP", params);
if (StringUtils.isNotEmpty(result)) {
ServiceInfo serviceInfo = processServiceJSON(result);
serviceInfo.setAllIPs(true);
}
if (oldService != null) {
synchronized (oldService) {
oldService.notifyAll();
}
}
//else nothing has changed
} catch (Exception e) {
LogUtils.LOG.error("NA", "failed to update serviceName: " + serviceName, e);
ScheduledFuture<?> future = addTask(new UpdateTask(serviceName, clusters));
futureMap.put(ServiceInfo.getKey(serviceName, clusters), future);
}
}
@SuppressFBWarnings("NN_NAKED_NOTIFY")
public void updateServiceNow(String serviceName, String clusters, String env) {
ServiceInfo oldService = getSerivceInfo0(serviceName, clusters, env);
public void updateServiceNow(String serviceName, String clusters) {
ServiceInfo oldService = getSerivceInfo0(serviceName, clusters);
try {
Map<String, String> params = new HashMap<String, String>(8);
params.put("dom", serviceName);
params.put("clusters", clusters);
params.put("udpPort", String.valueOf(pushRecver.getUDPPort()));
params.put("env", env);
params.put("clientIP", NetUtils.localIP());
StringBuilder stringBuilder = new StringBuilder();
for (String string : Balancer.UNCONSISTENT_SERVICE_WITH_ADDRESS_SERVER) {
stringBuilder.append(string).append(",");
}
Balancer.UNCONSISTENT_SERVICE_WITH_ADDRESS_SERVER.clear();
params.put("unconsistentDom", stringBuilder.toString());
String envSpliter = ",";
if (!StringUtils.isEmpty(env) && !env.contains(envSpliter)) {
params.put("useEnvId", "true");
}
if (oldService != null) {
params.put("checksum", oldService.getChecksum());
}
String result = serverProxy.reqAPI(UtilAndComs.NACOS_URL_BASE + "/api/srvIPXT", params);
String result = serverProxy.queryList(serviceName, clusters, pushReceiver.getUDPPort(), false);
if (StringUtils.isNotEmpty(result)) {
processServiceJSON(result);
}
//else nothing has changed
} catch (Exception e) {
LogUtils.LOG.error("NA", "failed to update serviceName: " + serviceName, e);
} finally {
@ -353,34 +287,9 @@ public class HostReactor {
}
}
public void refreshOnly(String serviceName, String clusters, String env, boolean allIPs) {
public void refreshOnly(String serviceName, String clusters) {
try {
Map<String, String> params = new HashMap<String, String>(16);
params.put("dom", serviceName);
params.put("clusters", clusters);
params.put("udpPort", String.valueOf(pushRecver.getUDPPort()));
params.put("unit", env);
params.put("clientIP", NetUtils.localIP());
String serviceSpliter = ",";
StringBuilder stringBuilder = new StringBuilder();
for (String string : Balancer.UNCONSISTENT_SERVICE_WITH_ADDRESS_SERVER) {
stringBuilder.append(string).append(serviceSpliter);
}
Balancer.UNCONSISTENT_SERVICE_WITH_ADDRESS_SERVER.clear();
params.put("unconsistentDom", stringBuilder.toString());
String envSpliter = ",";
if (!env.contains(envSpliter)) {
params.put("useEnvId", "true");
}
if (allIPs) {
serverProxy.reqAPI(UtilAndComs.NACOS_URL_BASE + "/api/srvAllIP", params);
} else {
serverProxy.reqAPI(UtilAndComs.NACOS_URL_BASE + "/api/srvIPXT", params);
}
serverProxy.queryList(serviceName, clusters, pushReceiver.getUDPPort(), false);
} catch (Exception e) {
LogUtils.LOG.error("NA", "failed to update serviceName: " + serviceName, e);
}
@ -390,50 +299,30 @@ public class HostReactor {
long lastRefTime = Long.MAX_VALUE;
private String clusters;
private String serviceName;
private String env;
private boolean allIPs = false;
public UpdateTask(String serviceName, String clusters, String env) {
public UpdateTask(String serviceName, String clusters) {
this.serviceName = serviceName;
this.clusters = clusters;
this.env = env;
}
public UpdateTask(String serviceName, String clusters, String env, boolean allIPs) {
this.serviceName = serviceName;
this.clusters = clusters;
this.env = env;
this.allIPs = allIPs;
}
@Override
public void run() {
try {
ServiceInfo serviceObj = serviceInfoMap.get(ServiceInfo.getKey(serviceName, clusters, env, allIPs));
ServiceInfo serviceObj = serviceInfoMap.get(ServiceInfo.getKey(serviceName, clusters));
if (serviceObj == null) {
if (allIPs) {
updateService4AllIPNow(serviceName, clusters, env);
} else {
updateServiceNow(serviceName, clusters, env);
executor.schedule(this, DEFAULT_DELAY, TimeUnit.MILLISECONDS);
}
updateServiceNow(serviceName, clusters);
executor.schedule(this, DEFAULT_DELAY, TimeUnit.MILLISECONDS);
return;
}
if (serviceObj.getLastRefTime() <= lastRefTime) {
if (allIPs) {
updateService4AllIPNow(serviceName, clusters, env);
serviceObj = serviceInfoMap.get(ServiceInfo.getKey(serviceName, clusters, env, true));
} else {
updateServiceNow(serviceName, clusters, env);
serviceObj = serviceInfoMap.get(ServiceInfo.getKey(serviceName, clusters, env));
}
updateServiceNow(serviceName, clusters);
serviceObj = serviceInfoMap.get(ServiceInfo.getKey(serviceName, clusters));
} else {
// if serviceName already updated by push, we should not override it
// since the push data may be different from pull through force push
refreshOnly(serviceName, clusters, env, allIPs);
refreshOnly(serviceName, clusters);
}
executor.schedule(this, serviceObj.getCacheMillis(), TimeUnit.MILLISECONDS);

View File

@ -30,7 +30,7 @@ import java.util.concurrent.ThreadFactory;
/**
* @author xuanyin
*/
public class PushRecver implements Runnable {
public class PushReceiver implements Runnable {
private ScheduledExecutorService executorService;
@ -40,7 +40,7 @@ public class PushRecver implements Runnable {
private HostReactor hostReactor;
public PushRecver(HostReactor hostReactor) {
public PushReceiver(HostReactor hostReactor) {
try {
this.hostReactor = hostReactor;
udpSocket = new DatagramSocket();

View File

@ -18,13 +18,17 @@ package com.alibaba.nacos.client.naming.net;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.alibaba.nacos.api.common.Constants;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.naming.pojo.Instance;
import com.alibaba.nacos.api.naming.pojo.ListView;
import com.alibaba.nacos.api.selector.AbstractSelector;
import com.alibaba.nacos.api.selector.SelectorType;
import com.alibaba.nacos.api.selector.ExpressionSelector;
import com.alibaba.nacos.api.selector.SelectorType;
import com.alibaba.nacos.client.monitor.MetricsMonitor;
import com.alibaba.nacos.client.naming.beat.BeatInfo;
import com.alibaba.nacos.client.naming.utils.*;
import com.alibaba.nacos.common.util.HttpMethod;
import com.alibaba.nacos.common.util.UuidUtils;
import java.io.IOException;
@ -43,7 +47,7 @@ public class NamingProxy {
private static final int DEFAULT_SERVER_PORT = 8848;
private String namespace;
private String namespaceId;
private String endpoint;
@ -59,9 +63,9 @@ public class NamingProxy {
private ScheduledExecutorService executorService;
public NamingProxy(String namespace, String endpoint, String serverList) {
public NamingProxy(String namespaceId, String endpoint, String serverList) {
this.namespace = namespace;
this.namespaceId = namespaceId;
this.endpoint = endpoint;
if (StringUtils.isNotEmpty(serverList)) {
this.serverList = Arrays.asList(serverList.split(","));
@ -96,9 +100,9 @@ public class NamingProxy {
String urlString = "http://" + endpoint + "/nacos/serverlist";
List<String> headers = Arrays.asList("Client-Version", UtilAndComs.VERSION,
"Accept-Encoding", "gzip,deflate,sdch",
"Connection", "Keep-Alive",
"RequestId", UuidUtils.generateUuid());
"Accept-Encoding", "gzip,deflate,sdch",
"Connection", "Keep-Alive",
"RequestId", UuidUtils.generateUuid());
HttpClient.HttpResult result = HttpClient.httpGet(urlString, headers, null, UtilAndComs.ENCODING);
if (HttpURLConnection.HTTP_OK != result.code) {
@ -154,10 +158,11 @@ public class NamingProxy {
public void registerService(String serviceName, Instance instance) throws NacosException {
LogUtils.LOG.info("REGISTER-SERVICE", "registering service " + serviceName + " with instance:" + instance);
LogUtils.LOG.info("REGISTER-SERVICE", "{} registering service {} with instance: {}",
namespaceId, serviceName, instance);
final Map<String, String> params = new HashMap<String, String>(8);
params.put("tenant", namespace);
params.put(Constants.REQUEST_PARAM_NAMESPACE_ID, namespaceId);
params.put("ip", instance.getIp());
params.put("port", String.valueOf(instance.getPort()));
params.put("weight", String.valueOf(instance.getWeight()));
@ -167,33 +172,55 @@ public class NamingProxy {
params.put("serviceName", serviceName);
params.put("clusterName", instance.getClusterName());
reqAPI(UtilAndComs.NACOS_URL_INSTANCE, params, "PUT");
reqAPI(UtilAndComs.NACOS_URL_INSTANCE, params, HttpMethod.POST);
}
public void deregisterService(String serviceName, String ip, int port, String cluster) throws NacosException {
LogUtils.LOG.info("DEREGISTER-SERVICE", "deregistering service " + serviceName
+ " with instance:" + ip + ":" + port + "@" + cluster);
LogUtils.LOG.info("DEREGISTER-SERVICE", "{} deregistering service {} with instance: {}:{}@{}",
namespaceId, serviceName, ip, port, cluster);
final Map<String, String> params = new HashMap<String, String>(8);
params.put("tenant", namespace);
params.put(Constants.REQUEST_PARAM_NAMESPACE_ID, namespaceId);
params.put("ip", ip);
params.put("port", String.valueOf(port));
params.put("serviceName", serviceName);
params.put("cluster", cluster);
reqAPI(UtilAndComs.NACOS_URL_INSTANCE, params, "DELETE");
reqAPI(UtilAndComs.NACOS_URL_INSTANCE, params, HttpMethod.DELETE);
}
public String queryList(String serviceName, String clusters, boolean healthyOnly) throws NacosException {
public String queryList(String serviceName, String clusters, int udpPort, boolean healthyOnly) throws NacosException {
final Map<String, String> params = new HashMap<String, String>(8);
params.put("tenant", namespace);
params.put(Constants.REQUEST_PARAM_NAMESPACE_ID, namespaceId);
params.put("serviceName", serviceName);
params.put("clusters", clusters);
params.put("udpPort", String.valueOf(udpPort));
params.put("clientIP", NetUtils.localIP());
params.put("healthyOnly", String.valueOf(healthyOnly));
return reqAPI(UtilAndComs.NACOS_URL_BASE + "/instance/list", params, "GET");
return reqAPI(UtilAndComs.NACOS_URL_BASE + "/instance/list", params, HttpMethod.GET);
}
public long sendBeat(BeatInfo beatInfo) {
try {
LogUtils.LOG.info("BEAT", "{} sending beat to server: {}", namespaceId, beatInfo.toString());
Map<String, String> params = new HashMap<String, String>(4);
params.put("beat", JSON.toJSONString(beatInfo));
params.put(Constants.REQUEST_PARAM_NAMESPACE_ID, namespaceId);
params.put("serviceName", beatInfo.getServiceName());
String result = reqAPI(UtilAndComs.NACOS_URL_BASE + "/instance/beat", params, HttpMethod.PUT);
JSONObject jsonObject = JSON.parseObject(result);
if (jsonObject != null) {
return jsonObject.getLong("clientBeatInterval");
}
} catch (Exception e) {
LogUtils.LOG.error("CLIENT-BEAT", "failed to send beat: " + JSON.toJSONString(beatInfo), e);
}
return 0L;
}
public boolean serverHealthy() {
@ -216,6 +243,7 @@ public class NamingProxy {
Map<String, String> params = new HashMap<String, String>(4);
params.put("pageNo", String.valueOf(pageNo));
params.put("pageSize", String.valueOf(pageSize));
params.put(Constants.REQUEST_PARAM_NAMESPACE_ID, namespaceId);
if (selector != null) {
switch (SelectorType.valueOf(selector.getType())) {
@ -241,27 +269,6 @@ public class NamingProxy {
return listView;
}
public String callAllServers(String api, Map<String, String> params) throws NacosException {
String result = "";
List<String> snapshot = serversFromEndpoint;
if (!CollectionUtils.isEmpty(serverList)) {
snapshot = serverList;
}
try {
result = reqAPI(api, params, snapshot);
} catch (Exception e) {
LogUtils.LOG.error("NA", "req api:" + api + " failed, servers: " + snapshot, e);
}
if (StringUtils.isNotEmpty(result)) {
return result;
}
throw new IllegalStateException("failed to req API:/api/" + api + " after all sites(" + snapshot + ") tried");
}
public String reqAPI(String api, Map<String, String> params) throws NacosException {
@ -284,11 +291,13 @@ public class NamingProxy {
}
public String callServer(String api, Map<String, String> params, String curServer) throws NacosException {
return callServer(api, params, curServer, "GET");
return callServer(api, params, curServer, HttpMethod.GET);
}
public String callServer(String api, Map<String, String> params, String curServer, String method)
throws NacosException {
long start = System.currentTimeMillis();
long end = 0;
List<String> headers = Arrays.asList("Client-Version", UtilAndComs.VERSION,
"Accept-Encoding", "gzip,deflate,sdch",
@ -304,6 +313,10 @@ public class NamingProxy {
url = HttpClient.getPrefix() + curServer + api;
HttpClient.HttpResult result = HttpClient.request(url, headers, params, UtilAndComs.ENCODING, method);
end = System.currentTimeMillis();
MetricsMonitor.getNamingRequestMonitor(method, url, String.valueOf(result.code))
.record(end - start, TimeUnit.MILLISECONDS);
if (HttpURLConnection.HTTP_OK == result.code) {
return result.content;
@ -323,11 +336,13 @@ public class NamingProxy {
}
public String reqAPI(String api, Map<String, String> params, List<String> servers) {
return reqAPI(api, params, servers, "GET");
return reqAPI(api, params, servers, HttpMethod.GET);
}
public String reqAPI(String api, Map<String, String> params, List<String> servers, String method) {
params.put(Constants.REQUEST_PARAM_NAMESPACE_ID, getNamespaceId());
if (CollectionUtils.isEmpty(servers) && StringUtils.isEmpty(nacosDomain)) {
throw new IllegalArgumentException("no server available");
}
@ -363,4 +378,7 @@ public class NamingProxy {
}
public String getNamespaceId() {
return namespaceId;
}
}

View File

@ -34,7 +34,7 @@ public class UtilAndComs {
public static final String NACOS_URL_INSTANCE = NACOS_URL_BASE + "/instance";
public static final String DEFAULT_NAMESPACE_ID = "default";
public static final String DEFAULT_NAMESPACE_ID = "public";
public static final int REQUEST_DOMAIN_RETRY_COUNT = 3;
@ -45,4 +45,10 @@ public class UtilAndComs {
public static final String NACOS_NAMING_LOG_LEVEL = "com.alibaba.nacos.naming.log.level";
public static final String SERVER_ADDR_IP_SPLITER = ":";
public static final int DEFAULT_CLIENT_BEAT_THREAD_COUNT = Runtime.getRuntime().availableProcessors() > 1 ?
Runtime.getRuntime().availableProcessors() / 2 : 1;
public static final int DEFAULT_POLLING_THREAD_COUNT = Runtime.getRuntime().availableProcessors() > 1 ?
Runtime.getRuntime().availableProcessors() / 2 : 1;
}

View File

@ -16,6 +16,8 @@
package com.alibaba.nacos.client;
import com.alibaba.nacos.api.NacosFactory;
import com.alibaba.nacos.api.PropertyKeyConst;
import com.alibaba.nacos.api.common.Constants;
import com.alibaba.nacos.api.naming.NamingService;
import com.alibaba.nacos.api.naming.pojo.Instance;
import com.alibaba.nacos.api.naming.pojo.ListView;
@ -25,6 +27,7 @@ import org.junit.Test;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
/**
* @author <a href="mailto:zpf.073@gmail.com">nkorange</a>
@ -35,7 +38,11 @@ public class NamingTest {
@Ignore
public void testServiceList() throws Exception {
NamingService namingService = NacosFactory.createNamingService("127.0.0.1:8848");
Properties properties = new Properties();
properties.put(PropertyKeyConst.SERVER_ADDR, "11.160.165.126:8848");
properties.put(PropertyKeyConst.NAMESPACE, "t1");
NamingService namingService = NacosFactory.createNamingService(properties);
Instance instance = new Instance();
instance.setIp("1.1.1.1");
@ -48,9 +55,9 @@ public class NamingTest {
namingService.registerInstance("nacos.test.1", instance);
ExpressionSelector expressionSelector = new ExpressionSelector();
expressionSelector.setExpression("INSTANCE.metadata.registerSource = 'dubbo'");
ListView<String> serviceList = namingService.getServicesOfServer(1, 10, expressionSelector);
// ExpressionSelector expressionSelector = new ExpressionSelector();
// expressionSelector.setExpression("INSTANCE.metadata.registerSource = 'dubbo'");
// ListView<String> serviceList = namingService.getServicesOfServer(1, 10, expressionSelector);
Thread.sleep(1000000000L);
}

View File

@ -18,7 +18,7 @@
<parent>
<artifactId>nacos-all</artifactId>
<groupId>com.alibaba.nacos</groupId>
<version>0.7.0</version>
<version>0.8.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -20,6 +20,7 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* @author <a href="mailto:zpf.073@gmail.com">nkorange</a>
* @since 0.7.0
*/
@SpringBootApplication
public class CmdbApp {

View File

@ -28,6 +28,7 @@ import javax.servlet.http.HttpServletRequest;
/**
* @author <a href="mailto:zpf.073@gmail.com">nkorange</a>
* @since 0.7.0
*/
@RestController
@RequestMapping(UtilsAndCommons.NACOS_CMDB_CONTEXT + "/ops")

View File

@ -17,6 +17,7 @@ package com.alibaba.nacos.cmdb.core;
/**
* @author <a href="mailto:zpf.073@gmail.com">nkorange</a>
* @since 0.7.0
*/
public class CmdbManager {
}

View File

@ -20,6 +20,7 @@ import org.springframework.stereotype.Component;
/**
* @author <a href="mailto:zpf.073@gmail.com">nkorange</a>
* @since 0.7.0
*/
@Component
public class SwitchAndOptions {

View File

@ -36,6 +36,7 @@ import java.util.concurrent.TimeUnit;
/**
* @author <a href="mailto:zpf.073@gmail.com">nkorange</a>
* @since 0.7.0
*/
@Component
public class CmdbProvider implements CmdbReader, CmdbWriter {

View File

@ -22,6 +22,7 @@ import java.util.List;
/**
* @author <a href="mailto:zpf.073@gmail.com">nkorange</a>
* @since 0.7.0
*/
public interface CmdbReader {

View File

@ -17,6 +17,7 @@ package com.alibaba.nacos.cmdb.service;
/**
* @author <a href="mailto:zpf.073@gmail.com">nkorange</a>
* @since 0.7.0
*/
public interface CmdbWriter {
}

View File

@ -20,6 +20,7 @@ import org.slf4j.LoggerFactory;
/**
* @author nacos
* @since 0.7.0
*/
public class Loggers {

View File

@ -21,6 +21,7 @@ import java.util.concurrent.ThreadFactory;
/**
* @author <a href="mailto:zpf.073@gmail.com">nkorange</a>
* @since 0.7.0
*/
public class UtilsAndCommons {

View File

@ -18,7 +18,7 @@
<parent>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-all</artifactId>
<version>0.7.0</version>
<version>0.8.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -0,0 +1,39 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.nacos.common.util;
/**
* @author <a href="mailto:zpf.073@gmail.com">nkorange</a>
* @since 0.8.0
*/
public class HttpMethod {
public static final String GET = "GET";
public static final String HEAD = "HEAD";
public static final String POST = "POST";
public static final String PUT = "PUT";
public static final String PATCH = "PATCH";
public static final String DELETE = "DELETE";
public static final String OPTIONS = "PATCH";
public static final String TRACE = "TRACE";
}

View File

@ -17,7 +17,7 @@
<parent>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-all</artifactId>
<version>0.7.0</version>
<version>0.8.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@ -126,6 +126,26 @@
<artifactId>commons-lang3</artifactId>
<version>3.4</version>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-influx</artifactId>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-elastic</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
</dependencies>
<build>
<plugins>

View File

@ -17,6 +17,7 @@ package com.alibaba.nacos.config.server;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;
import java.net.UnknownHostException;
@ -25,6 +26,7 @@ import java.net.UnknownHostException;
*
* @author Nacos
*/
@EnableScheduling
@SpringBootApplication
public class Config {

View File

@ -16,6 +16,7 @@
package com.alibaba.nacos.config.server.aspect;
import com.alibaba.nacos.config.server.service.ConfigService;
import com.alibaba.nacos.config.server.monitor.MetricsMonitor;
import com.alibaba.nacos.config.server.utils.GroupKey2;
import com.alibaba.nacos.config.server.utils.LogUtil;
import com.alibaba.nacos.config.server.utils.MD5;
@ -23,6 +24,7 @@ import com.alibaba.nacos.config.server.utils.RequestUtil;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@ -33,8 +35,8 @@ import javax.servlet.http.HttpServletResponse;
* @author Nacos
*/
@Aspect
@Component
public class RequestLogAspect {
/**
* publish config
*/
@ -54,22 +56,24 @@ public class RequestLogAspect {
*/
private static final String CLIENT_INTERFACE_REMOVE_ALL_CONFIG
= "execution(* com.alibaba.nacos.config.server.controller.ConfigController.deleteConfig(..)) && args(request,"
+ "response,dataId,group,..)";
+ "response,dataId,group,tenant,..)";
/**
* publishSingle
*/
* */
@Around(CLIENT_INTERFACE_PUBLISH_SINGLE_CONFIG)
public Object interfacePublishSingle(ProceedingJoinPoint pjp, HttpServletRequest request,
HttpServletResponse response, String dataId, String group, String tenant,
String content) throws Throwable {
final String md5 = content == null ? null : MD5.getInstance().getMD5String(content);
MetricsMonitor.getPublishMonitor().incrementAndGet();
return logClientRequest("publish", pjp, request, response, dataId, group, tenant, md5);
}
/**
* removeAll
*/
* */
@Around(CLIENT_INTERFACE_REMOVE_ALL_CONFIG)
public Object interfaceRemoveAll(ProceedingJoinPoint pjp, HttpServletRequest request, HttpServletResponse response,
String dataId, String group, String tenant) throws Throwable {
@ -84,6 +88,7 @@ public class RequestLogAspect {
String dataId, String group, String tenant) throws Throwable {
final String groupKey = GroupKey2.getKey(dataId, group, tenant);
final String md5 = ConfigService.getContentMd5(groupKey);
MetricsMonitor.getConfigMonitor().incrementAndGet();
return logClientRequest("get", pjp, request, response, dataId, group, tenant, md5);
}

View File

@ -252,7 +252,7 @@ public class ConfigController {
inner.doPollingConfig(request, response, clientMd5Map, probeModify.length());
}
/*
/**
* 订阅改配置的客户端信息
*/
@RequestMapping(value = "/listener", method = RequestMethod.GET)

View File

@ -60,7 +60,7 @@ public class ConfigServletInner {
private static final int TRY_GET_LOCK_TIMES = 9;
private static final int START_LONGPULLING_VERSION_NUM = 204;
private static final int START_LONGPOLLING_VERSION_NUM = 204;
/**
* 轮询接口
@ -70,8 +70,8 @@ public class ConfigServletInner {
throws IOException, ServletException {
// 长轮询
if (LongPollingService.isSupportLongPulling(request)) {
longPollingService.addLongPullingClient(request, response, clientMd5Map, probeRequestSize);
if (LongPollingService.isSupportLongPolling(request)) {
longPollingService.addLongPollingClient(request, response, clientMd5Map, probeRequestSize);
return HttpServletResponse.SC_OK + "";
}
@ -91,7 +91,7 @@ public class ConfigServletInner {
/**
* 2.0.4版本以前, 返回值放入header中
*/
if (versionNum < START_LONGPULLING_VERSION_NUM) {
if (versionNum < START_LONGPOLLING_VERSION_NUM) {
response.addHeader(Constants.PROBE_MODIFY_RESPONSE, oldResult);
response.addHeader(Constants.PROBE_MODIFY_RESPONSE_NEW, newResult);
} else {

View File

@ -64,17 +64,17 @@ public class HealthController {
} else if (dbStatus.contains(heathWarnStr) && ServerListService.isAddressServerHealth() && ServerListService
.isInIpList()) {
sb.append("WARN:");
sb.append("从数据库 ").append(dbStatus.split(":")[1]).append(" down. ");
sb.append("slave db (").append(dbStatus.split(":")[1]).append(") down. ");
} else {
sb.append("DOWN:");
if (dbStatus.contains(heathDownStr)) {
sb.append("主数据库 ").append(dbStatus.split(":")[1]).append(" down. ");
sb.append("master db (").append(dbStatus.split(":")[1]).append(") down. ");
}
if (!ServerListService.isAddressServerHealth()) {
sb.append("地址服务器 down. ");
sb.append("address server down. ");
}
if (!ServerListService.isInIpList()) {
sb.append("server ").append(LOCAL_IP).append(" 不在地址服务器的IP列表中. ");
sb.append("server ip ").append(LOCAL_IP).append(" is not in the serverList of address server. ");
}
}

View File

@ -35,7 +35,7 @@ import java.util.HashMap;
import java.util.Map;
/**
* Config longpulling
* Config longpolling
*
* @author Nacos
*/
@ -48,7 +48,7 @@ public class ListenerController {
@Autowired
public ListenerController(ConfigSubService configSubService) {this.configSubService = configSubService;}
/*
/**
* 获取客户端订阅配置信息
*/
@RequestMapping(method = RequestMethod.GET)

View File

@ -15,9 +15,13 @@
*/
package com.alibaba.nacos.config.server.controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.alibaba.nacos.config.server.constant.Constants;
import com.alibaba.nacos.config.server.service.PersistService;
import com.alibaba.nacos.config.server.service.dump.DumpService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
@ -26,9 +30,6 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 管理控制器
*
@ -50,7 +51,9 @@ public class OpsController {
this.dumpService = dumpService;
}
// ops call
/**
* ops call
*/
@RequestMapping(value = "/localCache", method = RequestMethod.POST)
@ResponseBody
public String updateLocalCacheFromStore(HttpServletRequest request, HttpServletResponse respons) {

View File

@ -15,6 +15,9 @@
*/
package com.alibaba.nacos.config.server.exception;
import com.alibaba.nacos.config.server.monitor.MetricsMonitor;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.CannotGetJdbcConnectionException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
@ -37,6 +40,7 @@ public class GlobalExceptionHandler {
*/
@ExceptionHandler(IllegalArgumentException.class)
public void handleIllegalArgumentException(HttpServletResponse response, Exception ex) throws IOException {
MetricsMonitor.getIllegalArgumentException().increment();
response.setStatus(400);
if (ex.getMessage() != null) {
response.getWriter().println(ex.getMessage());
@ -52,6 +56,7 @@ public class GlobalExceptionHandler {
*/
@ExceptionHandler(NacosException.class)
public void handleNacosException(HttpServletResponse response, NacosException ex) throws IOException {
MetricsMonitor.getNacosException().increment();
response.setStatus(ex.getErrCode());
if (ex.getErrMsg() != null) {
response.getWriter().println(ex.getErrMsg());
@ -60,4 +65,15 @@ public class GlobalExceptionHandler {
}
}
/**
* For DataAccessException
*
* @throws DataAccessException
*/
@ExceptionHandler(DataAccessException.class)
public void handleDataAccessException(HttpServletResponse response, DataAccessException ex) throws DataAccessException {
MetricsMonitor.getDbException().increment();
throw new CannotGetJdbcConnectionException(ex.getMessage());
}
}

View File

@ -16,6 +16,7 @@
package com.alibaba.nacos.config.server.manager;
import com.alibaba.nacos.config.server.constant.Constants;
import com.alibaba.nacos.config.server.monitor.MetricsMonitor;
import com.alibaba.nacos.config.server.utils.LogUtil;
import org.slf4j.Logger;
@ -51,6 +52,7 @@ public final class TaskManager implements TaskManagerMBean {
private String name;
class ProcessRunnable implements Runnable {
public void run() {
@ -140,6 +142,7 @@ public final class TaskManager implements TaskManagerMBean {
this.lock.lock();
try {
this.tasks.remove(type);
MetricsMonitor.getDumpTaskMonitor().set(tasks.size());
} finally {
this.lock.unlock();
}
@ -150,12 +153,12 @@ public final class TaskManager implements TaskManagerMBean {
*
* @param type
* @param task
* @param previousTask
*/
public void addTask(String type, AbstractTask task) {
this.lock.lock();
try {
AbstractTask oldTask = tasks.put(type, task);
MetricsMonitor.getDumpTaskMonitor().set(tasks.size());
if (null != oldTask) {
task.merge(oldTask);
}
@ -181,6 +184,7 @@ public final class TaskManager implements TaskManagerMBean {
}
// 先将任务从任务Map中删除
this.tasks.remove(entry.getKey());
MetricsMonitor.getDumpTaskMonitor().set(tasks.size());
}
} finally {
this.lock.unlock();

View File

@ -28,6 +28,6 @@ public interface TaskManagerMBean {
*
* @return info
*/
public String getTaskInfos();
String getTaskInfos();
}

View File

@ -0,0 +1,42 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.nacos.config.server.model;
/**
* user info
*
* @author wfnuser
*/
public class User {
private String username;
private String password;
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
}

View File

@ -20,10 +20,12 @@ import com.alibaba.nacos.config.server.service.ConfigService;
import com.alibaba.nacos.config.server.service.TimerTaskService;
import com.alibaba.nacos.config.server.service.notify.AsyncNotifyService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import static com.alibaba.nacos.config.server.utils.LogUtil.memoryLog;
@ -34,6 +36,7 @@ import static com.alibaba.nacos.config.server.utils.LogUtil.memoryLog;
*/
@Service
public class MemoryMonitor {
@Autowired
public MemoryMonitor(AsyncNotifyService notifySingleService) {
@ -45,9 +48,16 @@ public class MemoryMonitor {
TimerTaskService.scheduleWithFixedDelay(new NotifyTaskQueueMonitorTask(notifySingleService), DELAY_SECONDS,
DELAY_SECONDS, TimeUnit.SECONDS);
}
static final long DELAY_SECONDS = 10;
@Scheduled(cron = "0 0 0 * * ?")
public void clear() {
MetricsMonitor.getConfigMonitor().set(0);
MetricsMonitor.getPublishMonitor().set(0);
}
}
class PrintGetConfigResponeTask implements Runnable {
@ -58,6 +68,7 @@ class PrintGetConfigResponeTask implements Runnable {
}
class PrintMemoryTask implements Runnable {
@Override
public void run() {
int groupCount = ConfigService.groupCount();
@ -65,11 +76,14 @@ class PrintMemoryTask implements Runnable {
long subCount = ClientTrackService.subscriberCount();
memoryLog.info("groupCount={}, subscriberClientCount={}, subscriberCount={}", groupCount, subClientCount,
subCount);
MetricsMonitor.getConfigCountMonitor().set(groupCount);
}
}
class NotifyTaskQueueMonitorTask implements Runnable {
final private AsyncNotifyService notifySingleService;
private AtomicInteger notifyTask = new AtomicInteger();
NotifyTaskQueueMonitorTask(AsyncNotifyService notifySingleService) {
this.notifySingleService = notifySingleService;
@ -77,16 +91,10 @@ class NotifyTaskQueueMonitorTask implements Runnable {
@Override
public void run() {
int size = ((ScheduledThreadPoolExecutor)notifySingleService.getExecutor()).getQueue().size();
memoryLog.info("notifySingleServiceThreadPool-{}, toNotifyTaskSize={}",
new Object[] {((ScheduledThreadPoolExecutor)notifySingleService.getExecutor()).getClass().getName(),
((ScheduledThreadPoolExecutor)notifySingleService.getExecutor()).getQueue().size()});
// for(Map.Entry<String, Executor> entry: notifySingleService.getExecutors().entrySet()) {
// ThreadPoolExecutor pool = (ThreadPoolExecutor) entry.getValue();
// String target = entry.getKey();
// memoryLog.info("notifySingleServiceThreadPool-{}, toNotifyTaskSize={}",
// new Object[] { target, pool.getQueue().size() });
// }
size});
MetricsMonitor.getNotifyTaskMonitor().set(size);
}
}

View File

@ -0,0 +1,124 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.nacos.config.server.monitor;
import io.micrometer.core.instrument.*;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
/**
* Metrics Monitor
*
* @author Nacos
*/
public class MetricsMonitor {
private static AtomicInteger getConfig = new AtomicInteger();
private static AtomicInteger publish = new AtomicInteger();
private static AtomicInteger longPolling = new AtomicInteger();
private static AtomicInteger configCount = new AtomicInteger();
private static AtomicInteger notifyTask = new AtomicInteger();
private static AtomicInteger dumpTask = new AtomicInteger();
static {
List<Tag> tags = new ArrayList<Tag>();
tags.add(new ImmutableTag("module", "config"));
tags.add(new ImmutableTag("name", "getConfig"));
Metrics.gauge("nacos_monitor", tags, getConfig);
tags = new ArrayList<Tag>();
tags.add(new ImmutableTag("module", "config"));
tags.add(new ImmutableTag("name", "publish"));
Metrics.gauge("nacos_monitor", tags, publish);
tags = new ArrayList<Tag>();
tags.add(new ImmutableTag("module", "config"));
tags.add(new ImmutableTag("name", "longPolling"));
Metrics.gauge("nacos_monitor", tags, longPolling);
tags = new ArrayList<Tag>();
tags.add(new ImmutableTag("module", "config"));
tags.add(new ImmutableTag("name", "configCount"));
Metrics.gauge("nacos_monitor", tags, configCount);
tags = new ArrayList<Tag>();
tags.add(new ImmutableTag("module", "config"));
tags.add(new ImmutableTag("name", "notifyTask"));
Metrics.gauge("nacos_monitor", tags, notifyTask);
tags = new ArrayList<Tag>();
tags.add(new ImmutableTag("module", "config"));
tags.add(new ImmutableTag("name", "dumpTask"));
Metrics.gauge("nacos_monitor", tags, dumpTask);
}
public static AtomicInteger getConfigMonitor() {
return getConfig;
}
public static AtomicInteger getPublishMonitor() {
return publish;
}
public static AtomicInteger getLongPollingMonitor() {
return longPolling;
}
public static AtomicInteger getConfigCountMonitor() {
return configCount;
}
public static AtomicInteger getNotifyTaskMonitor() {
return notifyTask;
}
public static AtomicInteger getDumpTaskMonitor() {
return dumpTask;
}
public static Timer getNotifyRtTimer() {
return Metrics.timer("nacos_timer",
"module", "config", "name", "notifyRt");
}
public static Counter getIllegalArgumentException() {
return Metrics.counter("nacos_exception",
"module", "config", "name", "illegalArgument");
}
public static Counter getNacosException() {
return Metrics.counter("nacos_exception",
"module", "config", "name", "nacos");
}
public static Counter getDbException() {
return Metrics.counter("nacos_exception",
"module", "config", "name", "db");
}
public static Counter getConfigNotifyException() {
return Metrics.counter("nacos_exception",
"module", "config", "name", "configNotify");
}
public static Counter getUnhealthException() {
return Metrics.counter("nacos_exception",
"module", "config", "name", "unhealth");
}
}

View File

@ -15,7 +15,19 @@
*/
package com.alibaba.nacos.config.server.service;
import com.alibaba.nacos.config.server.monitor.MetricsMonitor;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.annotation.PostConstruct;
import javax.sql.DataSource;
import com.alibaba.nacos.config.server.utils.PropertyUtil;
import org.apache.commons.dbcp.BasicDataSource;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
@ -28,15 +40,6 @@ import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.stereotype.Service;
import org.springframework.transaction.support.TransactionTemplate;
import javax.annotation.PostConstruct;
import javax.sql.DataSource;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static com.alibaba.nacos.common.util.SystemUtils.STANDALONE_MODE;
import static com.alibaba.nacos.config.server.service.PersistService.CONFIG_INFO4BETA_ROW_MAPPER;
import static com.alibaba.nacos.config.server.utils.LogUtil.defaultLog;
@ -51,9 +54,6 @@ import static com.alibaba.nacos.config.server.utils.LogUtil.fatalLog;
public class BasicDataSourceServiceImpl implements DataSourceService {
private static final String JDBC_DRIVER_NAME = "com.mysql.jdbc.Driver";
@Autowired
private PropertyUtil propertyUtil;
/**
* JDBC执行超时时间, 单位秒
*/
@ -109,7 +109,7 @@ public class BasicDataSourceServiceImpl implements DataSourceService {
* 事务的超时时间需要与普通操作区分开
*/
tjt.setTimeout(TRANSACTION_QUERY_TIMEOUT);
if (!STANDALONE_MODE || propertyUtil.isStandaloneUseMysql()) {
if (!STANDALONE_MODE || PropertyUtil.isStandaloneUseMysql()) {
try {
reload();
} catch (IOException e) {
@ -124,6 +124,7 @@ public class BasicDataSourceServiceImpl implements DataSourceService {
}
}
@Override
public synchronized void reload() throws IOException {
List<BasicDataSource> dblist = new ArrayList<BasicDataSource>();
try {
@ -201,6 +202,7 @@ public class BasicDataSourceServiceImpl implements DataSourceService {
}
}
@Override
public boolean checkMasterWritable() {
testMasterWritableJT.setDataSource(jt.getDataSource());
@ -224,14 +226,17 @@ public class BasicDataSourceServiceImpl implements DataSourceService {
}
@Override
public JdbcTemplate getJdbcTemplate() {
return this.jt;
}
@Override
public TransactionTemplate getTransactionTemplate() {
return this.tjt;
}
@Override
public String getCurrentDBUrl() {
DataSource ds = this.jt.getDataSource();
if (ds == null) {
@ -241,6 +246,7 @@ public class BasicDataSourceServiceImpl implements DataSourceService {
return bds.getUrl();
}
@Override
public String getHealth() {
for (int i = 0; i < isHealthList.size(); i++) {
if (!isHealthList.get(i)) {
@ -276,6 +282,7 @@ public class BasicDataSourceServiceImpl implements DataSourceService {
}
class SelectMasterTask implements Runnable {
@Override
public void run() {
defaultLog.info("check master db.");
boolean isFound = false;
@ -303,12 +310,14 @@ public class BasicDataSourceServiceImpl implements DataSourceService {
if (!isFound) {
fatalLog.error("[master-db] master db not found.");
MetricsMonitor.getDbException().increment();
}
}
}
@SuppressWarnings("PMD.ClassNamingShouldBeCamelRule")
class CheckDBHealthTask implements Runnable {
@Override
public void run() {
defaultLog.info("check db health.");
String sql = "SELECT * FROM config_info_beta WHERE id = 1";
@ -325,6 +334,8 @@ public class BasicDataSourceServiceImpl implements DataSourceService {
fatalLog.error("[db-error] slave db {} down.", getIpFromUrl(dataSourceList.get(i).getUrl()));
}
isHealthList.set(i, Boolean.FALSE);
MetricsMonitor.getDbException().increment();
}
}
}

View File

@ -16,6 +16,7 @@
package com.alibaba.nacos.config.server.service;
import com.alibaba.nacos.config.server.model.SampleResult;
import com.alibaba.nacos.config.server.monitor.MetricsMonitor;
import com.alibaba.nacos.config.server.utils.GroupKey;
import com.alibaba.nacos.config.server.utils.LogUtil;
import com.alibaba.nacos.config.server.utils.MD5Util;
@ -65,7 +66,7 @@ public class LongPollingService extends AbstractEventListener {
}
public Map<String, String> getClientSubConfigInfo(String clientIp) {
ClientLongPulling record = getClientPollingRecord(clientIp);
ClientLongPolling record = getClientPollingRecord(clientIp);
if (record == null) {
return Collections.<String, String>emptyMap();
@ -79,9 +80,9 @@ public class LongPollingService extends AbstractEventListener {
SampleResult sampleResult = new SampleResult();
Map<String, String> lisentersGroupkeyStatus = new HashMap<String, String>(50);
for (ClientLongPulling clientLongPulling : allSubs) {
if (clientLongPulling.clientMd5Map.containsKey(groupKey)) {
lisentersGroupkeyStatus.put(clientLongPulling.ip, clientLongPulling.clientMd5Map.get(groupKey));
for (ClientLongPolling clientLongPolling : allSubs) {
if (clientLongPolling.clientMd5Map.containsKey(groupKey)) {
lisentersGroupkeyStatus.put(clientLongPolling.ip, clientLongPolling.clientMd5Map.get(groupKey));
}
}
sampleResult.setLisentersGroupkeyStatus(lisentersGroupkeyStatus);
@ -92,11 +93,11 @@ public class LongPollingService extends AbstractEventListener {
SampleResult sampleResult = new SampleResult();
Map<String, String> lisentersGroupkeyStatus = new HashMap<String, String>(50);
for (ClientLongPulling clientLongPulling : allSubs) {
if (clientLongPulling.ip.equals(clientIp)) {
for (ClientLongPolling clientLongPolling : allSubs) {
if (clientLongPolling.ip.equals(clientIp)) {
// 一个ip可能有多个监听
if (!lisentersGroupkeyStatus.equals(clientLongPulling.clientMd5Map)) {
lisentersGroupkeyStatus.putAll(clientLongPulling.clientMd5Map);
if (!lisentersGroupkeyStatus.equals(clientLongPolling.clientMd5Map)) {
lisentersGroupkeyStatus.putAll(clientLongPolling.clientMd5Map);
}
}
}
@ -128,18 +129,18 @@ public class LongPollingService extends AbstractEventListener {
return null;
}
HashMap<String, Set<String>> app2Groupkeys = new HashMap<String, Set<String>>(50);
for (ClientLongPulling clientLongPulling : allSubs) {
if (StringUtils.isEmpty(clientLongPulling.appName) || "unknown".equalsIgnoreCase(
clientLongPulling.appName)) {
for (ClientLongPolling clientLongPolling : allSubs) {
if (StringUtils.isEmpty(clientLongPolling.appName) || "unknown".equalsIgnoreCase(
clientLongPolling.appName)) {
continue;
}
Set<String> appSubscribeConfigs = app2Groupkeys.get(clientLongPulling.appName);
Set<String> clientSubscribeConfigs = clientLongPulling.clientMd5Map.keySet();
Set<String> appSubscribeConfigs = app2Groupkeys.get(clientLongPolling.appName);
Set<String> clientSubscribeConfigs = clientLongPolling.clientMd5Map.keySet();
if (appSubscribeConfigs == null) {
appSubscribeConfigs = new HashSet<String>(clientSubscribeConfigs.size());
}
appSubscribeConfigs.addAll(clientSubscribeConfigs);
app2Groupkeys.put(clientLongPulling.appName, appSubscribeConfigs);
app2Groupkeys.put(clientLongPolling.appName, appSubscribeConfigs);
}
return app2Groupkeys;
@ -187,27 +188,27 @@ public class LongPollingService extends AbstractEventListener {
return sampleResult;
}
private ClientLongPulling getClientPollingRecord(String clientIp) {
private ClientLongPolling getClientPollingRecord(String clientIp) {
if (allSubs == null) {
return null;
}
for (ClientLongPulling clientLongPulling : allSubs) {
HttpServletRequest request = (HttpServletRequest)clientLongPulling.asyncContext.getRequest();
for (ClientLongPolling clientLongPolling : allSubs) {
HttpServletRequest request = (HttpServletRequest) clientLongPolling.asyncContext.getRequest();
if (clientIp.equals(RequestUtil.getRemoteIp(request))) {
return clientLongPulling;
return clientLongPolling;
}
}
return null;
}
public void addLongPullingClient(HttpServletRequest req, HttpServletResponse rsp, Map<String, String> clientMd5Map,
public void addLongPollingClient(HttpServletRequest req, HttpServletResponse rsp, Map<String, String> clientMd5Map,
int probeRequestSize) {
String str = req.getHeader(LongPollingService.LONG_PULLING_HEADER);
String noHangUpFlag = req.getHeader(LongPollingService.LONG_PULLING_NO_HANG_UP_HEADER);
String str = req.getHeader(LongPollingService.LONG_POLLING_HEADER);
String noHangUpFlag = req.getHeader(LongPollingService.LONG_POLLING_NO_HANG_UP_HEADER);
String appName = req.getHeader(RequestUtil.CLIENT_APPNAME_HEADER);
String tag = req.getHeader("Vipserver-Tag");
int delayTime = SwitchService.getSwitchInteger(SwitchService.FIXED_DELAY_TIME, 500);
@ -241,7 +242,7 @@ public class LongPollingService extends AbstractEventListener {
asyncContext.setTimeout(0L);
scheduler.execute(
new ClientLongPulling(asyncContext, clientMd5Map, ip, probeRequestSize, timeout, appName, tag));
new ClientLongPolling(asyncContext, clientMd5Map, ip, probeRequestSize, timeout, appName, tag));
}
@Override
@ -263,20 +264,20 @@ public class LongPollingService extends AbstractEventListener {
}
}
static public boolean isSupportLongPulling(HttpServletRequest req) {
return null != req.getHeader(LONG_PULLING_HEADER);
static public boolean isSupportLongPolling(HttpServletRequest req) {
return null != req.getHeader(LONG_POLLING_HEADER);
}
@SuppressWarnings("PMD.ThreadPoolCreationRule")
public LongPollingService() {
allSubs = new ConcurrentLinkedQueue<ClientLongPulling>();
allSubs = new ConcurrentLinkedQueue<ClientLongPolling>();
scheduler = Executors.newScheduledThreadPool(1, new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r);
t.setDaemon(true);
t.setName("com.alibaba.nacos.LongPulling");
t.setName("com.alibaba.nacos.LongPolling");
return t;
}
});
@ -285,15 +286,15 @@ public class LongPollingService extends AbstractEventListener {
// =================
static public final String LONG_PULLING_HEADER = "Long-Pulling-Timeout";
static public final String LONG_PULLING_NO_HANG_UP_HEADER = "Long-Pulling-Timeout-No-Hangup";
static public final String LONG_POLLING_HEADER = "Long-Pulling-Timeout";
static public final String LONG_POLLING_NO_HANG_UP_HEADER = "Long-Pulling-Timeout-No-Hangup";
final ScheduledExecutorService scheduler;
/**
* 长轮询订阅关系
*/
final Queue<ClientLongPulling> allSubs;
final Queue<ClientLongPolling> allSubs;
// =================
@ -302,8 +303,8 @@ public class LongPollingService extends AbstractEventListener {
public void run() {
try {
ConfigService.getContentBetaMd5(groupKey);
for (Iterator<ClientLongPulling> iter = allSubs.iterator(); iter.hasNext(); ) {
ClientLongPulling clientSub = iter.next();
for (Iterator<ClientLongPolling> iter = allSubs.iterator(); iter.hasNext(); ) {
ClientLongPolling clientSub = iter.next();
if (clientSub.clientMd5Map.containsKey(groupKey)) {
// 如果beta发布且不在beta列表直接跳过
if (isBeta && !betaIps.contains(clientSub.ip)) {
@ -359,23 +360,24 @@ public class LongPollingService extends AbstractEventListener {
@Override
public void run() {
memoryLog.info("[long-pulling] client count " + allSubs.size());
MetricsMonitor.getLongPollingMonitor().set(allSubs.size());
}
}
// =================
class ClientLongPulling implements Runnable {
class ClientLongPolling implements Runnable {
@Override
public void run() {
asyncTimeoutFuture = scheduler.schedule(new Runnable() {
public void run() {
try {
getRetainIps().put(ClientLongPulling.this.ip, System.currentTimeMillis());
getRetainIps().put(ClientLongPolling.this.ip, System.currentTimeMillis());
/**
* 删除订阅关系
*/
allSubs.remove(ClientLongPulling.this);
allSubs.remove(ClientLongPolling.this);
if (isFixedPolling()) {
LogUtil.clientLog.info("{}|{}|{}|{}|{}|{}",
@ -400,7 +402,7 @@ public class LongPollingService extends AbstractEventListener {
sendResponse(null);
}
} catch (Throwable t) {
LogUtil.defaultLog.error("long pulling error:" + t.getMessage(), t.getCause());
LogUtil.defaultLog.error("long polling error:" + t.getMessage(), t.getCause());
}
}
@ -446,7 +448,7 @@ public class LongPollingService extends AbstractEventListener {
}
}
ClientLongPulling(AsyncContext ac, Map<String, String> clientMd5Map, String ip, int probeRequestSize,
ClientLongPolling(AsyncContext ac, Map<String, String> clientMd5Map, String ip, int probeRequestSize,
long timeoutTime, String appName, String tag) {
this.asyncContext = ac;
this.clientMd5Map = clientMd5Map;

View File

@ -33,6 +33,7 @@ import java.util.Map.Entry;
import javax.annotation.PostConstruct;
import com.alibaba.nacos.config.server.model.*;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
@ -53,19 +54,6 @@ import org.springframework.transaction.TransactionSystemException;
import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionTemplate;
import org.springframework.util.CollectionUtils;
import com.alibaba.nacos.config.server.model.ConfigAdvanceInfo;
import com.alibaba.nacos.config.server.model.ConfigAllInfo;
import com.alibaba.nacos.config.server.model.ConfigHistoryInfo;
import com.alibaba.nacos.config.server.model.ConfigInfo;
import com.alibaba.nacos.config.server.model.ConfigInfo4Beta;
import com.alibaba.nacos.config.server.model.ConfigInfo4Tag;
import com.alibaba.nacos.config.server.model.ConfigInfoAggr;
import com.alibaba.nacos.config.server.model.ConfigInfoBase;
import com.alibaba.nacos.config.server.model.ConfigInfoChanged;
import com.alibaba.nacos.config.server.model.ConfigKey;
import com.alibaba.nacos.config.server.model.Page;
import com.alibaba.nacos.config.server.model.SubInfo;
import com.alibaba.nacos.config.server.model.TenantInfo;
import com.alibaba.nacos.config.server.utils.LogUtil;
import com.alibaba.nacos.config.server.utils.MD5;
import com.alibaba.nacos.config.server.utils.PaginationHelper;
@ -455,6 +443,15 @@ public class PersistService {
}
}
static final class UserRowMapper implements RowMapper<User> {
public User mapRow(ResultSet rs, int rowNum) throws SQLException {
User user = new User();
user.setUsername(rs.getString("username"));
user.setPassword(rs.getString("password"));
return user;
}
}
public synchronized void reload() throws IOException {
this.dataSourceService.reload();
}
@ -3113,6 +3110,22 @@ public class PersistService {
}
}
public User findUserByUsername(String username) {
String sql = "SELECT username,password FROM users WHERE username=? ";
try {
return this.jt.queryForObject(sql, new Object[] {username}, USER_ROW_MAPPER);
} catch (CannotGetJdbcConnectionException e) {
fatalLog.error("[db-error] " + e.toString(), e);
throw e;
} catch (EmptyResultDataAccessException e) {
return null;
} catch (Exception e) {
fatalLog.error("[db-other-error]" + e.getMessage(), e);
throw new RuntimeException(e);
}
}
private List<ConfigInfo> convertDeletedConfig(List<Map<String, Object>> list) {
List<ConfigInfo> configs = new ArrayList<ConfigInfo>();
for (Map<String, Object> map : list) {
@ -3265,6 +3278,8 @@ public class PersistService {
static final TenantInfoRowMapper TENANT_INFO_ROW_MAPPER = new TenantInfoRowMapper();
static final UserRowMapper USER_ROW_MAPPER = new UserRowMapper();
static final ConfigInfoWrapperRowMapper CONFIG_INFO_WRAPPER_ROW_MAPPER = new ConfigInfoWrapperRowMapper();
static final ConfigKeyRowMapper CONFIG_KEY_ROW_MAPPER = new ConfigKeyRowMapper();

View File

@ -16,6 +16,7 @@
package com.alibaba.nacos.config.server.service;
import com.alibaba.nacos.config.server.constant.Constants;
import com.alibaba.nacos.config.server.monitor.MetricsMonitor;
import com.alibaba.nacos.config.server.service.notify.NotifyService;
import com.alibaba.nacos.config.server.service.notify.NotifyService.HttpResult;
import com.alibaba.nacos.config.server.utils.LogUtil;
@ -377,6 +378,7 @@ public class ServerListService implements ApplicationListener<WebServerInitializ
serverListUnhealth.add(serverIp);
}
defaultLog.error("unhealthIp:{}, unhealthCount:{}", serverIp, failCount);
MetricsMonitor.getUnhealthException().increment();
}
}
@ -391,6 +393,7 @@ public class ServerListService implements ApplicationListener<WebServerInitializ
serverListUnhealth.add(serverIp);
}
defaultLog.error("unhealthIp:{}, unhealthCount:{}", serverIp, failCount);
MetricsMonitor.getUnhealthException().increment();
}
}
}

View File

@ -17,6 +17,7 @@ package com.alibaba.nacos.config.server.service.notify;
import com.alibaba.nacos.config.server.constant.Constants;
import com.alibaba.nacos.config.server.service.ConfigDataChangeEvent;
import com.alibaba.nacos.config.server.monitor.MetricsMonitor;
import com.alibaba.nacos.config.server.service.ServerListService;
import com.alibaba.nacos.config.server.service.trace.ConfigTraceService;
import com.alibaba.nacos.config.server.utils.*;
@ -192,6 +193,7 @@ public class AsyncNotifyService extends AbstractEventListener {
ConfigTraceService.NOTIFY_EVENT_ERROR, delayed,
task.target);
//get delay time and set fail count to the task
int delay = getDelayTime(task);
@ -207,6 +209,7 @@ public class AsyncNotifyService extends AbstractEventListener {
new Object[] {task.target, task.getDataId(),
task.getGroup(), task.getLastModified()});
MetricsMonitor.getConfigNotifyException().increment();
}
HttpClientUtils.closeQuietly(response);
}
@ -238,6 +241,7 @@ public class AsyncNotifyService extends AbstractEventListener {
new Object[] {task.target, task.getDataId(),
task.getGroup(), task.getLastModified()});
MetricsMonitor.getConfigNotifyException().increment();
}
@Override
@ -262,6 +266,7 @@ public class AsyncNotifyService extends AbstractEventListener {
new Object[] {task.target, task.getDataId(),
task.getGroup(), task.getLastModified()});
MetricsMonitor.getConfigNotifyException().increment();
}
private NotifySingleTask task;

View File

@ -18,6 +18,7 @@ package com.alibaba.nacos.config.server.service.notify;
import com.alibaba.nacos.config.server.constant.Constants;
import com.alibaba.nacos.config.server.manager.AbstractTask;
import com.alibaba.nacos.config.server.manager.TaskProcessor;
import com.alibaba.nacos.config.server.monitor.MetricsMonitor;
import com.alibaba.nacos.config.server.service.ServerListService;
import com.alibaba.nacos.config.server.service.notify.NotifyService.HttpResult;
import com.alibaba.nacos.config.server.service.trace.ConfigTraceService;
@ -29,6 +30,7 @@ import org.slf4j.LoggerFactory;
import java.text.MessageFormat;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;
import static com.alibaba.nacos.common.util.SystemUtils.LOCAL_IP;
@ -76,8 +78,12 @@ public class NotifyTaskProcessor implements TaskProcessor {
if (result.code == HttpStatus.SC_OK) {
ConfigTraceService.logNotifyEvent(dataId, group, tenant, null, lastModified, LOCAL_IP,
ConfigTraceService.NOTIFY_EVENT_OK, delayed, serverIp);
MetricsMonitor.getNotifyRtTimer().record(delayed, TimeUnit.MILLISECONDS);
return true;
} else {
MetricsMonitor.getConfigNotifyException().increment();
log.error("[notify-error] {}, {}, to {}, result {}", new Object[] {dataId, group,
serverIp, result.code});
ConfigTraceService.logNotifyEvent(dataId, group, tenant, null, lastModified, LOCAL_IP,
@ -85,6 +91,7 @@ public class NotifyTaskProcessor implements TaskProcessor {
return false;
}
} catch (Exception e) {
MetricsMonitor.getConfigNotifyException().increment();
log.error(
"[notify-exception] " + dataId + ", " + group + ", to " + serverIp + ", "
+ e.toString());

View File

@ -15,11 +15,14 @@
*/
package com.alibaba.nacos.config.server.service.trace;
import com.alibaba.nacos.config.server.monitor.MetricsMonitor;
import com.alibaba.nacos.config.server.utils.LogUtil;
import com.alibaba.nacos.config.server.utils.MD5;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import java.util.concurrent.TimeUnit;
import static com.alibaba.nacos.common.util.SystemUtils.LOCAL_IP;
/**
@ -68,6 +71,7 @@ public class ConfigTraceService {
if (!LogUtil.traceLog.isInfoEnabled()) {
return;
}
MetricsMonitor.getNotifyRtTimer().record(delayed, TimeUnit.MILLISECONDS);
// 方便tlog切分
if (StringUtils.isBlank(tenant)) {
tenant = null;

View File

@ -24,15 +24,40 @@ import javax.servlet.http.HttpServletRequest;
*/
public class RequestUtil {
private static final String X_REAL_IP = "X-Real-IP";
private static final String X_FORWARDED_FOR = "X-Forwarded-For";
private static final String X_FORWARDED_FOR_SPLIT_SYMBOL = ",";
public static final String CLIENT_APPNAME_HEADER = "Client-AppName";
/**
* get real client ip
* <p>
* first use X-Forwarded-For header https://zh.wikipedia.org/wiki/X-Forwarded-For
* next nginx X-Real-IP
* last {@link HttpServletRequest#getRemoteAddr()}
*
* @param request {@link HttpServletRequest}
* @return
*/
public static String getRemoteIp(HttpServletRequest request) {
String nginxHeader = request.getHeader("X-Real-IP");
return (nginxHeader == null) ? request.getRemoteAddr() : nginxHeader;
String xForwardedFor = request.getHeader(X_FORWARDED_FOR);
if (!StringUtils.isBlank(xForwardedFor)) {
return xForwardedFor.split(X_FORWARDED_FOR_SPLIT_SYMBOL)[0].trim();
}
String nginxHeader = request.getHeader(X_REAL_IP);
return StringUtils.isBlank(nginxHeader) ? request.getRemoteAddr() : nginxHeader;
}
/**
* 获取 header 中的客服端应用名称
* <p>
*
* @param request {@link HttpServletRequest}
* @return 可能为 null
*/
public static String getAppName(HttpServletRequest request) {
return request.getHeader("Client-AppName");
return request.getHeader(CLIENT_APPNAME_HEADER);
}
}

View File

@ -177,3 +177,18 @@ CREATE TABLE `tenant_info` (
UNIQUE KEY `uk_tenant_info_kptenantid` (`kp`,`tenant_id`),
KEY `idx_tenant_id` (`tenant_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='tenant_info';
CREATE TABLE users (
username varchar(50) NOT NULL PRIMARY KEY,
password varchar(500) NOT NULL,
enabled boolean NOT NULL
);
CREATE TABLE roles (
username varchar(50) NOT NULL,
role varchar(50) NOT NULL
);
INSERT INTO users (username, password, enabled) VALUES ('admin', '$2a$10$HxtJtd59imujvbux.i55zOGewhnJiLVXX8D9AETDMV.XtBLDGOXtW', TRUE);
INSERT INTO roles (username, role) VALUES ('admin', 'ROLE_ADMIN');

View File

@ -173,3 +173,17 @@ CREATE TABLE tenant_info (
CREATE INDEX tenant_info_tenant_id_idx ON tenant_info(tenant_id);
CREATE TABLE users (
username varchar(50) NOT NULL PRIMARY KEY,
password varchar(500) NOT NULL,
enabled boolean NOT NULL
);
CREATE TABLE roles (
username varchar(50) NOT NULL,
role varchar(50) NOT NULL
);
INSERT INTO users (username, password, enabled) VALUES ('admin', '$2a$10$HxtJtd59imujvbux.i55zOGewhnJiLVXX8D9AETDMV.XtBLDGOXtW', TRUE);
INSERT INTO roles (username, role) VALUES ('admin', 'ROLE_ADMIN');

View File

@ -0,0 +1,61 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.nacos.config.server.utils;
import org.junit.Assert;
import org.junit.Test;
import org.mockito.Mockito;
import javax.servlet.http.HttpServletRequest;
import static org.mockito.ArgumentMatchers.eq;
public class RequestUtilTest {
private static final String X_REAL_IP = "X-Real-IP";
private static final String X_FORWARDED_FOR = "X-Forwarded-For";
@Test
public void getRemoteIp() {
HttpServletRequest request = Mockito.mock(HttpServletRequest.class);
Mockito.when(request.getRemoteAddr()).thenReturn("127.0.0.1");
Assert.assertEquals(RequestUtil.getRemoteIp(request), "127.0.0.1");
Mockito.when(request.getHeader(eq(X_REAL_IP))).thenReturn("127.0.0.2");
Assert.assertEquals(RequestUtil.getRemoteIp(request), "127.0.0.2");
Mockito.when(request.getHeader(eq(X_FORWARDED_FOR))).thenReturn("127.0.0.3");
Assert.assertEquals(RequestUtil.getRemoteIp(request), "127.0.0.3");
Mockito.when(request.getHeader(eq(X_FORWARDED_FOR))).thenReturn("127.0.0.3, 127.0.0.4");
Assert.assertEquals(RequestUtil.getRemoteIp(request), "127.0.0.3");
Mockito.when(request.getHeader(eq(X_FORWARDED_FOR))).thenReturn("");
Assert.assertEquals(RequestUtil.getRemoteIp(request), "127.0.0.2");
Mockito.when(request.getHeader(eq(X_REAL_IP))).thenReturn("");
Assert.assertEquals(RequestUtil.getRemoteIp(request), "127.0.0.1");
}
@Test
public void getAppName() {
HttpServletRequest request = Mockito.mock(HttpServletRequest.class);
Mockito.when(request.getHeader(eq(RequestUtil.CLIENT_APPNAME_HEADER))).thenReturn("test");
Assert.assertEquals(RequestUtil.getAppName(request), "test");
}
}

View File

@ -18,7 +18,7 @@
<parent>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-all</artifactId>
<version>0.7.0</version>
<version>0.8.0-SNAPSHOT</version>
</parent>
<artifactId>nacos-console</artifactId>
<!--<packaging>war</packaging>-->
@ -65,13 +65,33 @@
<artifactId>mockito-core</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
</dependency>
</dependencies>
<build>
<finalName>nacos-server</finalName>
<plugins>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
<addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.1.1.RELEASE</version>
<configuration>
<mainClass>com.alibaba.nacos.Nacos</mainClass>
</configuration>

View File

@ -19,12 +19,14 @@ package com.alibaba.nacos;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;
import org.springframework.scheduling.annotation.EnableScheduling;
/**
* @author nacos
*/
@SpringBootApplication(scanBasePackages = "com.alibaba.nacos")
@ServletComponentScan
@EnableScheduling
public class Nacos {
public static void main(String[] args) {

View File

@ -0,0 +1,107 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.nacos.console.config;
import com.alibaba.nacos.console.filter.JwtAuthenticationTokenFilter;
import com.alibaba.nacos.console.security.CustomUserDetailsServiceImpl;
import com.alibaba.nacos.console.security.JwtAuthenticationEntryPoint;
import com.alibaba.nacos.console.utils.JwtTokenUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.BeanIds;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
/**
* Spring security config
*
* @author Nacos
*/
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
public static final String AUTHORIZATION_HEADER = "Authorization";
public static final String AUTHORIZATION_TOKEN = "access_token";
public static final String SECURITY_IGNORE_URLS_SPILT_CHAR = ",";
@Autowired
private CustomUserDetailsServiceImpl userDetailsService;
@Autowired
private JwtAuthenticationEntryPoint unauthorizedHandler;
@Autowired
private JwtTokenUtils tokenProvider;
@Autowired
private Environment env;
@Bean(name = BeanIds.AUTHENTICATION_MANAGER)
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}
@Override
public void configure(WebSecurity web) {
String ignoreURLs = env.getProperty("nacos.security.ignore.urls", "/**");
for (String ignoreURL : ignoreURLs.trim().split(SECURITY_IGNORE_URLS_SPILT_CHAR)) {
web.ignoring().antMatchers(ignoreURL.trim());
}
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated().and()
// custom token authorize exception handler
.exceptionHandling()
.authenticationEntryPoint(unauthorizedHandler).and()
// since we use jwt, session is not necessary
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
// since we use jwt, csrf is not necessary
.csrf().disable();
http.addFilterBefore(new JwtAuthenticationTokenFilter(tokenProvider), UsernamePasswordAuthenticationFilter.class);
// disable cache
http.headers().cacheControl();
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}

View File

@ -0,0 +1,82 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.nacos.console.controller;
import com.alibaba.nacos.console.config.WebSecurityConfig;
import com.alibaba.nacos.config.server.model.RestResult;
import com.alibaba.nacos.console.utils.JwtTokenUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* auth
*
* @author wfnuser
*/
@RestController("auth")
@RequestMapping("/v1/auth")
public class AuthController {
@Autowired
private JwtTokenUtils jwtTokenUtils;
@Autowired
private AuthenticationManager authenticationManager;
/**
* Whether the Nacos is in broken states or not, and cannot recover except by being restarted
*
* @return HTTP code equal to 200 indicates that Nacos is in right states. HTTP code equal to 500 indicates that
* Nacos is in broken states.
*/
@ResponseBody
@RequestMapping(value = "login", method = RequestMethod.POST)
public RestResult<String> login(HttpServletRequest request, HttpServletResponse response) throws Exception {
String username = request.getParameter("username");
String password = request.getParameter("password");
// 通过用户名和密码创建一个 Authentication 认证对象实现类为 UsernamePasswordAuthenticationToken
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(username, password);
RestResult<String> rr = new RestResult<String>();
try {
//通过 AuthenticationManager默认实现为ProviderManager的authenticate方法验证 Authentication 对象
Authentication authentication = authenticationManager.authenticate(authenticationToken);
// Authentication 绑定到 SecurityContext
SecurityContextHolder.getContext().setAuthentication(authentication);
//生成Token
String token = jwtTokenUtils.createToken(authentication);
//将Token写入到Http头部
response.addHeader(WebSecurityConfig.AUTHORIZATION_HEADER, "Bearer " + token);
rr.setCode(200);
rr.setData("Bearer " + token);
return rr;
} catch (BadCredentialsException authentication) {
rr.setCode(401);
rr.setMessage("Login failed");
return rr;
}
}
}

View File

@ -0,0 +1,80 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.nacos.console.filter;
import com.alibaba.nacos.console.config.WebSecurityConfig;
import com.alibaba.nacos.console.utils.JwtTokenUtils;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* jwt auth token filter
*
* @author wfnuser
*/
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {
private static final String TOKEN_PREFIX = "Bearer ";
private JwtTokenUtils tokenProvider;
public JwtAuthenticationTokenFilter(JwtTokenUtils tokenProvider) {
this.tokenProvider = tokenProvider;
}
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
String jwt = resolveToken(request);
if (!StringUtils.isEmpty(jwt.trim()) && SecurityContextHolder.getContext().getAuthentication() == null) {
if (this.tokenProvider.validateToken(jwt)) {
/**
* get auth info
*/
Authentication authentication = this.tokenProvider.getAuthentication(jwt);
/**
* save user info to securityContext
*/
SecurityContextHolder.getContext().setAuthentication(authentication);
}
}
chain.doFilter(request, response);
}
/**
* Get token from header
*/
private String resolveToken(HttpServletRequest request) {
String bearerToken = request.getHeader(WebSecurityConfig.AUTHORIZATION_HEADER);
if (StringUtils.hasText(bearerToken) && bearerToken.startsWith(TOKEN_PREFIX)) {
return bearerToken.substring(7, bearerToken.length());
}
String jwt = request.getParameter(WebSecurityConfig.AUTHORIZATION_TOKEN);
if (StringUtils.hasText(jwt)) {
return jwt;
}
return null;
}
}

View File

@ -16,7 +16,7 @@
package com.alibaba.nacos.console.model;
/**
* 命名空间
* Namespace
*
* @author diamond
*/
@ -30,7 +30,7 @@ public class Namespace {
private int configCount;
/**
* 0 全局配置 1 默认私有命名空间 2 自定义命名空间
* 0 : Global configuration 1 : Default private namespace 2 : Custom namespace
*/
private int type;

View File

@ -0,0 +1,55 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.nacos.console.security;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;
/**
* auth provider
*
* @author wfnuser
*/
@Component
public class CustomAuthenticationProvider implements AuthenticationProvider {
@Autowired
private CustomUserDetailsServiceImpl userDetailsService;
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
String username = (String) authentication.getPrincipal();
String password = (String) authentication.getCredentials();
UserDetails userDetails = userDetailsService.loadUserByUsername(username);
if (!password.equals(userDetails.getPassword())) {
return new UsernamePasswordAuthenticationToken(username, null, null);
}
return null;
}
@Override
public boolean supports(Class<?> aClass) {
return aClass.equals(UsernamePasswordAuthenticationToken.class);
}
}

View File

@ -0,0 +1,73 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.nacos.console.security;
import com.alibaba.nacos.config.server.model.User;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.UserDetails;
import java.util.Collection;
/**
* custem user
*
* @author wfnuser
*/
public class CustomUserDetails implements UserDetails {
private User user;
public CustomUserDetails(User user) {
this.user = user;
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
// TODO: get authorities
return AuthorityUtils.commaSeparatedStringToAuthorityList("");
}
@Override
public String getPassword() {
return user.getPassword();
}
@Override
public String getUsername() {
return user.getUsername();
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return true;
}
}

Some files were not shown because too many files have changed in this diff Show More