Merge pull request #2 from alibaba/develop

sync code
This commit is contained in:
Brian Huang 2020-06-12 07:20:29 -05:00 committed by GitHub
commit 3ea2200fb0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
92 changed files with 2875 additions and 651 deletions

33
.github/stale.yml vendored Normal file
View File

@ -0,0 +1,33 @@
# Number of days of inactivity before an issue becomes stale
daysUntilStale: 180
# Number of days of inactivity before a stale issue is closed
daysUntilClose: 7
# Issues with these labels will never be considered stale
exemptLabels:
- good first issue
- contribution welcome
- dependencies
- kind/bug
- kind/code quality
- kind/enhancement
- kind/performance
- kind/proposal
- kind/refactor
- kind/user experience
- Soc2019
- SoC2020
# Label to use when marking an issue as stale
staleLabel: expired
# Comment to post when marking an issue as stale. Set to `false` to disable
markComment: >
Thanks for your feedback and contribution. But the issue/pull request has
not had recent activity more than **180 days**. This issue/pull request will
be closed if no further activity occurs **7 days later**.
We may solve this issue in new version. So can you upgrade to newest version
and retry?
If there are still issues or want to contribute again. Please create new issue
or pull request again.
# Comment to post when closing a stale issue. Set to `false` to disable
closeComment: false

View File

@ -29,6 +29,7 @@ before_install:
script:
- mvn -B clean package apache-rat:check findbugs:findbugs -Dmaven.test.skip=true
- mvn -Prelease-nacos -Dmaven.test.skip=true clean install -U
- mvn clean install -Pcit-test
- mvn clean package -Pit-test
after_success:
- mvn clean package -Pit-test

View File

@ -11,7 +11,7 @@
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${LOG_HOME}/nacos-address.log.%d{yyyy-MM-dd}.%i</fileNamePattern>
<maxFileSize>2GB</maxFileSize>
<MaxHistory>15</MaxHistory>
<maxHistory>15</maxHistory>
<totalSizeCap>7GB</totalSizeCap>
<cleanHistoryOnStart>true</cleanHistoryOnStart>
</rollingPolicy>

View File

@ -97,5 +97,4 @@ public class NacosFactory {
public static NamingMaintainService createMaintainService(Properties properties) throws NacosException {
return NamingMaintainFactory.createMaintainService(properties);
}
}

View File

@ -58,5 +58,4 @@ public class ConfigFactory {
properties.put(PropertyKeyConst.SERVER_ADDR, serverAddr);
return createConfigService(properties);
}
}

View File

@ -105,4 +105,10 @@ public interface ConfigService {
*/
String getServerStatus();
/**
* Shutdown the resource service
*
* @throws NacosException exception.
*/
void shutDown() throws NacosException;
}

View File

@ -145,5 +145,4 @@ public class NacosException extends Exception {
public static final int OVER_THRESHOLD = 503;
public static final int RESOURCE_NOT_FOUND = -404;
}

View File

@ -16,6 +16,8 @@
package com.alibaba.nacos.api.exception.runtime;
import java.lang.reflect.Type;
/**
* Nacos deserialization exception.
*
@ -42,6 +44,10 @@ public class NacosDeserializationException extends NacosRuntimeException {
this.targetClass = targetClass;
}
public NacosDeserializationException(Type targetType) {
super(ERROR_CODE, String.format(MSG_FOR_SPECIFIED_CLASS, targetType.toString()));
}
public NacosDeserializationException(Throwable throwable) {
super(ERROR_CODE, DEFAULT_MSG, throwable);
}
@ -51,6 +57,14 @@ public class NacosDeserializationException extends NacosRuntimeException {
this.targetClass = targetClass;
}
public NacosDeserializationException(Type targetType, Throwable throwable) {
super(ERROR_CODE, String.format(MSG_FOR_SPECIFIED_CLASS, targetType.toString()), throwable);
}
public Class<?> getTargetClass() {
return targetClass;
}

View File

@ -555,4 +555,11 @@ public interface NamingService {
* @return is server healthy
*/
String getServerStatus();
/**
* Shutdown the resource service.
*
* @throws NacosException exception.
*/
void shutDown() throws NacosException;
}

View File

@ -72,14 +72,15 @@ public class NacosConfigService implements ConfigService {
ValidatorUtils.checkInitParam(properties);
String encodeTmp = properties.getProperty(PropertyKeyConst.ENCODE);
if (StringUtils.isBlank(encodeTmp)) {
encode = Constants.ENCODE;
this.encode = Constants.ENCODE;
} else {
encode = encodeTmp.trim();
this.encode = encodeTmp.trim();
}
initNamespace(properties);
agent = new MetricsHttpAgent(new ServerHttpAgent(properties));
agent.start();
worker = new ClientWorker(agent, configFilterChainManager, properties);
this.agent = new MetricsHttpAgent(new ServerHttpAgent(properties));
this.agent.start();
this.worker = new ClientWorker(this.agent, this.configFilterChainManager, properties);
}
private void initNamespace(Properties properties) {
@ -281,4 +282,9 @@ public class NacosConfigService implements ConfigService {
}
}
@Override
public void shutDown() throws NacosException{
agent.shutdown();
worker.shutdown();
}
}

View File

@ -17,6 +17,7 @@ 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.common.lifecycle.Closeable;
import java.io.IOException;
import java.util.List;
@ -27,7 +28,8 @@ import java.util.List;
*
* @author Nacos
*/
public interface HttpAgent {
public interface HttpAgent extends Closeable {
/**
* start to get nacos ip list
* @return Nothing.

View File

@ -13,6 +13,11 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* MetricsHttpAgent
*
* @author Nacos
*/
package com.alibaba.nacos.client.config.http;
import com.alibaba.nacos.api.exception.NacosException;
@ -29,6 +34,7 @@ import java.util.List;
* @author Nacos
*/
public class MetricsHttpAgent implements HttpAgent {
private HttpAgent httpAgent;
public MetricsHttpAgent(HttpAgent httpAgent) {
@ -108,5 +114,10 @@ public class MetricsHttpAgent implements HttpAgent {
public String getEncode() {
return httpAgent.getEncode();
}
@Override
public void shutdown() throws NacosException{
httpAgent.shutdown();
}
}

View File

@ -29,6 +29,7 @@ import com.alibaba.nacos.client.utils.ParamUtil;
import com.alibaba.nacos.client.utils.TemplateUtils;
import com.alibaba.nacos.common.utils.IoUtils;
import com.alibaba.nacos.common.utils.JacksonUtils;
import com.alibaba.nacos.common.utils.ThreadUtils;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.type.TypeReference;
import org.apache.commons.lang3.StringUtils;
@ -44,7 +45,11 @@ import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.*;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.Callable;
/**
* Server Agent
@ -61,6 +66,8 @@ public class ServerHttpAgent implements HttpAgent {
private long securityInfoRefreshIntervalMills = TimeUnit.SECONDS.toMillis(5);
private ScheduledExecutorService executorService;
/**
* @param path 相对于web应用根/开头
* @param headers
@ -235,7 +242,7 @@ public class ServerHttpAgent implements HttpAgent {
private String getUrl(String serverAddr, String relativePath) {
String contextPath = serverListMgr.getContentPath().startsWith("/") ?
serverListMgr.getContentPath() : "/" + serverListMgr.getContentPath();
serverListMgr.getContentPath() : "/" + serverListMgr.getContentPath();
return serverAddr + contextPath + relativePath;
}
@ -244,22 +251,24 @@ public class ServerHttpAgent implements HttpAgent {
}
public ServerHttpAgent(ServerListManager mgr) {
serverListMgr = mgr;
this.serverListMgr = mgr;
}
public ServerHttpAgent(ServerListManager mgr, Properties properties) {
serverListMgr = mgr;
this.serverListMgr = mgr;
init(properties);
}
public ServerHttpAgent(Properties properties) throws NacosException {
serverListMgr = new ServerListManager(properties);
securityProxy = new SecurityProxy(properties);
namespaceId = properties.getProperty(PropertyKeyConst.NAMESPACE);
this.serverListMgr = new ServerListManager(properties);
this.securityProxy = new SecurityProxy(properties);
this.namespaceId = properties.getProperty(PropertyKeyConst.NAMESPACE);
init(properties);
securityProxy.login(serverListMgr.getServerUrls());
this.securityProxy.login(this.serverListMgr.getServerUrls());
ScheduledExecutorService executorService = new ScheduledThreadPoolExecutor(1, new ThreadFactory() {
// init executorService
this.executorService = new ScheduledThreadPoolExecutor(1, new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r);
@ -269,12 +278,13 @@ public class ServerHttpAgent implements HttpAgent {
}
});
executorService.scheduleWithFixedDelay(new Runnable() {
this.executorService.scheduleWithFixedDelay(new Runnable() {
@Override
public void run() {
securityProxy.login(serverListMgr.getServerUrls());
}
}, 0, securityInfoRefreshIntervalMills, TimeUnit.MILLISECONDS);
}, 0, this.securityInfoRefreshIntervalMills, TimeUnit.MILLISECONDS);
}
private void injectSecurityInfo(List<String> params) {
@ -329,7 +339,7 @@ public class ServerHttpAgent implements HttpAgent {
}
@Override
public synchronized void start() throws NacosException {
public void start() throws NacosException {
serverListMgr.start();
}
@ -430,6 +440,14 @@ public class ServerHttpAgent implements HttpAgent {
return encode;
}
@Override
public void shutdown() throws NacosException{
String className = this.getClass().getName();
LOGGER.info("{} do shutdown begin", className);
ThreadUtils.shutdownThreadPool(executorService, LOGGER);
LOGGER.info("{} do shutdown stop", className);
}
@SuppressWarnings("PMD.ClassNamingShouldBeCamelRule")
private static class STSCredential {
@JsonProperty(value = "AccessKeyId")

View File

@ -25,12 +25,14 @@ 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.common.lifecycle.Closeable;
import com.alibaba.nacos.common.utils.MD5Utils;
import com.alibaba.nacos.client.monitor.MetricsMonitor;
import com.alibaba.nacos.client.naming.utils.CollectionUtils;
import com.alibaba.nacos.client.utils.LogUtils;
import com.alibaba.nacos.client.utils.ParamUtil;
import com.alibaba.nacos.client.utils.TenantUtil;
import com.alibaba.nacos.common.utils.ThreadUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.slf4j.Logger;
@ -55,7 +57,7 @@ import static com.alibaba.nacos.api.common.Constants.CONFIG_TYPE;
*
* @author Nacos
*/
public class ClientWorker {
public class ClientWorker implements Closeable {
private static final Logger LOGGER = LogUtils.logger(ClientWorker.class);
@ -116,7 +118,7 @@ public class ClientWorker {
copy.remove(groupKey);
cacheMap.set(copy);
}
LOGGER.info("[{}] [unsubscribe] {}", agent.getName(), groupKey);
LOGGER.info("[{}] [unsubscribe] {}", this.agent.getName(), groupKey);
MetricsMonitor.getListenConfigCountMonitor().set(cacheMap.get().size());
}
@ -160,7 +162,7 @@ public class ClientWorker {
cacheMap.set(copy);
}
LOGGER.info("[{}] [subscribe] {}", agent.getName(), key);
LOGGER.info("[{}] [subscribe] {}", this.agent.getName(), key);
MetricsMonitor.getListenConfigCountMonitor().set(cacheMap.get().size());
@ -191,7 +193,7 @@ public class ClientWorker {
}
}
Map<String, CacheData> copy = new HashMap<String, CacheData>(cacheMap.get());
Map<String, CacheData> copy = new HashMap<String, CacheData>(this.cacheMap.get());
copy.put(key, cache);
cacheMap.set(copy);
}
@ -277,7 +279,6 @@ public class ClientWorker {
final String tenant = cacheData.tenant;
File path = LocalConfigInfoProcessor.getFailoverFile(agent.getName(), dataId, group, tenant);
// 没有 ->
if (!cacheData.isUseLocalConfigInfo() && path.exists()) {
String content = LocalConfigInfoProcessor.getFailover(agent.getName(), dataId, group, tenant);
String md5 = MD5Utils.md5Hex(content, Constants.ENCODE);
@ -290,7 +291,7 @@ public class ClientWorker {
return;
}
// -> 没有不通知业务监听器从server拿到配置后通知
// If use local config info, then it doesn't notify business listener and notify after getting from server.
if (cacheData.isUseLocalConfigInfo() && !path.exists()) {
cacheData.setUseLocalConfigInfo(false);
LOGGER.warn("[{}] [failover-change] failover file deleted. dataId={}, group={}, tenant={}", agent.getName(),
@ -298,7 +299,7 @@ public class ClientWorker {
return;
}
// 有变更
// When it changed.
if (cacheData.isUseLocalConfigInfo() && path.exists()
&& cacheData.getLocalConfigInfoVersion() != path.lastModified()) {
String content = LocalConfigInfoProcessor.getFailover(agent.getName(), dataId, group, tenant);
@ -316,13 +317,13 @@ public class ClientWorker {
}
public void checkConfigInfo() {
// 分任务
// Dispatch taskes.
int listenerSize = cacheMap.get().size();
// 向上取整为批数
// Round up the longingTaskCount.
int longingTaskCount = (int) Math.ceil(listenerSize / ParamUtil.getPerTaskConfigSize());
if (longingTaskCount > currentLongingTaskCount) {
for (int i = (int) currentLongingTaskCount; i < longingTaskCount; i++) {
// 要判断任务是否在执行 这块需要好好想想 任务列表现在是无序的变化过程可能有问题
// The task list is no order.So it maybe has issues when changing.
executorService.execute(new LongPollingRunnable(i));
}
currentLongingTaskCount = longingTaskCount;
@ -330,7 +331,13 @@ public class ClientWorker {
}
/**
* 从Server获取值变化了的DataID列表返回的对象里只有dataId和group是有效的 保证不返回NULL
* Fetch the dataId list from server.
*
* @param cacheDatas CacheDatas for config infomations.
* @param inInitializingCacheList initial cache lists.
* @return String include dataId and group (ps: it maybe null).
*
* @throws IOException Exception.
*/
List<String> checkUpdateDataIds(List<CacheData> cacheDatas, List<String> inInitializingCacheList) throws IOException {
StringBuilder sb = new StringBuilder();
@ -345,7 +352,7 @@ public class ClientWorker {
sb.append(cacheData.getTenant()).append(LINE_SEPARATOR);
}
if (cacheData.isInitializing()) {
// cacheData 首次出现在cacheMap中&首次check更新
// It updates when cacheData occours in cacheMap by first time.
inInitializingCacheList
.add(GroupKey.getKeyTenant(cacheData.dataId, cacheData.group, cacheData.tenant));
}
@ -356,7 +363,13 @@ public class ClientWorker {
}
/**
* 从Server获取值变化了的DataID列表返回的对象里只有dataId和group是有效的 保证不返回NULL
* Fetch the updated dataId list from server.
*
*
* @param probeUpdateString updated attribute string value.
* @param isInitializingCacheList initial cache lists.
* @return The updated dataId list(ps: it maybe null).
* @throws IOException Exception.
*/
List<String> checkUpdateConfigStr(String probeUpdateString, boolean isInitializingCacheList) throws IOException {
@ -403,7 +416,10 @@ public class ClientWorker {
}
/**
* 从HTTP响应拿到变化的groupKey保证不返回NULL
* Get the groupKey list from the http response.
*
* @param response Http response.
* @return GroupKey List, (ps: it maybe null).
*/
private List<String> parseUpdateDataIdResponse(String response) {
if (StringUtils.isBlank(response)) {
@ -448,7 +464,7 @@ public class ClientWorker {
init(properties);
executor = Executors.newScheduledThreadPool(1, new ThreadFactory() {
this.executor = Executors.newScheduledThreadPool(1, new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r);
@ -458,7 +474,7 @@ public class ClientWorker {
}
});
executorService = Executors.newScheduledThreadPool(Runtime.getRuntime().availableProcessors(), new ThreadFactory() {
this.executorService = Executors.newScheduledThreadPool(Runtime.getRuntime().availableProcessors(), new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r);
@ -468,7 +484,7 @@ public class ClientWorker {
}
});
executor.scheduleWithFixedDelay(new Runnable() {
this.executor.scheduleWithFixedDelay(new Runnable() {
@Override
public void run() {
try {
@ -482,12 +498,21 @@ public class ClientWorker {
private void init(Properties properties) {
timeout = Math.max(NumberUtils.toInt(properties.getProperty(PropertyKeyConst.CONFIG_LONG_POLL_TIMEOUT),
this.timeout = Math.max(NumberUtils.toInt(properties.getProperty(PropertyKeyConst.CONFIG_LONG_POLL_TIMEOUT),
Constants.CONFIG_LONG_POLL_TIMEOUT), Constants.MIN_CONFIG_LONG_POLL_TIMEOUT);
taskPenaltyTime = NumberUtils.toInt(properties.getProperty(PropertyKeyConst.CONFIG_RETRY_TIME), Constants.CONFIG_RETRY_TIME);
this.taskPenaltyTime = NumberUtils.toInt(properties.getProperty(PropertyKeyConst.CONFIG_RETRY_TIME), Constants.CONFIG_RETRY_TIME);
enableRemoteSyncConfig = Boolean.parseBoolean(properties.getProperty(PropertyKeyConst.ENABLE_REMOTE_SYNC_CONFIG));
this.enableRemoteSyncConfig = Boolean.parseBoolean(properties.getProperty(PropertyKeyConst.ENABLE_REMOTE_SYNC_CONFIG));
}
@Override
public void shutdown() throws NacosException {
String className = this.getClass().getName();
LOGGER.info("{} do shutdown begin", className);
ThreadUtils.shutdownThreadPool(executorService, LOGGER);
ThreadUtils.shutdownThreadPool(executor, LOGGER);
LOGGER.info("{} do shutdown stop", className);
}
class LongPollingRunnable implements Runnable {

View File

@ -20,35 +20,56 @@ import com.alibaba.nacos.api.SystemPropertyKeyConst;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.client.config.impl.EventDispatcher.ServerlistChangeEvent;
import com.alibaba.nacos.client.config.impl.HttpSimpleClient.HttpResult;
import com.alibaba.nacos.client.utils.*;
import com.alibaba.nacos.client.utils.EnvUtil;
import com.alibaba.nacos.client.utils.LogUtils;
import com.alibaba.nacos.client.utils.ParamUtil;
import com.alibaba.nacos.client.utils.TemplateUtils;
import com.alibaba.nacos.common.lifecycle.Closeable;
import com.alibaba.nacos.common.utils.IoUtils;
import com.alibaba.nacos.common.utils.StringUtils;
import com.alibaba.nacos.common.utils.ThreadUtils;
import org.slf4j.Logger;
import java.io.IOException;
import java.io.StringReader;
import java.net.HttpURLConnection;
import java.util.*;
import java.util.List;
import java.util.ArrayList;
import java.util.Properties;
import java.util.Iterator;
import java.util.Collections;
import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
/**
* Serverlist Manager
*
* @author Nacos
*/
public class ServerListManager {
public class ServerListManager implements Closeable {
private static final Logger LOGGER = LogUtils.logger(ServerListManager.class);
private static final String HTTPS = "https://";
private static final String HTTP = "http://";
private ScheduledExecutorService executorService = new ScheduledThreadPoolExecutor(1, new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r);
t.setName("com.alibaba.nacos.client.ServerListManager");
t.setDaemon(true);
return t;
}
});
public ServerListManager() {
isFixed = false;
isStarted = false;
name = DEFAULT_NAME;
this.isFixed = false;
this.isStarted = false;
this.name = DEFAULT_NAME;
}
public ServerListManager(List<String> fixed) {
@ -56,8 +77,8 @@ public class ServerListManager {
}
public ServerListManager(List<String> fixed, String namespace) {
isFixed = true;
isStarted = true;
this.isFixed = true;
this.isStarted = true;
List<String> serverAddrs = new ArrayList<String>();
for (String serverAddr : fixed) {
String[] serverAddrArr = serverAddr.split(":");
@ -67,21 +88,21 @@ public class ServerListManager {
serverAddrs.add(serverAddr);
}
}
serverUrls = new ArrayList<String>(serverAddrs);
this.serverUrls = new ArrayList<String>(serverAddrs);
if (StringUtils.isBlank(namespace)) {
name = FIXED_NAME + "-" + getFixedNameSuffix(serverAddrs.toArray(new String[serverAddrs.size()]));
this.name = FIXED_NAME + "-" + getFixedNameSuffix(serverAddrs.toArray(new String[serverAddrs.size()]));
} else {
this.namespace = namespace;
name = FIXED_NAME + "-" + getFixedNameSuffix(serverAddrs.toArray(new String[serverAddrs.size()])) + "-"
this.name = FIXED_NAME + "-" + getFixedNameSuffix(serverAddrs.toArray(new String[serverAddrs.size()])) + "-"
+ namespace;
}
}
public ServerListManager(String host, int port) {
isFixed = false;
isStarted = false;
name = CUSTOM_NAME + "-" + host + "-" + port;
addressServerUrl = String.format("http://%s:%d/%s/%s", host, port, contentPath, serverListName);
this.isFixed = false;
this.isStarted = false;
this.name = CUSTOM_NAME + "-" + host + "-" + port;
this.addressServerUrl = String.format("http://%s:%d/%s/%s", host, port, this.contentPath, this.serverListName);
}
public ServerListManager(String endpoint) throws NacosException {
@ -89,8 +110,8 @@ public class ServerListManager {
}
public ServerListManager(String endpoint, String namespace) throws NacosException {
isFixed = false;
isStarted = false;
this.isFixed = false;
this.isStarted = false;
Properties properties = new Properties();
properties.setProperty(PropertyKeyConst.ENDPOINT, endpoint);
endpoint = initEndpoint(properties);
@ -99,30 +120,33 @@ public class ServerListManager {
throw new NacosException(NacosException.CLIENT_INVALID_PARAM, "endpoint is blank");
}
if (StringUtils.isBlank(namespace)) {
name = endpoint;
addressServerUrl = String.format("http://%s:%d/%s/%s", endpoint, endpointPort, contentPath,
serverListName);
this.name = endpoint;
this.addressServerUrl = String.format("http://%s:%d/%s/%s", endpoint, this.endpointPort, this.contentPath,
this.serverListName);
} else {
if (StringUtils.isBlank(endpoint)) {
throw new NacosException(NacosException.CLIENT_INVALID_PARAM, "endpoint is blank");
}
name = endpoint + "-" + namespace;
this.name = endpoint + "-" + namespace;
this.namespace = namespace;
this.tenant = namespace;
addressServerUrl = String.format("http://%s:%d/%s/%s?namespace=%s", endpoint, endpointPort, contentPath,
serverListName, namespace);
this.addressServerUrl = String.format("http://%s:%d/%s/%s?namespace=%s", endpoint, this.endpointPort, this.contentPath,
this.serverListName, namespace);
}
}
public ServerListManager(Properties properties) throws NacosException {
isStarted = false;
serverAddrsStr = properties.getProperty(PropertyKeyConst.SERVER_ADDR);
this.isStarted = false;
this.serverAddrsStr = properties.getProperty(PropertyKeyConst.SERVER_ADDR);
String namespace = properties.getProperty(PropertyKeyConst.NAMESPACE);
initParam(properties);
if (StringUtils.isNotEmpty(serverAddrsStr)) {
isFixed = true;
this.isFixed = true;
List<String> serverAddrs = new ArrayList<String>();
String[] serverAddrsArr = serverAddrsStr.split(",");
String[] serverAddrsArr = this.serverAddrsStr.split(",");
for (String serverAddr: serverAddrsArr) {
if (serverAddr.startsWith(HTTPS) || serverAddr.startsWith(HTTP)) {
serverAddrs.add(serverAddr);
@ -135,45 +159,44 @@ public class ServerListManager {
}
}
}
serverUrls = serverAddrs;
this.serverUrls = serverAddrs;
if (StringUtils.isBlank(namespace)) {
name = FIXED_NAME + "-" + getFixedNameSuffix(serverUrls.toArray(new String[serverUrls.size()]));
this.name = FIXED_NAME + "-" + getFixedNameSuffix(this.serverUrls.toArray(new String[this.serverUrls.size()]));
} else {
this.namespace = namespace;
this.tenant = namespace;
name = FIXED_NAME + "-" + getFixedNameSuffix(serverUrls.toArray(new String[serverUrls.size()])) + "-"
this.name = FIXED_NAME + "-" + getFixedNameSuffix(this.serverUrls.toArray(new String[this.serverUrls.size()])) + "-"
+ namespace;
}
} else {
if (StringUtils.isBlank(endpoint)) {
throw new NacosException(NacosException.CLIENT_INVALID_PARAM, "endpoint is blank");
}
isFixed = false;
this.isFixed = false;
if (StringUtils.isBlank(namespace)) {
name = endpoint;
addressServerUrl = String.format("http://%s:%d/%s/%s", endpoint, endpointPort, contentPath,
serverListName);
this.name = endpoint;
this.addressServerUrl = String.format("http://%s:%d/%s/%s", this.endpoint, this.endpointPort, this.contentPath,
this.serverListName);
} else {
this.namespace = namespace;
this.tenant = namespace;
name = endpoint + "-" + namespace;
addressServerUrl = String.format("http://%s:%d/%s/%s?namespace=%s", endpoint, endpointPort,
contentPath, serverListName, namespace);
this.name = this.endpoint + "-" + namespace;
this.addressServerUrl = String.format("http://%s:%d/%s/%s?namespace=%s", this.endpoint, this.endpointPort,
this.contentPath, this.serverListName, namespace);
}
}
}
private void initParam(Properties properties) {
endpoint = initEndpoint(properties);
this.endpoint = initEndpoint(properties);
String contentPathTmp = properties.getProperty(PropertyKeyConst.CONTEXT_PATH);
if (!StringUtils.isBlank(contentPathTmp)) {
contentPath = contentPathTmp;
this.contentPath = contentPathTmp;
}
String serverListNameTmp = properties.getProperty(PropertyKeyConst.CLUSTER_NAME);
if (!StringUtils.isBlank(serverListNameTmp)) {
serverListName = serverListNameTmp;
this.serverListName = serverListNameTmp;
}
}
@ -187,7 +210,7 @@ public class ServerListManager {
});
if (StringUtils.isNotBlank(endpointPortTmp)) {
endpointPort = Integer.parseInt(endpointPortTmp);
this.endpointPort = Integer.parseInt(endpointPortTmp);
}
String endpointTmp = properties.getProperty(PropertyKeyConst.ENDPOINT);
@ -200,7 +223,7 @@ public class ServerListManager {
if (Boolean.parseBoolean(isUseEndpointRuleParsing)) {
String endpointUrl = ParamUtil.parsingEndpointRule(endpointTmp);
if (StringUtils.isNotBlank(endpointUrl)) {
serverAddrsStr = "";
this.serverAddrsStr = "";
}
return endpointUrl;
}
@ -231,7 +254,8 @@ public class ServerListManager {
"fail to get NACOS-server serverlist! env:" + name + ", not connnect url:" + addressServerUrl);
}
TimerService.scheduleWithFixedDelay(getServersTask, 0L, 30L, TimeUnit.SECONDS);
// executor schedules the timer task
this.executorService.scheduleWithFixedDelay(getServersTask,0L, 30L, TimeUnit.SECONDS);
isStarted = true;
}
@ -246,6 +270,14 @@ public class ServerListManager {
return new ServerAddressIterator(serverUrls);
}
@Override
public void shutdown() throws NacosException{
String className = this.getClass().getName();
LOGGER.info("{} do shutdown begin", className);
ThreadUtils.shutdownThreadPool(executorService, LOGGER);
LOGGER.info("{} do shutdown stop", className);
}
class GetServerListTask implements Runnable {
final String url;

View File

@ -1,44 +0,0 @@
/*
* 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.impl;
import java.util.concurrent.*;
/**
* Time Service
*
* @author Nacos
*/
public class TimerService {
static public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command, long initialDelay,
long delay, TimeUnit unit) {
return scheduledExecutor.scheduleWithFixedDelay(command, initialDelay, delay, unit);
}
@SuppressWarnings("PMD.ThreadPoolCreationRule")
static ScheduledExecutorService scheduledExecutor = Executors
.newSingleThreadScheduledExecutor(new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r);
t.setName("com.alibaba.nacos.client.Timer");
t.setDaemon(true);
return t;
}
});
}

View File

@ -85,18 +85,18 @@ public class NacosNamingService implements NamingService {
private void init(Properties properties) {
ValidatorUtils.checkInitParam(properties);
namespace = InitUtils.initNamespaceForNaming(properties);
this.namespace = InitUtils.initNamespaceForNaming(properties);
InitUtils.initSerialization();
initServerAddr(properties);
InitUtils.initWebRootContext();
initCacheDir();
initLogName(properties);
eventDispatcher = new EventDispatcher();
serverProxy = new NamingProxy(namespace, endpoint, serverList, properties);
beatReactor = new BeatReactor(serverProxy, initClientBeatThreadCount(properties));
hostReactor = new HostReactor(eventDispatcher, serverProxy, cacheDir, isLoadCacheAtStart(properties),
initPollingThreadCount(properties));
this.eventDispatcher = new EventDispatcher();
this.serverProxy = new NamingProxy(this.namespace, this.endpoint, this.serverList, properties);
this.beatReactor = new BeatReactor(this.serverProxy, initClientBeatThreadCount(properties));
this.hostReactor = new HostReactor(this.eventDispatcher, this.serverProxy, beatReactor, this.cacheDir,
isLoadCacheAtStart(properties), initPollingThreadCount(properties));
}
private int initClientBeatThreadCount(Properties properties) {
@ -189,21 +189,10 @@ public class NacosNamingService implements NamingService {
@Override
public void registerInstance(String serviceName, String groupName, Instance instance) throws NacosException {
if (instance.isEphemeral()) {
BeatInfo beatInfo = new BeatInfo();
beatInfo.setServiceName(NamingUtils.getGroupedName(serviceName, groupName));
beatInfo.setIp(instance.getIp());
beatInfo.setPort(instance.getPort());
beatInfo.setCluster(instance.getClusterName());
beatInfo.setWeight(instance.getWeight());
beatInfo.setMetadata(instance.getMetadata());
beatInfo.setScheduled(false);
beatInfo.setPeriod(instance.getInstanceHeartBeatInterval());
BeatInfo beatInfo = beatReactor.buildBeatInfo(instance);
beatReactor.addBeatInfo(NamingUtils.getGroupedName(serviceName, groupName), beatInfo);
}
serverProxy.registerService(NamingUtils.getGroupedName(serviceName, groupName), groupName, instance);
}
@ -487,4 +476,12 @@ public class NacosNamingService implements NamingService {
public BeatReactor getBeatReactor() {
return beatReactor;
}
@Override
public void shutDown() throws NacosException {
beatReactor.shutdown();
eventDispatcher.shutdown();
hostReactor.shutdown();
serverProxy.shutdown();
}
}

View File

@ -15,14 +15,17 @@
*/
package com.alibaba.nacos.client.naming.backups;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.naming.pojo.ServiceInfo;
import com.alibaba.nacos.client.naming.cache.ConcurrentDiskUtil;
import com.alibaba.nacos.client.naming.cache.DiskCache;
import com.alibaba.nacos.client.naming.core.HostReactor;
import com.alibaba.nacos.client.naming.utils.CollectionUtils;
import com.alibaba.nacos.client.naming.utils.UtilAndComs;
import com.alibaba.nacos.common.lifecycle.Closeable;
import com.alibaba.nacos.common.utils.JacksonUtils;
import com.alibaba.nacos.common.utils.ThreadUtils;
import org.apache.commons.lang3.StringUtils;
import java.io.BufferedReader;
@ -37,29 +40,31 @@ import static com.alibaba.nacos.client.utils.LogUtils.NAMING_LOGGER;
/**
* @author nkorange
*/
public class FailoverReactor {
public class FailoverReactor implements Closeable {
private String failoverDir;
private HostReactor hostReactor;
private ScheduledExecutorService executorService;
public FailoverReactor(HostReactor hostReactor, String cacheDir) {
this.hostReactor = hostReactor;
this.failoverDir = cacheDir + "/failover";
// init executorService
this.executorService = Executors.newSingleThreadScheduledExecutor(new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
Thread thread = new Thread(r);
thread.setDaemon(true);
thread.setName("com.alibaba.nacos.naming.failover");
return thread;
}
});
this.init();
}
private Map<String, ServiceInfo> serviceMap = new ConcurrentHashMap<String, ServiceInfo>();
private ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor(new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
Thread thread = new Thread(r);
thread.setDaemon(true);
thread.setName("com.alibaba.nacos.naming.failover");
return thread;
}
});
private Map<String, String> switchParams = new ConcurrentHashMap<String, String>();
private static final long DAY_PERIOD_MINUTES = 24 * 60;
@ -99,6 +104,14 @@ public class FailoverReactor {
return startDT.getTime();
}
@Override
public void shutdown() throws NacosException {
String className = this.getClass().getName();
NAMING_LOGGER.info("{} do shutdown begin", className);
ThreadUtils.shutdownThreadPool(executorService, NAMING_LOGGER);
NAMING_LOGGER.info("{} do shutdown stop", className);
}
class SwitchRefresher implements Runnable {
long lastModifiedMillis = 0L;

View File

@ -24,7 +24,9 @@ import com.alibaba.nacos.api.naming.utils.NamingUtils;
import com.alibaba.nacos.client.monitor.MetricsMonitor;
import com.alibaba.nacos.client.naming.net.NamingProxy;
import com.alibaba.nacos.client.naming.utils.UtilAndComs;
import com.alibaba.nacos.common.lifecycle.Closeable;
import com.alibaba.nacos.common.utils.JacksonUtils;
import com.alibaba.nacos.common.utils.ThreadUtils;
import com.fasterxml.jackson.databind.JsonNode;
import java.util.Map;
@ -35,7 +37,7 @@ import static com.alibaba.nacos.client.utils.LogUtils.NAMING_LOGGER;
/**
* @author harold
*/
public class BeatReactor {
public class BeatReactor implements Closeable {
private ScheduledExecutorService executorService;
@ -51,7 +53,7 @@ public class BeatReactor {
public BeatReactor(NamingProxy serverProxy, int threadCount) {
this.serverProxy = serverProxy;
executorService = new ScheduledThreadPoolExecutor(threadCount, new ThreadFactory() {
this.executorService = new ScheduledThreadPoolExecutor(threadCount, new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
Thread thread = new Thread(r);
@ -85,11 +87,32 @@ public class BeatReactor {
MetricsMonitor.getDom2BeatSizeMonitor().set(dom2Beat.size());
}
private String buildKey(String serviceName, String ip, int port) {
public BeatInfo buildBeatInfo(Instance instance) {
BeatInfo beatInfo = new BeatInfo();
beatInfo.setServiceName(instance.getServiceName());
beatInfo.setIp(instance.getIp());
beatInfo.setPort(instance.getPort());
beatInfo.setCluster(instance.getClusterName());
beatInfo.setWeight(instance.getWeight());
beatInfo.setMetadata(instance.getMetadata());
beatInfo.setScheduled(false);
beatInfo.setPeriod(instance.getInstanceHeartBeatInterval());
return beatInfo;
}
public String buildKey(String serviceName, String ip, int port) {
return serviceName + Constants.NAMING_INSTANCE_ID_SPLITTER
+ ip + Constants.NAMING_INSTANCE_ID_SPLITTER + port;
}
@Override
public void shutdown() throws NacosException{
String className = this.getClass().getName();
NAMING_LOGGER.info("{} do shutdown begin", className);
ThreadUtils.shutdownThreadPool(executorService, NAMING_LOGGER);
NAMING_LOGGER.info("{} do shutdown stop", className);
}
class BeatTask implements Runnable {
BeatInfo beatInfo;

View File

@ -23,7 +23,6 @@ import com.alibaba.nacos.client.naming.utils.Pair;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import static com.alibaba.nacos.client.utils.LogUtils.NAMING_LOGGER;
@ -32,11 +31,6 @@ import static com.alibaba.nacos.client.utils.LogUtils.NAMING_LOGGER;
*/
public class Balancer {
/**
* report status to server
*/
public final static List<String> UNCONSISTENT_SERVICE_WITH_ADDRESS_SERVER = new CopyOnWriteArrayList<String>();
public static class RandomByWeight {
public static List<Instance> selectAll(ServiceInfo serviceInfo) {

View File

@ -15,11 +15,14 @@
*/
package com.alibaba.nacos.client.naming.core;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.naming.listener.EventListener;
import com.alibaba.nacos.api.naming.listener.NamingEvent;
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.common.lifecycle.Closeable;
import com.alibaba.nacos.common.utils.ThreadUtils;
import java.util.ArrayList;
import java.util.Collections;
@ -32,7 +35,7 @@ import static com.alibaba.nacos.client.utils.LogUtils.NAMING_LOGGER;
/**
* @author xuanyin
*/
public class EventDispatcher {
public class EventDispatcher implements Closeable {
private ExecutorService executor = null;
@ -43,7 +46,7 @@ public class EventDispatcher {
public EventDispatcher() {
executor = Executors.newSingleThreadExecutor(new ThreadFactory() {
this.executor = Executors.newSingleThreadExecutor(new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
Thread thread = new Thread(r, "com.alibaba.nacos.naming.client.listener");
@ -53,7 +56,7 @@ public class EventDispatcher {
}
});
executor.execute(new Notifier());
this.executor.execute(new Notifier());
}
public void addListener(ServiceInfo serviceInfo, String clusters, EventListener listener) {
@ -109,6 +112,14 @@ public class EventDispatcher {
changedServices.add(serviceInfo);
}
@Override
public void shutdown() throws NacosException {
String className = this.getClass().getName();
NAMING_LOGGER.info("{} do shutdown begin", className);
ThreadUtils.shutdownThreadPool(executor, NAMING_LOGGER);
NAMING_LOGGER.info("{} do shutdown stop", className);
}
private class Notifier implements Runnable {
@Override
public void run() {

View File

@ -20,22 +20,37 @@ 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.beat.BeatInfo;
import com.alibaba.nacos.client.naming.beat.BeatReactor;
import com.alibaba.nacos.client.naming.cache.DiskCache;
import com.alibaba.nacos.client.naming.net.NamingProxy;
import com.alibaba.nacos.client.naming.utils.UtilAndComs;
import com.alibaba.nacos.common.lifecycle.Closeable;
import com.alibaba.nacos.common.utils.JacksonUtils;
import com.alibaba.nacos.common.utils.ThreadUtils;
import org.apache.commons.lang3.StringUtils;
import java.util.*;
import java.util.concurrent.*;
import java.util.HashSet;
import java.util.Map;
import java.util.HashMap;
import java.util.Set;
import java.util.List;
import java.util.ArrayList;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
import static com.alibaba.nacos.client.utils.LogUtils.NAMING_LOGGER;
/**
* @author xuanyin
*/
public class HostReactor {
public class HostReactor implements Closeable {
private static final long DEFAULT_DELAY = 1000L;
@ -51,6 +66,8 @@ public class HostReactor {
private EventDispatcher eventDispatcher;
private BeatReactor beatReactor;
private NamingProxy serverProxy;
private FailoverReactor failoverReactor;
@ -59,14 +76,14 @@ public class HostReactor {
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, BeatReactor beatReactor, String cacheDir) {
this(eventDispatcher, serverProxy, beatReactor, cacheDir, false, UtilAndComs.DEFAULT_POLLING_THREAD_COUNT);
}
public HostReactor(EventDispatcher eventDispatcher, NamingProxy serverProxy, String cacheDir,
public HostReactor(EventDispatcher eventDispatcher, NamingProxy serverProxy, BeatReactor beatReactor, String cacheDir,
boolean loadCacheAtStart, int pollingThreadCount) {
executor = new ScheduledThreadPoolExecutor(pollingThreadCount, new ThreadFactory() {
// init executorService
this.executor = new ScheduledThreadPoolExecutor(pollingThreadCount, new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
Thread thread = new Thread(r);
@ -75,8 +92,8 @@ public class HostReactor {
return thread;
}
});
this.eventDispatcher = eventDispatcher;
this.beatReactor = beatReactor;
this.serverProxy = serverProxy;
this.cacheDir = cacheDir;
if (loadCacheAtStart) {
@ -174,6 +191,7 @@ public class HostReactor {
if (modHosts.size() > 0) {
changed = true;
updateBeatInfo(modHosts);
NAMING_LOGGER.info("modified ips(" + modHosts.size() + ") service: "
+ serviceInfo.getKey() + " -> " + JacksonUtils.toJson(modHosts));
}
@ -205,6 +223,16 @@ public class HostReactor {
return serviceInfo;
}
private void updateBeatInfo(Set<Instance> modHosts) {
for (Instance instance : modHosts) {
String key = beatReactor.buildKey(instance.getServiceName(), instance.getIp(), instance.getPort());
if (beatReactor.dom2Beat.containsKey(key) && instance.isEphemeral()) {
BeatInfo beatInfo = beatReactor.buildBeatInfo(instance);
beatReactor.addBeatInfo(instance.getServiceName(), beatInfo);
}
}
}
private ServiceInfo getServiceInfo0(String serviceName, String clusters) {
String key = ServiceInfo.getKey(serviceName, clusters);
@ -259,7 +287,6 @@ public class HostReactor {
}
public void scheduleUpdateIfAbsent(String serviceName, String clusters) {
if (futureMap.get(ServiceInfo.getKey(serviceName, clusters)) != null) {
return;
@ -303,6 +330,14 @@ public class HostReactor {
}
}
@Override
public void shutdown() throws NacosException {
String className = this.getClass().getName();
NAMING_LOGGER.info("{} do shutdown begin", className);
ThreadUtils.shutdownThreadPool(executor, NAMING_LOGGER);
NAMING_LOGGER.info("{} do shutdown stop", className);
}
public class UpdateTask implements Runnable {
long lastRefTime = Long.MAX_VALUE;
private String clusters;

View File

@ -15,9 +15,12 @@
*/
package com.alibaba.nacos.client.naming.core;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.common.lifecycle.Closeable;
import com.alibaba.nacos.common.utils.JacksonUtils;
import com.alibaba.nacos.common.utils.StringUtils;
import com.alibaba.nacos.common.utils.IoUtils;
import com.alibaba.nacos.common.utils.ThreadUtils;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
@ -31,7 +34,7 @@ import static com.alibaba.nacos.client.utils.LogUtils.NAMING_LOGGER;
/**
* @author xuanyin
*/
public class PushReceiver implements Runnable {
public class PushReceiver implements Runnable, Closeable {
private ScheduledExecutorService executorService;
@ -44,9 +47,9 @@ public class PushReceiver implements Runnable {
public PushReceiver(HostReactor hostReactor) {
try {
this.hostReactor = hostReactor;
udpSocket = new DatagramSocket();
this.udpSocket = new DatagramSocket();
executorService = new ScheduledThreadPoolExecutor(1, new ThreadFactory() {
this.executorService = new ScheduledThreadPoolExecutor(1, new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
Thread thread = new Thread(r);
@ -56,7 +59,7 @@ public class PushReceiver implements Runnable {
}
});
executorService.execute(this);
this.executorService.execute(this);
} catch (Exception e) {
NAMING_LOGGER.error("[NA] init udp socket failed", e);
}
@ -106,6 +109,14 @@ public class PushReceiver implements Runnable {
}
}
@Override
public void shutdown() throws NacosException {
String className = this.getClass().getName();
NAMING_LOGGER.info("{} do shutdown begin", className);
ThreadUtils.shutdownThreadPool(executorService, NAMING_LOGGER);
NAMING_LOGGER.info("{} do shutdown stop", className);
}
public static class PushPacket {
public String type;
public long lastRefTime;
@ -113,6 +124,6 @@ public class PushReceiver implements Runnable {
}
public int getUDPPort() {
return udpSocket.getLocalPort();
return this.udpSocket.getLocalPort();
}
}

View File

@ -37,11 +37,8 @@ import com.alibaba.nacos.client.security.SecurityProxy;
import com.alibaba.nacos.client.utils.AppNameUtils;
import com.alibaba.nacos.client.utils.TemplateUtils;
import com.alibaba.nacos.common.constant.HttpHeaderConsts;
import com.alibaba.nacos.common.utils.HttpMethod;
import com.alibaba.nacos.common.utils.IoUtils;
import com.alibaba.nacos.common.utils.JacksonUtils;
import com.alibaba.nacos.common.utils.UuidUtils;
import com.alibaba.nacos.common.utils.VersionUtils;
import com.alibaba.nacos.common.lifecycle.Closeable;
import com.alibaba.nacos.common.utils.*;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonNode;
@ -60,7 +57,7 @@ import static com.alibaba.nacos.client.utils.LogUtils.NAMING_LOGGER;
/**
* @author nkorange
*/
public class NamingProxy {
public class NamingProxy implements Closeable {
private static final int DEFAULT_SERVER_PORT = 8848;
@ -86,9 +83,11 @@ public class NamingProxy {
private Properties properties;
private ScheduledExecutorService executorService;
public NamingProxy(String namespaceId, String endpoint, String serverList, Properties properties) {
securityProxy = new SecurityProxy(properties);
this.securityProxy = new SecurityProxy(properties);
this.properties = properties;
this.setServerPort(DEFAULT_SERVER_PORT);
this.namespaceId = namespaceId;
@ -99,13 +98,12 @@ public class NamingProxy {
this.nacosDomain = serverList;
}
}
initRefreshTask();
this.initRefreshTask();
}
private void initRefreshTask() {
ScheduledExecutorService executorService = new ScheduledThreadPoolExecutor(2, new ThreadFactory() {
this.executorService = new ScheduledThreadPoolExecutor(2, new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r);
@ -115,7 +113,7 @@ public class NamingProxy {
}
});
executorService.scheduleWithFixedDelay(new Runnable() {
this.executorService.scheduleWithFixedDelay(new Runnable() {
@Override
public void run() {
refreshSrvIfNeed();
@ -123,7 +121,7 @@ public class NamingProxy {
}, 0, vipSrvRefInterMillis, TimeUnit.MILLISECONDS);
executorService.scheduleWithFixedDelay(new Runnable() {
this.executorService.scheduleWithFixedDelay(new Runnable() {
@Override
public void run() {
securityProxy.login(getServerList());
@ -131,7 +129,7 @@ public class NamingProxy {
}, 0, securityInfoRefreshIntervalMills, TimeUnit.MILLISECONDS);
refreshSrvIfNeed();
securityProxy.login(getServerList());
this.securityProxy.login(getServerList());
}
public List<String> getServerListFromEndpoint() {
@ -197,7 +195,7 @@ public class NamingProxy {
NAMING_LOGGER.info("[REGISTER-SERVICE] {} registering service {} with instance: {}",
namespaceId, serviceName, instance);
final Map<String, String> params = new HashMap<String, String>(9);
final Map<String, String> params = new HashMap<String, String>(16);
params.put(CommonParams.NAMESPACE_ID, namespaceId);
params.put(CommonParams.SERVICE_NAME, serviceName);
params.put(CommonParams.GROUP_NAME, groupName);
@ -583,5 +581,12 @@ public class NamingProxy {
}
}
@Override
public void shutdown() throws NacosException{
String className = this.getClass().getName();
NAMING_LOGGER.info("{} do shutdown begin", className);
ThreadUtils.shutdownThreadPool(executorService, NAMING_LOGGER);
NAMING_LOGGER.info("{} do shutdown stop", className);
}
}

View File

@ -23,15 +23,11 @@ import com.alibaba.nacos.api.PropertyKeyConst;
import com.alibaba.nacos.api.config.ConfigService;
import com.alibaba.nacos.api.config.listener.AbstractListener;
import com.alibaba.nacos.common.utils.ThreadUtils;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.*;
import java.util.Objects;
import java.util.Properties;
import java.util.Scanner;
import java.util.concurrent.CountDownLatch;
/**
* @author <a href="mailto:liaochuntao@live.com">liaochuntao</a>
@ -52,6 +48,12 @@ public class ConfigTest {
configService = NacosFactory.createConfigService(properties);
}
@After
public void cleanup() throws Exception {
configService.shutDown();
}
@Test
public static void test() throws Exception {
final String dataId = "lessspring";
final String group = "lessspring";

View File

@ -16,20 +16,23 @@
package com.alibaba.nacos.client.naming.core;
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.naming.beat.BeatInfo;
import com.alibaba.nacos.client.naming.beat.BeatReactor;
import com.alibaba.nacos.client.naming.net.NamingProxy;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import java.util.HashMap;
import static org.junit.Assert.*;
import static org.mockito.Mockito.when;
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.naming.net.NamingProxy;
@RunWith(MockitoJUnitRunner.class)
public class HostReactorTest {
@ -43,15 +46,31 @@ public class HostReactorTest {
private HostReactor hostReactor;
private BeatReactor beatReactor;
@Before
public void setUp() throws Exception {
hostReactor = new HostReactor(eventDispatcher, namingProxy, CACHE_DIR);
beatReactor = new BeatReactor(namingProxy);
BeatInfo beatInfo = new BeatInfo();
beatInfo.setServiceName("testName");
beatInfo.setIp("1.1.1.1");
beatInfo.setPort(1234);
beatInfo.setCluster("clusterName");
beatInfo.setWeight(1);
beatInfo.setMetadata(new HashMap<String, String>());
beatInfo.setScheduled(false);
beatInfo.setPeriod(1000L);
beatReactor.addBeatInfo("testName", beatInfo);
hostReactor = new HostReactor(eventDispatcher, namingProxy, beatReactor, CACHE_DIR);
}
@Test
public void testProcessServiceJSON() {
ServiceInfo actual = hostReactor.processServiceJSON(EXAMPLE);
assertServiceInfo(actual);
hostReactor.processServiceJSON(CHANGE_DATA_EXAMPLE);
BeatInfo actualBeatInfo = beatReactor.dom2Beat.get(beatReactor.buildKey("testName", "1.1.1.1", 1234));
assertEquals(2.0, actualBeatInfo.getWeight(), 0.0);
}
@Test
@ -105,4 +124,30 @@ public class HostReactorTest {
+ "\t\"allIPs\": false,\n"
+ "\t\"valid\": true\n"
+ "}";
//the weight changed from 1.0 to 2.0
private static final String CHANGE_DATA_EXAMPLE = "{\n"
+ "\t\"name\": \"testName\",\n"
+ "\t\"clusters\": \"testClusters\",\n"
+ "\t\"cacheMillis\": 1000,\n"
+ "\t\"hosts\": [{\n"
+ "\t\t\"ip\": \"1.1.1.1\",\n"
+ "\t\t\"port\": 1234,\n"
+ "\t\t\"weight\": 2.0,\n"
+ "\t\t\"healthy\": true,\n"
+ "\t\t\"enabled\": true,\n"
+ "\t\t\"ephemeral\": true,\n"
+ "\t\t\"clusterName\": \"testClusters\",\n"
+ "\t\t\"serviceName\": \"testName\",\n"
+ "\t\t\"metadata\": {},\n"
+ "\t\t\"instanceHeartBeatInterval\": 5000,\n"
+ "\t\t\"instanceHeartBeatTimeOut\": 15000,\n"
+ "\t\t\"ipDeleteTimeout\": 30000,\n"
+ "\t\t\"instanceIdGenerator\": \"simple\"\n"
+ "\t}],\n"
+ "\t\"lastRefTime\": 0,\n"
+ "\t\"checksum\": \"\",\n"
+ "\t\"allIPs\": false,\n"
+ "\t\"valid\": true\n"
+ "}";
}

View File

@ -25,5 +25,10 @@ public interface HttpHeaderConsts {
String CLIENT_VERSION_HEADER = "Client-Version";
String USER_AGENT_HEADER = "User-Agent";
String REQUEST_SOURCE_HEADER = "Request-Source";
String CONTENT_TYPE = "Content-Type";
String CONTENT_LENGTH = "Content-Length";
String ACCEPT_CHARSET = "Accept-Charset";
String ACCEPT_ENCODING = "Accept-Encoding";
String CONTENT_ENCODING = "Content-Encoding";
}

View File

@ -16,14 +16,22 @@
package com.alibaba.nacos.common.http;
import com.alibaba.nacos.api.common.Constants;
import com.alibaba.nacos.common.http.handler.RequestHandler;
import com.alibaba.nacos.common.http.param.Header;
import com.alibaba.nacos.common.http.param.MediaType;
import com.alibaba.nacos.common.utils.HttpMethod;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpEntityEnclosingRequest;
import org.apache.http.HttpRequest;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpHead;
@ -34,6 +42,7 @@ import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.client.methods.HttpTrace;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.message.BasicNameValuePair;
/**
* @author <a href="mailto:liaochuntao@live.com">liaochuntao</a>
@ -157,7 +166,6 @@ public enum BaseHttpMethod {
if (body == null) {
return;
}
if (requestBase instanceof HttpEntityEnclosingRequest) {
HttpEntityEnclosingRequest request = (HttpEntityEnclosingRequest) requestBase;
ContentType contentType = ContentType.create(mediaType);
@ -166,6 +174,21 @@ public enum BaseHttpMethod {
}
}
public void initFromEntity(Map<String, String> body, String charset) throws Exception{
if (body.isEmpty()) {
return;
}
List<NameValuePair> params = new ArrayList<NameValuePair>(body.size());
for (Map.Entry<String, String> entry : body.entrySet()) {
params.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
}
if (requestBase instanceof HttpEntityEnclosingRequest) {
HttpEntityEnclosingRequest request = (HttpEntityEnclosingRequest) requestBase;
HttpEntity entity = new UrlEncodedFormEntity(params, charset);
request.setEntity(entity);
}
}
public HttpRequestBase getRequestBase() {
return (HttpRequestBase) requestBase;
}

View File

@ -16,8 +16,12 @@
package com.alibaba.nacos.common.http;
import com.alibaba.nacos.common.utils.ExceptionUtil;
import com.alibaba.nacos.common.http.client.DefaultAsyncHttpClientRequest;
import com.alibaba.nacos.common.http.client.DefaultHttpClientRequest;
import com.alibaba.nacos.common.http.client.NacosAsyncRestTemplate;
import com.alibaba.nacos.common.http.client.NacosRestTemplate;
import com.alibaba.nacos.common.utils.ShutdownUtils;
import com.alibaba.nacos.common.utils.ExceptionUtil;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.nio.client.HttpAsyncClients;
@ -47,8 +51,15 @@ public class HttpClientManager {
private static final NAsyncHttpClient ASYNC_HTTP_CLIENT = new NacosAsyncHttpClient(
HttpAsyncClients.custom().setDefaultRequestConfig(DEFAULT_CONFIG).build());
private static final NacosRestTemplate NACOS_REST_TEMPLATE = new NacosRestTemplate(
new DefaultHttpClientRequest(HttpClients.custom().setDefaultRequestConfig(DEFAULT_CONFIG).build()));
private static final NacosAsyncRestTemplate NACOS_ASYNC_REST_TEMPLATE = new NacosAsyncRestTemplate(
new DefaultAsyncHttpClientRequest(HttpAsyncClients.custom().setDefaultRequestConfig(DEFAULT_CONFIG).build()));
private static final AtomicBoolean alreadyShutdown = new AtomicBoolean(false);
static {
ShutdownUtils.addShutdownHook(new Runnable() {
@Override
@ -67,6 +78,14 @@ public class HttpClientManager {
return ASYNC_HTTP_CLIENT;
}
public static NacosRestTemplate getNacosRestTemplate() {
return NACOS_REST_TEMPLATE;
}
public static NacosAsyncRestTemplate getNacosAsyncRestTemplate() {
return NACOS_ASYNC_REST_TEMPLATE;
}
public static void shutdown() {
if (!alreadyShutdown.compareAndSet(false, true)) {
return;
@ -75,6 +94,8 @@ public class HttpClientManager {
try {
SYNC_HTTP_CLIENT.close();
ASYNC_HTTP_CLIENT.close();
NACOS_REST_TEMPLATE.close();
NACOS_ASYNC_REST_TEMPLATE.close();
}
catch (Exception ex) {
logger.error("An exception occurred when the HTTP client was closed : {}",

View File

@ -0,0 +1,48 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.nacos.common.http;
import com.alibaba.nacos.common.http.param.Header;
import com.alibaba.nacos.common.model.RestResult;
/**
* http RestResult
*
* @author mai.jh
* @date 2020/5/31
*/
public class HttpRestResult<T> extends RestResult<T> {
private static final long serialVersionUID = 3766947816720175947L;
private Header header;
public HttpRestResult() {
}
public HttpRestResult(Header header, int code, T data) {
super(code, data);
this.header = header;
}
public Header getHeader() {
return header;
}
public void setHeader(Header header) {
this.header = header;
}
}

View File

@ -16,9 +16,12 @@
package com.alibaba.nacos.common.http;
import com.alibaba.nacos.common.http.param.Query;
import com.alibaba.nacos.common.utils.StringUtils;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.HashMap;
@ -120,6 +123,19 @@ public final class HttpUtils {
return innerDecode(null, str, encode);
}
/**
* build URI By url and query
* @param url url
* @param query query param {@link Query}
* @return
*/
public static URI buildUri(String url, Query query) throws URISyntaxException {
if (!query.isEmpty()) {
url = url + "?" + query.toQueryUrl();
}
return new URI(url);
}
private static String innerDecode(String pre, String now, String encode) throws UnsupportedEncodingException {
// Because the data may be encoded by the URL more than once,
// it needs to be decoded recursively until it is fully successful

View File

@ -0,0 +1,48 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.nacos.common.http.client;
import com.alibaba.nacos.common.http.Callback;
import com.alibaba.nacos.common.model.RequestHttpEntity;
import java.io.Closeable;
import java.lang.reflect.Type;
import java.net.URI;
/**
* Represents a client-side Async HTTP request.
* Created via an implementation execute.
*
* @author mai.jh
* @date 2020/5/29
*/
public interface AsyncHttpClientRequest extends Closeable {
/**
* execute async http request
*
* @param uri http url
* @param httpMethod http request method
* @param requestHttpEntity http request entity
* @param responseType http response type
* @param callback http response callback
* @throws Exception ex
*/
<T> void execute(URI uri, String httpMethod, RequestHttpEntity requestHttpEntity,
final Type responseType, final Callback<T> callback) throws Exception;
}

View File

@ -0,0 +1,82 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.nacos.common.http.client;
import com.alibaba.nacos.common.http.Callback;
import com.alibaba.nacos.common.http.HttpRestResult;
import com.alibaba.nacos.common.http.handler.ResponseHandler;
import com.alibaba.nacos.common.model.RequestHttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.concurrent.FutureCallback;
import org.apache.http.impl.nio.client.CloseableHttpAsyncClient;
import java.io.IOException;
import java.lang.reflect.Type;
import java.net.URI;
/**
* {@link AsyncHttpClientRequest} implementation that uses apache async http client to
* execute streaming requests
*
* @author mai.jh
* @date 2020/5/29
*/
public class DefaultAsyncHttpClientRequest implements AsyncHttpClientRequest {
private final CloseableHttpAsyncClient asyncClient;
public DefaultAsyncHttpClientRequest(CloseableHttpAsyncClient asyncClient) {
this.asyncClient = asyncClient;
if (!this.asyncClient.isRunning()) {
this.asyncClient.start();
}
}
@Override
public <T> void execute(URI uri, String httpMethod, RequestHttpEntity requestHttpEntity, final Type responseType, final Callback<T> callback) throws Exception {
HttpRequestBase httpRequestBase = DefaultHttpClientRequest.build(uri, httpMethod, requestHttpEntity);
asyncClient.execute(httpRequestBase, new FutureCallback<HttpResponse>() {
@Override
public void completed(HttpResponse result) {
DefaultClientHttpResponse response = new DefaultClientHttpResponse(result);
try {
HttpRestResult<T> httpRestResult = ResponseHandler.responseEntityExtractor(response, responseType);
callback.onReceive(httpRestResult);
} catch (Exception e) {
callback.onError(e);
}
}
@Override
public void failed(Exception ex) {
callback.onError(ex);
}
@Override
public void cancelled() {
}
});
}
@Override
public void close() throws IOException {
this.asyncClient.close();
}
}

View File

@ -0,0 +1,79 @@
/*
* 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.http.client;
import com.alibaba.nacos.common.http.param.Header;
import org.apache.http.HttpResponse;
import org.apache.http.client.utils.HttpClientUtils;
import java.io.IOException;
import java.io.InputStream;
/**
* ApacheClientHttpResponse implementation {@link HttpClientResponse}
*
* @author mai.jh
* @date 2020/5/25
*/
public class DefaultClientHttpResponse implements HttpClientResponse {
private HttpResponse response;
private Header responseHeader;
public DefaultClientHttpResponse(HttpResponse response) {
this.response = response;
}
@Override
public int getStatusCode() {
return this.response.getStatusLine().getStatusCode();
}
@Override
public String getStatusText() {
return this.response.getStatusLine().getReasonPhrase();
}
@Override
public Header getHeaders() {
if (this.responseHeader == null) {
this.responseHeader = Header.newInstance();
org.apache.http.Header[] allHeaders = response.getAllHeaders();
for (org.apache.http.Header header : allHeaders) {
this.responseHeader.addParam(header.getName(), header.getValue());
}
}
return this.responseHeader;
}
@Override
public InputStream getBody() throws IOException{
return response.getEntity().getContent();
}
@Override
public void close() {
try {
if (this.response != null) {
HttpClientUtils.closeQuietly(response);
}
} catch (Exception ex) {
// ignore
}
}
}

View File

@ -0,0 +1,80 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.nacos.common.http.client;
import com.alibaba.nacos.common.constant.HttpHeaderConsts;
import com.alibaba.nacos.common.http.BaseHttpMethod;
import com.alibaba.nacos.common.http.param.Header;
import com.alibaba.nacos.common.http.param.MediaType;
import com.alibaba.nacos.common.model.RequestHttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.impl.client.CloseableHttpClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.net.URI;
import java.util.Map;
/**
* {@link HttpClientRequest} implementation that uses apache http client to
* execute streaming requests
*
* @author mai.jh
* @date 2020/5/24
*/
@SuppressWarnings({"unchecked", "rawtypes", "resource"})
public class DefaultHttpClientRequest implements HttpClientRequest {
private static final Logger logger = LoggerFactory.getLogger(DefaultHttpClientRequest.class);
private final CloseableHttpClient client;
public DefaultHttpClientRequest(CloseableHttpClient client) {
this.client = client;
}
@Override
public HttpClientResponse execute(URI uri, String httpMethod, RequestHttpEntity requestHttpEntity) throws Exception {
HttpRequestBase request = build(uri, httpMethod, requestHttpEntity);
CloseableHttpResponse response = client.execute(request);
if (logger.isDebugEnabled()) {
logger.debug("Request from server: " + request.getURI().toString());
}
return new DefaultClientHttpResponse(response);
}
static HttpRequestBase build(URI uri, String method, RequestHttpEntity requestHttpEntity) throws Exception {
Header headers = requestHttpEntity.getHeaders();
BaseHttpMethod httpMethod = BaseHttpMethod.sourceOf(method);
httpMethod.init(uri.toString());
httpMethod.initHeader(headers);
if (MediaType.APPLICATION_FORM_URLENCODED.equals(headers.getValue(HttpHeaderConsts.CONTENT_TYPE))
&& requestHttpEntity.getBody() instanceof Map) {
httpMethod.initFromEntity((Map<String, String>) requestHttpEntity.getBody(), headers.getCharset());
} else {
httpMethod.initEntity(requestHttpEntity.getBody(), headers.getValue(HttpHeaderConsts.CONTENT_TYPE));
}
return httpMethod.getRequestBase();
}
@Override
public void close() throws IOException {
client.close();
}
}

View File

@ -0,0 +1,42 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.nacos.common.http.client;
import com.alibaba.nacos.common.model.RequestHttpEntity;
import java.io.Closeable;
import java.net.URI;
/**
* Represents a client-side HTTP request.
* Created via an implementation execute.
*
* @author mai.jh
* @date 2020/5/23
*/
public interface HttpClientRequest extends Closeable {
/**
* execute http request
* @param uri http url
* @param httpMethod http request method
* @param requestHttpEntity http request entity
* @return HttpClientResponse
* @throws Exception ex
*/
HttpClientResponse execute(URI uri, String httpMethod, RequestHttpEntity requestHttpEntity) throws Exception;
}

View File

@ -0,0 +1,66 @@
/*
* 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.http.client;
import com.alibaba.nacos.common.http.param.Header;
import com.alibaba.nacos.common.model.RequestHttpEntity;
import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
/**
* Represents a client-side HTTP response.
*
* @author mai.jh
* @date 2020/5/23
*/
public interface HttpClientResponse extends Closeable {
/**
* Return the headers of this message.
* @return a corresponding HttpHeaders object (never {@code null})
*/
Header getHeaders();
/**
* Return the body of the message as an input stream.
* @return String response body
* @throws IOException IOException
*/
InputStream getBody() throws IOException;
/**
* Return the HTTP status code
* @return the HTTP status as an integer
*/
int getStatusCode();
/**
* Return the HTTP status text of the response.
* @return the HTTP status text
*/
String getStatusText();
/**
* close response InputStream
* @throws IOException ex
*/
@Override
void close() throws IOException;
}

View File

@ -0,0 +1,338 @@
/*
* 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.http.client;
import com.alibaba.nacos.common.http.Callback;
import com.alibaba.nacos.common.http.HttpUtils;
import com.alibaba.nacos.common.http.param.Header;
import com.alibaba.nacos.common.http.param.MediaType;
import com.alibaba.nacos.common.http.param.Query;
import com.alibaba.nacos.common.model.RequestHttpEntity;
import com.alibaba.nacos.common.utils.HttpMethod;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.reflect.Type;
import java.net.URI;
import java.util.Map;
/**
* NacosAsyncRestTemplate async
*
* @author mai.jh
* @date 2020/5/29
* @see AsyncHttpClientRequest
* @see HttpClientResponse
*/
public class NacosAsyncRestTemplate {
private static final Logger logger = LoggerFactory.getLogger(NacosAsyncRestTemplate.class);
private AsyncHttpClientRequest clientRequest;
public NacosAsyncRestTemplate(AsyncHttpClientRequest clientRequest) {
this.clientRequest = clientRequest;
}
/**
* async http get
* URL request params are expanded using the given query {@link Query}.
* <p>{@code responseType} can be an RestResult or RestResult data {@code T} type.
* <p>{@code callback} Result callback execution,
* if you need response headers, you can convert the received RestResult to HttpRestResult.
*
* @param url url
* @param responseType return type
* @param header http header param
* @param query http query param
* @param callback callback {@link Callback#onReceive(com.alibaba.nacos.common.model.RestResult)}
* @throws Exception ex
*/
public <T> void get(String url, Header header, Query query, Type responseType, Callback<T> callback) throws Exception {
execute(url, HttpMethod.GET, new RequestHttpEntity(header, query), responseType, callback);
}
/**
* async http get
* URL request params are expanded using the given map {@code paramValues}.
* <p>{@code responseType} can be an RestResult or RestResult data {@code T} type.
* <p>{@code callback} Result callback execution,
* if you need response headers, you can convert the received RestResult to HttpRestResult.
*
* @param url url
* @param header headers
* @param paramValues paramValues
* @param responseType return type
* @param callback callback {@link Callback#onReceive(com.alibaba.nacos.common.model.RestResult)}
* @throws Exception ex
*/
public <T> void get(String url, Header header, Map<String, String> paramValues,
Type responseType, Callback<T> callback) throws Exception {
execute(url, HttpMethod.GET, new RequestHttpEntity(header,
Query.newInstance().initParams(paramValues)), responseType, callback);
}
/**
* async get request, may be pulling a lot of data
* URL request params are expanded using the given query {@link Query},
* More request parameters can be set via body.
* <p>{@code responseType} can be an RestResult or RestResult data {@code T} type.
* <p>{@code callback} Result callback execution,
* if you need response headers, you can convert the received RestResult to HttpRestResult.
*
* @param url url
* @param header http header param
* @param query http query param
* @param body get with body
* @param responseType return type
* @param callback callback {@link Callback#onReceive(com.alibaba.nacos.common.model.RestResult)}
* @throws Exception ex
*/
public <T> void getLarge(String url, Header header, Query query, Object body,
Type responseType, Callback<T> callback) throws Exception {
execute(url, HttpMethod.GET_LARGE,
new RequestHttpEntity(header, query, body), responseType, callback);
}
/**
* async http delete
* URL request params are expanded using the given query {@link Query},
* <p>{@code responseType} can be an RestResult or RestResult data {@code T} type
* <p>{@code callback} Result callback execution,
* if you need response headers, you can convert the received RestResult to HttpRestResult.
*
* @param url url
* @param header http header param
* @param query http query param
* @param responseType return type
* @param callback callback {@link Callback#onReceive(com.alibaba.nacos.common.model.RestResult)}
* @throws Exception ex
*/
public <T> void delete(String url, Header header, Query query,
Type responseType, Callback<T> callback) throws Exception {
execute(url, HttpMethod.DELETE,
new RequestHttpEntity(header, query), responseType, callback);
}
/**
* async http put
* Create a new resource by PUTting the given body to http request.
* <p>URL request params are expanded using the given query {@link Query}.
* <p>{@code responseType} can be an RestResult or RestResult data {@code T} type
* <p>{@code callback} Result callback execution,
* if you need response headers, you can convert the received RestResult to HttpRestResult.
*
* @param url url
* @param header http header param
* @param query http query param
* @param body http body param
* @param responseType return type
* @param callback callback {@link Callback#onReceive(com.alibaba.nacos.common.model.RestResult)}
* @throws Exception ex
*/
public <T> void put(String url, Header header, Query query, Object body,
Type responseType, Callback<T> callback) throws Exception {
execute(url, HttpMethod.PUT,
new RequestHttpEntity(header, query, body), responseType, callback);
}
/**
* async http put Json
* Create a new resource by PUTting the given body to http request,
* http header contentType default 'application/json;charset=UTF-8'.
* <p>URL request params are expanded using the given map {@code paramValues}.
* <p>{@code responseType} can be an RestResult or RestResult data {@code T} type
* <p>{@code callback} Result callback execution,
* if you need response headers, you can convert the received RestResult to HttpRestResult.
*
* @param url url
* @param header http header param
* @param paramValues http query param
* @param body http body param
* @param responseType return type
* @param callback callback {@link Callback#onReceive(com.alibaba.nacos.common.model.RestResult)}
* @throws Exception ex
*/
public <T> void putJson(String url, Header header, Map<String, String> paramValues,
String body, Type responseType, Callback<T> callback) throws Exception {
execute(url, HttpMethod.PUT, new RequestHttpEntity(
header.setContentType(MediaType.APPLICATION_JSON),
Query.newInstance().initParams(paramValues), body),
responseType, callback);
}
/**
* async http put from
* Create a new resource by PUTting the given map {@code bodyValues} to http request,
* http header contentType default 'application/x-www-form-urlencoded;charset=utf-8'.
* <p>URL request params are expanded using the given query {@link Query}.
* <p>{@code responseType} can be an RestResult or RestResult data {@code T} type.
* <p>{@code callback} Result callback execution,
* if you need response headers, you can convert the received RestResult to HttpRestResult.
*
* @param url url
* @param header http header param
* @param query http query param
* @param bodyValues http body param
* @param responseType return type
* @param callback callback {@link Callback#onReceive(com.alibaba.nacos.common.model.RestResult)}
* @throws Exception ex
*/
public <T> void putFrom(String url, Header header, Query query, Map<String, String> bodyValues,
Type responseType, Callback<T> callback) throws Exception {
execute(url, HttpMethod.PUT, new RequestHttpEntity(
header.setContentType(MediaType.APPLICATION_FORM_URLENCODED),
query, bodyValues), responseType, callback);
}
/**
* async http put from
* Create a new resource by PUTting the given map {@code bodyValues} to http request,
* http header contentType default 'application/x-www-form-urlencoded;charset=utf-8'.
* <p>URL request params are expanded using the given map {@code paramValues}.
* <p>{@code responseType} can be an RestResult or RestResult data {@code T} type.
* <p>{@code callback} Result callback execution,
* if you need response headers, you can convert the received RestResult to HttpRestResult.
*
* @param url url
* @param header http header param
* @param paramValues http query param
* @param bodyValues http body param
* @param responseType return type
* @param callback callback {@link Callback#onReceive(com.alibaba.nacos.common.model.RestResult)}
* @throws Exception ex
*/
public <T> void putFrom(String url, Header header, Map<String, String> paramValues,
Map<String, String> bodyValues, Type responseType, Callback<T> callback) throws Exception {
execute(url, HttpMethod.PUT, new RequestHttpEntity(
header.setContentType(MediaType.APPLICATION_FORM_URLENCODED),
Query.newInstance().initParams(paramValues), bodyValues), responseType, callback);
}
/**
* async http post
* Create a new resource by POSTing the given object to the http request.
* <p>URL request params are expanded using the given query {@link Query}.
* <p>{@code responseType} can be an RestResult or RestResult data {@code T} type.
* <p>{@code callback} Result callback execution,
* if you need response headers, you can convert the received RestResult to HttpRestResult.
*
* @param url url
* @param header http header param
* @param query http query param
* @param body http body param
* @param responseType return type
* @param callback callback {@link Callback#onReceive(com.alibaba.nacos.common.model.RestResult)}
* @throws Exception ex
*/
public <T> void post(String url, Header header, Query query, Object body,
Type responseType, Callback<T> callback) throws Exception {
execute(url, HttpMethod.POST, new RequestHttpEntity(
header, query, body), responseType, callback);
}
/**
* async http post Json
* Create a new resource by POSTing the given object to the http request,
* http header contentType default 'application/json;charset=UTF-8'.
* <p>URL request params are expanded using the given map {@code paramValues}.
* <p>{@code responseType} can be an RestResult or RestResult data {@code T} type.
* <p>{@code callback} Result callback execution,
* if you need response headers, you can convert the received RestResult to HttpRestResult.
*
* @param url url
* @param header http header param
* @param paramValues http query param
* @param body http body param
* @param responseType return type
* @param callback callback {@link Callback#onReceive(com.alibaba.nacos.common.model.RestResult)}
* @throws Exception ex
*/
public <T> void postJson(String url, Header header, Map<String, String> paramValues,
String body, Type responseType, Callback<T> callback) throws Exception {
execute(url, HttpMethod.POST, new RequestHttpEntity(
header.setContentType(MediaType.APPLICATION_JSON),
Query.newInstance().initParams(paramValues), body),
responseType, callback);
}
/**
* async http post from
* Create a new resource by PUTting the given map {@code bodyValues} to http request,
* http header contentType default 'application/x-www-form-urlencoded;charset=utf-8'.
* <p>URL request params are expanded using the given query {@link Query}.
* <p>{@code responseType} can be an RestResult or RestResult data {@code T} type.
* <p>{@code callback} Result callback execution,
* if you need response headers, you can convert the received RestResult to HttpRestResult.
*
* @param url url
* @param header http header param
* @param query http query param
* @param bodyValues http body param
* @param responseType return type
* @param callback callback {@link Callback#onReceive(com.alibaba.nacos.common.model.RestResult)}
* @throws Exception ex
*/
public <T> void postFrom(String url, Header header, Query query, Map<String, String> bodyValues,
Type responseType, Callback<T> callback) throws Exception {
execute(url, HttpMethod.POST, new RequestHttpEntity(
header.setContentType(MediaType.APPLICATION_FORM_URLENCODED), query, bodyValues),
responseType, callback);
}
/**
* async http post from
* Create a new resource by PUTting the given map {@code bodyValues} to http request,
* http header contentType default 'application/x-www-form-urlencoded;charset=utf-8'.
* <p>URL request params are expanded using the given map {@code paramValues}.
* <p>{@code responseType} can be an RestResult or RestResult data {@code T} type.
* <p>{@code callback} Result callback execution,
* if you need response headers, you can convert the received RestResult to HttpRestResult.
*
* @param url url
* @param header http header param
* @param paramValues http query param
* @param bodyValues http body param
* @param responseType return type
* @param callback callback {@link Callback#onReceive(com.alibaba.nacos.common.model.RestResult)}
* @throws Exception ex
*/
public <T> void postFrom(String url, Header header, Map<String, String> paramValues,
Map<String, String> bodyValues, Type responseType, Callback<T> callback) throws Exception {
execute(url, HttpMethod.POST, new RequestHttpEntity(
header.setContentType(MediaType.APPLICATION_FORM_URLENCODED),
Query.newInstance().initParams(paramValues),
bodyValues), responseType, callback);
}
private <T> void execute(String url, String httpMethod, RequestHttpEntity requestEntity,
Type responseType, Callback<T> callback) throws Exception {
URI uri = HttpUtils.buildUri(url, requestEntity.getQuery());
if (logger.isDebugEnabled()) {
logger.debug("HTTP " + httpMethod + " " + url);
}
clientRequest.execute(uri, httpMethod, requestEntity, responseType, callback);
}
/**
* close request client
*/
public void close() throws Exception {
clientRequest.close();
}
}

View File

@ -0,0 +1,315 @@
/*
* 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.http.client;
import com.alibaba.nacos.common.http.HttpRestResult;
import com.alibaba.nacos.common.http.HttpUtils;
import com.alibaba.nacos.common.http.handler.ResponseHandler;
import com.alibaba.nacos.common.http.param.Header;
import com.alibaba.nacos.common.http.param.MediaType;
import com.alibaba.nacos.common.http.param.Query;
import com.alibaba.nacos.common.model.RequestHttpEntity;
import com.alibaba.nacos.common.utils.HttpMethod;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.reflect.Type;
import java.net.URI;
import java.util.Map;
/**
* NacosRestTemplate
* Interface specifying a basic set of RESTful operations.
*
* @author mai.jh
* @date 2020/5/24
* @see HttpClientRequest
* @see HttpClientResponse
*/
public class NacosRestTemplate {
private static final Logger logger = LoggerFactory.getLogger(NacosRestTemplate.class);
private HttpClientRequest requestClient;
public NacosRestTemplate(HttpClientRequest requestClient) {
this.requestClient = requestClient;
}
/**
* http get
* URL request params are expanded using the given query {@link Query}.
* <p>{@code responseType} can be an HttpRestResult or HttpRestResult data {@code T} type.
*
* @param url url
* @param header http header param
* @param query http query param
* @param responseType return type
* @return {@link HttpRestResult}
* @throws Exception ex
*/
public <T> HttpRestResult<T> get(String url, Header header, Query query, Type responseType) throws Exception {
return execute(url, HttpMethod.GET, new RequestHttpEntity(header, query), responseType);
}
/**
* http get
* URL request params are expanded using the given query {@link Query}.
* <p>{@code responseType} can be an HttpRestResult or HttpRestResult data {@code T} type.
*
* @param url url
* @param header headers
* @param paramValues paramValues
* @param responseType return type
* @return {@link HttpRestResult}
* @throws Exception ex
*/
public <T> HttpRestResult<T> get(String url, Header header, Map<String, String> paramValues, Type responseType) throws Exception {
RequestHttpEntity requestHttpEntity = new RequestHttpEntity(header, Query.newInstance().initParams(paramValues));
return execute(url, HttpMethod.GET, requestHttpEntity, responseType);
}
/**
* get request, may be pulling a lot of data
* URL request params are expanded using the given query {@link Query},
* More request parameters can be set via body.
* <p>{@code responseType} can be an HttpRestResult or HttpRestResult data {@code T} type.
*
* @param url url
* @param header http header param
* @param query http query param
* @param body get with body
* @param responseType return type
* @return {@link HttpRestResult}
* @throws Exception ex
*/
public <T> HttpRestResult<T> getLarge(String url, Header header, Query query, Object body, Type responseType) throws Exception {
return execute(url, HttpMethod.GET_LARGE, new RequestHttpEntity(header, query, body), responseType);
}
/**
* http delete
* URL request params are expanded using the given query {@link Query}.
* <p>{@code responseType} can be an HttpRestResult or HttpRestResult data {@code T} type.
*
* @param url url
* @param header http header param
* @param query http query param
* @param responseType return type
* @return {@link HttpRestResult}
* @throws Exception ex
*/
public <T> HttpRestResult<T> delete(String url, Header header, Query query, Type responseType) throws Exception {
return execute(url, HttpMethod.DELETE, new RequestHttpEntity(header, query), responseType);
}
/**
* http put
* Create a new resource by PUTting the given body to http request.
* <p>URL request params are expanded using the given query {@link Query}.
* <p>{@code responseType} can be an HttpRestResult or HttpRestResult data {@code T} type.
*
* @param url url
* @param header http header param
* @param query http query param
* @param body http body param
* @param responseType return type
* @return {@link HttpRestResult}
* @throws Exception ex
*/
public <T> HttpRestResult<T> put(String url, Header header, Query query, Object body, Type responseType) throws Exception {
return execute(url, HttpMethod.PUT, new RequestHttpEntity(header, query, body), responseType);
}
/**
* http put json
* Create a new resource by PUTting the given body to http request,
* http header contentType default 'application/json;charset=UTF-8'.
* <p>URL request params are expanded using the given map {@code paramValues}.
* <p>{@code responseType} can be an HttpRestResult or HttpRestResult data {@code T} type.
*
* @param url url
* @param header http header param
* @param paramValues http query param
* @param body http body param
* @param responseType return type
* @return {@link HttpRestResult}
* @throws Exception ex
*/
public <T> HttpRestResult<T> putJson(String url, Header header, Map<String, String> paramValues, String body, Type responseType) throws Exception {
RequestHttpEntity requestHttpEntity = new RequestHttpEntity(
header.setContentType(MediaType.APPLICATION_JSON),
Query.newInstance().initParams(paramValues),
body);
return execute(url, HttpMethod.PUT, requestHttpEntity, responseType);
}
/**
* http put from
* Create a new resource by PUTting the given map {@code bodyValues} to http request,
* http header contentType default 'application/x-www-form-urlencoded;charset=utf-8'.
* <p>URL request params are expanded using the given query {@code Query}.
* <p>{@code responseType} can be an HttpRestResult or HttpRestResult data {@code T} type.
*
* @param url url
* @param header http header param
* @param query http query param
* @param bodyValues http body param
* @param responseType return type
* @return {@link HttpRestResult}
* @throws Exception ex
*/
public <T> HttpRestResult<T> putFrom(String url, Header header, Query query, Map<String, String> bodyValues, Type responseType) throws Exception {
RequestHttpEntity requestHttpEntity = new RequestHttpEntity(
header.setContentType(MediaType.APPLICATION_FORM_URLENCODED), query, bodyValues);
return execute(url, HttpMethod.PUT, requestHttpEntity, responseType);
}
/**
* http put from
* Create a new resource by PUTting the given map {@code bodyValues} to http request,
* http header contentType default 'application/x-www-form-urlencoded;charset=utf-8'.
* <p>URL request params are expanded using the given map {@code paramValues}.
* <p>{@code responseType} can be an HttpRestResult or HttpRestResult data {@code T} type.
*
* @param url url
* @param header http header param
* @param paramValues http query param
* @param bodyValues http body param
* @param responseType return type
* @return {@link HttpRestResult}
* @throws Exception ex
*/
public <T> HttpRestResult<T> putFrom(String url, Header header, Map<String, String> paramValues, Map<String, String> bodyValues, Type responseType) throws Exception {
RequestHttpEntity requestHttpEntity = new RequestHttpEntity(
header.setContentType(MediaType.APPLICATION_FORM_URLENCODED),
Query.newInstance().initParams(paramValues),
bodyValues);
return execute(url, HttpMethod.PUT, requestHttpEntity, responseType);
}
/**
* http post
* Create a new resource by POSTing the given object to the http request.
* <p>URL request params are expanded using the given query {@link Query}.
* <p>{@code responseType} can be an HttpRestResult or HttpRestResult data {@code T} type.
*
* @param url url
* @param header http header param
* @param query http query param
* @param body http body param
* @param responseType return type
* @return {@link HttpRestResult}
* @throws Exception ex
*/
public <T> HttpRestResult<T> post(String url, Header header, Query query, Object body, Type responseType) throws Exception {
return execute(url, HttpMethod.POST, new RequestHttpEntity(header, query, body),
responseType);
}
/**
* http post json
* Create a new resource by POSTing the given object to the http request,
* http header contentType default 'application/json;charset=UTF-8'.
* <p>URL request params are expanded using the given map {@code paramValues}.
* <p>{@code responseType} can be an HttpRestResult or HttpRestResult data {@code T} type.
*
* @param url url
* @param header http header param
* @param paramValues http query param
* @param body http body param
* @param responseType return type
* @return {@link HttpRestResult}
* @throws Exception ex
*/
public <T> HttpRestResult<T> postJson(String url, Header header, Map<String, String> paramValues, String body, Type responseType) throws Exception {
RequestHttpEntity requestHttpEntity = new RequestHttpEntity(
header.setContentType(MediaType.APPLICATION_JSON),
Query.newInstance().initParams(paramValues),
body);
return execute(url, HttpMethod.POST, requestHttpEntity, responseType);
}
/**
* http post from
* Create a new resource by PUTting the given map {@code bodyValues} to http request,
* http header contentType default 'application/x-www-form-urlencoded;charset=utf-8'.
* <p>URL request params are expanded using the given query {@link Query}.
* <p>{@code responseType} can be an HttpRestResult or HttpRestResult data {@code T} type.
*
* @param url url
* @param header http header param
* @param query http query param
* @param bodyValues http body param
* @param responseType return type
* @return {@link HttpRestResult}
* @throws Exception ex
*/
public <T> HttpRestResult<T> postFrom(String url, Header header, Query query, Map<String, String> bodyValues, Type responseType) throws Exception {
RequestHttpEntity requestHttpEntity = new RequestHttpEntity(
header.setContentType(MediaType.APPLICATION_FORM_URLENCODED), query, bodyValues);
return execute(url, HttpMethod.POST, requestHttpEntity, responseType);
}
/**
* http post from
* Create a new resource by PUTting the given map {@code bodyValues} to http request,
* http header contentType default 'application/x-www-form-urlencoded;charset=utf-8'.
* <p>URL request params are expanded using the given map {@code paramValues}.
* <p>{@code responseType} can be an HttpRestResult or HttpRestResult data {@code T} type.
*
* @param url url
* @param header http header param
* @param paramValues http query param
* @param bodyValues http body param
* @param responseType return type
* @return {@link HttpRestResult}
* @throws Exception ex
*/
public <T> HttpRestResult<T> postFrom(String url, Header header, Map<String, String> paramValues, Map<String, String> bodyValues, Type responseType) throws Exception {
RequestHttpEntity requestHttpEntity = new RequestHttpEntity(
header.setContentType(MediaType.APPLICATION_FORM_URLENCODED),
Query.newInstance().initParams(paramValues),
bodyValues);
return execute(url, HttpMethod.POST, requestHttpEntity, responseType);
}
private <T> HttpRestResult<T> execute(String url, String httpMethod, RequestHttpEntity requestEntity,
Type responseType) throws Exception {
URI uri = HttpUtils.buildUri(url, requestEntity.getQuery());
if (logger.isDebugEnabled()) {
logger.debug("HTTP " + httpMethod + " " + url);
}
HttpClientResponse response = null;
try {
response = requestClient.execute(uri, httpMethod, requestEntity);
return ResponseHandler.responseEntityExtractor(response, responseType);
} finally {
if (response != null) {
response.close();
}
}
}
/**
* close request client
*/
public void close() throws Exception{
requestClient.close();
}
}

View File

@ -16,10 +16,21 @@
package com.alibaba.nacos.common.http.handler;
import com.alibaba.nacos.api.exception.runtime.NacosDeserializationException;
import com.alibaba.nacos.common.constant.HttpHeaderConsts;
import com.alibaba.nacos.common.http.HttpRestResult;
import com.alibaba.nacos.common.http.client.HttpClientResponse;
import com.alibaba.nacos.common.http.param.Header;
import com.alibaba.nacos.common.http.param.MediaType;
import com.alibaba.nacos.common.model.RestResult;
import com.alibaba.nacos.common.utils.IoUtils;
import com.alibaba.nacos.common.utils.JacksonUtils;
import org.apache.http.HttpStatus;
import org.slf4j.LoggerFactory;
import java.io.InputStream;
import java.lang.reflect.Type;
import org.slf4j.Logger;
/**
@ -37,4 +48,41 @@ public final class ResponseHandler {
return JacksonUtils.toObj(s, type);
}
public static <T> T convert(InputStream inputStream, Type type) throws Exception {
return JacksonUtils.toObj(inputStream, type);
}
@SuppressWarnings({"unchecked", "rawtypes", "resource"})
public static <T> HttpRestResult<T> responseEntityExtractor(HttpClientResponse response, Type type) throws Exception {
Header headers = response.getHeaders();
String contentType = headers.getValue(HttpHeaderConsts.CONTENT_TYPE);
InputStream body = response.getBody();
T extractBody = null;
if (MediaType.APPLICATION_JSON.equals(contentType) && HttpStatus.SC_OK == response.getStatusCode()) {
extractBody = convert(body, type);
}
if (extractBody == null) {
if (!String.class.toString().equals(type.toString())) {
logger.error("if the response contentType is not [application/json]," +
" only support to java.lang.String");
throw new NacosDeserializationException(type);
}
extractBody = (T)IoUtils.toString(body, headers.getCharset());
}
if (extractBody instanceof RestResult) {
HttpRestResult<T> httpRestResult = convert((RestResult<T>) extractBody);
httpRestResult.setHeader(headers);
return httpRestResult;
}
return new HttpRestResult<T>(response.getHeaders(), response.getStatusCode(), extractBody);
}
private static <T> HttpRestResult<T> convert(RestResult<T> restResult) {
HttpRestResult<T> httpRestResult = new HttpRestResult<T>();
httpRestResult.setCode(restResult.getCode());
httpRestResult.setData(restResult.getData());
httpRestResult.setMessage(restResult.getMessage());
return httpRestResult;
}
}

View File

@ -17,6 +17,10 @@
package com.alibaba.nacos.common.http.param;
import com.alibaba.nacos.api.common.Constants;
import com.alibaba.nacos.common.constant.HttpHeaderConsts;
import com.alibaba.nacos.common.utils.StringUtils;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashMap;
@ -34,10 +38,10 @@ public class Header {
private Header() {
header = new LinkedHashMap<String, String>();
addParam("Content-Type", "application/json");
addParam("Accept-Charset", "UTF-8");
addParam("Accept-Encoding", "gzip");
addParam("Content-Encoding", "gzip");
addParam(HttpHeaderConsts.CONTENT_TYPE, MediaType.APPLICATION_JSON);
addParam(HttpHeaderConsts.ACCEPT_CHARSET, "UTF-8");
addParam(HttpHeaderConsts.ACCEPT_ENCODING, "gzip");
addParam(HttpHeaderConsts.CONTENT_ENCODING, "gzip");
}
public static Header newInstance() {
@ -49,7 +53,14 @@ public class Header {
return this;
}
public Header builded() {
public Header setContentType(String contentType) {
if (contentType == null) {
contentType = MediaType.APPLICATION_JSON;
}
return addParam(HttpHeaderConsts.CONTENT_TYPE, contentType);
}
public Header build() {
return this;
}
@ -76,13 +87,14 @@ public class Header {
return list;
}
public void addAll(List<String> list) {
public Header addAll(List<String> list) {
if ((list.size() & 1) != 0) {
throw new IllegalArgumentException("list size must be a multiple of 2");
}
for (int i = 0; i < list.size();) {
header.put(list.get(i++), list.get(i++));
}
return this;
}
public void addAll(Map<String, String> params) {
@ -91,9 +103,38 @@ public class Header {
}
}
public String getCharset() {
String acceptCharset = getValue(HttpHeaderConsts.ACCEPT_CHARSET);
if (acceptCharset == null) {
String contentType = getValue(HttpHeaderConsts.CONTENT_TYPE);
acceptCharset = StringUtils.isNotBlank(contentType) ? analysisCharset(contentType) : Constants.ENCODE;
}
return acceptCharset;
}
private String analysisCharset(String contentType) {
String[] values = contentType.split(";");
String charset = Constants.ENCODE;
if (values.length == 0) {
return charset;
}
for (String value : values) {
if (value.startsWith("charset=")) {
charset = value.substring("charset=".length());
}
}
return charset;
}
public void clear() {
header.clear();
}
@Override
public String toString() {
return "Header{" +
"headerToMap=" + header +
'}';
}
}

View File

@ -35,6 +35,8 @@ public final class MediaType {
public static final String APPLICATION_XML = "application/xml";
public static final String APPLICATION_JSON = "application/json";
public static final String MULTIPART_FORM_DATA = "multipart/form-data";
public static final String TEXT_HTML = "text/html";

View File

@ -52,10 +52,11 @@ public class Query {
return params.get(key);
}
public void initParams(Map<String, String> params) {
public Query initParams(Map<String, String> params) {
for (Map.Entry<String, String> entry : params.entrySet()) {
addParam(entry.getKey(), entry.getValue());
}
return this;
}
public void initParams(List<String> list) {

View File

@ -13,15 +13,25 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.nacos.common.lifecycle;
package com.alibaba.nacos.config.server.filter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import com.alibaba.nacos.api.exception.NacosException;
/**
* @author <a href="mailto:liaochuntao@live.com">liaochuntao</a>
* An interface is used to define the resource's close and shutdown,
* such as IO Connection and ThreadPool.
*
* @author zongtanghu
*
*/
@Retention(RetentionPolicy.RUNTIME)
public @interface ToLeader {
public interface Closeable {
/**
* Shutdown the Resources, such as Thread Pool.
*
* @throws NacosException exception.
*/
public void shutdown() throws NacosException;
}

View File

@ -0,0 +1,73 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.nacos.common.model;
import com.alibaba.nacos.common.http.param.Header;
import com.alibaba.nacos.common.http.param.Query;
import java.util.Map;
/**
*
* Represents an HTTP request , consisting of headers and body.
*
* @author mai.jh
* @date 2020/5/23
*/
public class RequestHttpEntity {
private final Header headers = Header.newInstance();
private final Query query;
private Object body;
public RequestHttpEntity(Header header, Query query) {
handleHeader(header);
this.query = query;
}
public RequestHttpEntity(Header header, Query query, Object body) {
handleHeader(header);
this.query = query;
this.body = body;
}
private void handleHeader(Header header) {
if (header != null && !header.getHeader().isEmpty()) {
Map<String, String> headerMap = header.getHeader();
headers.addAll(headerMap);
}
}
public Header getHeaders() {
return headers;
}
public Query getQuery() {
return query;
}
public Object getBody() {
return body;
}
public boolean isEmptyBody() {
return body == null;
}
}

View File

@ -179,6 +179,13 @@ public final class CollectionUtils {
}
}
public static <T> boolean contains(Collection<T> coll, T target) {
if (isEmpty(coll)) {
return false;
}
return coll.contains(target);
}
/**
* Null-safe check if the specified collection is empty.
* <p>

View File

@ -28,6 +28,7 @@ import com.fasterxml.jackson.databind.jsontype.NamedType;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import java.io.InputStream;
import java.io.IOException;
import java.lang.reflect.Type;
@ -46,8 +47,7 @@ public final class JacksonUtils {
public static String toJson(Object obj) {
try {
return mapper.writeValueAsString(obj);
}
catch (JsonProcessingException e) {
} catch (JsonProcessingException e) {
throw new NacosSerializationException(obj.getClass(), e);
}
}
@ -55,8 +55,7 @@ public final class JacksonUtils {
public static byte[] toJsonBytes(Object obj) {
try {
return ByteUtils.toBytes(mapper.writeValueAsString(obj));
}
catch (JsonProcessingException e) {
} catch (JsonProcessingException e) {
throw new NacosSerializationException(obj.getClass(), e);
}
}
@ -64,35 +63,39 @@ public final class JacksonUtils {
public static <T> T toObj(byte[] json, Class<T> cls) {
try {
return toObj(StringUtils.newString4UTF8(json), cls);
}
catch (Exception e) {
} catch (Exception e) {
throw new NacosDeserializationException(cls, e);
}
}
public static <T> T toObj(byte[] json, Type cls) {
try {
return toObj(StringUtils.newString4UTF8(json), cls);
}
catch (Exception e) {
throw new NacosDeserializationException(e);
}
}
try {
return toObj(StringUtils.newString4UTF8(json), cls);
} catch (Exception e) {
throw new NacosDeserializationException(e);
}
}
public static <T> T toObj(byte[] json, TypeReference<T> typeReference) {
try {
return toObj(StringUtils.newString4UTF8(json), typeReference);
}
catch (Exception e) {
throw new NacosDeserializationException(e);
}
}
public static <T> T toObj(InputStream inputStream, Class<T> tClass) {
try {
return mapper.readValue(inputStream, tClass);
} catch (IOException e) {
throw new NacosDeserializationException(e);
}
}
public static <T> T toObj(byte[] json, TypeReference<T> typeReference) {
try {
return toObj(StringUtils.newString4UTF8(json), typeReference);
} catch (Exception e) {
throw new NacosDeserializationException(e);
}
}
public static <T> T toObj(String json, Class<T> cls) {
try {
return mapper.readValue(json, cls);
}
catch (IOException e) {
} catch (IOException e) {
throw new NacosDeserializationException(cls, e);
}
}
@ -100,8 +103,7 @@ public final class JacksonUtils {
public static <T> T toObj(String json, Type type) {
try {
return mapper.readValue(json, mapper.constructType(type));
}
catch (IOException e) {
} catch (IOException e) {
throw new NacosDeserializationException(e);
}
}
@ -109,17 +111,23 @@ public final class JacksonUtils {
public static <T> T toObj(String json, TypeReference<T> typeReference) {
try {
return mapper.readValue(json, typeReference);
}
catch (IOException e) {
} catch (IOException e) {
throw new NacosDeserializationException(typeReference.getClass(), e);
}
}
public static <T> T toObj(InputStream inputStream, Type type) {
try {
return mapper.readValue(inputStream, mapper.constructType(type));
} catch (IOException e) {
throw new NacosDeserializationException(type, e);
}
}
public static JsonNode toObj(String json) {
try {
return mapper.readTree(json);
}
catch (IOException e) {
} catch (IOException e) {
throw new NacosDeserializationException(e);
}
}

View File

@ -1,12 +0,0 @@
package com.alibaba.nacos.common.http;
import org.junit.Test;
public class HttpUtilsTest {
@Test
public void test_url_encode() throws Exception {
}
}

View File

@ -21,7 +21,6 @@ import com.alibaba.nacos.common.utils.MapUtils;
import com.alibaba.nacos.config.server.auth.ConfigResourceParser;
import com.alibaba.nacos.config.server.constant.Constants;
import com.alibaba.nacos.config.server.controller.parameters.SameNamespaceCloneConfigBean;
import com.alibaba.nacos.config.server.filter.ToLeader;
import com.alibaba.nacos.config.server.model.ConfigAdvanceInfo;
import com.alibaba.nacos.config.server.model.ConfigAllInfo;
import com.alibaba.nacos.config.server.model.ConfigInfo;
@ -34,6 +33,7 @@ import com.alibaba.nacos.config.server.result.ResultBuilder;
import com.alibaba.nacos.config.server.result.code.ResultCodeEnum;
import com.alibaba.nacos.config.server.service.AggrWhitelist;
import com.alibaba.nacos.config.server.model.event.ConfigDataChangeEvent;
import com.alibaba.nacos.config.server.service.ConfigChangePublisher;
import com.alibaba.nacos.config.server.service.ConfigSubService;
import com.alibaba.nacos.config.server.service.repository.PersistService;
import com.alibaba.nacos.config.server.service.trace.ConfigTraceService;
@ -42,7 +42,6 @@ import com.alibaba.nacos.config.server.utils.ParamUtils;
import com.alibaba.nacos.config.server.utils.RequestUtil;
import com.alibaba.nacos.config.server.utils.TimeUtils;
import com.alibaba.nacos.config.server.utils.ZipUtils;
import com.alibaba.nacos.config.server.utils.event.EventDispatcher;
import com.alibaba.nacos.core.auth.ActionTypes;
import com.alibaba.nacos.core.auth.Secured;
import com.alibaba.nacos.core.utils.InetUtils;
@ -113,17 +112,16 @@ public class ConfigController {
}
/**
* 增加或更新非聚合数据
* Adds or updates non-aggregated data.
*
* @throws NacosException
*/
@PostMapping
@ToLeader
@Secured(action = ActionTypes.WRITE, parser = ConfigResourceParser.class)
public Boolean publishConfig(HttpServletRequest request, HttpServletResponse response,
@RequestParam("dataId") String dataId, @RequestParam("group") String group,
@RequestParam(value = "dataId") String dataId, @RequestParam(value = "group") String group,
@RequestParam(value = "tenant", required = false, defaultValue = StringUtils.EMPTY) String tenant,
@RequestParam("content") String content,
@RequestParam(value = "content") String content,
@RequestParam(value = "tag", required = false) String tag,
@RequestParam(value = "appName", required = false) String appName,
@RequestParam(value = "src_user", required = false) String srcUser,
@ -165,16 +163,19 @@ public class ConfigController {
if (StringUtils.isBlank(tag)) {
persistService.insertOrUpdate(srcIp, srcUser, configInfo, time,
configAdvanceInfo, true);
ConfigChangePublisher.notifyConfigChange(new ConfigDataChangeEvent(false, dataId, group, tenant, time.getTime()));
}
else {
persistService
.insertOrUpdateTag(configInfo, tag, srcIp, srcUser, time, true);
ConfigChangePublisher.notifyConfigChange(new ConfigDataChangeEvent(false, dataId, group, tenant, tag, time.getTime()));
}
}
else {
// beta publish
persistService
.insertOrUpdateBeta(configInfo, betaIps, srcIp, srcUser, time, true);
ConfigChangePublisher.notifyConfigChange(new ConfigDataChangeEvent(true, dataId, group, tenant, time.getTime()));
}
ConfigTraceService.logPersistenceEvent(dataId, group, tenant, requestIpApp, time.getTime(),
InetUtils.getSelfIp(), ConfigTraceService.PERSISTENCE_EVENT_PUB, content);
@ -182,7 +183,7 @@ public class ConfigController {
}
/**
* 取数据
* get configure board infomation fail
*
* @throws ServletException
* @throws IOException
@ -207,7 +208,7 @@ public class ConfigController {
}
/**
* 取数据
* Get the specific configuration information that the console USES
*
* @throws NacosException
*/
@ -226,12 +227,11 @@ public class ConfigController {
}
/**
* 同步删除某个dataId下面所有的聚合前数据
* Synchronously delete all pre-aggregation data under a dataId
*
* @throws NacosException
*/
@DeleteMapping
@ToLeader
@Secured(action = ActionTypes.WRITE, parser = ConfigResourceParser.class)
public Boolean deleteConfig(HttpServletRequest request, HttpServletResponse response,
@RequestParam("dataId") String dataId, //
@ -255,6 +255,7 @@ public class ConfigController {
ConfigTraceService
.logPersistenceEvent(dataId, group, tenant, null, time.getTime(),
clientIp, ConfigTraceService.PERSISTENCE_EVENT_REMOVE, null);
ConfigChangePublisher.notifyConfigChange(new ConfigDataChangeEvent(false, dataId, group, tenant, tag, time.getTime()));
return true;
}
@ -266,7 +267,6 @@ public class ConfigController {
* @Param [request, response, dataId, group, tenant, tag]
*/
@DeleteMapping(params = "delType=ids")
@ToLeader
@Secured(action = ActionTypes.WRITE, parser = ConfigResourceParser.class)
public RestResult<Boolean> deleteConfigs(HttpServletRequest request,
HttpServletResponse response, @RequestParam(value = "ids") List<Long> ids) {
@ -276,6 +276,8 @@ public class ConfigController {
.removeConfigInfoByIds(ids, clientIp, null);
if (!CollectionUtils.isEmpty(configInfoList)) {
for (ConfigInfo configInfo : configInfoList) {
ConfigChangePublisher.notifyConfigChange(new ConfigDataChangeEvent(false, configInfo.getDataId(),
configInfo.getGroup(), configInfo.getTenant(), time.getTime()));
ConfigTraceService.logPersistenceEvent(configInfo.getDataId(),
configInfo.getGroup(), configInfo.getTenant(), null,
time.getTime(), clientIp,
@ -299,7 +301,7 @@ public class ConfigController {
}
/**
* 比较MD5
* The client listens for configuration changes
*/
@PostMapping("/listener")
@Secured(action = ActionTypes.READ, parser = ConfigResourceParser.class)
@ -326,7 +328,7 @@ public class ConfigController {
}
/**
* 订阅改配置的客户端信息
* Subscribe to configured client information
*/
@GetMapping("/listener")
@Secured(action = ActionTypes.READ, parser = ConfigResourceParser.class)
@ -348,7 +350,7 @@ public class ConfigController {
}
/**
* 查询配置信息返回JSON格式
* Query the configuration information and return it in JSON format.
*/
@GetMapping(params = "search=accurate")
@Secured(action = ActionTypes.READ, parser = ConfigResourceParser.class)
@ -379,7 +381,8 @@ public class ConfigController {
}
/**
* 模糊查询配置信息不允许只根据内容模糊查询即dataId和group都为NULL但content不是NULL这种情况下返回所有配置
* Fuzzy query configuration information. Fuzzy queries based only on content are not allowed, that is,
* both dataId and group are NULL, but content is not NULL. In this case, all configurations are returned.
*/
@GetMapping(params = "search=blur")
@Secured(action = ActionTypes.READ, parser = ConfigResourceParser.class)
@ -410,7 +413,6 @@ public class ConfigController {
}
@DeleteMapping(params = "beta=true")
@ToLeader
@Secured(action = ActionTypes.WRITE, parser = ConfigResourceParser.class)
public RestResult<Boolean> stopBeta(@RequestParam(value = "dataId") String dataId,
@RequestParam(value = "group") String group,
@ -426,6 +428,7 @@ public class ConfigController {
rr.setMessage("remove beta data error");
return rr;
}
ConfigChangePublisher.notifyConfigChange(new ConfigDataChangeEvent(true, dataId, group, tenant, System.currentTimeMillis()));
rr.setCode(200);
rr.setData(true);
rr.setMessage("stop beta ok");
@ -504,7 +507,6 @@ public class ConfigController {
}
@PostMapping(params = "import=true")
@ToLeader
@Secured(action = ActionTypes.WRITE, parser = ConfigResourceParser.class)
public RestResult<Map<String, Object>> importAndPublishConfig(
HttpServletRequest request,
@ -593,7 +595,7 @@ public class ConfigController {
.batchInsertOrUpdate(configInfoList, srcUser, srcIp, null, time, false,
policy);
for (ConfigInfo configInfo : configInfoList) {
EventDispatcher.fireEvent(
ConfigChangePublisher.notifyConfigChange(
new ConfigDataChangeEvent(false, configInfo.getDataId(),
configInfo.getGroup(), configInfo.getTenant(),
time.getTime()));
@ -607,7 +609,6 @@ public class ConfigController {
}
@PostMapping(params = "clone=true")
@ToLeader
@Secured(action = ActionTypes.WRITE, parser = ConfigResourceParser.class)
public RestResult<Map<String, Object>> cloneConfig(HttpServletRequest request,
@RequestParam(value = "src_user", required = false) String srcUser,
@ -681,7 +682,7 @@ public class ConfigController {
.batchInsertOrUpdate(configInfoList4Clone, srcUser, srcIp, null, time,
false, policy);
for (ConfigInfo configInfo : configInfoList4Clone) {
EventDispatcher.fireEvent(
ConfigChangePublisher.notifyConfigChange(
new ConfigDataChangeEvent(false, configInfo.getDataId(),
configInfo.getGroup(), configInfo.getTenant(),
time.getTime()));
@ -691,7 +692,7 @@ public class ConfigController {
InetUtils.getSelfIp(), ConfigTraceService.PERSISTENCE_EVENT_PUB,
configInfo.getContent());
}
return ResultBuilder.buildSuccessResult("克隆成功", saveResult);
return ResultBuilder.buildSuccessResult("Clone Completed Successfully", saveResult);
}
private String processTenant(String tenant) {

View File

@ -0,0 +1,36 @@
/*
* 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.service;
import com.alibaba.nacos.config.server.model.event.ConfigDataChangeEvent;
import com.alibaba.nacos.config.server.utils.PropertyUtil;
import com.alibaba.nacos.config.server.utils.event.EventDispatcher;
import com.alibaba.nacos.core.utils.ApplicationUtils;
/**
* @author <a href="mailto:liaochuntao@live.com">liaochuntao</a>
*/
public class ConfigChangePublisher {
public static void notifyConfigChange(ConfigDataChangeEvent event) {
if (PropertyUtil.isEmbeddedStorage() && !ApplicationUtils.getStandaloneMode()) {
return;
}
EventDispatcher.fireEvent(event);
}
}

View File

@ -15,6 +15,8 @@
*/
package com.alibaba.nacos.config.server.service;
import com.alibaba.nacos.common.utils.CollectionUtils;
import com.alibaba.nacos.common.utils.ExceptionUtil;
import com.alibaba.nacos.config.server.model.SampleResult;
import com.alibaba.nacos.config.server.model.event.LocalDataChangeEvent;
import com.alibaba.nacos.config.server.monitor.MetricsMonitor;
@ -308,7 +310,7 @@ public class LongPollingService extends AbstractEventListener {
ClientLongPolling clientSub = iter.next();
if (clientSub.clientMd5Map.containsKey(groupKey)) {
// 如果beta发布且不在beta列表直接跳过
if (isBeta && !betaIps.contains(clientSub.ip)) {
if (isBeta && !CollectionUtils.contains(betaIps, clientSub.ip)) {
continue;
}
@ -329,14 +331,10 @@ public class LongPollingService extends AbstractEventListener {
}
}
} catch (Throwable t) {
LogUtil.defaultLog.error("data change error:" + t.getMessage(), t.getCause());
LogUtil.defaultLog.error("data change error: {}", ExceptionUtil.getStackTrace(t));
}
}
DataChangeTask(String groupKey) {
this(groupKey, false, null);
}
DataChangeTask(String groupKey, boolean isBeta, List<String> betaIps) {
this(groupKey, isBeta, betaIps, null);
}
@ -475,6 +473,14 @@ public class LongPollingService extends AbstractEventListener {
final long timeoutTime;
Future<?> asyncTimeoutFuture;
@Override
public String toString() {
return "ClientLongPolling{" + "clientMd5Map=" + clientMd5Map + ", createTime="
+ createTime + ", ip='" + ip + '\'' + ", appName='" + appName + '\''
+ ", tag='" + tag + '\'' + ", probeRequestSize=" + probeRequestSize
+ ", timeoutTime=" + timeoutTime + '}';
}
}
void generateResponse(HttpServletRequest request, HttpServletResponse response, List<String> changedGroups) {

View File

@ -93,6 +93,12 @@ public abstract class DumpService {
this.dumpAllTaskMgr = new TaskManager("com.alibaba.nacos.server.DumpAllTaskManager");
this.dumpAllTaskMgr.setDefaultTaskProcessor(dumpAllProcessor);
this.dumpAllTaskMgr.addProcessor(DumpAllTask.TASK_ID, dumpAllProcessor);
this.dumpAllTaskMgr.addProcessor(DumpAllBetaTask.TASK_ID, dumpAllBetaProcessor);
this.dumpAllTaskMgr.addProcessor(DumpAllTagTask.TASK_ID, dumpAllTagProcessor);
DynamicDataSource.getInstance().getDataSource();
}
@ -124,6 +130,9 @@ public abstract class DumpService {
Runnable dumpAllBeta = () -> dumpAllTaskMgr
.addTask(DumpAllBetaTask.TASK_ID, new DumpAllBetaTask());
Runnable dumpAllTag = () -> dumpAllTaskMgr
.addTask(DumpAllTagTask.TASK_ID, new DumpAllTagTask());
Runnable clearConfigHistory = () -> {
log.warn("clearConfigHistory start");
if (canExecute()) {
@ -212,7 +221,10 @@ public abstract class DumpService {
DUMP_ALL_INTERVAL_IN_MINUTE, TimeUnit.MINUTES);
ConfigExecutor.scheduleWithFixedDelay(dumpAllBeta, initialDelay,
DUMP_ALL_INTERVAL_IN_MINUTE, TimeUnit.MINUTES);
DUMP_ALL_INTERVAL_IN_MINUTE, TimeUnit.MINUTES);
ConfigExecutor.scheduleWithFixedDelay(dumpAllTag, initialDelay,
DUMP_ALL_INTERVAL_IN_MINUTE, TimeUnit.MINUTES);
}
ConfigExecutor

View File

@ -160,17 +160,11 @@ public class EmbeddedDumpService extends DumpService {
@Override
protected boolean canExecute() {
try {
// if is derby + raft mode, only leader can execute
CPProtocol protocol = protocolManager.getCpProtocol();
return protocol.isLeader(Constants.CONFIG_MODEL_RAFT_GROUP);
}
catch (NoSuchRaftGroupException e) {
if (ApplicationUtils.getStandaloneMode()) {
return true;
}
catch (Throwable e) {
// It's impossible to get to this point
throw new RuntimeException(e);
}
// if is derby + raft mode, only leader can execute
CPProtocol protocol = protocolManager.getCpProtocol();
return protocol.isLeader(Constants.CONFIG_MODEL_RAFT_GROUP);
}
}

View File

@ -26,7 +26,9 @@ import com.alibaba.nacos.config.server.utils.ContentUtils;
import com.alibaba.nacos.config.server.utils.PropertyUtil;
import com.alibaba.nacos.config.server.utils.TimeUtils;
import com.alibaba.nacos.consistency.cp.CPProtocol;
import com.alibaba.nacos.core.distributed.ProtocolManager;
import com.alibaba.nacos.core.distributed.raft.exception.NoSuchRaftGroupException;
import com.alibaba.nacos.core.utils.ApplicationUtils;
import com.alibaba.nacos.core.utils.InetUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -53,8 +55,6 @@ public class MergeDatumService {
static final AtomicInteger FINISHED = new AtomicInteger();
static int total = 0;
private CPProtocol protocol;
@Autowired
public MergeDatumService(PersistService persistService) {
this.persistService = persistService;
@ -109,14 +109,11 @@ public class MergeDatumService {
if (!PropertyUtil.isEmbeddedStorage()) {
return true;
}
try {
return protocol.isLeader(Constants.CONFIG_MODEL_RAFT_GROUP);
} catch (NoSuchRaftGroupException e) {
if (ApplicationUtils.getStandaloneMode()) {
return true;
} catch (Exception e) {
// It's impossible to get to this point
throw new RuntimeException(e);
}
ProtocolManager protocolManager = ApplicationUtils.getBean(ProtocolManager.class);
return protocolManager.getCpProtocol().isLeader(Constants.CONFIG_MODEL_RAFT_GROUP);
}
class MergeAllDataWorker extends Thread {

View File

@ -49,7 +49,6 @@ import com.google.common.collect.Lists;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.context.annotation.Conditional;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;
import org.springframework.transaction.support.TransactionTemplate;
@ -2610,3 +2609,4 @@ public class EmbeddedStoragePersistServiceImpl implements PersistService {
}
}

View File

@ -38,13 +38,10 @@ import com.alibaba.nacos.config.server.model.Page;
import com.alibaba.nacos.config.server.model.SameConfigPolicy;
import com.alibaba.nacos.config.server.model.SubInfo;
import com.alibaba.nacos.config.server.model.TenantInfo;
import com.alibaba.nacos.config.server.model.event.ConfigDataChangeEvent;
import com.alibaba.nacos.config.server.service.datasource.DataSourceService;
import com.alibaba.nacos.config.server.service.datasource.DynamicDataSource;
import com.alibaba.nacos.config.server.service.trace.ConfigTraceService;
import com.alibaba.nacos.config.server.utils.LogUtil;
import com.alibaba.nacos.config.server.utils.ParamUtils;
import com.alibaba.nacos.config.server.utils.event.EventDispatcher;
import com.google.common.base.Joiner;
import com.google.common.collect.Lists;
import org.apache.commons.collections.CollectionUtils;
@ -184,12 +181,6 @@ public class ExternalStoragePersistServiceImpl implements PersistService {
addConfigTagsRelation(configId, configTags, configInfo.getDataId(),
configInfo.getGroup(), configInfo.getTenant());
insertConfigHistoryAtomic(0, configInfo, srcIp, srcUser, time, "I");
if (notify) {
EventDispatcher.fireEvent(
new ConfigDataChangeEvent(false, configInfo.getDataId(),
configInfo.getGroup(), configInfo.getTenant(),
time.getTime()));
}
}
catch (CannotGetJdbcConnectionException e) {
LogUtil.fatalLog.error("[db-error] " + e.toString(), e);
@ -349,10 +340,6 @@ public class ExternalStoragePersistServiceImpl implements PersistService {
updateConfigInfo4Beta(configInfo, betaIps, srcIp, null, time,
notify);
}
EventDispatcher.fireEvent(
new ConfigDataChangeEvent(true, configInfo.getDataId(),
configInfo.getGroup(), configInfo.getTenant(),
time.getTime()));
}
public void insertOrUpdateTag(final ConfigInfo configInfo,
@ -364,10 +351,6 @@ public class ExternalStoragePersistServiceImpl implements PersistService {
catch (DataIntegrityViolationException ive) { // 唯一性约束冲突
updateConfigInfo4Tag(configInfo, tag, srcIp, null, time, notify);
}
EventDispatcher.fireEvent(
new ConfigDataChangeEvent(false, configInfo.getDataId(),
configInfo.getGroup(), configInfo.getTenant(), tag,
time.getTime()));
}
/**
@ -406,10 +389,6 @@ public class ExternalStoragePersistServiceImpl implements PersistService {
updateConfigInfo(configInfo, srcIp, srcUser, time, configAdvanceInfo,
notify);
}
EventDispatcher.fireEvent(
new ConfigDataChangeEvent(false, configInfo.getDataId(),
configInfo.getGroup(), configInfo.getTenant(),
time.getTime()));
}
/**
@ -452,9 +431,6 @@ public class ExternalStoragePersistServiceImpl implements PersistService {
return Boolean.TRUE;
}
});
EventDispatcher.fireEvent(new ConfigDataChangeEvent(false, dataId, group, tenant,
System.currentTimeMillis()));
}
/**
@ -496,20 +472,6 @@ public class ExternalStoragePersistServiceImpl implements PersistService {
}
}
});
if (!CollectionUtils.isEmpty(result)) {
long currentTime = System.currentTimeMillis();
for (ConfigInfo configInfo : result) {
ConfigTraceService.logPersistenceEvent(configInfo.getDataId(),
configInfo.getGroup(), configInfo.getTenant(), null, currentTime,
srcIp, ConfigTraceService.PERSISTENCE_EVENT_REMOVE, null);
EventDispatcher.fireEvent(
new ConfigDataChangeEvent(false, configInfo.getDataId(),
configInfo.getGroup(), configInfo.getTenant(),
currentTime));
}
}
return result;
}
@ -519,27 +481,21 @@ public class ExternalStoragePersistServiceImpl implements PersistService {
public void removeConfigInfo4Beta(final String dataId, final String group,
final String tenant) {
final String tenantTmp = StringUtils.isBlank(tenant) ? StringUtils.EMPTY : tenant;
tjt.execute(new TransactionCallback<Boolean>() {
@Override
public Boolean doInTransaction(TransactionStatus status) {
try {
ConfigInfo configInfo = findConfigInfo4Beta(dataId, group, tenant);
if (configInfo != null) {
jt.update(
"DELETE FROM config_info_beta WHERE data_id=? AND group_id=? AND tenant_id=?",
dataId, group, tenantTmp);
}
tjt.execute(status -> {
try {
ConfigInfo configInfo = findConfigInfo4Beta(dataId, group, tenant);
if (configInfo != null) {
jt.update(
"DELETE FROM config_info_beta WHERE data_id=? AND group_id=? AND tenant_id=?",
dataId, group, tenantTmp);
}
catch (CannotGetJdbcConnectionException e) {
LogUtil.fatalLog.error("[db-error] " + e.toString(), e);
throw e;
}
return Boolean.TRUE;
}
catch (CannotGetJdbcConnectionException e) {
LogUtil.fatalLog.error("[db-error] " + e.toString(), e);
throw e;
}
return Boolean.TRUE;
});
EventDispatcher.fireEvent(new ConfigDataChangeEvent(true, dataId, group, tenant,
System.currentTimeMillis()));
}
// ----------------------- config_aggr_info insert update delete
@ -2688,9 +2644,6 @@ public class ExternalStoragePersistServiceImpl implements PersistService {
LogUtil.fatalLog.error("[db-error] " + e.toString(), e);
throw e;
}
EventDispatcher.fireEvent(
new ConfigDataChangeEvent(false, dataId, group, tenant, tag,
System.currentTimeMillis()));
}
/**

View File

@ -9,7 +9,7 @@
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${LOG_HOME}/config-dump.log.%d{yyyy-MM-dd}.%i</fileNamePattern>
<maxFileSize>2GB</maxFileSize>
<MaxHistory>15</MaxHistory>
<maxHistory>15</maxHistory>
<totalSizeCap>7GB</totalSizeCap>
<cleanHistoryOnStart>true</cleanHistoryOnStart>
</rollingPolicy>
@ -25,7 +25,7 @@
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${LOG_HOME}/config-pull.log.%d{yyyy-MM-dd}.%i</fileNamePattern>
<maxFileSize>20MB</maxFileSize>
<MaxHistory>15</MaxHistory>
<maxHistory>15</maxHistory>
<totalSizeCap>128MB</totalSizeCap>
<cleanHistoryOnStart>true</cleanHistoryOnStart>
</rollingPolicy>
@ -41,7 +41,7 @@
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${LOG_HOME}/config-fatal.log.%d{yyyy-MM-dd}.%i</fileNamePattern>
<maxFileSize>20MB</maxFileSize>
<MaxHistory>15</MaxHistory>
<maxHistory>15</maxHistory>
<totalSizeCap>128MB</totalSizeCap>
<cleanHistoryOnStart>true</cleanHistoryOnStart>
</rollingPolicy>
@ -57,7 +57,7 @@
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${LOG_HOME}/config-memory.log.%d{yyyy-MM-dd}.%i</fileNamePattern>
<maxFileSize>20MB</maxFileSize>
<MaxHistory>15</MaxHistory>
<maxHistory>15</maxHistory>
<totalSizeCap>128MB</totalSizeCap>
<cleanHistoryOnStart>true</cleanHistoryOnStart>
</rollingPolicy>
@ -73,7 +73,7 @@
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${LOG_HOME}/config-pull-check.log.%d{yyyy-MM-dd}.%i</fileNamePattern>
<maxFileSize>1GB</maxFileSize>
<MaxHistory>15</MaxHistory>
<maxHistory>15</maxHistory>
<totalSizeCap>3GB</totalSizeCap>
<cleanHistoryOnStart>true</cleanHistoryOnStart>
</rollingPolicy>
@ -90,7 +90,7 @@
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${LOG_HOME}/config-acl.log.%d{yyyy-MM-dd}.%i</fileNamePattern>
<maxFileSize>50MB</maxFileSize>
<MaxHistory>15</MaxHistory>
<maxHistory>15</maxHistory>
<totalSizeCap>512MB</totalSizeCap>
<cleanHistoryOnStart>true</cleanHistoryOnStart>
</rollingPolicy>
@ -107,7 +107,7 @@
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${LOG_HOME}/config-client-request.log.%d{yyyy-MM-dd}.%i</fileNamePattern>
<maxFileSize>2GB</maxFileSize>
<MaxHistory>15</MaxHistory>
<maxHistory>15</maxHistory>
<totalSizeCap>7GB</totalSizeCap>
<cleanHistoryOnStart>true</cleanHistoryOnStart>
</rollingPolicy>
@ -124,7 +124,7 @@
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${LOG_HOME}/config-sdk-request.log.%d{yyyy-MM-dd}.%i</fileNamePattern>
<maxFileSize>1GB</maxFileSize>
<MaxHistory>15</MaxHistory>
<maxHistory>15</maxHistory>
<totalSizeCap>3GB</totalSizeCap>
<cleanHistoryOnStart>true</cleanHistoryOnStart>
</rollingPolicy>
@ -141,7 +141,7 @@
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${LOG_HOME}/config-trace.log.%d{yyyy-MM-dd}.%i</fileNamePattern>
<maxFileSize>2GB</maxFileSize>
<MaxHistory>15</MaxHistory>
<maxHistory>15</maxHistory>
<totalSizeCap>7GB</totalSizeCap>
<cleanHistoryOnStart>true</cleanHistoryOnStart>
</rollingPolicy>
@ -158,7 +158,7 @@
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${LOG_HOME}/config-notify.log.%d{yyyy-MM-dd}.%i</fileNamePattern>
<maxFileSize>1GB</maxFileSize>
<MaxHistory>15</MaxHistory>
<maxHistory>15</maxHistory>
<totalSizeCap>3GB</totalSizeCap>
<cleanHistoryOnStart>true</cleanHistoryOnStart>
</rollingPolicy>
@ -175,7 +175,7 @@
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${LOG_HOME}/config-app.log.%d{yyyy-MM-dd}.%i</fileNamePattern>
<maxFileSize>20MB</maxFileSize>
<MaxHistory>15</MaxHistory>
<maxHistory>15</maxHistory>
<totalSizeCap>128MB</totalSizeCap>
<cleanHistoryOnStart>true</cleanHistoryOnStart>
</rollingPolicy>
@ -192,7 +192,7 @@
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${LOG_HOME}/config-server.log.%d{yyyy-MM-dd}.%i</fileNamePattern>
<maxFileSize>50MB</maxFileSize>
<MaxHistory>15</MaxHistory>
<maxHistory>15</maxHistory>
<totalSizeCap>512MB</totalSizeCap>
<cleanHistoryOnStart>true</cleanHistoryOnStart>
</rollingPolicy>

View File

@ -0,0 +1,69 @@
package com.alibaba.nacos.config.server.service;
import com.alibaba.nacos.config.server.model.event.ConfigDataChangeEvent;
import com.alibaba.nacos.config.server.utils.PropertyUtil;
import com.alibaba.nacos.config.server.utils.event.EventDispatcher;
import com.alibaba.nacos.core.utils.ApplicationUtils;
import org.junit.Assert;
import org.junit.Test;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
public class ConfigChangePublisherTest {
@Test
public void testConfigChangeNotify() {
AtomicReference<ConfigDataChangeEvent> reference = new AtomicReference<>();
EventDispatcher.addEventListener(new EventDispatcher.AbstractEventListener() {
@Override
public List<Class<? extends EventDispatcher.Event>> interest() {
return Collections.singletonList(ConfigDataChangeEvent.class);
}
@Override
public void onEvent(EventDispatcher.Event event) {
reference.set((ConfigDataChangeEvent) event);
}
});
// nacos is standalone mode and use embedded storage
ApplicationUtils.setIsStandalone(true);
PropertyUtil.setEmbeddedStorage(true);
ConfigChangePublisher.notifyConfigChange(new ConfigDataChangeEvent("chuntaojun", "chuntaojun", System.currentTimeMillis()));
Assert.assertNotNull(reference.get());
reference.set(null);
// nacos is standalone mode and use external storage
ApplicationUtils.setIsStandalone(true);
PropertyUtil.setEmbeddedStorage(false);
ConfigChangePublisher.notifyConfigChange(new ConfigDataChangeEvent("chuntaojun", "chuntaojun", System.currentTimeMillis()));
Assert.assertNotNull(reference.get());
reference.set(null);
// nacos is cluster mode and use embedded storage
ApplicationUtils.setIsStandalone(false);
PropertyUtil.setEmbeddedStorage(true);
ConfigChangePublisher.notifyConfigChange(new ConfigDataChangeEvent("chuntaojun", "chuntaojun", System.currentTimeMillis()));
Assert.assertNull(reference.get());
reference.set(null);
// nacos is cluster mode and use external storage
ApplicationUtils.setIsStandalone(false);
PropertyUtil.setEmbeddedStorage(false);
ConfigChangePublisher.notifyConfigChange(new ConfigDataChangeEvent("chuntaojun", "chuntaojun", System.currentTimeMillis()));
Assert.assertNotNull(reference.get());
reference.set(null);
}
}

View File

@ -30,8 +30,7 @@ public interface CPProtocol<C extends Config, P extends LogProcessor4CP> extends
*
* @param group business module info
* @return is leader
* @throws Exception
*/
boolean isLeader(String group) throws Exception;
boolean isLeader(String group);
}

View File

@ -57,7 +57,7 @@ public class JwtTokenManager {
public String createToken(String userName) {
long now = (new Date()).getTime();
long now = System.currentTimeMillis();
Date validity;
validity = new Date(now + authConfigs.getTokenValidityInSeconds() * 1000L);

View File

@ -104,7 +104,7 @@ public class JwtTokenUtils {
/**
* Current time
*/
long now = (new Date()).getTime();
long now = System.currentTimeMillis();
/**
* Validity date
*/

View File

@ -209,7 +209,7 @@ public class JRaftProtocol
}
@Override
public boolean isLeader(String group) throws Exception {
public boolean isLeader(String group) {
Node node = raftServer.findNodeByGroup(group);
if (node == null) {
throw new NoSuchRaftGroupException(group);

View File

@ -16,10 +16,10 @@
package com.alibaba.nacos.core.distributed.raft;
import com.alibaba.nacos.common.JustForTest;
import com.alibaba.nacos.common.model.RestResult;
import com.alibaba.nacos.common.utils.ConvertUtils;
import com.alibaba.nacos.common.utils.LoggerUtils;
import com.alibaba.nacos.common.utils.StringUtils;
import com.alibaba.nacos.common.utils.ThreadUtils;
import com.alibaba.nacos.consistency.LogProcessor;
import com.alibaba.nacos.consistency.SerializeFactory;
@ -39,11 +39,8 @@ import com.alibaba.nacos.core.distributed.raft.utils.JRaftUtils;
import com.alibaba.nacos.core.distributed.raft.utils.RaftExecutor;
import com.alibaba.nacos.core.distributed.raft.utils.RaftOptionsBuilder;
import com.alibaba.nacos.core.monitor.MetricsMonitor;
import com.alibaba.nacos.core.notify.NotifyCenter;
import com.alibaba.nacos.core.utils.ApplicationUtils;
import com.alibaba.nacos.core.utils.ClassUtils;
import com.alibaba.nacos.core.utils.Loggers;
import com.alibaba.nacos.core.utils.TimerContext;
import com.alipay.sofa.jraft.CliService;
import com.alipay.sofa.jraft.Node;
import com.alipay.sofa.jraft.RaftGroupService;
@ -64,8 +61,8 @@ import com.alipay.sofa.jraft.rpc.RpcServer;
import com.alipay.sofa.jraft.rpc.impl.cli.CliClientServiceImpl;
import com.alipay.sofa.jraft.util.BytesUtil;
import com.alipay.sofa.jraft.util.Endpoint;
import com.google.protobuf.Message;
import com.google.common.base.Joiner;
import com.google.protobuf.Message;
import org.springframework.util.CollectionUtils;
import java.nio.ByteBuffer;
@ -138,11 +135,13 @@ public class JRaftServer {
// System.getProperties().setProperty("bolt.channel_write_buf_low_water_mark", String.valueOf(64 * 1024 * 1024));
// System.getProperties().setProperty("bolt.channel_write_buf_high_water_mark", String.valueOf(256 * 1024 * 1024));
System.getProperties().setProperty("bolt.netty.buffer.low.watermark", String.valueOf(128 * 1024 * 1024));
System.getProperties().setProperty("bolt.netty.buffer.high.watermark", String.valueOf(256 * 1024 * 1024));
System.getProperties().setProperty("bolt.netty.buffer.low.watermark",
String.valueOf(128 * 1024 * 1024));
System.getProperties().setProperty("bolt.netty.buffer.high.watermark",
String.valueOf(256 * 1024 * 1024));
}
public JRaftServer() throws Exception {
public JRaftServer() {
this.conf = new Configuration();
}
@ -272,7 +271,8 @@ public class JRaftServer {
machine.setNode(node);
RouteTable.getInstance().updateConfiguration(groupName, configuration);
RaftExecutor.executeByCommon(() -> registerSelfToCluster(groupName, localPeerId, configuration));
RaftExecutor.executeByCommon(
() -> registerSelfToCluster(groupName, localPeerId, configuration));
// Turn on the leader auto refresh for this group
Random random = new Random();
@ -305,21 +305,25 @@ public class JRaftServer {
}
catch (Throwable t) {
MetricsMonitor.raftReadIndexFailed();
future.completeExceptionally(new ConsistencyException("The conformance protocol is temporarily unavailable for reading", t));
future.completeExceptionally(new ConsistencyException(
"The conformance protocol is temporarily unavailable for reading",
t));
}
return;
}
MetricsMonitor.raftReadIndexFailed();
Loggers.RAFT.error("ReadIndex has error : {}", status.getErrorMsg());
future.completeExceptionally(
new ConsistencyException("The conformance protocol is temporarily unavailable for reading, " + status.getErrorMsg()));
future.completeExceptionally(new ConsistencyException(
"The conformance protocol is temporarily unavailable for reading, "
+ status.getErrorMsg()));
}
});
return future;
}
catch (Throwable e) {
MetricsMonitor.raftReadFromLeader();
Loggers.RAFT.warn("Raft linear read failed, go to Leader read logic : {}", e.toString());
Loggers.RAFT.warn("Raft linear read failed, go to Leader read logic : {}",
e.toString());
// run raft read
readFromLeader(request, future);
return future;
@ -333,20 +337,25 @@ public class JRaftServer {
@Override
public void accept(Response response, Throwable throwable) {
if (Objects.nonNull(throwable)) {
future.completeExceptionally(new ConsistencyException("The conformance protocol is temporarily unavailable for reading", throwable));
future.completeExceptionally(new ConsistencyException(
"The conformance protocol is temporarily unavailable for reading",
throwable));
return;
}
if (response.getSuccess()) {
future.complete(response);
} else {
future.completeExceptionally(
new ConsistencyException("The conformance protocol is temporarily unavailable for reading, " + response.getErrMsg()));
}
else {
future.completeExceptionally(new ConsistencyException(
"The conformance protocol is temporarily unavailable for reading, "
+ response.getErrMsg()));
}
}
});
}
public CompletableFuture<Response> commit(final String group, final Message data, final CompletableFuture<Response> future) {
public CompletableFuture<Response> commit(final String group, final Message data,
final CompletableFuture<Response> future) {
LoggerUtils
.printIfDebugEnabled(Loggers.RAFT, "data requested this time : {}", data);
final RaftGroupTuple tuple = findTupleByGroup(group);
@ -374,12 +383,12 @@ public class JRaftServer {
* Add yourself to the Raft cluster
*
* @param groupId raft group
* @param selfIp local raft node address
* @param conf {@link Configuration} without self info
* @param selfIp local raft node address
* @param conf {@link Configuration} without self info
* @return join success
*/
void registerSelfToCluster(String groupId, PeerId selfIp, Configuration conf) {
for ( ; ; ) {
for (; ; ) {
List<PeerId> peerIds = cliService.getPeers(groupId, conf);
if (peerIds.contains(selfIp)) {
return;
@ -428,14 +437,10 @@ public class JRaftServer {
public void applyOperation(Node node, Message data, FailoverClosure closure) {
final Task task = new Task();
task.setDone(new NacosClosure(data, status -> {
NacosClosure.NStatus nStatus = (NacosClosure.NStatus) status;
if (Objects.nonNull(nStatus.getThrowable())) {
closure.setThrowable(nStatus.getThrowable());
}
else {
closure.setData(nStatus.getResult());
}
closure.run(nStatus);
NacosClosure.NacosStatus nacosStatus = (NacosClosure.NacosStatus) status;
closure.setThrowable(nacosStatus.getThrowable());
closure.setResponse(nacosStatus.getResponse());
closure.run(nacosStatus);
}));
task.setData(ByteBuffer.wrap(data.toByteArray()));
node.apply(task);
@ -452,10 +457,11 @@ public class JRaftServer {
public void complete(Object o, Throwable ex) {
if (Objects.nonNull(ex)) {
closure.setThrowable(ex);
closure.run(new Status(RaftError.UNKNOWN, ex.getMessage()));
closure.run(
new Status(RaftError.UNKNOWN, ex.getMessage()));
return;
}
closure.setData(o);
closure.setResponse((Response) o);
closure.run(Status.OK());
}
@ -491,7 +497,8 @@ public class JRaftServer {
RestResult<String> result = maintainService.execute(params);
if (result.ok()) {
successCnt.incrementAndGet();
} else {
}
else {
Loggers.RAFT.error("Node removal failed : {}", result);
}
}
@ -513,7 +520,8 @@ public class JRaftServer {
Configuration oldConf = instance.getConfiguration(groupName);
String oldLeader = Optional.ofNullable(instance.selectLeader(groupName))
.orElse(PeerId.emptyPeer()).getEndpoint().toString();
status = instance.refreshConfiguration(this.cliClientService, groupName, rpcRequestTimeoutMs);
status = instance.refreshConfiguration(this.cliClientService, groupName,
rpcRequestTimeoutMs);
if (!status.isOk()) {
Loggers.RAFT
.error("Fail to refresh route configuration for group : {}, status is : {}",
@ -548,12 +556,16 @@ public class JRaftServer {
return cliService;
}
public class RaftGroupTuple {
public static class RaftGroupTuple {
private final LogProcessor processor;
private final Node node;
private final RaftGroupService raftGroupService;
private final NacosStateMachine machine;
private LogProcessor processor;
private Node node;
private RaftGroupService raftGroupService;
private NacosStateMachine machine;
@JustForTest
public RaftGroupTuple() {
}
public RaftGroupTuple(Node node, LogProcessor processor,
RaftGroupService raftGroupService, NacosStateMachine machine) {

View File

@ -16,8 +16,10 @@
package com.alibaba.nacos.core.distributed.raft;
import com.alibaba.nacos.consistency.entity.Response;
import com.alipay.sofa.jraft.Closure;
import com.alipay.sofa.jraft.Status;
import com.alipay.sofa.jraft.error.RaftError;
import com.google.protobuf.Message;
/**
@ -25,76 +27,113 @@ import com.google.protobuf.Message;
*/
public class NacosClosure implements Closure {
private final Message log;
private final Message message;
private final Closure closure;
private Throwable throwable;
private Object object;
private final NacosStatus nacosStatus = new NacosStatus();
public NacosClosure(Message log, Closure closure) {
this.log = log;
public NacosClosure(Message message, Closure closure) {
this.message = message;
this.closure = closure;
}
@Override
public void run(Status status) {
if (closure != null) {
NStatus status1 = new NStatus(status, throwable);
status1.setResult(object);
closure.run(status1);
}
nacosStatus.setStatus(status);
closure.run(nacosStatus);
}
public Object getObject() {
return object;
}
public void setObject(Object object) {
this.object = object;
public void setResponse(Response response) {
this.nacosStatus.setResponse(response);
}
public void setThrowable(Throwable throwable) {
this.throwable = throwable;
this.nacosStatus.setThrowable(throwable);
}
public Closure getClosure() {
return closure;
}
public Message getLog() {
return log;
public Message getMessage() {
return message;
}
// Pass the Throwable inside the state machine to the outer layer
@SuppressWarnings("PMD.ClassNamingShouldBeCamelRule")
public static class NStatus extends Status {
public static class NacosStatus extends Status {
private Status status;
private Object result;
private Response response = null;
private Throwable throwable;
public NStatus(Status status, Throwable throwable) {
super();
this.status = status;
this.throwable = throwable;
}
public Status getStatus() {
return status;
}
private Throwable throwable = null;
public void setStatus(Status status) {
this.status = status;
}
public Object getResult() {
return result;
@Override
public void reset() {
status.reset();
}
public void setResult(Object result) {
this.result = result;
@Override
public boolean isOk() {
return status.isOk();
}
@Override
public void setCode(int code) {
status.setCode(code);
}
@Override
public int getCode() {
return status.getCode();
}
@Override
public RaftError getRaftError() {
return status.getRaftError();
}
@Override
public void setErrorMsg(String errMsg) {
status.setErrorMsg(errMsg);
}
@Override
public void setError(int code, String fmt, Object... args) {
status.setError(code, fmt, args);
}
@Override
public void setError(RaftError error, String fmt, Object... args) {
status.setError(error, fmt, args);
}
@Override
public String toString() {
return status.toString();
}
@Override
public Status copy() {
NacosStatus copy = new NacosStatus();
copy.status = this.status;
copy.response = this.response;
copy.throwable = this.throwable;
return copy;
}
@Override
public String getErrorMsg() {
return status.getErrorMsg();
}
public Response getResponse() {
return response;
}
public void setResponse(Response response) {
this.response = response;
}
public Throwable getThrowable() {

View File

@ -32,7 +32,6 @@ import com.alibaba.nacos.consistency.snapshot.Writer;
import com.alibaba.nacos.core.distributed.raft.utils.JRaftUtils;
import com.alibaba.nacos.core.notify.NotifyCenter;
import com.alibaba.nacos.core.utils.Loggers;
import com.alibaba.nacos.core.utils.TimerContext;
import com.alipay.sofa.jraft.Closure;
import com.alipay.sofa.jraft.Iterator;
import com.alipay.sofa.jraft.Node;
@ -94,7 +93,7 @@ class NacosStateMachine extends StateMachineAdapter {
try {
if (iter.done() != null) {
closure = (NacosClosure) iter.done();
message = closure.getLog();
message = closure.getMessage();
}
else {
final ByteBuffer data = iter.getData();
@ -246,9 +245,9 @@ class NacosStateMachine extends StateMachineAdapter {
RouteTable.getInstance().getConfiguration(node.getGroupId()).getPeers());
}
private void postProcessor(Object data, NacosClosure closure) {
private void postProcessor(Response data, NacosClosure closure) {
if (Objects.nonNull(closure)) {
closure.setObject(data);
closure.setResponse(data);
}
}

View File

@ -19,7 +19,7 @@ package com.alibaba.nacos.core.distributed.raft.exception;
/**
* @author <a href="mailto:liaochuntao@live.com">liaochuntao</a>
*/
public class NoSuchRaftGroupException extends Exception {
public class NoSuchRaftGroupException extends RuntimeException {
private static final long serialVersionUID = 1755681688785678765L;

View File

@ -71,13 +71,13 @@ public abstract class AbstractProcessor {
}
protected void execute(JRaftServer server, final RpcContext asyncCtx, final Message log, final JRaftServer.RaftGroupTuple tuple) {
FailoverClosure<Object> closure = new FailoverClosure<Object>() {
FailoverClosure closure = new FailoverClosure() {
Object data;
Response data;
Throwable ex;
@Override
public void setData(Object data) {
public void setResponse(Response data) {
this.data = data;
}
@ -93,14 +93,7 @@ public abstract class AbstractProcessor {
asyncCtx.sendResponse(Response.newBuilder().setErrMsg(ex.toString())
.setSuccess(false).build());
} else {
ByteString bytes = Objects.nonNull(data) ? ByteString.copyFrom(serializer.serialize(data)) : ByteString.EMPTY;
Response response = Response.newBuilder()
.setSuccess(true)
.setData(bytes)
.build();
asyncCtx.sendResponse(response);
asyncCtx.sendResponse(data);
}
}
};

View File

@ -16,6 +16,7 @@
package com.alibaba.nacos.core.distributed.raft.utils;
import com.alibaba.nacos.consistency.entity.Response;
import com.alipay.sofa.jraft.Closure;
/**
@ -23,14 +24,14 @@ import com.alipay.sofa.jraft.Closure;
*
* @author <a href="mailto:liaochuntao@live.com">liaochuntao</a>
*/
public interface FailoverClosure<T> extends Closure {
public interface FailoverClosure extends Closure {
/**
* Set the return interface if needed
*
* @param data data
* @param response {@link Response} data
*/
void setData(T data);
void setResponse(Response response);
/**
* Catch exception

View File

@ -16,11 +16,11 @@
package com.alibaba.nacos.core.distributed.raft.utils;
import com.alibaba.nacos.common.utils.LoggerUtils;
import com.alibaba.nacos.common.utils.Objects;
import com.alibaba.nacos.consistency.entity.Response;
import com.alibaba.nacos.consistency.exception.ConsistencyException;
import com.alibaba.nacos.core.utils.Loggers;
import com.alipay.sofa.jraft.Status;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
/**
@ -28,39 +28,36 @@ import java.util.concurrent.CompletableFuture;
*
* @author <a href="mailto:liaochuntao@live.com">liaochuntao</a>
*/
public class FailoverClosureImpl<T> implements FailoverClosure<T> {
public class FailoverClosureImpl implements FailoverClosure {
private final CompletableFuture<T> future;
private volatile T data;
private volatile Throwable throwable;
private final CompletableFuture<Response> future;
private volatile Response data;
private volatile Throwable throwable;
public FailoverClosureImpl(final CompletableFuture<T> future) {
this.future = future;
}
public FailoverClosureImpl(final CompletableFuture<Response> future) {
this.future = future;
}
@Override
public void setData(T data) {
this.data = data;
}
@Override
public void setResponse(Response data) {
this.data = data;
}
@Override
public void setThrowable(Throwable throwable) {
this.throwable = throwable;
}
@Override
public void setThrowable(Throwable throwable) {
this.throwable = throwable;
}
@Override
public void run(Status status) {
if (status.isOk()) {
boolean success = future.complete(data);
LoggerUtils.printIfDebugEnabled(Loggers.RAFT, "future.complete execute {}", success);
return;
}
final Throwable throwable = this.throwable;
if (Objects.nonNull(throwable)) {
future.completeExceptionally(new ConsistencyException(throwable.toString()));
} else {
future.completeExceptionally(new ConsistencyException("operation failure"));
}
}
@Override
public void run(Status status) {
if (status.isOk()) {
future.complete(data);
return;
}
final Throwable throwable = this.throwable;
future.completeExceptionally(Objects.nonNull(throwable) ?
new ConsistencyException(throwable.toString()) :
new ConsistencyException("operation failure"));
}
}

View File

@ -25,7 +25,7 @@
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${LOG_HOME}/nacos.log.%d{yyyy-MM-dd}.%i</fileNamePattern>
<maxFileSize>50MB</maxFileSize>
<MaxHistory>15</MaxHistory>
<maxHistory>15</maxHistory>
<totalSizeCap>512MB</totalSizeCap>
<cleanHistoryOnStart>true</cleanHistoryOnStart>
</rollingPolicy>
@ -42,7 +42,7 @@
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${LOG_HOME}/core-auth.log.%d{yyyy-MM-dd}.%i</fileNamePattern>
<maxFileSize>2GB</maxFileSize>
<MaxHistory>7</MaxHistory>
<maxHistory>7</maxHistory>
<totalSizeCap>7GB</totalSizeCap>
<cleanHistoryOnStart>true</cleanHistoryOnStart>
</rollingPolicy>
@ -59,7 +59,7 @@
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${LOG_HOME}/protocol-raft.log.%d{yyyy-MM-dd}.%i</fileNamePattern>
<maxFileSize>2GB</maxFileSize>
<MaxHistory>7</MaxHistory>
<maxHistory>7</maxHistory>
<totalSizeCap>7GB</totalSizeCap>
<cleanHistoryOnStart>true</cleanHistoryOnStart>
</rollingPolicy>
@ -76,7 +76,7 @@
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${LOG_HOME}/protocol-distro.log.%d{yyyy-MM-dd}.%i</fileNamePattern>
<maxFileSize>2GB</maxFileSize>
<MaxHistory>7</MaxHistory>
<maxHistory>7</maxHistory>
<totalSizeCap>7GB</totalSizeCap>
<cleanHistoryOnStart>true</cleanHistoryOnStart>
</rollingPolicy>
@ -93,7 +93,7 @@
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${LOG_HOME}/nacos-cluster.log.%d{yyyy-MM-dd}.%i</fileNamePattern>
<maxFileSize>2GB</maxFileSize>
<MaxHistory>7</MaxHistory>
<maxHistory>7</maxHistory>
<totalSizeCap>7GB</totalSizeCap>
<cleanHistoryOnStart>true</cleanHistoryOnStart>
</rollingPolicy>
@ -110,7 +110,7 @@
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${LOG_HOME}/alipay-jraft.log.%d{yyyy-MM-dd}.%i</fileNamePattern>
<maxFileSize>2GB</maxFileSize>
<MaxHistory>7</MaxHistory>
<maxHistory>7</maxHistory>
<totalSizeCap>7GB</totalSizeCap>
<cleanHistoryOnStart>true</cleanHistoryOnStart>
</rollingPolicy>

View File

@ -0,0 +1,59 @@
package com.alibaba.nacos.core.distributed.raft.processor;
import com.alibaba.nacos.consistency.SerializeFactory;
import com.alibaba.nacos.consistency.entity.Log;
import com.alibaba.nacos.consistency.entity.Response;
import com.alibaba.nacos.core.distributed.raft.JRaftServer;
import com.alibaba.nacos.core.distributed.raft.utils.FailoverClosure;
import com.alipay.sofa.jraft.Node;
import com.alipay.sofa.jraft.Status;
import com.alipay.sofa.jraft.error.RaftError;
import com.alipay.sofa.jraft.rpc.Connection;
import com.alipay.sofa.jraft.rpc.RpcContext;
import com.google.protobuf.Message;
import org.junit.Assert;
import org.junit.Test;
import java.util.concurrent.atomic.AtomicReference;
public class AbstractProcessorTest {
private JRaftServer server = new JRaftServer() {
@Override
public void applyOperation(Node node, Message data, FailoverClosure closure) {
closure.setResponse(Response.newBuilder().setSuccess(false).setErrMsg("Error message transmission").build());
closure.run(new Status(RaftError.UNKNOWN, "Error message transmission"));
}
};
@Test
public void testErrorThroughRPC() {
final AtomicReference<Response> reference = new AtomicReference<>();
RpcContext context = new RpcContext() {
@Override
public void sendResponse(Object responseObj) {
reference.set((Response) responseObj);
}
@Override
public Connection getConnection() {
return null;
}
@Override
public String getRemoteAddress() {
return null;
}
};
AbstractProcessor processor = new NacosLogProcessor(server, SerializeFactory.getDefault());
processor.execute(server, context, Log.newBuilder().build(), new JRaftServer.RaftGroupTuple());
Response response = reference.get();
Assert.assertNotNull(response);
Assert.assertEquals("Error message transmission", response.getErrMsg());
Assert.assertFalse(response.getSuccess());
}
}

View File

@ -13,7 +13,7 @@ server.port=8848
#*************** Config Module Related Configurations ***************#
### If user MySQL as datasource:
### If use MySQL as datasource:
# spring.datasource.platform=mysql
### Count of DB:

View File

@ -11,7 +11,7 @@
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${nacos.home}/logs/cmdb-main.log.%d{yyyy-MM-dd}.%i</fileNamePattern>
<maxFileSize>2GB</maxFileSize>
<MaxHistory>7</MaxHistory>
<maxHistory>7</maxHistory>
<totalSizeCap>7GB</totalSizeCap>
<cleanHistoryOnStart>true</cleanHistoryOnStart>
</rollingPolicy>
@ -35,7 +35,7 @@
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${LOG_HOME}/naming-server.log.%d{yyyy-MM-dd}.%i</fileNamePattern>
<maxFileSize>1GB</maxFileSize>
<MaxHistory>7</MaxHistory>
<maxHistory>7</maxHistory>
<totalSizeCap>7GB</totalSizeCap>
<cleanHistoryOnStart>true</cleanHistoryOnStart>
</rollingPolicy>
@ -59,7 +59,7 @@
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${LOG_HOME}/naming-raft.log.%d{yyyy-MM-dd}.%i</fileNamePattern>
<maxFileSize>1GB</maxFileSize>
<MaxHistory>7</MaxHistory>
<maxHistory>7</maxHistory>
<totalSizeCap>3GB</totalSizeCap>
<cleanHistoryOnStart>true</cleanHistoryOnStart>
</rollingPolicy>
@ -84,7 +84,7 @@
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${LOG_HOME}/naming-distro.log.%d{yyyy-MM-dd}.%i</fileNamePattern>
<maxFileSize>1GB</maxFileSize>
<MaxHistory>7</MaxHistory>
<maxHistory>7</maxHistory>
<totalSizeCap>3GB</totalSizeCap>
<cleanHistoryOnStart>true</cleanHistoryOnStart>
</rollingPolicy>
@ -108,7 +108,7 @@
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${LOG_HOME}/naming-event.log.%d{yyyy-MM-dd}.%i</fileNamePattern>
<maxFileSize>1GB</maxFileSize>
<MaxHistory>7</MaxHistory>
<maxHistory>7</maxHistory>
<totalSizeCap>3GB</totalSizeCap>
<cleanHistoryOnStart>true</cleanHistoryOnStart>
</rollingPolicy>
@ -132,7 +132,7 @@
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${LOG_HOME}/naming-push.log.%d{yyyy-MM-dd}.%i</fileNamePattern>
<maxFileSize>1GB</maxFileSize>
<MaxHistory>7</MaxHistory>
<maxHistory>7</maxHistory>
<totalSizeCap>3GB</totalSizeCap>
<cleanHistoryOnStart>true</cleanHistoryOnStart>
</rollingPolicy>
@ -148,7 +148,7 @@
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${LOG_HOME}/naming-rt.log.%d{yyyy-MM-dd}.%i</fileNamePattern>
<maxFileSize>1GB</maxFileSize>
<MaxHistory>7</MaxHistory>
<maxHistory>7</maxHistory>
<totalSizeCap>3GB</totalSizeCap>
<cleanHistoryOnStart>true</cleanHistoryOnStart>
</rollingPolicy>
@ -165,7 +165,7 @@
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${LOG_HOME}/naming-performance.log.%d{yyyy-MM-dd}.%i</fileNamePattern>
<maxFileSize>1GB</maxFileSize>
<MaxHistory>7</MaxHistory>
<maxHistory>7</maxHistory>
<totalSizeCap>3GB</totalSizeCap>
<cleanHistoryOnStart>true</cleanHistoryOnStart>
</rollingPolicy>
@ -183,7 +183,7 @@
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${LOG_HOME}/config-dump.log.%d{yyyy-MM-dd}.%i</fileNamePattern>
<maxFileSize>2GB</maxFileSize>
<MaxHistory>7</MaxHistory>
<maxHistory>7</maxHistory>
<totalSizeCap>7GB</totalSizeCap>
<cleanHistoryOnStart>true</cleanHistoryOnStart>
</rollingPolicy>
@ -199,7 +199,7 @@
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${LOG_HOME}/config-pull.log.%d{yyyy-MM-dd}.%i</fileNamePattern>
<maxFileSize>20MB</maxFileSize>
<MaxHistory>7</MaxHistory>
<maxHistory>7</maxHistory>
<totalSizeCap>128MB</totalSizeCap>
<cleanHistoryOnStart>true</cleanHistoryOnStart>
</rollingPolicy>
@ -215,7 +215,7 @@
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${LOG_HOME}/config-fatal.log.%d{yyyy-MM-dd}.%i</fileNamePattern>
<maxFileSize>20MB</maxFileSize>
<MaxHistory>7</MaxHistory>
<maxHistory>7</maxHistory>
<totalSizeCap>128MB</totalSizeCap>
<cleanHistoryOnStart>true</cleanHistoryOnStart>
</rollingPolicy>
@ -231,7 +231,7 @@
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${LOG_HOME}/config-memory.log.%d{yyyy-MM-dd}.%i</fileNamePattern>
<maxFileSize>20MB</maxFileSize>
<MaxHistory>7</MaxHistory>
<maxHistory>7</maxHistory>
<totalSizeCap>128MB</totalSizeCap>
<cleanHistoryOnStart>true</cleanHistoryOnStart>
</rollingPolicy>
@ -247,7 +247,7 @@
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${LOG_HOME}/config-pull-check.log.%d{yyyy-MM-dd}.%i</fileNamePattern>
<maxFileSize>1GB</maxFileSize>
<MaxHistory>7</MaxHistory>
<maxHistory>7</maxHistory>
<totalSizeCap>3GB</totalSizeCap>
<cleanHistoryOnStart>true</cleanHistoryOnStart>
</rollingPolicy>
@ -264,7 +264,7 @@
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${LOG_HOME}/config-client-request.log.%d{yyyy-MM-dd}.%i</fileNamePattern>
<maxFileSize>2GB</maxFileSize>
<MaxHistory>7</MaxHistory>
<maxHistory>7</maxHistory>
<totalSizeCap>7GB</totalSizeCap>
<cleanHistoryOnStart>true</cleanHistoryOnStart>
</rollingPolicy>
@ -281,7 +281,7 @@
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${LOG_HOME}/config-trace.log.%d{yyyy-MM-dd}.%i</fileNamePattern>
<maxFileSize>2GB</maxFileSize>
<MaxHistory>7</MaxHistory>
<maxHistory>7</maxHistory>
<totalSizeCap>7GB</totalSizeCap>
<cleanHistoryOnStart>true</cleanHistoryOnStart>
</rollingPolicy>
@ -298,7 +298,7 @@
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${LOG_HOME}/config-notify.log.%d{yyyy-MM-dd}.%i</fileNamePattern>
<maxFileSize>1GB</maxFileSize>
<MaxHistory>7</MaxHistory>
<maxHistory>7</maxHistory>
<totalSizeCap>3GB</totalSizeCap>
<cleanHistoryOnStart>true</cleanHistoryOnStart>
</rollingPolicy>
@ -315,7 +315,7 @@
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${LOG_HOME}/config-server.log.%d{yyyy-MM-dd}.%i</fileNamePattern>
<maxFileSize>50MB</maxFileSize>
<MaxHistory>7</MaxHistory>
<maxHistory>7</maxHistory>
<totalSizeCap>512MB</totalSizeCap>
<cleanHistoryOnStart>true</cleanHistoryOnStart>
</rollingPolicy>
@ -332,7 +332,7 @@
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${LOG_HOME}/nacos.log.%d{yyyy-MM-dd}.%i</fileNamePattern>
<maxFileSize>50MB</maxFileSize>
<MaxHistory>7</MaxHistory>
<maxHistory>7</maxHistory>
<totalSizeCap>512MB</totalSizeCap>
<cleanHistoryOnStart>true</cleanHistoryOnStart>
</rollingPolicy>
@ -349,7 +349,7 @@
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${LOG_HOME}/nacos-address.log.%d{yyyy-MM-dd}.%i</fileNamePattern>
<maxFileSize>2GB</maxFileSize>
<MaxHistory>7</MaxHistory>
<maxHistory>7</maxHistory>
<totalSizeCap>7GB</totalSizeCap>
<cleanHistoryOnStart>true</cleanHistoryOnStart>
</rollingPolicy>
@ -366,7 +366,7 @@
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${LOG_HOME}/istio-main.log.%d{yyyy-MM-dd}.%i</fileNamePattern>
<maxFileSize>2GB</maxFileSize>
<MaxHistory>7</MaxHistory>
<maxHistory>7</maxHistory>
<totalSizeCap>7GB</totalSizeCap>
<cleanHistoryOnStart>true</cleanHistoryOnStart>
</rollingPolicy>
@ -383,7 +383,7 @@
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${LOG_HOME}/core-auth.log.%d{yyyy-MM-dd}.%i</fileNamePattern>
<maxFileSize>2GB</maxFileSize>
<MaxHistory>7</MaxHistory>
<maxHistory>7</maxHistory>
<totalSizeCap>7GB</totalSizeCap>
<cleanHistoryOnStart>true</cleanHistoryOnStart>
</rollingPolicy>
@ -400,7 +400,7 @@
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${LOG_HOME}/protocol-raft.log.%d{yyyy-MM-dd}.%i</fileNamePattern>
<maxFileSize>2GB</maxFileSize>
<MaxHistory>7</MaxHistory>
<maxHistory>7</maxHistory>
<totalSizeCap>7GB</totalSizeCap>
<cleanHistoryOnStart>true</cleanHistoryOnStart>
</rollingPolicy>
@ -417,7 +417,7 @@
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${LOG_HOME}/protocol-distro.log.%d{yyyy-MM-dd}.%i</fileNamePattern>
<maxFileSize>2GB</maxFileSize>
<MaxHistory>7</MaxHistory>
<maxHistory>7</maxHistory>
<totalSizeCap>7GB</totalSizeCap>
<cleanHistoryOnStart>true</cleanHistoryOnStart>
</rollingPolicy>
@ -434,7 +434,7 @@
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${LOG_HOME}/nacos-cluster.log.%d{yyyy-MM-dd}.%i</fileNamePattern>
<maxFileSize>2GB</maxFileSize>
<MaxHistory>7</MaxHistory>
<maxHistory>7</maxHistory>
<totalSizeCap>7GB</totalSizeCap>
<cleanHistoryOnStart>true</cleanHistoryOnStart>
</rollingPolicy>
@ -451,7 +451,7 @@
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${LOG_HOME}/alipay-jraft.log.%d{yyyy-MM-dd}.%i</fileNamePattern>
<maxFileSize>2GB</maxFileSize>
<MaxHistory>7</MaxHistory>
<maxHistory>7</maxHistory>
<totalSizeCap>7GB</totalSizeCap>
<cleanHistoryOnStart>true</cleanHistoryOnStart>
</rollingPolicy>

View File

@ -192,7 +192,7 @@ CREATE TABLE `roles` (
CREATE TABLE `permissions` (
`role` varchar(50) NOT NULL,
`resource` varchar(512) NOT NULL,
`resource` varchar(255) NOT NULL,
`action` varchar(8) NOT NULL,
UNIQUE INDEX `uk_role_permission` (`role`,`resource`,`action`) USING BTREE
);

View File

@ -50,11 +50,13 @@ import java.util.concurrent.ConcurrentMap;
@Component
public class RaftStore {
private Properties meta = new Properties();
private final Properties meta = new Properties();
private String metaFileName = UtilsAndCommons.DATA_BASE_DIR + File.separator + "meta.properties";
private static final String META_FILE_NAME = UtilsAndCommons.DATA_BASE_DIR + File.separator + "meta.properties";
private String cacheDir = UtilsAndCommons.DATA_BASE_DIR + File.separator + "data";
private static final String CACHE_DIR = UtilsAndCommons.DATA_BASE_DIR + File.separator + "data";
private static final String CACHE_FILE_SUFFIX = ".datum";
public synchronized void loadDatums(RaftCore.Notifier notifier, ConcurrentMap<String, Datum> datums) throws Exception {
@ -81,7 +83,7 @@ public class RaftStore {
}
public synchronized Properties loadMeta() throws Exception {
File metaFile = new File(metaFileName);
File metaFile = new File(META_FILE_NAME);
if (!metaFile.exists() && !metaFile.getParentFile().mkdirs() && !metaFile.createNewFile()) {
throw new IllegalStateException("failed to create meta file: " + metaFile.getAbsolutePath());
}
@ -100,7 +102,7 @@ public class RaftStore {
Loggers.RAFT.warn("warning: encountered directory in cache dir: {}", cache.getAbsolutePath());
}
if (!StringUtils.equals(cache.getName(), encodeFileName(key))) {
if (!StringUtils.equals(cache.getName(), encodeDatumKey(key) + CACHE_FILE_SUFFIX)) {
continue;
}
@ -112,12 +114,16 @@ public class RaftStore {
return null;
}
public synchronized Datum readDatum(File file, String namespaceId) throws IOException {
private boolean isDatumCacheFile(String fileName) {
return fileName.endsWith(CACHE_FILE_SUFFIX);
}
public synchronized Datum readDatum(File file, String namespaceId) throws IOException {
if (!isDatumCacheFile(file.getName())) {
return null;
}
ByteBuffer buffer;
FileChannel fc = null;
try {
fc = new FileInputStream(file).getChannel();
try (FileChannel fc = new FileInputStream(file).getChannel()) {
buffer = ByteBuffer.allocate((int) file.length());
fc.read(buffer);
@ -192,24 +198,25 @@ public class RaftStore {
} catch (Exception e) {
Loggers.RAFT.warn("waning: failed to deserialize key: {}", file.getName());
throw e;
} finally {
if (fc != null) {
fc.close();
}
}
}
private String cacheFileName(String namespaceId, Datum datum) {
String fileName;
if (StringUtils.isNotBlank(namespaceId)) {
fileName = CACHE_DIR + File.separator + namespaceId + File.separator + encodeDatumKey(datum.key);
} else {
fileName = CACHE_DIR + File.separator + encodeDatumKey(datum.key);
}
fileName += CACHE_FILE_SUFFIX;
return fileName;
}
public synchronized void write(final Datum datum) throws Exception {
String namespaceId = KeyBuilder.getNamespace(datum.key);
File cacheFile;
if (StringUtils.isNotBlank(namespaceId)) {
cacheFile = new File(cacheDir + File.separator + namespaceId + File.separator + encodeFileName(datum.key));
} else {
cacheFile = new File(cacheDir + File.separator + encodeFileName(datum.key));
}
File cacheFile = new File(cacheFileName(namespaceId, datum));
if (!cacheFile.exists() && !cacheFile.getParentFile().mkdirs() && !cacheFile.createNewFile()) {
MetricsMonitor.getDiskException().increment();
@ -241,7 +248,7 @@ public class RaftStore {
String oldFormatKey =
datum.key.replace(Constants.DEFAULT_GROUP + Constants.SERVICE_INFO_SPLITER, StringUtils.EMPTY);
cacheFile = new File(cacheDir + File.separator + namespaceId + File.separator + encodeFileName(oldFormatKey));
cacheFile = new File(cacheFileName(namespaceId, datum));
if (cacheFile.exists() && !cacheFile.delete()) {
Loggers.RAFT.error("[RAFT-DELETE] failed to delete old format datum: {}, value: {}",
datum.key, datum.value);
@ -252,7 +259,7 @@ public class RaftStore {
}
private File[] listCaches() throws Exception {
File cacheDir = new File(this.cacheDir);
File cacheDir = new File(CACHE_DIR);
if (!cacheDir.exists() && !cacheDir.mkdirs()) {
throw new IllegalStateException("cloud not make out directory: " + cacheDir.getName());
}
@ -267,7 +274,7 @@ public class RaftStore {
if (StringUtils.isNotBlank(namespaceId)) {
File cacheFile = new File(cacheDir + File.separator + namespaceId + File.separator + encodeFileName(datum.key));
File cacheFile = new File(cacheFileName(namespaceId, datum));
if (cacheFile.exists() && !cacheFile.delete()) {
Loggers.RAFT.error("[RAFT-DELETE] failed to delete datum: {}, value: {}", datum.key, datum.value);
throw new IllegalStateException("failed to delete datum: " + datum.key);
@ -276,7 +283,7 @@ public class RaftStore {
}
public void updateTerm(long term) throws Exception {
File file = new File(metaFileName);
File file = new File(META_FILE_NAME);
if (!file.exists() && !file.getParentFile().mkdirs() && !file.createNewFile()) {
throw new IllegalStateException("failed to create meta file");
}
@ -288,11 +295,11 @@ public class RaftStore {
}
}
private static String encodeFileName(String fileName) {
return fileName.replace(':', '#');
private static String encodeDatumKey(String datumKey) {
return datumKey.replace(':', '#');
}
private static String decodeFileName(String fileName) {
return fileName.replace("#", ":");
private static String decodeDatumKey(String datumKey) {
return datumKey.replace("#", ":");
}
}

View File

@ -106,13 +106,13 @@ public class DistroController {
datumMap.put(key, datum);
}
String content = new String(serializer.serialize(datumMap), StandardCharsets.UTF_8);
byte[] content = serializer.serialize(datumMap);
return ResponseEntity.ok(content);
}
@GetMapping("/datums")
public ResponseEntity getAllDatums() {
String content = new String(serializer.serialize(dataStore.getDataMap()), StandardCharsets.UTF_8);
byte[] content = serializer.serialize(dataStore.getDataMap());
return ResponseEntity.ok(content);
}
}

View File

@ -21,17 +21,13 @@ import com.alibaba.nacos.naming.core.Instance;
import com.alibaba.nacos.naming.misc.Loggers;
import com.alibaba.nacos.naming.misc.SwitchDomain;
import com.alibaba.nacos.naming.monitor.MetricsMonitor;
import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;
import io.netty.channel.ConnectTimeoutException;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.net.SocketTimeoutException;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.*;
import java.util.List;
import java.util.concurrent.*;
@ -149,17 +145,11 @@ public class MysqlHealthCheckProcessor implements HealthCheckProcessor {
Mysql config = (Mysql) cluster.getHealthChecker();
if (connection == null || connection.isClosed()) {
MysqlDataSource dataSource = new MysqlDataSource();
dataSource.setConnectTimeout(CONNECT_TIMEOUT_MS);
dataSource.setSocketTimeout(CONNECT_TIMEOUT_MS);
dataSource.setUser(config.getUser());
dataSource.setPassword(config.getPwd());
dataSource.setLoginTimeout(1);
dataSource.setServerName(ip.getIp());
dataSource.setPort(ip.getPort());
connection = dataSource.getConnection();
String url = "jdbc:mysql://" + ip.getIp() + ":" + ip.getPort() +
"?connectTimeout=" + CONNECT_TIMEOUT_MS +
"&socketTimeout=" + CONNECT_TIMEOUT_MS +
"&loginTimeout=" + 1;
connection = DriverManager.getConnection(url, config.getUser(), config.getPwd());
CONNECTION_POOL.put(key, connection);
}

View File

@ -32,6 +32,7 @@ import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
@ -318,18 +319,16 @@ public class HttpClient {
public static HttpResult httpPutLarge(String url, Map<String, String> headers, byte[] content) {
try {
HttpClientBuilder builder = HttpClients.custom();
builder.setUserAgent(UtilsAndCommons.SERVER_VERSION);
builder.setConnectionTimeToLive(500, TimeUnit.MILLISECONDS);
HttpClientBuilder builder = HttpClients.custom()
.setUserAgent(UtilsAndCommons.SERVER_VERSION)
.setConnectionTimeToLive(500, TimeUnit.MILLISECONDS);
CloseableHttpClient httpClient = builder.build();
HttpPut httpPut = new HttpPut(url);
HttpPut httpPut = new HttpPut(url);
for (Map.Entry<String, String> entry : headers.entrySet()) {
httpPut.setHeader(entry.getKey(), entry.getValue());
}
httpPut.setEntity(new StringEntity(new String(content, StandardCharsets.UTF_8), ContentType.create("application/json", StandardCharsets.UTF_8)));
httpPut.setEntity(new ByteArrayEntity(content, ContentType.APPLICATION_JSON));
HttpResponse response = httpClient.execute(httpPut);
HttpEntity entity = response.getEntity();

View File

@ -11,7 +11,7 @@
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${LOG_HOME}/naming-server.log.%d{yyyy-MM-dd}.%i</fileNamePattern>
<maxFileSize>2GB</maxFileSize>
<MaxHistory>15</MaxHistory>
<maxHistory>15</maxHistory>
<totalSizeCap>7GB</totalSizeCap>
<cleanHistoryOnStart>true</cleanHistoryOnStart>
</rollingPolicy>
@ -27,7 +27,7 @@
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${LOG_HOME}/naming-raft.log.%d{yyyy-MM-dd}.%i</fileNamePattern>
<maxFileSize>20MB</maxFileSize>
<MaxHistory>15</MaxHistory>
<maxHistory>15</maxHistory>
<totalSizeCap>128MB</totalSizeCap>
<cleanHistoryOnStart>true</cleanHistoryOnStart>
</rollingPolicy>
@ -43,7 +43,7 @@
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${LOG_HOME}/naming-event.log.%d{yyyy-MM-dd}.%i</fileNamePattern>
<maxFileSize>20MB</maxFileSize>
<MaxHistory>15</MaxHistory>
<maxHistory>15</maxHistory>
<totalSizeCap>128MB</totalSizeCap>
<cleanHistoryOnStart>true</cleanHistoryOnStart>
</rollingPolicy>
@ -59,7 +59,7 @@
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${LOG_HOME}/naming-push.log.%d{yyyy-MM-dd}.%i</fileNamePattern>
<maxFileSize>20MB</maxFileSize>
<MaxHistory>15</MaxHistory>
<maxHistory>15</maxHistory>
<totalSizeCap>128MB</totalSizeCap>
<cleanHistoryOnStart>true</cleanHistoryOnStart>
</rollingPolicy>
@ -75,7 +75,7 @@
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${LOG_HOME}/naming-rt.log.%d{yyyy-MM-dd}.%i</fileNamePattern>
<maxFileSize>1GB</maxFileSize>
<MaxHistory>15</MaxHistory>
<maxHistory>15</maxHistory>
<totalSizeCap>3GB</totalSizeCap>
<cleanHistoryOnStart>true</cleanHistoryOnStart>
</rollingPolicy>
@ -92,7 +92,7 @@
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${LOG_HOME}/naming-performance.log.%d{yyyy-MM-dd}.%i</fileNamePattern>
<maxFileSize>50MB</maxFileSize>
<MaxHistory>15</MaxHistory>
<maxHistory>15</maxHistory>
<totalSizeCap>512MB</totalSizeCap>
<cleanHistoryOnStart>true</cleanHistoryOnStart>
</rollingPolicy>
@ -109,7 +109,7 @@
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${LOG_HOME}/naming-router.log.%d{yyyy-MM-dd}.%i</fileNamePattern>
<maxFileSize>2GB</maxFileSize>
<MaxHistory>15</MaxHistory>
<maxHistory>15</maxHistory>
<totalSizeCap>7GB</totalSizeCap>
<cleanHistoryOnStart>true</cleanHistoryOnStart>
</rollingPolicy>
@ -126,7 +126,7 @@
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${LOG_HOME}/naming-cache.log.%d{yyyy-MM-dd}.%i</fileNamePattern>
<maxFileSize>1GB</maxFileSize>
<MaxHistory>15</MaxHistory>
<maxHistory>15</maxHistory>
<totalSizeCap>3GB</totalSizeCap>
<cleanHistoryOnStart>true</cleanHistoryOnStart>
</rollingPolicy>
@ -143,7 +143,7 @@
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${LOG_HOME}/naming-device.log.%d{yyyy-MM-dd}.%i</fileNamePattern>
<maxFileSize>2GB</maxFileSize>
<MaxHistory>15</MaxHistory>
<maxHistory>15</maxHistory>
<totalSizeCap>7GB</totalSizeCap>
<cleanHistoryOnStart>true</cleanHistoryOnStart>
</rollingPolicy>
@ -160,7 +160,7 @@
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${LOG_HOME}/naming-tag.log.%d{yyyy-MM-dd}.%i</fileNamePattern>
<maxFileSize>1GB</maxFileSize>
<MaxHistory>15</MaxHistory>
<maxHistory>15</maxHistory>
<totalSizeCap>3GB</totalSizeCap>
<cleanHistoryOnStart>true</cleanHistoryOnStart>
</rollingPolicy>
@ -177,7 +177,7 @@
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${LOG_HOME}/naming-debug.log.%d{yyyy-MM-dd}.%i</fileNamePattern>
<maxFileSize>20MB</maxFileSize>
<MaxHistory>15</MaxHistory>
<maxHistory>15</maxHistory>
<totalSizeCap>128MB</totalSizeCap>
<cleanHistoryOnStart>true</cleanHistoryOnStart>
</rollingPolicy>
@ -194,7 +194,7 @@
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${LOG_HOME}/naming-distro.log.%d{yyyy-MM-dd}.%i</fileNamePattern>
<maxFileSize>1GB</maxFileSize>
<MaxHistory>7</MaxHistory>
<maxHistory>7</maxHistory>
<totalSizeCap>3GB</totalSizeCap>
<cleanHistoryOnStart>true</cleanHistoryOnStart>
</rollingPolicy>

28
pom.xml
View File

@ -460,6 +460,34 @@
</build>
</profile>
<profile>
<!-- Run integration tests for configuration modules separately -->
<id>cit-test</id>
<build>
<plugins>
<plugin>
<artifactId>maven-failsafe-plugin</artifactId>
<version>${maven-failsafe-plugin.version}</version>
<configuration>
<argLine>@{failsafeArgLine}</argLine>
<argLine>-Dnacos.standalone=true</argLine>
<includes>
<include>**/*CITCase.java</include>
</includes>
</configuration>
<executions>
<execution>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
<profile>
<!-- Run integration tests for all modules separately -->
<id>it-test</id>
<build>
<plugins>

View File

@ -0,0 +1,168 @@
/*
* 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.test.common;
import com.alibaba.nacos.Nacos;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.common.http.Callback;
import com.alibaba.nacos.common.http.HttpClientManager;
import com.alibaba.nacos.common.http.HttpRestResult;
import com.alibaba.nacos.common.http.client.NacosAsyncRestTemplate;
import com.alibaba.nacos.common.http.param.Header;
import com.alibaba.nacos.common.http.param.Query;
import com.alibaba.nacos.common.model.RestResult;
import org.junit.Assert;
import org.junit.Before;
import org.junit.FixMethodOrder;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.MethodSorters;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.web.server.LocalServerPort;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.HashMap;
import java.util.Map;
/**
* NacosAsyncRestTemplate_ITCase
*
* @author mai.jh
* @date 2020/5/29
*/
@SuppressWarnings("all")
@FixMethodOrder(MethodSorters.JVM)
@RunWith(SpringRunner.class)
@SpringBootTest(classes = Nacos.class, properties = {"server.servlet.context-path=/nacos"},
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class NacosAsyncRestTemplate_ITCase {
@LocalServerPort
private int port;
private NacosAsyncRestTemplate nacosRestTemplate = HttpClientManager.getNacosAsyncRestTemplate();
private final String CONFIG_INSTANCE_PATH = "/nacos/v1/ns";
private String IP = null;
@Before
public void init() throws NacosException {
IP = String.format("http://localhost:%d", port);
}
private class CallbackMap<T> implements Callback<T> {
private HttpRestResult<T> restResult;
private Throwable throwable;
@Override
public void onReceive(RestResult<T> result) {
restResult = (HttpRestResult<T>) result;
}
@Override
public void onError(Throwable throwable) {
throwable = throwable;
}
public HttpRestResult<T> getRestResult() {
return restResult;
}
public Throwable getThrowable() {
return throwable;
}
}
@Test
public void test_url_post_from() throws Exception{
String url = IP + CONFIG_INSTANCE_PATH + "/instance";
Map<String, String> param = new HashMap<>();
param.put("serviceName", "app-test");
param.put("port", "8080");
param.put("ip", "11.11.11.11");
CallbackMap<String> callbackMap = new CallbackMap<>();
nacosRestTemplate.postFrom(url, Header.newInstance(), Query.newInstance(), param, String.class, callbackMap);
Thread.sleep(2000);
HttpRestResult<String> restResult = callbackMap.getRestResult();
System.out.println(restResult.getData());
System.out.println(restResult.getHeader());
Assert.assertTrue(restResult.ok());
}
@Test
public void test_url_put_from() throws Exception{
String url = IP + CONFIG_INSTANCE_PATH + "/instance";
Map<String, String> param = new HashMap<>();
param.put("serviceName", "app-test-change");
param.put("port", "8080");
param.put("ip", "11.11.11.11");
CallbackMap<String> callbackMap = new CallbackMap<>();
nacosRestTemplate.putFrom(url, Header.newInstance(), Query.newInstance(), param, String.class, callbackMap);
Thread.sleep(2000);
HttpRestResult<String> restResult = callbackMap.getRestResult();
System.out.println(restResult.getData());
System.out.println(restResult.getHeader());
Assert.assertTrue(restResult.ok());
}
@Test
public void test_url_get() throws Exception {
String url = IP + CONFIG_INSTANCE_PATH + "/instance/list";
Query query = Query.newInstance().addParam("serviceName", "app-test");
CallbackMap<Map> callbackMap = new CallbackMap<>();
nacosRestTemplate.get(url, Header.newInstance(), query, Map.class, callbackMap);
Thread.sleep(2000);
HttpRestResult<Map> restResult = callbackMap.getRestResult();
System.out.println(restResult.getData());
System.out.println(restResult.getHeader());
Assert.assertTrue(restResult.ok());
Assert.assertEquals(restResult.getData().get("dom"), "app-test");
}
@Test
public void test_url_by_map() throws Exception{
String url = IP + CONFIG_INSTANCE_PATH + "/instance/list";
Map<String, String> param = new HashMap<>();
param.put("serviceName", "app-test");
CallbackMap<Map> callbackMap = new CallbackMap<>();
nacosRestTemplate.get(url, Header.newInstance(), param, Map.class, callbackMap);
Thread.sleep(2000);
HttpRestResult<Map> restResult = callbackMap.getRestResult();
System.out.println(restResult.getData());
System.out.println(restResult.getHeader());
Assert.assertTrue(restResult.ok());
Assert.assertEquals(restResult.getData().get("dom"), "app-test");
}
@Test
public void test_url_delete() throws Exception{
String url = IP + CONFIG_INSTANCE_PATH + "/instance";
Query query = Query.newInstance()
.addParam("ip", "11.11.11.11")
.addParam("port", "8080")
.addParam("serviceName", "app-test");
CallbackMap<String> callbackMap = new CallbackMap<>();
nacosRestTemplate.delete(url, Header.newInstance(), query, String.class, callbackMap);
Thread.sleep(2000);
HttpRestResult<String> restResult = callbackMap.getRestResult();
System.out.println(restResult.getData());
System.out.println(restResult.getHeader());
Assert.assertTrue(restResult.ok());
}
}

View File

@ -0,0 +1,133 @@
/*
* 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.test.common;
import com.alibaba.nacos.Nacos;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.common.http.HttpClientManager;
import com.alibaba.nacos.common.http.HttpRestResult;
import com.alibaba.nacos.common.http.client.NacosRestTemplate;
import com.alibaba.nacos.common.http.param.Header;
import com.alibaba.nacos.common.http.param.Query;
import com.alibaba.nacos.common.model.RestResult;
import org.junit.Assert;
import org.junit.Before;
import org.junit.FixMethodOrder;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.MethodSorters;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.web.server.LocalServerPort;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.HashMap;
import java.util.Map;
/**
* NacosRestTemplate_ITCase
*
* @author mai.jh
* @date 2020/5/30
*/
@RunWith(SpringRunner.class)
@SpringBootTest(classes = Nacos.class, properties = {"server.servlet.context-path=/nacos"},
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@FixMethodOrder(MethodSorters.JVM)
public class NacosRestTemplate_ITCase {
@LocalServerPort
private int port;
private NacosRestTemplate nacosRestTemplate = HttpClientManager.getNacosRestTemplate();
private final String INSTANCE_PATH = "/nacos/v1/ns";
private final String CONFIG_PATH = "/nacos/v1/cs";
private String IP = null;
@Before
public void init() throws NacosException {
IP = String.format("http://localhost:%d", port);
}
@Test
public void test_url_get_return_restResult() throws Exception{
String url = IP + CONFIG_PATH + "/configs";
Query query = Query.newInstance().addParam("beta", true).addParam("dataId","test-1").addParam("group", "DEFAULT_GROUP");
HttpRestResult<String> restResult = nacosRestTemplate.get(url, Header.newInstance(), query, RestResult.class);
Assert.assertTrue(restResult.ok());
System.out.println(restResult.getData());
System.out.println(restResult.getHeader());
}
@Test
public void test_url_post_from() throws Exception{
String url = IP + INSTANCE_PATH + "/instance";
Map<String, String> param = new HashMap<>();
param.put("serviceName", "app-test");
param.put("port", "8080");
param.put("ip", "11.11.11.11");
HttpRestResult<String> restResult = nacosRestTemplate.postFrom(url, Header.newInstance(), Query.newInstance(), param, String.class);
Assert.assertTrue(restResult.ok());
System.out.println(restResult.getData());
}
@Test
public void test_url_put_from() throws Exception{
String url = IP + INSTANCE_PATH + "/instance";
Map<String, String> param = new HashMap<>();
param.put("serviceName", "app-test-change");
param.put("port", "8080");
param.put("ip", "11.11.11.11");
HttpRestResult<String> restResult = nacosRestTemplate.putFrom(url, Header.newInstance(), Query.newInstance(), param, String.class);
Assert.assertTrue(restResult.ok());
System.out.println(restResult.getData());
}
@Test
public void test_url_get() throws Exception {
String url = IP + INSTANCE_PATH + "/instance/list";
Query query = Query.newInstance().addParam("serviceName", "app-test");
HttpRestResult<Map> restResult = nacosRestTemplate.get(url, Header.newInstance(), query, Map.class);
Assert.assertTrue(restResult.ok());
Assert.assertEquals(restResult.getData().get("dom"), "app-test");
System.out.println(restResult.getData());
}
@Test
public void test_url_get_by_map() throws Exception {
String url = IP + INSTANCE_PATH + "/instance/list";
Map<String, String> param = new HashMap<>();
param.put("serviceName", "app-test");
HttpRestResult<Map> restResult = nacosRestTemplate.get(url, Header.newInstance(), param, Map.class);
Assert.assertTrue(restResult.ok());
Assert.assertEquals(restResult.getData().get("dom"), "app-test");
System.out.println(restResult.getData());
}
@Test
public void test_url_delete() throws Exception{
String url = IP + INSTANCE_PATH + "/instance";
Query query = Query.newInstance()
.addParam("ip", "11.11.11.11")
.addParam("port", "8080")
.addParam("serviceName", "app-test");
HttpRestResult<String> restResult = nacosRestTemplate.delete(url, Header.newInstance(), query, String.class);
Assert.assertTrue(restResult.ok());
System.out.println(restResult);
}
}

View File

@ -50,9 +50,9 @@ import java.util.concurrent.atomic.AtomicInteger;
* @author xiaochun.xxc
*/
@RunWith(SpringRunner.class)
@SpringBootTest(classes = Nacos.class, properties = {"server.servlet.context-path=/nacos"},
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class ConfigAPI_ITCase {
@SpringBootTest(classes = Nacos.class, properties = {"server.servlet.context-path=/nacos", "server.port=7001"},
webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
public class ConfigAPI_CITCase {
public static final long TIME_OUT = 5000;
static ConfigService iconfig = null;
@ -72,7 +72,6 @@ public class ConfigAPI_ITCase {
properties.put(PropertyKeyConst.SERVER_ADDR, "127.0.0.1"+":"+port);
properties.put(PropertyKeyConst.CONTEXT_PATH, "/nacos");
iconfig = NacosFactory.createConfigService(properties);
agent = new MetricsHttpAgent(new ServerHttpAgent(properties));
agent.start();
}
@ -85,6 +84,7 @@ public class ConfigAPI_ITCase {
result = agent.httpDelete(CONFIG_CONTROLLER_PATH + "/", null, params, agent.getEncode(), TIME_OUT);
Assert.assertEquals(HttpURLConnection.HTTP_OK, result.code);
Assert.assertTrue(JacksonUtils.toObj(result.content).get("data").booleanValue());
Assert.assertTrue(JacksonUtils.toObj(result.content).get("data").booleanValue());
} catch (Exception e) {
e.printStackTrace();
Assert.fail();
@ -378,7 +378,7 @@ public class ConfigAPI_ITCase {
* @author xiaochun.xxc
* @since 3.6.8
*/
@Test(timeout = 5 * TIME_OUT)
@Test(timeout = Constants.CONFIG_LONG_POLL_TIMEOUT << 2)
public void nacos_addListener_3() throws InterruptedException, NacosException {
final AtomicInteger count = new AtomicInteger(0);
final String dataId = "nacos_addListener_3";
@ -386,7 +386,6 @@ public class ConfigAPI_ITCase {
final String content = "test-abc";
final String newContent = "nacos_addListener_3";
boolean result = iconfig.publishConfig(dataId, group, content);
Thread.sleep(TIME_OUT);
Assert.assertTrue(result);
Listener ml = new AbstractListener() {
@ -399,9 +398,6 @@ public class ConfigAPI_ITCase {
iconfig.addListener(dataId, group, ml);
result = iconfig.publishConfig(dataId, group, newContent);
Assert.assertTrue(result);
while (count.get() == 0) {
Thread.sleep(2000);
}
// Get enough sleep to ensure that the monitor is triggered only once
// during the two long training sessions
ThreadUtils.sleep(Constants.CONFIG_LONG_POLL_TIMEOUT << 1);

View File

@ -19,6 +19,7 @@ package com.alibaba.nacos.test.config;
import com.alibaba.nacos.Nacos;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.common.utils.JacksonUtils;
import com.alibaba.nacos.common.utils.ThreadUtils;
import com.alibaba.nacos.test.base.Params;
import org.junit.Assert;
import org.junit.Before;
@ -41,9 +42,9 @@ import org.springframework.web.util.UriComponentsBuilder;
* @date 2019-07-03
**/
@RunWith(SpringRunner.class)
@SpringBootTest(classes = Nacos.class, properties = {"server.servlet.context-path=/nacos"},
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class ConfigBeta_ITCase {
@SpringBootTest(classes = Nacos.class, properties = {"server.servlet.context-path=/nacos", "server.port=7002"},
webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
public class ConfigBeta_CITCase {
@LocalServerPort
private int port;
@ -178,6 +179,8 @@ public class ConfigBeta_ITCase {
Assert.assertTrue(response.getStatusCode().is2xxSuccessful());
Assert.assertEquals("true", response.getBody());
ThreadUtils.sleep(10_000L);
ResponseEntity<String> response1 = request(CONFIG_CONTROLLER_PATH + "/configs?beta=false",
Params.newParams()
.appendParam("dataId", dataId)

View File

@ -41,9 +41,9 @@ import java.util.*;
* @date 2019/5/23 15:26
*/
@RunWith(SpringRunner.class)
@SpringBootTest(classes = Nacos.class, properties = {"server.servlet.context-path=/nacos"},
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class ConfigExportAndImportAPI_ITCase {
@SpringBootTest(classes = Nacos.class, properties = {"server.servlet.context-path=/nacos", "server.port=7003"},
webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
public class ConfigExportAndImportAPI_CITCase {
private static final long TIME_OUT = 2000;
private static final String CONFIG_CONTROLLER_PATH = "/v1/cs/configs";
@ -90,7 +90,7 @@ public class ConfigExportAndImportAPI_ITCase {
}
@After
public void cleanup(){
public void cleanup() throws Exception{
HttpSimpleClient.HttpResult result;
try {
List<String> params2 = Arrays.asList("dataId", "testNoAppname1.yml", "group", "EXPORT_IMPORT_TEST_GROUP", "beta", "false");
@ -119,9 +119,10 @@ public class ConfigExportAndImportAPI_ITCase {
} catch (Exception e) {
Assert.fail();
}
agent.shutdown();
}
@Test(timeout = 3*TIME_OUT)
@Test()
public void testExportByIds(){
String getDataUrl = "?search=accurate&dataId=&group=&appName=&config_tags=&pageNo=1&pageSize=10&tenant=&namespaceId=";
String queryResult = httpClient.get(SERVER_ADDR + CONFIG_CONTROLLER_PATH + getDataUrl, null);
@ -129,8 +130,9 @@ public class ConfigExportAndImportAPI_ITCase {
JsonNode resultConfigs = resultObj.get("pageItems");
JsonNode config1 = resultConfigs.get(0);
JsonNode config2 = resultConfigs.get(1);
String exportByIdsUrl = "?export=true&tenant=&group=&appName=&ids=" + config1.get("id").longValue()
+ "," + config2.get("id").longValue();
String id1 = config1.get("id").asText();
String id2 = config2.get("id").asText();
String exportByIdsUrl = "?export=true&tenant=&group=&appName=&ids=" + id1 + "," + id2;
System.out.println(exportByIdsUrl);
byte[] zipData = httpClient.download(SERVER_ADDR + CONFIG_CONTROLLER_PATH + exportByIdsUrl, null);
ZipUtils.UnZipResult unZiped = ZipUtils.unzip(zipData);

View File

@ -24,6 +24,7 @@ import com.alibaba.nacos.api.config.ConfigService;
import com.alibaba.nacos.api.config.PropertyChangeType;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.client.config.listener.impl.AbstractConfigChangeListener;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
@ -37,9 +38,9 @@ import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@RunWith(SpringRunner.class)
@SpringBootTest(classes = Nacos.class, properties = {"server.servlet.context-path=/nacos"},
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class ConfigLongPollReturnChanges_ITCase {
@SpringBootTest(classes = Nacos.class, properties = {"server.servlet.context-path=/nacos", "server.port=7005"},
webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
public class ConfigLongPollReturnChanges_CITCase {
@LocalServerPort
private int port;
@ -56,6 +57,14 @@ public class ConfigLongPollReturnChanges_ITCase {
configService = NacosFactory.createConfigService(properties);
}
@After
public void destroy(){
try {
configService.shutDown();
}catch (NacosException ex) {
}
}
@Test
public void testAdd() throws InterruptedException, NacosException {
CountDownLatch latch = new CountDownLatch(1);

View File

@ -22,7 +22,7 @@ import com.alibaba.nacos.api.PropertyKeyConst;
import com.alibaba.nacos.api.config.ConfigService;
import com.alibaba.nacos.api.config.listener.Listener;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.core.utils.ApplicationUtils;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@ -39,9 +39,9 @@ import java.util.concurrent.TimeUnit;
* @date 2019-06-07 22:24
**/
@RunWith(SpringRunner.class)
@SpringBootTest(classes = Nacos.class, properties = {"server.servlet.context-path=/nacos"},
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class ConfigLongPoll_ITCase {
@SpringBootTest(classes = Nacos.class, properties = {"server.servlet.context-path=/nacos", "server.port=7004"},
webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
public class ConfigLongPoll_CITCase {
@LocalServerPort
private int port;
@ -58,6 +58,14 @@ public class ConfigLongPoll_ITCase {
configService = NacosFactory.createConfigService(properties);
}
@After
public void destroy(){
try {
configService.shutDown();
}catch (NacosException ex) {
}
}
@Test
public void test() throws InterruptedException, NacosException {

View File

@ -29,7 +29,7 @@ import java.util.concurrent.Executors;
/**
* @author <a href="mailto:liaochuntao@live.com">liaochuntao</a>
*/
public class EmbeddedStorageContextUtils_ITCase {
public class EmbeddedStorageContextUtils_CITCase {
@Test
public void test_multi_thread_sql_contexts() throws Exception {

View File

@ -157,7 +157,14 @@ public class BaseClusterTest extends HttpClient4Test {
try {
System.out.println("start close : " + context);
context.close();
} catch (Exception ignore) {
iconfig7.shutDown();
iconfig8.shutDown();
iconfig9.shutDown();
inaming7.shutDown();
inaming8.shutDown();
inaming9.shutDown();
} catch (Exception ignore) {
} finally {
System.out.println("finished close : " + context);
latch.countDown();

View File

@ -23,7 +23,6 @@ import com.alibaba.nacos.api.config.ConfigChangeItem;
import com.alibaba.nacos.api.config.ConfigService;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.client.config.listener.impl.AbstractConfigChangeListener;
import com.alibaba.nacos.core.utils.ApplicationUtils;
import org.apache.http.HttpStatus;
import org.junit.After;
import org.junit.Assert;
@ -65,8 +64,12 @@ public class ConfigAuth_ITCase extends AuthBase {
}
@After
public void destroy() {
super.destroy();
public void destroy(){
try {
iconfig.shutDown();
}catch (NacosException ex) {
}
}

View File

@ -81,6 +81,7 @@ public class NamingAuth_ITCase extends AuthBase {
} catch (NacosException ne) {
Assert.assertEquals(HttpStatus.SC_FORBIDDEN, ne.getErrCode());
}
namingService.shutDown();
}
@Test
@ -97,6 +98,8 @@ public class NamingAuth_ITCase extends AuthBase {
List<Instance> list = namingService.getAllInstances("test.1");
Assert.assertEquals(1, list.size());
namingService1.shutDown();
namingService.shutDown();
}
@Test
@ -111,6 +114,7 @@ public class NamingAuth_ITCase extends AuthBase {
TimeUnit.SECONDS.sleep(5L);
namingService.deregisterInstance("test.1", "1.2.3.4", 80);
namingService.shutDown();
}
@Test
@ -126,7 +130,7 @@ public class NamingAuth_ITCase extends AuthBase {
List<Instance> list = namingService.getAllInstances("test.1");
Assert.assertEquals(0, list.size());
namingService.shutDown();
}
@Test
@ -142,6 +146,7 @@ public class NamingAuth_ITCase extends AuthBase {
List<Instance> list = namingService.getAllInstances("test.1");
Assert.assertEquals(1, list.size());
namingService.shutDown();
}
}

View File

@ -0,0 +1,114 @@
/*
* 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.test.naming;
import com.alibaba.nacos.api.PropertyKeyConst;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.naming.NamingFactory;
import com.alibaba.nacos.api.naming.NamingService;
import com.alibaba.nacos.api.naming.utils.NamingUtils;
import com.alibaba.nacos.naming.NamingApp;
import com.alibaba.nacos.naming.cluster.transport.Serializer;
import com.alibaba.nacos.naming.consistency.Datum;
import com.alibaba.nacos.naming.consistency.KeyBuilder;
import com.alibaba.nacos.naming.consistency.ephemeral.distro.DataStore;
import com.alibaba.nacos.naming.core.Instance;
import com.alibaba.nacos.naming.core.Instances;
import com.alibaba.nacos.naming.misc.NamingProxy;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.web.server.LocalServerPort;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.TimeUnit;
@RunWith(SpringRunner.class)
@SpringBootTest(classes = NamingApp.class, properties = {"server.servlet.context-path=/nacos"},
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class NamingProxy_ITCase {
@LocalServerPort
private int port;
@Autowired
private Serializer serializer;
private final DataStore dataStore = new DataStore();
private NamingService namingService;
private final String namespaceId = "dev";
private final String serviceName = "biz";
private final String groupName = "DEFAULT_GROUP";
@Before
public void init() throws NacosException {
Properties properties = new Properties();
properties.put(PropertyKeyConst.NAMESPACE, namespaceId);
properties.put(PropertyKeyConst.SERVER_ADDR, "localhost:" + port);
namingService = NamingFactory.createNamingService(properties);
}
@Test
public void testSyncData() throws NacosException, InterruptedException {
// write data to DataStore
String groupedName = NamingUtils.getGroupedName(serviceName, groupName);
Instances instances = new Instances();
Instance instance = new Instance();
instance.setIp("1.2.3.4");
instance.setPort(8888);
instance.setEphemeral(true);
instance.setServiceName(groupedName);
List<Instance> instanceList = new ArrayList<Instance>(1);
instanceList.add(instance);
instances.setInstanceList(instanceList);
String key = KeyBuilder.buildInstanceListKey(namespaceId, instance.getServiceName(), true);
Datum<Instances> datum = new Datum<>();
datum.value = instances;
datum.key = key;
datum.timestamp.incrementAndGet();
this.dataStore.put(key, datum);
// sync data to server
Map<String, Datum> dataMap = dataStore.getDataMap();
byte[] content = serializer.serialize(dataMap);
boolean result = NamingProxy.syncData(content, "localhost:" + port);
if (!result) {
Assert.fail("NamingProxy.syncData error");
}
// query instance by api
List<com.alibaba.nacos.api.naming.pojo.Instance> allInstances = namingService.getAllInstances(serviceName, false);
for (int i = 0; i < 3 && allInstances.isEmpty(); i++) {
// wait for async op
TimeUnit.SECONDS.sleep(100);
allInstances = namingService.getAllInstances(serviceName, false);
}
if (allInstances.isEmpty()) {
Assert.fail("instance is empty");
}
com.alibaba.nacos.api.naming.pojo.Instance dst = allInstances.get(0);
Assert.assertEquals(instance.getIp(), dst.getIp());
Assert.assertEquals(instance.getPort(), dst.getPort());
Assert.assertEquals(instance.getServiceName(), dst.getServiceName());
}
}