Merge branch 'develop' into master
This commit is contained in:
commit
a689f0f694
2
.gitignore
vendored
2
.gitignore
vendored
@ -5,7 +5,9 @@
|
||||
target
|
||||
.project
|
||||
.idea
|
||||
.vscode
|
||||
.DS_Store
|
||||
.factorypath
|
||||
/logs
|
||||
*.iml
|
||||
node_modules
|
||||
|
@ -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>
|
||||
|
@ -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
|
||||
|
@ -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";
|
||||
|
||||
}
|
||||
|
@ -19,6 +19,7 @@ import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:zpf.073@gmail.com">nkorange</a>
|
||||
* @since 0.7.0
|
||||
*/
|
||||
public class Entity {
|
||||
|
||||
|
@ -17,6 +17,7 @@ package com.alibaba.nacos.api.cmdb.pojo;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:zpf.073@gmail.com">nkorange</a>
|
||||
* @since 0.7.0
|
||||
*/
|
||||
public class EntityEvent {
|
||||
|
||||
|
@ -17,6 +17,7 @@ package com.alibaba.nacos.api.cmdb.pojo;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:zpf.073@gmail.com">nkorange</a>
|
||||
* @since 0.7.0
|
||||
*/
|
||||
public enum EntityEventType {
|
||||
/**
|
||||
|
@ -19,6 +19,7 @@ import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:zpf.073@gmail.com">nkorange</a>
|
||||
* @since 0.7.0
|
||||
*/
|
||||
public class Label {
|
||||
|
||||
|
@ -17,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
|
||||
}
|
||||
|
@ -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 {
|
||||
|
||||
|
@ -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";
|
||||
}
|
||||
|
@ -32,7 +32,7 @@ public class ConfigFactory {
|
||||
* Create Config
|
||||
*
|
||||
* @param properties init param
|
||||
* @return Config
|
||||
* @return ConfigService
|
||||
* @throws NacosException Exception
|
||||
*/
|
||||
public static ConfigService createConfigService(Properties properties) throws NacosException {
|
||||
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -24,7 +24,7 @@ import com.alibaba.nacos.api.exception.NacosException;
|
||||
*/
|
||||
public interface IConfigFilter {
|
||||
/**
|
||||
* Init Fuction
|
||||
* Init
|
||||
*
|
||||
* @param filterConfig Filter Config
|
||||
*/
|
||||
@ -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();
|
||||
|
||||
|
@ -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;
|
||||
|
||||
}
|
||||
|
@ -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();
|
||||
|
||||
}
|
||||
|
@ -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();
|
||||
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ package com.alibaba.nacos.api.config.listener;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
/**
|
||||
* shared listener
|
||||
* Shared Listener
|
||||
*
|
||||
* @author Nacos
|
||||
*/
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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 {
|
||||
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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 {
|
||||
}
|
||||
|
@ -16,7 +16,7 @@
|
||||
package com.alibaba.nacos.api.naming.listener;
|
||||
|
||||
/**
|
||||
* event listener
|
||||
* Event Listener
|
||||
*
|
||||
* @author Nacos
|
||||
*/
|
||||
|
@ -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 {
|
||||
|
||||
|
@ -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 {
|
||||
|
||||
|
@ -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>();
|
||||
|
||||
|
@ -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> {
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
@ -19,6 +19,7 @@ package com.alibaba.nacos.api.selector;
|
||||
* Abstract selector that only contains a type
|
||||
*
|
||||
* @author <a href="mailto:zpf.073@gmail.com">nkorange</a>
|
||||
* @since 0.7.0
|
||||
*/
|
||||
public abstract class AbstractSelector {
|
||||
|
||||
|
@ -19,6 +19,7 @@ package com.alibaba.nacos.api.selector;
|
||||
* The selector to filter resource with flexible expression.
|
||||
*
|
||||
* @author <a href="mailto:zpf.073@gmail.com">nkorange</a>
|
||||
* @since 0.7.0
|
||||
*/
|
||||
public class ExpressionSelector extends AbstractSelector {
|
||||
|
||||
|
@ -19,6 +19,7 @@ package com.alibaba.nacos.api.selector;
|
||||
* The types of selector accepted by Nacos
|
||||
*
|
||||
* @author <a href="mailto:zpf.073@gmail.com">nkorange</a>
|
||||
* @since 0.7.0
|
||||
*/
|
||||
public enum SelectorType {
|
||||
/**
|
||||
|
@ -16,7 +16,7 @@
|
||||
<parent>
|
||||
<groupId>com.alibaba.nacos</groupId>
|
||||
<artifactId>nacos-all</artifactId>
|
||||
<version>0.7.0</version>
|
||||
<version>0.8.0-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
@ -107,5 +107,10 @@
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.micrometer</groupId>
|
||||
<artifactId>micrometer-core</artifactId>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
</project>
|
||||
|
@ -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()) {
|
||||
|
@ -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();
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
@ -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;
|
||||
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -104,10 +104,14 @@ public class LocalConfigInfoProcessor {
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
boolean isMdOk = file.getParentFile().mkdirs();
|
||||
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);
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
@ -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) {
|
||||
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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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,7 +29,22 @@ import java.util.concurrent.*;
|
||||
*/
|
||||
public class BeatReactor {
|
||||
|
||||
private ScheduledExecutorService executorService = new ScheduledThreadPoolExecutor(1, new ThreadFactory() {
|
||||
private ScheduledExecutorService executorService;
|
||||
|
||||
private long clientBeatInterval = 5 * 1000;
|
||||
|
||||
private NamingProxy serverProxy;
|
||||
|
||||
public final Map<String, BeatInfo> dom2Beat = new ConcurrentHashMap<String, BeatInfo>();
|
||||
|
||||
public BeatReactor(NamingProxy serverProxy) {
|
||||
this(serverProxy, UtilAndComs.DEFAULT_CLIENT_BEAT_THREAD_COUNT);
|
||||
}
|
||||
|
||||
public BeatReactor(NamingProxy serverProxy, int threadCount) {
|
||||
this.serverProxy = serverProxy;
|
||||
|
||||
executorService = new ScheduledThreadPoolExecutor(threadCount, new ThreadFactory() {
|
||||
@Override
|
||||
public Thread newThread(Runnable r) {
|
||||
Thread thread = new Thread(r);
|
||||
@ -41,25 +54,19 @@ public class BeatReactor {
|
||||
}
|
||||
});
|
||||
|
||||
private long clientBeatInterval = 5 * 1000;
|
||||
|
||||
private NamingProxy serverProxy;
|
||||
|
||||
public final Map<String, BeatInfo> dom2Beat = new ConcurrentHashMap<String, BeatInfo>();
|
||||
|
||||
public BeatReactor(NamingProxy serverProxy) {
|
||||
this.serverProxy = serverProxy;
|
||||
executorService.scheduleAtFixedRate(new BeatProcessor(), 0, clientBeatInterval, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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,8 +82,19 @@ 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) {
|
||||
|
@ -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);
|
||||
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);
|
||||
|
@ -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();
|
@ -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(","));
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -34,7 +34,7 @@ public class UtilAndComs {
|
||||
|
||||
public static final String NACOS_URL_INSTANCE = NACOS_URL_BASE + "/instance";
|
||||
|
||||
public static final String DEFAULT_NAMESPACE_ID = "default";
|
||||
public static final String DEFAULT_NAMESPACE_ID = "public";
|
||||
|
||||
public static final int REQUEST_DOMAIN_RETRY_COUNT = 3;
|
||||
|
||||
@ -45,4 +45,10 @@ public class UtilAndComs {
|
||||
public static final String NACOS_NAMING_LOG_LEVEL = "com.alibaba.nacos.naming.log.level";
|
||||
|
||||
public static final String SERVER_ADDR_IP_SPLITER = ":";
|
||||
|
||||
public static final int DEFAULT_CLIENT_BEAT_THREAD_COUNT = Runtime.getRuntime().availableProcessors() > 1 ?
|
||||
Runtime.getRuntime().availableProcessors() / 2 : 1;
|
||||
|
||||
public static final int DEFAULT_POLLING_THREAD_COUNT = Runtime.getRuntime().availableProcessors() > 1 ?
|
||||
Runtime.getRuntime().availableProcessors() / 2 : 1;
|
||||
}
|
||||
|
@ -16,6 +16,8 @@
|
||||
package com.alibaba.nacos.client;
|
||||
|
||||
import com.alibaba.nacos.api.NacosFactory;
|
||||
import com.alibaba.nacos.api.PropertyKeyConst;
|
||||
import com.alibaba.nacos.api.common.Constants;
|
||||
import com.alibaba.nacos.api.naming.NamingService;
|
||||
import com.alibaba.nacos.api.naming.pojo.Instance;
|
||||
import com.alibaba.nacos.api.naming.pojo.ListView;
|
||||
@ -25,6 +27,7 @@ import org.junit.Test;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:zpf.073@gmail.com">nkorange</a>
|
||||
@ -35,7 +38,11 @@ public class NamingTest {
|
||||
@Ignore
|
||||
public void testServiceList() throws Exception {
|
||||
|
||||
NamingService namingService = NacosFactory.createNamingService("127.0.0.1:8848");
|
||||
Properties properties = new Properties();
|
||||
properties.put(PropertyKeyConst.SERVER_ADDR, "11.160.165.126:8848");
|
||||
properties.put(PropertyKeyConst.NAMESPACE, "t1");
|
||||
|
||||
NamingService namingService = NacosFactory.createNamingService(properties);
|
||||
|
||||
Instance instance = new Instance();
|
||||
instance.setIp("1.1.1.1");
|
||||
@ -48,9 +55,9 @@ public class NamingTest {
|
||||
|
||||
namingService.registerInstance("nacos.test.1", instance);
|
||||
|
||||
ExpressionSelector expressionSelector = new ExpressionSelector();
|
||||
expressionSelector.setExpression("INSTANCE.metadata.registerSource = 'dubbo'");
|
||||
ListView<String> serviceList = namingService.getServicesOfServer(1, 10, expressionSelector);
|
||||
// ExpressionSelector expressionSelector = new ExpressionSelector();
|
||||
// expressionSelector.setExpression("INSTANCE.metadata.registerSource = 'dubbo'");
|
||||
// ListView<String> serviceList = namingService.getServicesOfServer(1, 10, expressionSelector);
|
||||
|
||||
Thread.sleep(1000000000L);
|
||||
}
|
||||
|
@ -18,7 +18,7 @@
|
||||
<parent>
|
||||
<artifactId>nacos-all</artifactId>
|
||||
<groupId>com.alibaba.nacos</groupId>
|
||||
<version>0.7.0</version>
|
||||
<version>0.8.0-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
@ -20,6 +20,7 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:zpf.073@gmail.com">nkorange</a>
|
||||
* @since 0.7.0
|
||||
*/
|
||||
@SpringBootApplication
|
||||
public class CmdbApp {
|
||||
|
@ -28,6 +28,7 @@ import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:zpf.073@gmail.com">nkorange</a>
|
||||
* @since 0.7.0
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping(UtilsAndCommons.NACOS_CMDB_CONTEXT + "/ops")
|
||||
|
@ -17,6 +17,7 @@ package com.alibaba.nacos.cmdb.core;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:zpf.073@gmail.com">nkorange</a>
|
||||
* @since 0.7.0
|
||||
*/
|
||||
public class CmdbManager {
|
||||
}
|
||||
|
@ -20,6 +20,7 @@ import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:zpf.073@gmail.com">nkorange</a>
|
||||
* @since 0.7.0
|
||||
*/
|
||||
@Component
|
||||
public class SwitchAndOptions {
|
||||
|
@ -36,6 +36,7 @@ import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:zpf.073@gmail.com">nkorange</a>
|
||||
* @since 0.7.0
|
||||
*/
|
||||
@Component
|
||||
public class CmdbProvider implements CmdbReader, CmdbWriter {
|
||||
|
@ -22,6 +22,7 @@ import java.util.List;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:zpf.073@gmail.com">nkorange</a>
|
||||
* @since 0.7.0
|
||||
*/
|
||||
public interface CmdbReader {
|
||||
|
||||
|
@ -17,6 +17,7 @@ package com.alibaba.nacos.cmdb.service;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:zpf.073@gmail.com">nkorange</a>
|
||||
* @since 0.7.0
|
||||
*/
|
||||
public interface CmdbWriter {
|
||||
}
|
||||
|
@ -20,6 +20,7 @@ import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* @author nacos
|
||||
* @since 0.7.0
|
||||
*/
|
||||
public class Loggers {
|
||||
|
||||
|
@ -21,6 +21,7 @@ import java.util.concurrent.ThreadFactory;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:zpf.073@gmail.com">nkorange</a>
|
||||
* @since 0.7.0
|
||||
*/
|
||||
public class UtilsAndCommons {
|
||||
|
||||
|
@ -18,7 +18,7 @@
|
||||
<parent>
|
||||
<groupId>com.alibaba.nacos</groupId>
|
||||
<artifactId>nacos-all</artifactId>
|
||||
<version>0.7.0</version>
|
||||
<version>0.8.0-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 1999-2018 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.alibaba.nacos.common.util;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:zpf.073@gmail.com">nkorange</a>
|
||||
* @since 0.8.0
|
||||
*/
|
||||
public class HttpMethod {
|
||||
|
||||
public static final String GET = "GET";
|
||||
|
||||
public static final String HEAD = "HEAD";
|
||||
|
||||
public static final String POST = "POST";
|
||||
|
||||
public static final String PUT = "PUT";
|
||||
|
||||
public static final String PATCH = "PATCH";
|
||||
|
||||
public static final String DELETE = "DELETE";
|
||||
|
||||
public static final String OPTIONS = "PATCH";
|
||||
|
||||
public static final String TRACE = "TRACE";
|
||||
}
|
@ -17,7 +17,7 @@
|
||||
<parent>
|
||||
<groupId>com.alibaba.nacos</groupId>
|
||||
<artifactId>nacos-all</artifactId>
|
||||
<version>0.7.0</version>
|
||||
<version>0.8.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
@ -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>
|
||||
|
@ -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 {
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -252,7 +252,7 @@ public class ConfigController {
|
||||
inner.doPollingConfig(request, response, clientMd5Map, probeModify.length());
|
||||
}
|
||||
|
||||
/*
|
||||
/**
|
||||
* 订阅改配置的客户端信息
|
||||
*/
|
||||
@RequestMapping(value = "/listener", method = RequestMethod.GET)
|
||||
|
@ -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 {
|
||||
|
@ -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. ");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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) {
|
||||
|
@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -28,6 +28,6 @@ public interface TaskManagerMBean {
|
||||
*
|
||||
* @return info
|
||||
*/
|
||||
public String getTaskInfos();
|
||||
String getTaskInfos();
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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");
|
||||
}
|
||||
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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());
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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');
|
||||
|
@ -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');
|
||||
|
@ -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");
|
||||
}
|
||||
}
|
@ -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>
|
||||
|
@ -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) {
|
||||
|
@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Copyright 1999-2018 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.alibaba.nacos.console.config;
|
||||
|
||||
import com.alibaba.nacos.console.filter.JwtAuthenticationTokenFilter;
|
||||
import com.alibaba.nacos.console.security.CustomUserDetailsServiceImpl;
|
||||
import com.alibaba.nacos.console.security.JwtAuthenticationEntryPoint;
|
||||
import com.alibaba.nacos.console.utils.JwtTokenUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.config.BeanIds;
|
||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.builders.WebSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||
import org.springframework.security.config.http.SessionCreationPolicy;
|
||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
||||
|
||||
/**
|
||||
* Spring security config
|
||||
*
|
||||
* @author Nacos
|
||||
*/
|
||||
@Configuration
|
||||
@EnableGlobalMethodSecurity(prePostEnabled = true)
|
||||
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
|
||||
public static final String AUTHORIZATION_HEADER = "Authorization";
|
||||
|
||||
public static final String AUTHORIZATION_TOKEN = "access_token";
|
||||
|
||||
public static final String SECURITY_IGNORE_URLS_SPILT_CHAR = ",";
|
||||
|
||||
@Autowired
|
||||
private CustomUserDetailsServiceImpl userDetailsService;
|
||||
|
||||
@Autowired
|
||||
private JwtAuthenticationEntryPoint unauthorizedHandler;
|
||||
|
||||
@Autowired
|
||||
private JwtTokenUtils tokenProvider;
|
||||
|
||||
@Autowired
|
||||
private Environment env;
|
||||
|
||||
@Bean(name = BeanIds.AUTHENTICATION_MANAGER)
|
||||
@Override
|
||||
public AuthenticationManager authenticationManagerBean() throws Exception {
|
||||
return super.authenticationManagerBean();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(WebSecurity web) {
|
||||
String ignoreURLs = env.getProperty("nacos.security.ignore.urls", "/**");
|
||||
for (String ignoreURL : ignoreURLs.trim().split(SECURITY_IGNORE_URLS_SPILT_CHAR)) {
|
||||
web.ignoring().antMatchers(ignoreURL.trim());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.authorizeRequests()
|
||||
.anyRequest().authenticated().and()
|
||||
// custom token authorize exception handler
|
||||
.exceptionHandling()
|
||||
.authenticationEntryPoint(unauthorizedHandler).and()
|
||||
// since we use jwt, session is not necessary
|
||||
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
|
||||
// since we use jwt, csrf is not necessary
|
||||
.csrf().disable();
|
||||
http.addFilterBefore(new JwtAuthenticationTokenFilter(tokenProvider), UsernamePasswordAuthenticationFilter.class);
|
||||
|
||||
// disable cache
|
||||
http.headers().cacheControl();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public PasswordEncoder passwordEncoder() {
|
||||
return new BCryptPasswordEncoder();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright 1999-2018 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.alibaba.nacos.console.controller;
|
||||
|
||||
import com.alibaba.nacos.console.config.WebSecurityConfig;
|
||||
import com.alibaba.nacos.config.server.model.RestResult;
|
||||
import com.alibaba.nacos.console.utils.JwtTokenUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.authentication.BadCredentialsException;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
/**
|
||||
* auth
|
||||
*
|
||||
* @author wfnuser
|
||||
*/
|
||||
@RestController("auth")
|
||||
@RequestMapping("/v1/auth")
|
||||
public class AuthController {
|
||||
|
||||
@Autowired
|
||||
private JwtTokenUtils jwtTokenUtils;
|
||||
@Autowired
|
||||
private AuthenticationManager authenticationManager;
|
||||
|
||||
/**
|
||||
* Whether the Nacos is in broken states or not, and cannot recover except by being restarted
|
||||
*
|
||||
* @return HTTP code equal to 200 indicates that Nacos is in right states. HTTP code equal to 500 indicates that
|
||||
* Nacos is in broken states.
|
||||
*/
|
||||
|
||||
@ResponseBody
|
||||
@RequestMapping(value = "login", method = RequestMethod.POST)
|
||||
public RestResult<String> login(HttpServletRequest request, HttpServletResponse response) throws Exception {
|
||||
String username = request.getParameter("username");
|
||||
String password = request.getParameter("password");
|
||||
|
||||
// 通过用户名和密码创建一个 Authentication 认证对象,实现类为 UsernamePasswordAuthenticationToken
|
||||
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(username, password);
|
||||
RestResult<String> rr = new RestResult<String>();
|
||||
|
||||
try {
|
||||
//通过 AuthenticationManager(默认实现为ProviderManager)的authenticate方法验证 Authentication 对象
|
||||
Authentication authentication = authenticationManager.authenticate(authenticationToken);
|
||||
//将 Authentication 绑定到 SecurityContext
|
||||
SecurityContextHolder.getContext().setAuthentication(authentication);
|
||||
//生成Token
|
||||
String token = jwtTokenUtils.createToken(authentication);
|
||||
//将Token写入到Http头部
|
||||
response.addHeader(WebSecurityConfig.AUTHORIZATION_HEADER, "Bearer " + token);
|
||||
rr.setCode(200);
|
||||
rr.setData("Bearer " + token);
|
||||
return rr;
|
||||
} catch (BadCredentialsException authentication) {
|
||||
rr.setCode(401);
|
||||
rr.setMessage("Login failed");
|
||||
return rr;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright 1999-2018 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.alibaba.nacos.console.filter;
|
||||
|
||||
import com.alibaba.nacos.console.config.WebSecurityConfig;
|
||||
import com.alibaba.nacos.console.utils.JwtTokenUtils;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* jwt auth token filter
|
||||
*
|
||||
* @author wfnuser
|
||||
*/
|
||||
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {
|
||||
|
||||
private static final String TOKEN_PREFIX = "Bearer ";
|
||||
|
||||
private JwtTokenUtils tokenProvider;
|
||||
|
||||
public JwtAuthenticationTokenFilter(JwtTokenUtils tokenProvider) {
|
||||
this.tokenProvider = tokenProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
|
||||
String jwt = resolveToken(request);
|
||||
|
||||
if (!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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
|
||||
|
@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright 1999-2018 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.alibaba.nacos.console.security;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.authentication.AuthenticationProvider;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* auth provider
|
||||
*
|
||||
* @author wfnuser
|
||||
*/
|
||||
@Component
|
||||
public class CustomAuthenticationProvider implements AuthenticationProvider {
|
||||
|
||||
@Autowired
|
||||
private CustomUserDetailsServiceImpl userDetailsService;
|
||||
|
||||
@Override
|
||||
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
|
||||
|
||||
String username = (String) authentication.getPrincipal();
|
||||
String password = (String) authentication.getCredentials();
|
||||
UserDetails userDetails = userDetailsService.loadUserByUsername(username);
|
||||
|
||||
if (!password.equals(userDetails.getPassword())) {
|
||||
return new UsernamePasswordAuthenticationToken(username, null, null);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supports(Class<?> aClass) {
|
||||
return aClass.equals(UsernamePasswordAuthenticationToken.class);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright 1999-2018 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.alibaba.nacos.console.security;
|
||||
|
||||
import com.alibaba.nacos.config.server.model.User;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.authority.AuthorityUtils;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* custem user
|
||||
*
|
||||
* @author wfnuser
|
||||
*/
|
||||
public class CustomUserDetails implements UserDetails {
|
||||
|
||||
private User user;
|
||||
|
||||
public CustomUserDetails(User user) {
|
||||
this.user = user;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<? extends GrantedAuthority> getAuthorities() {
|
||||
// TODO: get authorities
|
||||
return AuthorityUtils.commaSeparatedStringToAuthorityList("");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPassword() {
|
||||
return user.getPassword();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUsername() {
|
||||
return user.getUsername();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAccountNonExpired() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAccountNonLocked() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCredentialsNonExpired() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
return true;
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user