Merge branch 'upstream-develop' into feature_support_grpc_core
# Conflicts: # client/src/main/java/com/alibaba/nacos/client/config/NacosConfigService.java # client/src/main/java/com/alibaba/nacos/client/config/http/HttpAgent.java # client/src/main/java/com/alibaba/nacos/client/config/http/MetricsHttpAgent.java # client/src/main/java/com/alibaba/nacos/client/config/impl/ClientWorker.java # config/src/main/java/com/alibaba/nacos/config/server/service/LongPollingService.java
This commit is contained in:
commit
79c8521bde
@ -154,4 +154,10 @@ public class NacosException extends Exception {
|
||||
public static final int OVER_THRESHOLD = 503;
|
||||
|
||||
public static final int RESOURCE_NOT_FOUND = -404;
|
||||
|
||||
/**
|
||||
* http client error code,
|
||||
* ome exceptions that occurred when the use the Nacos RestTemplate and Nacos AsyncRestTemplate.
|
||||
*/
|
||||
public static final int HTTP_CLIENT_ERROR_CODE = -500;
|
||||
}
|
||||
|
@ -30,21 +30,20 @@ import com.alibaba.nacos.client.config.http.HttpAgent;
|
||||
import com.alibaba.nacos.client.config.http.MetricsHttpAgent;
|
||||
import com.alibaba.nacos.client.config.http.ServerHttpAgent;
|
||||
import com.alibaba.nacos.client.config.impl.ClientWorker;
|
||||
import com.alibaba.nacos.client.config.impl.HttpSimpleClient.HttpResult;
|
||||
import com.alibaba.nacos.client.config.impl.LocalConfigInfoProcessor;
|
||||
import com.alibaba.nacos.client.config.utils.ContentUtils;
|
||||
import com.alibaba.nacos.client.config.utils.ParamUtils;
|
||||
import com.alibaba.nacos.client.utils.LogUtils;
|
||||
import com.alibaba.nacos.client.utils.ParamUtil;
|
||||
import com.alibaba.nacos.client.utils.ValidatorUtils;
|
||||
import com.alibaba.nacos.common.http.HttpRestResult;
|
||||
import com.alibaba.nacos.common.utils.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
@ -181,42 +180,39 @@ public class NacosConfigService implements ConfigService {
|
||||
group = null2defaultGroup(group);
|
||||
ParamUtils.checkKeyParam(dataId, group);
|
||||
String url = Constants.CONFIG_CONTROLLER_PATH;
|
||||
List<String> params = new ArrayList<String>();
|
||||
params.add("dataId");
|
||||
params.add(dataId);
|
||||
params.add("group");
|
||||
params.add(group);
|
||||
Map<String, String> params = new HashMap<String, String>(4);
|
||||
params.put("dataId", dataId);
|
||||
params.put("group", group);
|
||||
|
||||
if (StringUtils.isNotEmpty(tenant)) {
|
||||
params.add("tenant");
|
||||
params.add(tenant);
|
||||
params.put("tenant", tenant);
|
||||
}
|
||||
if (StringUtils.isNotEmpty(tag)) {
|
||||
params.add("tag");
|
||||
params.add(tag);
|
||||
params.put("tag", tag);
|
||||
}
|
||||
|
||||
|
||||
if (!ParamUtils.useHttpSwitch()) {
|
||||
return removeConfigInRpc(tenant, dataId, group, tag);
|
||||
}
|
||||
|
||||
HttpResult result = null;
|
||||
HttpRestResult<String> result = null;
|
||||
try {
|
||||
result = agent.httpDelete(url, null, params, encode, POST_TIMEOUT);
|
||||
} catch (IOException ioe) {
|
||||
LOGGER.warn("[remove] error, " + dataId + ", " + group + ", " + tenant + ", msg: " + ioe.toString());
|
||||
} catch (Exception ex) {
|
||||
LOGGER.warn("[remove] error, " + dataId + ", " + group + ", " + tenant + ", msg: " + ex.toString());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (HttpURLConnection.HTTP_OK == result.code) {
|
||||
if (result.ok()) {
|
||||
LOGGER.info("[{}] [remove] ok, dataId={}, group={}, tenant={}", agent.getName(), dataId, group, tenant);
|
||||
return true;
|
||||
} else if (HttpURLConnection.HTTP_FORBIDDEN == result.code) {
|
||||
} else if (HttpURLConnection.HTTP_FORBIDDEN == result.getCode()) {
|
||||
LOGGER.warn("[{}] [remove] error, dataId={}, group={}, tenant={}, code={}, msg={}", agent.getName(), dataId,
|
||||
group, tenant, result.code, result.content);
|
||||
throw new NacosException(result.code, result.content);
|
||||
group, tenant, result.getCode(), result.getMessage());
|
||||
throw new NacosException(result.getCode(), result.getMessage());
|
||||
} else {
|
||||
LOGGER.warn("[{}] [remove] error, dataId={}, group={}, tenant={}, code={}, msg={}", agent.getName(), dataId,
|
||||
group, tenant, result.code, result.content);
|
||||
group, tenant, result.getCode(), result.getMessage());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -248,56 +244,48 @@ public class NacosConfigService implements ConfigService {
|
||||
content = cr.getContent();
|
||||
|
||||
String url = Constants.CONFIG_CONTROLLER_PATH;
|
||||
List<String> params = new ArrayList<String>();
|
||||
params.add("dataId");
|
||||
params.add(dataId);
|
||||
params.add("group");
|
||||
params.add(group);
|
||||
params.add("content");
|
||||
params.add(content);
|
||||
Map<String, String> params = new HashMap<String, String>(6);
|
||||
params.put("dataId", dataId);
|
||||
params.put("group", group);
|
||||
params.put("content", content);
|
||||
if (StringUtils.isNotEmpty(tenant)) {
|
||||
params.add("tenant");
|
||||
params.add(tenant);
|
||||
params.put("tenant", tenant);
|
||||
}
|
||||
if (StringUtils.isNotEmpty(appName)) {
|
||||
params.add("appName");
|
||||
params.add(appName);
|
||||
params.put("appName", appName);
|
||||
}
|
||||
if (StringUtils.isNotEmpty(tag)) {
|
||||
params.add("tag");
|
||||
params.add(tag);
|
||||
params.put("tag", tag);
|
||||
}
|
||||
|
||||
List<String> headers = new ArrayList<String>();
|
||||
Map<String, String> headers = new HashMap<String, String>(1);
|
||||
if (StringUtils.isNotEmpty(betaIps)) {
|
||||
headers.add("betaIps");
|
||||
headers.add(betaIps);
|
||||
headers.put("betaIps", betaIps);
|
||||
}
|
||||
|
||||
if (!ParamUtils.useHttpSwitch()) {
|
||||
return publishConfigWithRpc(dataId, group, tenant, content);
|
||||
}
|
||||
|
||||
HttpResult result = null;
|
||||
HttpRestResult<String> result = null;
|
||||
try {
|
||||
result = agent.httpPost(url, headers, params, encode, POST_TIMEOUT);
|
||||
} catch (IOException ioe) {
|
||||
} catch (Exception ex) {
|
||||
LOGGER.warn("[{}] [publish-single] exception, dataId={}, group={}, msg={}", agent.getName(), dataId, group,
|
||||
ioe.toString());
|
||||
ex.toString());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (HttpURLConnection.HTTP_OK == result.code) {
|
||||
if (result.ok()) {
|
||||
LOGGER.info("[{}] [publish-single] ok, dataId={}, group={}, tenant={}, config={}", agent.getName(), dataId,
|
||||
group, tenant, ContentUtils.truncateContent(content));
|
||||
return true;
|
||||
} else if (HttpURLConnection.HTTP_FORBIDDEN == result.code) {
|
||||
} else if (HttpURLConnection.HTTP_FORBIDDEN == result.getCode()) {
|
||||
LOGGER.warn("[{}] [publish-single] error, dataId={}, group={}, tenant={}, code={}, msg={}", agent.getName(),
|
||||
dataId, group, tenant, result.code, result.content);
|
||||
throw new NacosException(result.code, result.content);
|
||||
dataId, group, tenant, result.getCode(), result.getMessage());
|
||||
throw new NacosException(result.getCode(), result.getMessage());
|
||||
} else {
|
||||
LOGGER.warn("[{}] [publish-single] error, dataId={}, group={}, tenant={}, code={}, msg={}", agent.getName(),
|
||||
dataId, group, tenant, result.code, result.content);
|
||||
dataId, group, tenant, result.getCode(), result.getMessage());
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -17,12 +17,11 @@
|
||||
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.http.HttpRestResult;
|
||||
import com.alibaba.nacos.client.config.impl.ServerListManager;
|
||||
import com.alibaba.nacos.common.lifecycle.Closeable;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* HttpAgent.
|
||||
@ -54,11 +53,11 @@ public interface HttpAgent extends Closeable {
|
||||
* @param encoding http encode
|
||||
* @param readTimeoutMs http timeout
|
||||
* @return HttpResult http response
|
||||
* @throws IOException If an input or output exception occurred
|
||||
* @throws Exception If an input or output exception occurred
|
||||
*/
|
||||
|
||||
HttpResult httpGet(String path, List<String> headers, List<String> paramValues, String encoding, long readTimeoutMs)
|
||||
throws IOException;
|
||||
HttpRestResult<String> httpGet(String path, Map<String, String> headers, Map<String, String> paramValues,
|
||||
String encoding, long readTimeoutMs) throws Exception;
|
||||
|
||||
/**
|
||||
* invoke http post method.
|
||||
@ -69,10 +68,10 @@ public interface HttpAgent extends Closeable {
|
||||
* @param encoding http encode
|
||||
* @param readTimeoutMs http timeout
|
||||
* @return HttpResult http response
|
||||
* @throws IOException If an input or output exception occurred
|
||||
* @throws Exception If an input or output exception occurred
|
||||
*/
|
||||
HttpResult httpPost(String path, List<String> headers, List<String> paramValues, String encoding,
|
||||
long readTimeoutMs) throws IOException;
|
||||
HttpRestResult<String> httpPost(String path, Map<String, String> headers, Map<String, String> paramValues,
|
||||
String encoding, long readTimeoutMs) throws Exception;
|
||||
|
||||
/**
|
||||
* invoke http delete method.
|
||||
@ -83,10 +82,10 @@ public interface HttpAgent extends Closeable {
|
||||
* @param encoding http encode
|
||||
* @param readTimeoutMs http timeout
|
||||
* @return HttpResult http response
|
||||
* @throws IOException If an input or output exception occurred
|
||||
* @throws Exception If an input or output exception occurred
|
||||
*/
|
||||
HttpResult httpDelete(String path, List<String> headers, List<String> paramValues, String encoding,
|
||||
long readTimeoutMs) throws IOException;
|
||||
HttpRestResult<String> httpDelete(String path, Map<String, String> headers, Map<String, String> paramValues,
|
||||
String encoding, long readTimeoutMs) throws Exception;
|
||||
|
||||
/**
|
||||
* get name.
|
||||
|
@ -17,13 +17,13 @@
|
||||
package com.alibaba.nacos.client.config.http;
|
||||
|
||||
import com.alibaba.nacos.api.exception.NacosException;
|
||||
import com.alibaba.nacos.client.config.impl.HttpSimpleClient.HttpResult;
|
||||
import com.alibaba.nacos.client.config.impl.ServerListManager;
|
||||
import com.alibaba.nacos.client.monitor.MetricsMonitor;
|
||||
import com.alibaba.nacos.common.http.HttpRestResult;
|
||||
import io.prometheus.client.Histogram;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* MetricsHttpAgent.
|
||||
@ -49,12 +49,12 @@ public class MetricsHttpAgent implements HttpAgent {
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpResult httpGet(String path, List<String> headers, List<String> paramValues, String encoding,
|
||||
long readTimeoutMs) throws IOException {
|
||||
public HttpRestResult<String> httpGet(String path, Map<String, String> headers, Map<String, String> paramValues,
|
||||
String encode, long readTimeoutMs) throws Exception {
|
||||
Histogram.Timer timer = MetricsMonitor.getConfigRequestMonitor("GET", path, "NA");
|
||||
HttpResult result;
|
||||
HttpRestResult<String> result;
|
||||
try {
|
||||
result = httpAgent.httpGet(path, headers, paramValues, encoding, readTimeoutMs);
|
||||
result = httpAgent.httpGet(path, headers, paramValues, encode, readTimeoutMs);
|
||||
} catch (IOException e) {
|
||||
throw e;
|
||||
} finally {
|
||||
@ -66,12 +66,12 @@ public class MetricsHttpAgent implements HttpAgent {
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpResult httpPost(String path, List<String> headers, List<String> paramValues, String encoding,
|
||||
long readTimeoutMs) throws IOException {
|
||||
public HttpRestResult<String> httpPost(String path, Map<String, String> headers, Map<String, String> paramValues,
|
||||
String encode, long readTimeoutMs) throws Exception {
|
||||
Histogram.Timer timer = MetricsMonitor.getConfigRequestMonitor("POST", path, "NA");
|
||||
HttpResult result;
|
||||
HttpRestResult<String> result;
|
||||
try {
|
||||
result = httpAgent.httpPost(path, headers, paramValues, encoding, readTimeoutMs);
|
||||
result = httpAgent.httpPost(path, headers, paramValues, encode, readTimeoutMs);
|
||||
} catch (IOException e) {
|
||||
throw e;
|
||||
} finally {
|
||||
@ -83,12 +83,12 @@ public class MetricsHttpAgent implements HttpAgent {
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpResult httpDelete(String path, List<String> headers, List<String> paramValues, String encoding,
|
||||
long readTimeoutMs) throws IOException {
|
||||
public HttpRestResult<String> httpDelete(String path, Map<String, String> headers, Map<String, String> paramValues,
|
||||
String encode, long readTimeoutMs) throws Exception {
|
||||
Histogram.Timer timer = MetricsMonitor.getConfigRequestMonitor("DELETE", path, "NA");
|
||||
HttpResult result;
|
||||
HttpRestResult<String> result;
|
||||
try {
|
||||
result = httpAgent.httpDelete(path, headers, paramValues, encoding, readTimeoutMs);
|
||||
result = httpAgent.httpDelete(path, headers, paramValues, encode, readTimeoutMs);
|
||||
} catch (IOException e) {
|
||||
|
||||
throw e;
|
||||
|
@ -19,8 +19,7 @@ package com.alibaba.nacos.client.config.http;
|
||||
import com.alibaba.nacos.api.PropertyKeyConst;
|
||||
import com.alibaba.nacos.api.common.Constants;
|
||||
import com.alibaba.nacos.api.exception.NacosException;
|
||||
import com.alibaba.nacos.client.config.impl.HttpSimpleClient;
|
||||
import com.alibaba.nacos.client.config.impl.HttpSimpleClient.HttpResult;
|
||||
import com.alibaba.nacos.client.config.impl.ConfigHttpClientManager;
|
||||
import com.alibaba.nacos.client.config.impl.ServerListManager;
|
||||
import com.alibaba.nacos.client.config.impl.SpasAdapter;
|
||||
import com.alibaba.nacos.client.identify.StsConfig;
|
||||
@ -28,29 +27,36 @@ import com.alibaba.nacos.client.security.SecurityProxy;
|
||||
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.constant.HttpHeaderConsts;
|
||||
import com.alibaba.nacos.common.http.HttpClientConfig;
|
||||
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.utils.ConvertUtils;
|
||||
import com.alibaba.nacos.common.utils.IoUtils;
|
||||
import com.alibaba.nacos.common.utils.ExceptionUtil;
|
||||
import com.alibaba.nacos.common.utils.JacksonUtils;
|
||||
import com.alibaba.nacos.common.utils.MD5Utils;
|
||||
import com.alibaba.nacos.common.utils.StringUtils;
|
||||
import com.alibaba.nacos.common.utils.ThreadUtils;
|
||||
import com.alibaba.nacos.common.utils.UuidUtils;
|
||||
import com.alibaba.nacos.common.utils.VersionUtils;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.ConnectException;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ScheduledThreadPoolExecutor;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.ScheduledThreadPoolExecutor;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
/**
|
||||
* Server Agent.
|
||||
@ -61,6 +67,9 @@ public class ServerHttpAgent implements HttpAgent {
|
||||
|
||||
private static final Logger LOGGER = LogUtils.logger(ServerHttpAgent.class);
|
||||
|
||||
private static final NacosRestTemplate NACOS_RESTTEMPLATE = ConfigHttpClientManager.getInstance()
|
||||
.getNacosRestTemplate();
|
||||
|
||||
private SecurityProxy securityProxy;
|
||||
|
||||
private String namespaceId;
|
||||
@ -69,40 +78,28 @@ public class ServerHttpAgent implements HttpAgent {
|
||||
|
||||
private ScheduledExecutorService executorService;
|
||||
|
||||
/**
|
||||
* Invoke http get method.
|
||||
*
|
||||
* @param path 相对于web应用根,以/开头
|
||||
* @param headers headers
|
||||
* @param paramValues parameters
|
||||
* @param encoding encoding
|
||||
* @param readTimeoutMs time out milliseconds
|
||||
* @return http result
|
||||
* @throws IOException io exception
|
||||
*/
|
||||
@Override
|
||||
public HttpResult httpGet(String path, List<String> headers, List<String> paramValues, String encoding,
|
||||
long readTimeoutMs) throws IOException {
|
||||
public HttpRestResult<String> httpGet(String path, Map<String, String> headers, Map<String, String> paramValues,
|
||||
String encode, long readTimeoutMs) throws Exception {
|
||||
final long endTime = System.currentTimeMillis() + readTimeoutMs;
|
||||
final boolean isSsl = false;
|
||||
injectSecurityInfo(paramValues);
|
||||
String currentServerAddr = serverListMgr.getCurrentServerAddr();
|
||||
int maxRetry = this.maxRetry;
|
||||
|
||||
HttpClientConfig httpConfig = HttpClientConfig.builder()
|
||||
.setReadTimeOutMillis(Long.valueOf(readTimeoutMs).intValue())
|
||||
.setConTimeOutMillis(ConfigHttpClientManager.getInstance().getConnectTimeoutOrDefault(100)).build();
|
||||
do {
|
||||
try {
|
||||
List<String> newHeaders = getSpasHeaders(paramValues);
|
||||
Header newHeaders = getSpasHeaders(paramValues, encode);
|
||||
if (headers != null) {
|
||||
newHeaders.addAll(headers);
|
||||
}
|
||||
HttpResult result = HttpSimpleClient
|
||||
.httpGet(getUrl(currentServerAddr, path), newHeaders, paramValues, encoding, readTimeoutMs,
|
||||
isSsl);
|
||||
if (result.code == HttpURLConnection.HTTP_INTERNAL_ERROR
|
||||
|| result.code == HttpURLConnection.HTTP_BAD_GATEWAY
|
||||
|| result.code == HttpURLConnection.HTTP_UNAVAILABLE) {
|
||||
|
||||
HttpRestResult<String> result = NACOS_RESTTEMPLATE
|
||||
.get(getUrl(currentServerAddr, path), httpConfig, newHeaders, paramValues, String.class);
|
||||
if (isFail(result)) {
|
||||
LOGGER.error("[NACOS ConnectException] currentServerAddr: {}, httpCode: {}",
|
||||
serverListMgr.getCurrentServerAddr(), result.code);
|
||||
serverListMgr.getCurrentServerAddr(), result.getCode());
|
||||
} else {
|
||||
// Update the currently available server addr
|
||||
serverListMgr.updateCurrentServerAddr(currentServerAddr);
|
||||
@ -114,10 +111,10 @@ public class ServerHttpAgent implements HttpAgent {
|
||||
} catch (SocketTimeoutException socketTimeoutException) {
|
||||
LOGGER.error("[NACOS SocketTimeoutException httpGet] currentServerAddr:{}, err : {}",
|
||||
serverListMgr.getCurrentServerAddr(), socketTimeoutException.getMessage());
|
||||
} catch (IOException ioException) {
|
||||
LOGGER.error("[NACOS IOException httpGet] currentServerAddr: " + serverListMgr.getCurrentServerAddr(),
|
||||
ioException);
|
||||
throw ioException;
|
||||
} catch (Exception ex) {
|
||||
LOGGER.error("[NACOS Exception httpGet] currentServerAddr: " + serverListMgr.getCurrentServerAddr(),
|
||||
ex);
|
||||
throw ex;
|
||||
}
|
||||
|
||||
if (serverListMgr.getIterator().hasNext()) {
|
||||
@ -138,30 +135,29 @@ public class ServerHttpAgent implements HttpAgent {
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpResult httpPost(String path, List<String> headers, List<String> paramValues, String encoding,
|
||||
long readTimeoutMs) throws IOException {
|
||||
public HttpRestResult<String> httpPost(String path, Map<String, String> headers, Map<String, String> paramValues,
|
||||
String encode, long readTimeoutMs) throws Exception {
|
||||
final long endTime = System.currentTimeMillis() + readTimeoutMs;
|
||||
boolean isSsl = false;
|
||||
injectSecurityInfo(paramValues);
|
||||
String currentServerAddr = serverListMgr.getCurrentServerAddr();
|
||||
int maxRetry = this.maxRetry;
|
||||
|
||||
HttpClientConfig httpConfig = HttpClientConfig.builder()
|
||||
.setReadTimeOutMillis(Long.valueOf(readTimeoutMs).intValue())
|
||||
.setConTimeOutMillis(ConfigHttpClientManager.getInstance().getConnectTimeoutOrDefault(3000)).build();
|
||||
do {
|
||||
|
||||
try {
|
||||
List<String> newHeaders = getSpasHeaders(paramValues);
|
||||
Header newHeaders = getSpasHeaders(paramValues, encode);
|
||||
if (headers != null) {
|
||||
newHeaders.addAll(headers);
|
||||
}
|
||||
HttpRestResult<String> result = NACOS_RESTTEMPLATE
|
||||
.postForm(getUrl(currentServerAddr, path), httpConfig, newHeaders,
|
||||
new HashMap<String, String>(0), paramValues, String.class);
|
||||
|
||||
HttpResult result = HttpSimpleClient
|
||||
.httpPost(getUrl(currentServerAddr, path), newHeaders, paramValues, encoding, readTimeoutMs,
|
||||
isSsl);
|
||||
if (result.code == HttpURLConnection.HTTP_INTERNAL_ERROR
|
||||
|| result.code == HttpURLConnection.HTTP_BAD_GATEWAY
|
||||
|| result.code == HttpURLConnection.HTTP_UNAVAILABLE) {
|
||||
if (isFail(result)) {
|
||||
LOGGER.error("[NACOS ConnectException] currentServerAddr: {}, httpCode: {}", currentServerAddr,
|
||||
result.code);
|
||||
result.getCode());
|
||||
} else {
|
||||
// Update the currently available server addr
|
||||
serverListMgr.updateCurrentServerAddr(currentServerAddr);
|
||||
@ -173,9 +169,9 @@ public class ServerHttpAgent implements HttpAgent {
|
||||
} catch (SocketTimeoutException socketTimeoutException) {
|
||||
LOGGER.error("[NACOS SocketTimeoutException httpPost] currentServerAddr: {}, err : {}",
|
||||
currentServerAddr, socketTimeoutException.getMessage());
|
||||
} catch (IOException ioe) {
|
||||
LOGGER.error("[NACOS IOException httpPost] currentServerAddr: " + currentServerAddr, ioe);
|
||||
throw ioe;
|
||||
} catch (Exception ex) {
|
||||
LOGGER.error("[NACOS Exception httpPost] currentServerAddr: " + currentServerAddr, ex);
|
||||
throw ex;
|
||||
}
|
||||
|
||||
if (serverListMgr.getIterator().hasNext()) {
|
||||
@ -196,46 +192,42 @@ public class ServerHttpAgent implements HttpAgent {
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpResult httpDelete(String path, List<String> headers, List<String> paramValues, String encoding,
|
||||
long readTimeoutMs) throws IOException {
|
||||
public HttpRestResult<String> httpDelete(String path, Map<String, String> headers, Map<String, String> paramValues,
|
||||
String encode, long readTimeoutMs) throws Exception {
|
||||
final long endTime = System.currentTimeMillis() + readTimeoutMs;
|
||||
boolean isSsl = false;
|
||||
injectSecurityInfo(paramValues);
|
||||
String currentServerAddr = serverListMgr.getCurrentServerAddr();
|
||||
int maxRetry = this.maxRetry;
|
||||
|
||||
HttpClientConfig httpConfig = HttpClientConfig.builder()
|
||||
.setReadTimeOutMillis(Long.valueOf(readTimeoutMs).intValue())
|
||||
.setConTimeOutMillis(ConfigHttpClientManager.getInstance().getConnectTimeoutOrDefault(100)).build();
|
||||
do {
|
||||
try {
|
||||
List<String> newHeaders = getSpasHeaders(paramValues);
|
||||
Header newHeaders = getSpasHeaders(paramValues, encode);
|
||||
if (headers != null) {
|
||||
newHeaders.addAll(headers);
|
||||
}
|
||||
HttpResult result = HttpSimpleClient
|
||||
.httpDelete(getUrl(currentServerAddr, path), newHeaders, paramValues, encoding, readTimeoutMs,
|
||||
isSsl);
|
||||
if (result.code == HttpURLConnection.HTTP_INTERNAL_ERROR
|
||||
|| result.code == HttpURLConnection.HTTP_BAD_GATEWAY
|
||||
|| result.code == HttpURLConnection.HTTP_UNAVAILABLE) {
|
||||
HttpRestResult<String> result = NACOS_RESTTEMPLATE
|
||||
.delete(getUrl(currentServerAddr, path), httpConfig, newHeaders, paramValues, String.class);
|
||||
if (isFail(result)) {
|
||||
LOGGER.error("[NACOS ConnectException] currentServerAddr: {}, httpCode: {}",
|
||||
serverListMgr.getCurrentServerAddr(), result.code);
|
||||
serverListMgr.getCurrentServerAddr(), result.getCode());
|
||||
} else {
|
||||
// Update the currently available server addr
|
||||
serverListMgr.updateCurrentServerAddr(currentServerAddr);
|
||||
return result;
|
||||
}
|
||||
} catch (ConnectException connectException) {
|
||||
connectException.printStackTrace();
|
||||
LOGGER.error("[NACOS ConnectException httpDelete] currentServerAddr:{}, err : {}",
|
||||
serverListMgr.getCurrentServerAddr(), connectException.getMessage());
|
||||
serverListMgr.getCurrentServerAddr(), ExceptionUtil.getStackTrace(connectException));
|
||||
} catch (SocketTimeoutException stoe) {
|
||||
stoe.printStackTrace();
|
||||
LOGGER.error("[NACOS SocketTimeoutException httpDelete] currentServerAddr:{}, err : {}",
|
||||
serverListMgr.getCurrentServerAddr(), stoe.getMessage());
|
||||
} catch (IOException ioe) {
|
||||
serverListMgr.getCurrentServerAddr(), ExceptionUtil.getStackTrace(stoe));
|
||||
} catch (Exception ex) {
|
||||
LOGGER.error(
|
||||
"[NACOS IOException httpDelete] currentServerAddr: " + serverListMgr.getCurrentServerAddr(),
|
||||
ioe);
|
||||
throw ioe;
|
||||
"[NACOS Exception httpDelete] currentServerAddr: " + serverListMgr.getCurrentServerAddr(),
|
||||
ex);
|
||||
throw ex;
|
||||
}
|
||||
|
||||
if (serverListMgr.getIterator().hasNext()) {
|
||||
@ -261,6 +253,12 @@ public class ServerHttpAgent implements HttpAgent {
|
||||
return serverAddr + contextPath + relativePath;
|
||||
}
|
||||
|
||||
private boolean isFail(HttpRestResult<String> result) {
|
||||
return result.getCode() == HttpURLConnection.HTTP_INTERNAL_ERROR
|
||||
|| result.getCode() == HttpURLConnection.HTTP_BAD_GATEWAY
|
||||
|| result.getCode() == HttpURLConnection.HTTP_UNAVAILABLE;
|
||||
}
|
||||
|
||||
public static String getAppname() {
|
||||
return ParamUtil.getAppName();
|
||||
}
|
||||
@ -276,7 +274,7 @@ public class ServerHttpAgent implements HttpAgent {
|
||||
|
||||
public ServerHttpAgent(Properties properties) throws NacosException {
|
||||
this.serverListMgr = new ServerListManager(properties);
|
||||
this.securityProxy = new SecurityProxy(properties);
|
||||
this.securityProxy = new SecurityProxy(properties, NACOS_RESTTEMPLATE);
|
||||
this.namespaceId = properties.getProperty(PropertyKeyConst.NAMESPACE);
|
||||
init(properties);
|
||||
this.securityProxy.login(this.serverListMgr.getServerUrls());
|
||||
@ -301,14 +299,12 @@ public class ServerHttpAgent implements HttpAgent {
|
||||
|
||||
}
|
||||
|
||||
private void injectSecurityInfo(List<String> params) {
|
||||
private void injectSecurityInfo(Map<String, String> params) {
|
||||
if (StringUtils.isNotBlank(securityProxy.getAccessToken())) {
|
||||
params.add(Constants.ACCESS_TOKEN);
|
||||
params.add(securityProxy.getAccessToken());
|
||||
params.put(Constants.ACCESS_TOKEN, securityProxy.getAccessToken());
|
||||
}
|
||||
if (StringUtils.isNotBlank(namespaceId) && !params.contains(SpasAdapter.TENANT_KEY)) {
|
||||
params.add(SpasAdapter.TENANT_KEY);
|
||||
params.add(namespaceId);
|
||||
if (StringUtils.isNotBlank(namespaceId) && !params.containsKey(SpasAdapter.TENANT_KEY)) {
|
||||
params.put(SpasAdapter.TENANT_KEY, namespaceId);
|
||||
}
|
||||
}
|
||||
|
||||
@ -363,29 +359,37 @@ public class ServerHttpAgent implements HttpAgent {
|
||||
serverListMgr.start();
|
||||
}
|
||||
|
||||
private List<String> getSpasHeaders(List<String> paramValues) throws IOException {
|
||||
List<String> newHeaders = new ArrayList<String>();
|
||||
private Header getSpasHeaders(Map<String, String> paramValues, String encode) throws Exception {
|
||||
Header header = Header.newInstance();
|
||||
// STS 临时凭证鉴权的优先级高于 AK/SK 鉴权
|
||||
if (StsConfig.getInstance().isStsOn()) {
|
||||
StsCredential stsCredential = getStsCredential();
|
||||
accessKey = stsCredential.accessKeyId;
|
||||
secretKey = stsCredential.accessKeySecret;
|
||||
newHeaders.add("Spas-SecurityToken");
|
||||
newHeaders.add(stsCredential.securityToken);
|
||||
header.addParam("Spas-SecurityToken", stsCredential.securityToken);
|
||||
}
|
||||
|
||||
if (StringUtils.isNotEmpty(accessKey) && StringUtils.isNotEmpty(secretKey)) {
|
||||
newHeaders.add("Spas-AccessKey");
|
||||
newHeaders.add(accessKey);
|
||||
List<String> signHeaders = SpasAdapter.getSignHeaders(paramValues, secretKey);
|
||||
header.addParam("Spas-AccessKey", accessKey);
|
||||
Map<String, String> signHeaders = SpasAdapter.getSignHeaders(paramValues, secretKey);
|
||||
if (signHeaders != null) {
|
||||
newHeaders.addAll(signHeaders);
|
||||
header.addAll(signHeaders);
|
||||
}
|
||||
}
|
||||
return newHeaders;
|
||||
String ts = String.valueOf(System.currentTimeMillis());
|
||||
String token = MD5Utils.md5Hex(ts + ParamUtil.getAppKey(), Constants.ENCODE);
|
||||
|
||||
header.addParam(Constants.CLIENT_APPNAME_HEADER, ParamUtil.getAppName());
|
||||
header.addParam(Constants.CLIENT_REQUEST_TS_HEADER, ts);
|
||||
header.addParam(Constants.CLIENT_REQUEST_TOKEN_HEADER, token);
|
||||
header.addParam(HttpHeaderConsts.CLIENT_VERSION_HEADER, VersionUtils.version);
|
||||
header.addParam("exConfigInfo", "true");
|
||||
header.addParam(HttpHeaderConsts.REQUEST_ID, UuidUtils.generateUuid());
|
||||
header.addParam(HttpHeaderConsts.ACCEPT_CHARSET, encode);
|
||||
return header;
|
||||
}
|
||||
|
||||
private StsCredential getStsCredential() throws IOException {
|
||||
private StsCredential getStsCredential() throws Exception {
|
||||
boolean cacheSecurityCredentials = StsConfig.getInstance().isCacheSecurityCredentials();
|
||||
if (cacheSecurityCredentials && stsCredential != null) {
|
||||
long currentTime = System.currentTimeMillis();
|
||||
@ -405,40 +409,29 @@ public class ServerHttpAgent implements HttpAgent {
|
||||
return stsCredential;
|
||||
}
|
||||
|
||||
private static String getStsResponse() throws IOException {
|
||||
private static String getStsResponse() throws Exception {
|
||||
String securityCredentials = StsConfig.getInstance().getSecurityCredentials();
|
||||
if (securityCredentials != null) {
|
||||
return securityCredentials;
|
||||
}
|
||||
String securityCredentialsUrl = StsConfig.getInstance().getSecurityCredentialsUrl();
|
||||
HttpURLConnection conn = null;
|
||||
int respCode;
|
||||
String response;
|
||||
try {
|
||||
conn = (HttpURLConnection) new URL(securityCredentialsUrl).openConnection();
|
||||
conn.setRequestMethod("GET");
|
||||
conn.setConnectTimeout(ParamUtil.getConnectTimeout() > 100 ? ParamUtil.getConnectTimeout() : 100);
|
||||
conn.setReadTimeout(1000);
|
||||
conn.connect();
|
||||
respCode = conn.getResponseCode();
|
||||
if (HttpURLConnection.HTTP_OK == respCode) {
|
||||
response = IoUtils.toString(conn.getInputStream(), Constants.ENCODE);
|
||||
} else {
|
||||
response = IoUtils.toString(conn.getErrorStream(), Constants.ENCODE);
|
||||
HttpRestResult<String> result = NACOS_RESTTEMPLATE
|
||||
.get(securityCredentialsUrl, Header.EMPTY, Query.EMPTY, String.class);
|
||||
|
||||
if (!result.ok()) {
|
||||
LOGGER.error(
|
||||
"can not get security credentials, securityCredentialsUrl: {}, responseCode: {}, response: {}",
|
||||
securityCredentialsUrl, result.getCode(), result.getMessage());
|
||||
throw new NacosException(NacosException.SERVER_ERROR,
|
||||
"can not get security credentials, responseCode: " + result.getCode() + ", response: " + result
|
||||
.getMessage());
|
||||
}
|
||||
} catch (IOException e) {
|
||||
return result.getData();
|
||||
} catch (Exception e) {
|
||||
LOGGER.error("can not get security credentials", e);
|
||||
throw e;
|
||||
} finally {
|
||||
IoUtils.closeQuietly(conn);
|
||||
}
|
||||
if (HttpURLConnection.HTTP_OK == respCode) {
|
||||
return response;
|
||||
}
|
||||
LOGGER.error("can not get security credentials, securityCredentialsUrl: {}, responseCode: {}, response: {}",
|
||||
securityCredentialsUrl, respCode, response);
|
||||
throw new IOException(
|
||||
"can not get security credentials, responseCode: " + respCode + ", response: " + response);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -466,6 +459,7 @@ public class ServerHttpAgent implements HttpAgent {
|
||||
String className = this.getClass().getName();
|
||||
LOGGER.info("{} do shutdown begin", className);
|
||||
ThreadUtils.shutdownThreadPool(executorService, LOGGER);
|
||||
ConfigHttpClientManager.getInstance().shutdown();
|
||||
LOGGER.info("{} do shutdown stop", className);
|
||||
}
|
||||
|
||||
|
@ -20,7 +20,6 @@ import com.alibaba.nacos.api.PropertyKeyConst;
|
||||
import com.alibaba.nacos.api.common.Constants;
|
||||
import com.alibaba.nacos.api.config.ConfigType;
|
||||
import com.alibaba.nacos.api.config.listener.Listener;
|
||||
import com.alibaba.nacos.api.config.remote.request.ConfigChangeListenRequest;
|
||||
import com.alibaba.nacos.api.config.remote.response.ConfigChangeNotifyResponse;
|
||||
import com.alibaba.nacos.api.config.remote.response.ConfigQueryResponse;
|
||||
import com.alibaba.nacos.api.exception.NacosException;
|
||||
@ -28,7 +27,6 @@ import com.alibaba.nacos.api.remote.response.Response;
|
||||
import com.alibaba.nacos.client.config.common.GroupKey;
|
||||
import com.alibaba.nacos.client.config.filter.impl.ConfigFilterChainManager;
|
||||
import com.alibaba.nacos.client.config.http.HttpAgent;
|
||||
import com.alibaba.nacos.client.config.impl.HttpSimpleClient.HttpResult;
|
||||
import com.alibaba.nacos.client.config.remote.ConfigGrpcClientProxy;
|
||||
import com.alibaba.nacos.client.config.utils.ContentUtils;
|
||||
import com.alibaba.nacos.client.config.utils.ParamUtils;
|
||||
@ -40,6 +38,7 @@ import com.alibaba.nacos.client.remote.ServerListFactory;
|
||||
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.http.HttpRestResult;
|
||||
import com.alibaba.nacos.common.lifecycle.Closeable;
|
||||
import com.alibaba.nacos.common.utils.ConvertUtils;
|
||||
import com.alibaba.nacos.common.utils.MD5Utils;
|
||||
@ -52,7 +51,6 @@ import java.io.IOException;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URLDecoder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
@ -330,29 +328,32 @@ public class ClientWorker implements Closeable {
|
||||
return getServerConfigInRpc(dataId, group, tenant, readTimeout);
|
||||
}
|
||||
|
||||
HttpResult result = null;
|
||||
HttpRestResult<String> result = null;
|
||||
try {
|
||||
List<String> params = null;
|
||||
Map<String, String> params = new HashMap<String, String>(3);
|
||||
if (StringUtils.isBlank(tenant)) {
|
||||
params = new ArrayList<String>(Arrays.asList("dataId", dataId, "group", group));
|
||||
params.put("dataId", dataId);
|
||||
params.put("group", group);
|
||||
} else {
|
||||
params = new ArrayList<String>(Arrays.asList("dataId", dataId, "group", group, "tenant", tenant));
|
||||
params.put("dataId", dataId);
|
||||
params.put("group", group);
|
||||
params.put("tenant", tenant);
|
||||
}
|
||||
result = agent.httpGet(Constants.CONFIG_CONTROLLER_PATH, null, params, agent.getEncode(), readTimeout);
|
||||
} catch (IOException e) {
|
||||
} catch (Exception ex) {
|
||||
String message = String
|
||||
.format("[%s] [sub-server] get server config exception, dataId=%s, group=%s, tenant=%s",
|
||||
agent.getName(), dataId, group, tenant);
|
||||
LOGGER.error(message, e);
|
||||
throw new NacosException(NacosException.SERVER_ERROR, e);
|
||||
LOGGER.error(message, ex);
|
||||
throw new NacosException(NacosException.SERVER_ERROR, ex);
|
||||
}
|
||||
|
||||
switch (result.code) {
|
||||
switch (result.getCode()) {
|
||||
case HttpURLConnection.HTTP_OK:
|
||||
LocalConfigInfoProcessor.saveSnapshot(agent.getName(), dataId, group, tenant, result.content);
|
||||
ct[0] = result.content;
|
||||
if (result.headers.containsKey(CONFIG_TYPE)) {
|
||||
ct[1] = result.headers.get(CONFIG_TYPE).get(0);
|
||||
LocalConfigInfoProcessor.saveSnapshot(agent.getName(), dataId, group, tenant, result.getData());
|
||||
ct[0] = result.getData();
|
||||
if (result.getHeader().getValue(CONFIG_TYPE) != null) {
|
||||
ct[1] = result.getHeader().getValue(CONFIG_TYPE);
|
||||
} else {
|
||||
ct[1] = ConfigType.TEXT.getType();
|
||||
}
|
||||
@ -370,13 +371,13 @@ public class ClientWorker implements Closeable {
|
||||
case HttpURLConnection.HTTP_FORBIDDEN: {
|
||||
LOGGER.error("[{}] [sub-server-error] no right, dataId={}, group={}, tenant={}", agent.getName(),
|
||||
dataId, group, tenant);
|
||||
throw new NacosException(result.code, result.content);
|
||||
throw new NacosException(result.getCode(), result.getMessage());
|
||||
}
|
||||
default: {
|
||||
LOGGER.error("[{}] [sub-server-error] dataId={}, group={}, tenant={}, code={}", agent.getName(),
|
||||
dataId, group, tenant, result.code);
|
||||
throw new NacosException(result.code,
|
||||
"http error, code=" + result.code + ",dataId=" + dataId + ",group=" + group + ",tenant="
|
||||
dataId, group, tenant, result.getCode());
|
||||
throw new NacosException(result.getCode(),
|
||||
"http error, code=" + result.getCode() + ",dataId=" + dataId + ",group=" + group + ",tenant="
|
||||
+ tenant);
|
||||
}
|
||||
}
|
||||
@ -481,10 +482,9 @@ public class ClientWorker implements Closeable {
|
||||
* @param cacheDatas CacheDatas for config infomations.
|
||||
* @param inInitializingCacheList initial cache lists.
|
||||
* @return String include dataId and group (ps: it maybe null).
|
||||
* @throws IOException Exception.
|
||||
* @throws Exception Exception.
|
||||
*/
|
||||
List<String> checkUpdateDataIds(List<CacheData> cacheDatas, List<String> inInitializingCacheList)
|
||||
throws IOException {
|
||||
List<String> checkUpdateDataIds(List<CacheData> cacheDatas, List<String> inInitializingCacheList) throws Exception {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (CacheData cacheData : cacheDatas) {
|
||||
if (!cacheData.isUseLocalConfigInfo()) {
|
||||
@ -515,20 +515,16 @@ public class ClientWorker implements Closeable {
|
||||
* @return The updated dataId list(ps: it maybe null).
|
||||
* @throws IOException Exception.
|
||||
*/
|
||||
List<String> checkUpdateConfigStr(String probeUpdateString, boolean isInitializingCacheList) throws IOException {
|
||||
List<String> checkUpdateConfigStr(String probeUpdateString, boolean isInitializingCacheList) throws Exception {
|
||||
|
||||
List<String> params = new ArrayList<String>(2);
|
||||
params.add(Constants.PROBE_MODIFY_REQUEST);
|
||||
params.add(probeUpdateString);
|
||||
|
||||
List<String> headers = new ArrayList<String>(2);
|
||||
headers.add("Long-Pulling-Timeout");
|
||||
headers.add("" + timeout);
|
||||
Map<String, String> params = new HashMap<String, String>(2);
|
||||
params.put(Constants.PROBE_MODIFY_REQUEST, probeUpdateString);
|
||||
Map<String, String> headers = new HashMap<String, String>(2);
|
||||
headers.put("Long-Pulling-Timeout", "" + timeout);
|
||||
|
||||
// told server do not hang me up if new initializing cacheData added in
|
||||
if (isInitializingCacheList) {
|
||||
headers.add("Long-Pulling-Timeout-No-Hangup");
|
||||
headers.add("true");
|
||||
headers.put("Long-Pulling-Timeout-No-Hangup", "true");
|
||||
}
|
||||
|
||||
if (StringUtils.isBlank(probeUpdateString)) {
|
||||
@ -540,18 +536,19 @@ public class ClientWorker implements Closeable {
|
||||
// increase the client's read timeout to avoid this problem.
|
||||
|
||||
long readTimeoutMs = timeout + (long) Math.round(timeout >> 1);
|
||||
HttpResult result = agent
|
||||
HttpRestResult<String> result = agent
|
||||
.httpPost(Constants.CONFIG_CONTROLLER_PATH + "/listener", headers, params, agent.getEncode(),
|
||||
readTimeoutMs);
|
||||
|
||||
if (HttpURLConnection.HTTP_OK == result.code) {
|
||||
if (result.ok()) {
|
||||
setHealthServer(true);
|
||||
return parseUpdateDataIdResponse(result.content);
|
||||
return parseUpdateDataIdResponse(result.getData());
|
||||
} else {
|
||||
setHealthServer(false);
|
||||
LOGGER.error("[{}] [check-update] get changed dataId error, code: {}", agent.getName(), result.code);
|
||||
LOGGER.error("[{}] [check-update] get changed dataId error, code: {}", agent.getName(),
|
||||
result.getCode());
|
||||
}
|
||||
} catch (IOException e) {
|
||||
} catch (Exception e) {
|
||||
setHealthServer(false);
|
||||
LOGGER.error("[" + agent.getName() + "] [check-update] get changed dataId exception", e);
|
||||
throw e;
|
||||
|
@ -0,0 +1,171 @@
|
||||
/*
|
||||
* 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 com.alibaba.nacos.api.common.Constants;
|
||||
import com.alibaba.nacos.api.exception.NacosException;
|
||||
import com.alibaba.nacos.client.utils.LogUtils;
|
||||
import com.alibaba.nacos.client.utils.ParamUtil;
|
||||
import com.alibaba.nacos.common.http.AbstractHttpClientFactory;
|
||||
import com.alibaba.nacos.common.http.HttpClientBeanHolder;
|
||||
import com.alibaba.nacos.common.http.HttpClientConfig;
|
||||
import com.alibaba.nacos.common.http.HttpClientFactory;
|
||||
import com.alibaba.nacos.common.http.client.HttpClientRequestInterceptor;
|
||||
import com.alibaba.nacos.common.http.client.HttpClientResponse;
|
||||
import com.alibaba.nacos.common.http.client.NacosRestTemplate;
|
||||
import com.alibaba.nacos.common.http.param.Header;
|
||||
import com.alibaba.nacos.common.lifecycle.Closeable;
|
||||
import com.alibaba.nacos.common.model.RequestHttpEntity;
|
||||
import com.alibaba.nacos.common.utils.ExceptionUtil;
|
||||
import com.alibaba.nacos.common.utils.JacksonUtils;
|
||||
import com.alibaba.nacos.common.utils.MD5Utils;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URI;
|
||||
|
||||
import static com.alibaba.nacos.client.utils.LogUtils.NAMING_LOGGER;
|
||||
|
||||
/**
|
||||
* config http Manager.
|
||||
*
|
||||
* @author mai.jh
|
||||
*/
|
||||
public class ConfigHttpClientManager implements Closeable {
|
||||
|
||||
private static final Logger LOGGER = LogUtils.logger(ConfigHttpClientManager.class);
|
||||
|
||||
private static final HttpClientFactory HTTP_CLIENT_FACTORY = new ConfigHttpClientFactory();
|
||||
|
||||
private static final int CON_TIME_OUT_MILLIS = ParamUtil.getConnectTimeout();
|
||||
|
||||
private static final int READ_TIME_OUT_MILLIS = 3000;
|
||||
|
||||
private static final NacosRestTemplate NACOS_REST_TEMPLATE;
|
||||
|
||||
static {
|
||||
NACOS_REST_TEMPLATE = HttpClientBeanHolder.getNacosRestTemplate(HTTP_CLIENT_FACTORY);
|
||||
NACOS_REST_TEMPLATE.getInterceptors().add(new LimiterHttpClientRequestInterceptor());
|
||||
}
|
||||
|
||||
private static class ConfigHttpClientManagerInstance {
|
||||
|
||||
private static final ConfigHttpClientManager INSTANCE = new ConfigHttpClientManager();
|
||||
}
|
||||
|
||||
public static ConfigHttpClientManager getInstance() {
|
||||
return ConfigHttpClientManagerInstance.INSTANCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shutdown() throws NacosException {
|
||||
NAMING_LOGGER.warn("[ConfigHttpClientManager] Start destroying NacosRestTemplate");
|
||||
try {
|
||||
HttpClientBeanHolder.shutdownNacostSyncRest(HTTP_CLIENT_FACTORY.getClass().getName());
|
||||
} catch (Exception ex) {
|
||||
NAMING_LOGGER.error("[ConfigHttpClientManager] An exception occurred when the HTTP client was closed : {}",
|
||||
ExceptionUtil.getStackTrace(ex));
|
||||
}
|
||||
NAMING_LOGGER.warn("[ConfigHttpClientManager] Destruction of the end");
|
||||
}
|
||||
|
||||
/**
|
||||
* get connectTimeout.
|
||||
*
|
||||
* @param connectTimeout connectTimeout
|
||||
* @return int return max timeout
|
||||
*/
|
||||
public int getConnectTimeoutOrDefault(int connectTimeout) {
|
||||
return Math.max(CON_TIME_OUT_MILLIS, connectTimeout);
|
||||
}
|
||||
|
||||
/**
|
||||
* get NacosRestTemplate Instance.
|
||||
*
|
||||
* @return NacosRestTemplate
|
||||
*/
|
||||
public NacosRestTemplate getNacosRestTemplate() {
|
||||
return NACOS_REST_TEMPLATE;
|
||||
}
|
||||
|
||||
/**
|
||||
* ConfigHttpClientFactory.
|
||||
*/
|
||||
private static class ConfigHttpClientFactory extends AbstractHttpClientFactory {
|
||||
|
||||
@Override
|
||||
protected HttpClientConfig buildHttpClientConfig() {
|
||||
return HttpClientConfig.builder().setConTimeOutMillis(CON_TIME_OUT_MILLIS)
|
||||
.setReadTimeOutMillis(READ_TIME_OUT_MILLIS).build();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Logger assignLogger() {
|
||||
return LOGGER;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* config Limiter implement.
|
||||
*/
|
||||
private static class LimiterHttpClientRequestInterceptor implements HttpClientRequestInterceptor {
|
||||
|
||||
@Override
|
||||
public boolean isIntercept(URI uri, String httpMethod, RequestHttpEntity requestHttpEntity) {
|
||||
final String body = requestHttpEntity.getBody() == null ? "" : JacksonUtils.toJson(requestHttpEntity.getBody());
|
||||
return Limiter.isLimit(MD5Utils.md5Hex(uri + body, Constants.ENCODE));
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpClientResponse intercept() {
|
||||
return new LimitResponse();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Limit Interrupt response.
|
||||
*/
|
||||
private static class LimitResponse implements HttpClientResponse {
|
||||
|
||||
@Override
|
||||
public Header getHeaders() {
|
||||
return Header.EMPTY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getBody() throws IOException {
|
||||
return new ByteArrayInputStream("More than client-side current limit threshold".getBytes());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getStatusCode() {
|
||||
return NacosException.CLIENT_OVER_THRESHOLD;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getStatusText() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@ -1,128 +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 com.alibaba.nacos.client.utils.LogUtils;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
/**
|
||||
* Event subscription and publishing tools.
|
||||
*
|
||||
* @author Nacos
|
||||
*/
|
||||
public class EventDispatcher {
|
||||
|
||||
private static final Logger LOGGER = LogUtils.logger(EventDispatcher.class);
|
||||
|
||||
/**
|
||||
* 添加事件监听器.
|
||||
*/
|
||||
public static void addEventListener(AbstractEventListener listener) {
|
||||
for (Class<? extends AbstractEvent> type : listener.interest()) {
|
||||
getListenerList(type).addIfAbsent(listener);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 发布事件,首先发布该事件暗示的其他事件,最后通知所有对应的监听器.
|
||||
*/
|
||||
public static void fireEvent(AbstractEvent abstractEvent) {
|
||||
if (null == abstractEvent) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 发布该事件暗示的其他事件
|
||||
for (AbstractEvent implyEvent : abstractEvent.implyEvents()) {
|
||||
try {
|
||||
// 避免死循环
|
||||
if (abstractEvent != implyEvent) {
|
||||
fireEvent(implyEvent);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LOGGER.warn(e.toString(), e);
|
||||
}
|
||||
}
|
||||
|
||||
for (AbstractEventListener listener : getListenerList(abstractEvent.getClass())) {
|
||||
try {
|
||||
listener.onEvent(abstractEvent);
|
||||
} catch (Exception e) {
|
||||
LOGGER.warn(e.toString(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static synchronized CopyOnWriteArrayList<AbstractEventListener> getListenerList(
|
||||
Class<? extends AbstractEvent> eventType) {
|
||||
CopyOnWriteArrayList<AbstractEventListener> listeners = LISTENER_MAP.get(eventType);
|
||||
if (null == listeners) {
|
||||
listeners = new CopyOnWriteArrayList<AbstractEventListener>();
|
||||
LISTENER_MAP.put(eventType, listeners);
|
||||
}
|
||||
return listeners;
|
||||
}
|
||||
|
||||
@SuppressWarnings("checkstyle:linelength")
|
||||
static final Map<Class<? extends AbstractEvent>, CopyOnWriteArrayList<AbstractEventListener>> LISTENER_MAP = new HashMap<Class<? extends AbstractEvent>, CopyOnWriteArrayList<AbstractEventListener>>();
|
||||
|
||||
/**
|
||||
* Client事件.
|
||||
*/
|
||||
public abstract static class AbstractEvent {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected List<AbstractEvent> implyEvents() {
|
||||
return Collections.EMPTY_LIST;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 事件监听器.
|
||||
*/
|
||||
public abstract static class AbstractEventListener {
|
||||
|
||||
public AbstractEventListener() {
|
||||
EventDispatcher.addEventListener(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* 感兴趣的事件列表.
|
||||
*
|
||||
* @return event list
|
||||
*/
|
||||
public abstract List<Class<? extends AbstractEvent>> interest();
|
||||
|
||||
/**
|
||||
* 处理事件.
|
||||
*
|
||||
* @param abstractEvent event to do
|
||||
*/
|
||||
public abstract void onEvent(AbstractEvent abstractEvent);
|
||||
}
|
||||
|
||||
/**
|
||||
* serverList has changed.
|
||||
*/
|
||||
public static class ServerlistChangeEvent extends AbstractEvent {
|
||||
}
|
||||
}
|
@ -20,6 +20,7 @@ import com.alibaba.nacos.api.common.Constants;
|
||||
import com.alibaba.nacos.api.exception.NacosException;
|
||||
import com.alibaba.nacos.client.utils.ParamUtil;
|
||||
import com.alibaba.nacos.common.constant.HttpHeaderConsts;
|
||||
import com.alibaba.nacos.common.http.client.NacosRestTemplate;
|
||||
import com.alibaba.nacos.common.utils.IoUtils;
|
||||
import com.alibaba.nacos.common.utils.MD5Utils;
|
||||
import com.alibaba.nacos.common.utils.UuidUtils;
|
||||
@ -39,7 +40,9 @@ import java.util.Map;
|
||||
* Http tool.
|
||||
*
|
||||
* @author Nacos
|
||||
* @deprecated Use NacosRestTemplate{@link NacosRestTemplate} unified http client
|
||||
*/
|
||||
@Deprecated
|
||||
public class HttpSimpleClient {
|
||||
|
||||
/**
|
||||
|
@ -19,21 +19,22 @@ package com.alibaba.nacos.client.config.impl;
|
||||
import com.alibaba.nacos.api.PropertyKeyConst;
|
||||
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.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.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.lifecycle.Closeable;
|
||||
import com.alibaba.nacos.common.notify.NotifyCenter;
|
||||
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.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
@ -59,6 +60,8 @@ public class ServerListManager implements Closeable {
|
||||
|
||||
private static final String HTTP = "http://";
|
||||
|
||||
private final NacosRestTemplate nacosRestTemplate = ConfigHttpClientManager.getInstance().getNacosRestTemplate();
|
||||
|
||||
private final ScheduledExecutorService executorService = new ScheduledThreadPoolExecutor(1, new ThreadFactory() {
|
||||
@Override
|
||||
public Thread newThread(Runnable r) {
|
||||
@ -335,19 +338,20 @@ public class ServerListManager implements Closeable {
|
||||
iterator = iterator();
|
||||
currentServerAddr = iterator.next();
|
||||
|
||||
EventDispatcher.fireEvent(new ServerlistChangeEvent());
|
||||
// Using unified event processor, NotifyCenter
|
||||
NotifyCenter.publishEvent(new ServerlistChangeEvent());
|
||||
LOGGER.info("[{}] [update-serverlist] serverlist updated to {}", name, serverUrls);
|
||||
}
|
||||
|
||||
private List<String> getApacheServerList(String url, String name) {
|
||||
try {
|
||||
HttpResult httpResult = HttpSimpleClient.httpGet(url, null, null, null, 3000);
|
||||
|
||||
if (HttpURLConnection.HTTP_OK == httpResult.code) {
|
||||
HttpRestResult<String> httpResult = nacosRestTemplate.get(url, Header.EMPTY, Query.EMPTY, String.class);
|
||||
|
||||
if (httpResult.ok()) {
|
||||
if (DEFAULT_NAME.equals(name)) {
|
||||
EnvUtil.setSelfEnv(httpResult.headers);
|
||||
EnvUtil.setSelfEnv(httpResult.getHeader().getOriginalResponseHeader());
|
||||
}
|
||||
List<String> lines = IoUtils.readLines(new StringReader(httpResult.content));
|
||||
List<String> lines = IoUtils.readLines(new StringReader(httpResult.getData()));
|
||||
List<String> result = new ArrayList<String>(lines.size());
|
||||
for (String serverAddr : lines) {
|
||||
if (StringUtils.isNotBlank(serverAddr)) {
|
||||
@ -363,10 +367,10 @@ public class ServerListManager implements Closeable {
|
||||
return result;
|
||||
} else {
|
||||
LOGGER.error("[check-serverlist] error. addressServerUrl: {}, code: {}", addressServerUrl,
|
||||
httpResult.code);
|
||||
httpResult.getCode());
|
||||
return null;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
} catch (Exception e) {
|
||||
LOGGER.error("[check-serverlist] exception. url: " + url, e);
|
||||
return null;
|
||||
}
|
||||
|
@ -14,13 +14,14 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.core.notify;
|
||||
package com.alibaba.nacos.client.config.impl;
|
||||
|
||||
import com.alibaba.nacos.common.notify.SlowEvent;
|
||||
|
||||
/**
|
||||
* this event share one event-queue.
|
||||
* Server List Change Event.
|
||||
*
|
||||
* @author <a href="mailto:liaochuntao@live.com">liaochuntao</a>
|
||||
* @author zongtanghu
|
||||
*/
|
||||
public interface SlowEvent extends Event {
|
||||
|
||||
public class ServerlistChangeEvent extends SlowEvent {
|
||||
}
|
@ -24,11 +24,7 @@ import com.alibaba.nacos.common.utils.StringUtils;
|
||||
import javax.crypto.Mac;
|
||||
import javax.crypto.SecretKey;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
@ -37,44 +33,34 @@ import java.util.Map;
|
||||
* @author Nacos
|
||||
*/
|
||||
public class SpasAdapter {
|
||||
|
||||
public static List<String> getSignHeaders(String resource, String secretKey) {
|
||||
List<String> header = new ArrayList<String>();
|
||||
|
||||
public static Map<String, String> getSignHeaders(String resource, String secretKey) {
|
||||
Map<String, String> header = new HashMap<String, String>(2);
|
||||
String timeStamp = String.valueOf(System.currentTimeMillis());
|
||||
header.add("Timestamp");
|
||||
header.add(timeStamp);
|
||||
header.put("Timestamp", timeStamp);
|
||||
if (secretKey != null) {
|
||||
header.add("Spas-Signature");
|
||||
String signature = "";
|
||||
if (StringUtils.isBlank(resource)) {
|
||||
signature = signWithHmacSha1Encrypt(timeStamp, secretKey);
|
||||
} else {
|
||||
signature = signWithHmacSha1Encrypt(resource + "+" + timeStamp, secretKey);
|
||||
}
|
||||
header.add(signature);
|
||||
header.put("Spas-Signature", signature);
|
||||
}
|
||||
return header;
|
||||
}
|
||||
|
||||
public static List<String> getSignHeaders(List<String> paramValues, String secretKey) {
|
||||
|
||||
public static Map<String, String> getSignHeaders(Map<String, String> paramValues, String secretKey) {
|
||||
if (null == paramValues) {
|
||||
return null;
|
||||
}
|
||||
Map<String, String> signMap = new HashMap<String, String>(5);
|
||||
for (Iterator<String> iter = paramValues.iterator(); iter.hasNext(); ) {
|
||||
String key = iter.next();
|
||||
if (TENANT_KEY.equals(key) || GROUP_KEY.equals(key)) {
|
||||
signMap.put(key, iter.next());
|
||||
} else {
|
||||
iter.next();
|
||||
}
|
||||
}
|
||||
|
||||
String resource = "";
|
||||
if (signMap.size() > 1) {
|
||||
resource = signMap.get(TENANT_KEY) + "+" + signMap.get(GROUP_KEY);
|
||||
if (paramValues.containsKey(TENANT_KEY) && paramValues.containsKey(GROUP_KEY)) {
|
||||
resource = paramValues.get(TENANT_KEY) + "+" + paramValues.get(GROUP_KEY);
|
||||
} else {
|
||||
if (!StringUtils.isBlank(signMap.get(GROUP_KEY))) {
|
||||
resource = signMap.get(GROUP_KEY);
|
||||
if (!StringUtils.isBlank(paramValues.get(GROUP_KEY))) {
|
||||
resource = paramValues.get(GROUP_KEY);
|
||||
}
|
||||
}
|
||||
return getSignHeaders(resource, secretKey);
|
||||
@ -97,14 +83,14 @@ public class SpasAdapter {
|
||||
*/
|
||||
public static String signWithHmacSha1Encrypt(String encryptText, String encryptKey) {
|
||||
try {
|
||||
byte[] data = encryptKey.getBytes(StandardCharsets.UTF_8);
|
||||
byte[] data = encryptKey.getBytes(Constants.ENCODE);
|
||||
// 根据给定的字节数组构造一个密钥,第二参数指定一个密钥算法的名称
|
||||
SecretKey secretKey = new SecretKeySpec(data, "HmacSHA1");
|
||||
// 生成一个指定 Mac 算法 的 Mac 对象
|
||||
Mac mac = Mac.getInstance("HmacSHA1");
|
||||
// 用给定密钥初始化 Mac 对象
|
||||
mac.init(secretKey);
|
||||
byte[] text = encryptText.getBytes(StandardCharsets.UTF_8);
|
||||
byte[] text = encryptText.getBytes(Constants.ENCODE);
|
||||
byte[] textFinal = mac.doFinal(text);
|
||||
// 完成 Mac 操作, base64编码,将byte数组转换为字符串
|
||||
return new String(Base64.encodeBase64(textFinal), Constants.ENCODE);
|
||||
|
@ -165,7 +165,7 @@ public class BeatReactor implements Closeable {
|
||||
long nextTime = beatInfo.getPeriod();
|
||||
try {
|
||||
JsonNode result = serverProxy.sendBeat(beatInfo, BeatReactor.this.lightBeatEnabled);
|
||||
long interval = result.get("clientBeatInterval").asInt();
|
||||
long interval = result.get("clientBeatInterval").asLong();
|
||||
boolean lightBeatEnabled = false;
|
||||
if (result.has(CommonParams.LIGHT_BEAT_ENABLED)) {
|
||||
lightBeatEnabled = result.get(CommonParams.LIGHT_BEAT_ENABLED).asBoolean();
|
||||
|
@ -16,18 +16,24 @@
|
||||
|
||||
package com.alibaba.nacos.client.naming.net;
|
||||
|
||||
import com.alibaba.nacos.api.exception.NacosException;
|
||||
import com.alibaba.nacos.common.http.AbstractHttpClientFactory;
|
||||
import com.alibaba.nacos.common.http.HttpClientBeanHolder;
|
||||
import com.alibaba.nacos.common.http.HttpClientConfig;
|
||||
import com.alibaba.nacos.common.http.HttpClientFactory;
|
||||
import com.alibaba.nacos.common.http.client.NacosRestTemplate;
|
||||
import com.alibaba.nacos.common.lifecycle.Closeable;
|
||||
import com.alibaba.nacos.common.utils.ExceptionUtil;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import static com.alibaba.nacos.client.utils.LogUtils.NAMING_LOGGER;
|
||||
|
||||
/**
|
||||
* http Manager.
|
||||
*
|
||||
* @author mai.jh
|
||||
*/
|
||||
public class NamingHttpClientManager {
|
||||
public class NamingHttpClientManager implements Closeable {
|
||||
|
||||
private static final int READ_TIME_OUT_MILLIS = Integer
|
||||
.getInteger("com.alibaba.nacos.client.naming.rtimeout", 50000);
|
||||
@ -40,17 +46,38 @@ public class NamingHttpClientManager {
|
||||
|
||||
private static final HttpClientFactory HTTP_CLIENT_FACTORY = new NamingHttpClientFactory();
|
||||
|
||||
public static String getPrefix() {
|
||||
private static class NamingHttpClientManagerInstance {
|
||||
|
||||
private static final NamingHttpClientManager INSTANCE = new NamingHttpClientManager();
|
||||
}
|
||||
|
||||
public static NamingHttpClientManager getInstance() {
|
||||
return NamingHttpClientManagerInstance.INSTANCE;
|
||||
}
|
||||
|
||||
public String getPrefix() {
|
||||
if (ENABLE_HTTPS) {
|
||||
return "https://";
|
||||
}
|
||||
return "http://";
|
||||
}
|
||||
|
||||
public static NacosRestTemplate getNacosRestTemplate() {
|
||||
public NacosRestTemplate getNacosRestTemplate() {
|
||||
return HttpClientBeanHolder.getNacosRestTemplate(HTTP_CLIENT_FACTORY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shutdown() throws NacosException {
|
||||
NAMING_LOGGER.warn("[NamingHttpClientManager] Start destroying NacosRestTemplate");
|
||||
try {
|
||||
HttpClientBeanHolder.shutdownNacostSyncRest(HTTP_CLIENT_FACTORY.getClass().getName());
|
||||
} catch (Exception ex) {
|
||||
NAMING_LOGGER.error("[NamingHttpClientManager] An exception occurred when the HTTP client was closed : {}",
|
||||
ExceptionUtil.getStackTrace(ex));
|
||||
}
|
||||
NAMING_LOGGER.warn("[NamingHttpClientManager] Destruction of the end");
|
||||
}
|
||||
|
||||
private static class NamingHttpClientFactory extends AbstractHttpClientFactory {
|
||||
|
||||
@Override
|
||||
@ -58,5 +85,10 @@ public class NamingHttpClientManager {
|
||||
return HttpClientConfig.builder().setConTimeOutMillis(CON_TIME_OUT_MILLIS)
|
||||
.setReadTimeOutMillis(READ_TIME_OUT_MILLIS).setMaxRedirects(MAX_REDIRECTS).build();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Logger assignLogger() {
|
||||
return NAMING_LOGGER;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -80,7 +80,7 @@ import static com.alibaba.nacos.client.utils.LogUtils.NAMING_LOGGER;
|
||||
*/
|
||||
public class NamingProxy implements Closeable {
|
||||
|
||||
private final NacosRestTemplate nacosRestTemplate = NamingHttpClientManager.getNacosRestTemplate();
|
||||
private final NacosRestTemplate nacosRestTemplate = NamingHttpClientManager.getInstance().getNacosRestTemplate();
|
||||
|
||||
private static final int DEFAULT_SERVER_PORT = 8848;
|
||||
|
||||
@ -110,7 +110,7 @@ public class NamingProxy implements Closeable {
|
||||
|
||||
public NamingProxy(String namespaceId, String endpoint, String serverList, Properties properties) {
|
||||
|
||||
this.securityProxy = new SecurityProxy(properties);
|
||||
this.securityProxy = new SecurityProxy(properties, nacosRestTemplate);
|
||||
this.properties = properties;
|
||||
this.setServerPort(DEFAULT_SERVER_PORT);
|
||||
this.namespaceId = namespaceId;
|
||||
@ -592,7 +592,7 @@ public class NamingProxy implements Closeable {
|
||||
if (!curServer.contains(UtilAndComs.SERVER_ADDR_IP_SPLITER)) {
|
||||
curServer = curServer + UtilAndComs.SERVER_ADDR_IP_SPLITER + serverPort;
|
||||
}
|
||||
url = NamingHttpClientManager.getPrefix() + curServer + api;
|
||||
url = NamingHttpClientManager.getInstance().getPrefix() + curServer + api;
|
||||
}
|
||||
|
||||
try {
|
||||
@ -609,7 +609,7 @@ public class NamingProxy implements Closeable {
|
||||
if (HttpStatus.SC_NOT_MODIFIED == restResult.getCode()) {
|
||||
return StringUtils.EMPTY;
|
||||
}
|
||||
throw new NacosException(restResult.getCode(), restResult.getData());
|
||||
throw new NacosException(restResult.getCode(), restResult.getMessage());
|
||||
} catch (Exception e) {
|
||||
NAMING_LOGGER.error("[NA] failed to request", e);
|
||||
throw new NacosException(NacosException.SERVER_ERROR, e);
|
||||
@ -715,6 +715,7 @@ public class NamingProxy implements Closeable {
|
||||
String className = this.getClass().getName();
|
||||
NAMING_LOGGER.info("{} do shutdown begin", className);
|
||||
ThreadUtils.shutdownThreadPool(executorService, NAMING_LOGGER);
|
||||
NamingHttpClientManager.getInstance().shutdown();
|
||||
NAMING_LOGGER.info("{} do shutdown stop", className);
|
||||
}
|
||||
}
|
||||
|
@ -18,7 +18,6 @@ package com.alibaba.nacos.client.security;
|
||||
|
||||
import com.alibaba.nacos.api.PropertyKeyConst;
|
||||
import com.alibaba.nacos.api.common.Constants;
|
||||
import com.alibaba.nacos.client.naming.net.NamingHttpClientManager;
|
||||
import com.alibaba.nacos.common.http.HttpRestResult;
|
||||
import com.alibaba.nacos.common.http.client.NacosRestTemplate;
|
||||
import com.alibaba.nacos.common.http.param.Header;
|
||||
@ -46,7 +45,7 @@ public class SecurityProxy {
|
||||
|
||||
private static final String LOGIN_URL = "/v1/auth/users/login";
|
||||
|
||||
private final NacosRestTemplate nacosRestTemplate = NamingHttpClientManager.getNacosRestTemplate();
|
||||
private final NacosRestTemplate nacosRestTemplate;
|
||||
|
||||
private String contextPath;
|
||||
|
||||
@ -85,11 +84,12 @@ public class SecurityProxy {
|
||||
*
|
||||
* @param properties a bunch of properties to read
|
||||
*/
|
||||
public SecurityProxy(Properties properties) {
|
||||
public SecurityProxy(Properties properties, NacosRestTemplate nacosRestTemplate) {
|
||||
username = properties.getProperty(PropertyKeyConst.USERNAME, StringUtils.EMPTY);
|
||||
password = properties.getProperty(PropertyKeyConst.PASSWORD, StringUtils.EMPTY);
|
||||
contextPath = properties.getProperty(PropertyKeyConst.CONTEXT_PATH, "/nacos");
|
||||
contextPath = contextPath.startsWith("/") ? contextPath : "/" + contextPath;
|
||||
this.nacosRestTemplate = nacosRestTemplate;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -19,7 +19,6 @@ package com.alibaba.nacos.client.utils;
|
||||
import com.alibaba.nacos.api.PropertyKeyConst;
|
||||
import com.alibaba.nacos.api.SystemPropertyKeyConst;
|
||||
import com.alibaba.nacos.api.common.Constants;
|
||||
import com.alibaba.nacos.client.config.impl.HttpSimpleClient;
|
||||
import com.alibaba.nacos.common.utils.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
@ -82,7 +81,7 @@ public class ParamUtil {
|
||||
LOGGER.info("[settings] [http-client] connect timeout:{}", connectTimeout);
|
||||
|
||||
try {
|
||||
InputStream in = HttpSimpleClient.class.getClassLoader().getResourceAsStream("application.properties");
|
||||
InputStream in = ValidatorUtils.class.getClassLoader().getResourceAsStream("application.properties");
|
||||
Properties props = new Properties();
|
||||
props.load(in);
|
||||
String val = null;
|
||||
|
@ -24,8 +24,8 @@ import com.alibaba.nacos.api.exception.NacosException;
|
||||
import com.alibaba.nacos.cmdb.core.SwitchAndOptions;
|
||||
import com.alibaba.nacos.cmdb.service.CmdbReader;
|
||||
import com.alibaba.nacos.cmdb.service.CmdbWriter;
|
||||
import com.alibaba.nacos.cmdb.utils.CmdbExecutor;
|
||||
import com.alibaba.nacos.cmdb.utils.Loggers;
|
||||
import com.alibaba.nacos.cmdb.utils.UtilsAndCommons;
|
||||
import com.alibaba.nacos.common.utils.JacksonUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
@ -117,11 +117,9 @@ public class CmdbProvider implements CmdbReader, CmdbWriter {
|
||||
initCmdbService();
|
||||
load();
|
||||
|
||||
UtilsAndCommons.GLOBAL_EXECUTOR.schedule(new CmdbDumpTask(), switches.getDumpTaskInterval(), TimeUnit.SECONDS);
|
||||
UtilsAndCommons.GLOBAL_EXECUTOR
|
||||
.schedule(new CmdbLabelTask(), switches.getLabelTaskInterval(), TimeUnit.SECONDS);
|
||||
UtilsAndCommons.GLOBAL_EXECUTOR
|
||||
.schedule(new CmdbEventTask(), switches.getEventTaskInterval(), TimeUnit.SECONDS);
|
||||
CmdbExecutor.scheduleCmdbTask(new CmdbDumpTask(), switches.getDumpTaskInterval(), TimeUnit.SECONDS);
|
||||
CmdbExecutor.scheduleCmdbTask(new CmdbLabelTask(), switches.getLabelTaskInterval(), TimeUnit.SECONDS);
|
||||
CmdbExecutor.scheduleCmdbTask(new CmdbEventTask(), switches.getEventTaskInterval(), TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -205,7 +203,7 @@ public class CmdbProvider implements CmdbReader, CmdbWriter {
|
||||
} catch (Exception e) {
|
||||
Loggers.MAIN.error("CMDB-LABEL-TASK {}", "dump failed!", e);
|
||||
} finally {
|
||||
UtilsAndCommons.GLOBAL_EXECUTOR.schedule(this, switches.getLabelTaskInterval(), TimeUnit.SECONDS);
|
||||
CmdbExecutor.scheduleCmdbTask(this, switches.getLabelTaskInterval(), TimeUnit.SECONDS);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -227,7 +225,7 @@ public class CmdbProvider implements CmdbReader, CmdbWriter {
|
||||
} catch (Exception e) {
|
||||
Loggers.MAIN.error("DUMP-TASK {}", "dump failed!", e);
|
||||
} finally {
|
||||
UtilsAndCommons.GLOBAL_EXECUTOR.schedule(this, switches.getDumpTaskInterval(), TimeUnit.SECONDS);
|
||||
CmdbExecutor.scheduleCmdbTask(this, switches.getDumpTaskInterval(), TimeUnit.SECONDS);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -271,7 +269,7 @@ public class CmdbProvider implements CmdbReader, CmdbWriter {
|
||||
} catch (Exception e) {
|
||||
Loggers.MAIN.error("CMDB-EVENT {}", "event task failed!", e);
|
||||
} finally {
|
||||
UtilsAndCommons.GLOBAL_EXECUTOR.schedule(this, switches.getEventTaskInterval(), TimeUnit.SECONDS);
|
||||
CmdbExecutor.scheduleCmdbTask(this, switches.getEventTaskInterval(), TimeUnit.SECONDS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* 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.cmdb.utils;
|
||||
|
||||
import com.alibaba.nacos.cmdb.CmdbApp;
|
||||
import com.alibaba.nacos.common.executor.ExecutorFactory;
|
||||
import com.alibaba.nacos.common.executor.NameThreadFactory;
|
||||
import com.alibaba.nacos.core.utils.ClassUtils;
|
||||
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* Cmdb executor.
|
||||
*
|
||||
* @author wangweizZZ
|
||||
* @date 2020/7/13 1:54 PM
|
||||
*/
|
||||
public class CmdbExecutor {
|
||||
|
||||
private static final ScheduledExecutorService GLOBAL_EXECUTOR = ExecutorFactory.Managed
|
||||
.newScheduledExecutorService(ClassUtils.getCanonicalName(CmdbApp.class),
|
||||
Runtime.getRuntime().availableProcessors(),
|
||||
new NameThreadFactory("com.alibaba.nacos.cmdb.global.executor"));
|
||||
|
||||
public static void scheduleCmdbTask(Runnable runnable, long delay, TimeUnit unit) {
|
||||
GLOBAL_EXECUTOR.schedule(runnable, delay, unit);
|
||||
}
|
||||
}
|
@ -16,10 +16,6 @@
|
||||
|
||||
package com.alibaba.nacos.cmdb.utils;
|
||||
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ScheduledThreadPoolExecutor;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
|
||||
/**
|
||||
* Utils and constants.
|
||||
*
|
||||
@ -32,19 +28,4 @@ public class UtilsAndCommons {
|
||||
|
||||
public static final String NACOS_CMDB_CONTEXT = NACOS_SERVER_VERSION + "/cmdb";
|
||||
|
||||
public static final ScheduledExecutorService GLOBAL_EXECUTOR;
|
||||
|
||||
static {
|
||||
|
||||
GLOBAL_EXECUTOR = new ScheduledThreadPoolExecutor(Runtime.getRuntime().availableProcessors(),
|
||||
new ThreadFactory() {
|
||||
@Override
|
||||
public Thread newThread(Runnable r) {
|
||||
Thread t = new Thread(r);
|
||||
t.setName("nacos.cmdb.global.executor");
|
||||
t.setDaemon(true);
|
||||
return t;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -14,24 +14,19 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.core.notify;
|
||||
|
||||
import java.io.Serializable;
|
||||
package com.alibaba.nacos.common.constant;
|
||||
|
||||
/**
|
||||
* event.
|
||||
* Response Handler Type.
|
||||
*
|
||||
* @author <a href="mailto:liaochuntao@live.com">liaochuntao</a>
|
||||
* @author mai.jh
|
||||
*/
|
||||
public interface Event extends Serializable {
|
||||
public final class ResponseHandlerType {
|
||||
|
||||
/**
|
||||
* Event sequence number, which can be used to handle the sequence of events.
|
||||
*
|
||||
* @return sequence num, It's best to make sure it's monotone
|
||||
*/
|
||||
default long sequence() {
|
||||
return System.currentTimeMillis();
|
||||
}
|
||||
public static final String STRING_TYPE = "java.lang.String";
|
||||
|
||||
public static final String RESTRESULT_TYPE = "com.alibaba.nacos.common.model.RestResult";
|
||||
|
||||
public static final String DEFAULT_BEAN_TYPE = "default_bean_handler";
|
||||
|
||||
}
|
@ -38,10 +38,6 @@ import java.util.concurrent.TimeUnit;
|
||||
"checkstyle:missingjavadocmethod"})
|
||||
public final class ExecutorFactory {
|
||||
|
||||
private static final String DEFAULT_NAMESPACE = "nacos";
|
||||
|
||||
private static final ThreadPoolManager THREAD_POOL_MANAGER = ThreadPoolManager.getInstance();
|
||||
|
||||
public static ExecutorService newSingleExecutorService() {
|
||||
return Executors.newFixedThreadPool(1);
|
||||
}
|
||||
@ -73,61 +69,6 @@ public final class ExecutorFactory {
|
||||
new LinkedBlockingQueue<Runnable>(), threadFactory);
|
||||
}
|
||||
|
||||
//TODO remove Deprecated function after replace all module
|
||||
@Deprecated
|
||||
public static ExecutorService newSingleExecutorService(final String group) {
|
||||
ExecutorService executorService = Executors.newFixedThreadPool(1);
|
||||
THREAD_POOL_MANAGER.register(DEFAULT_NAMESPACE, group, executorService);
|
||||
return executorService;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static ExecutorService newSingleExecutorService(final String group, final ThreadFactory threadFactory) {
|
||||
ExecutorService executorService = Executors.newFixedThreadPool(1, threadFactory);
|
||||
THREAD_POOL_MANAGER.register(DEFAULT_NAMESPACE, group, executorService);
|
||||
return executorService;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static ExecutorService newFixedExecutorService(final String group, final int nThreads) {
|
||||
ExecutorService executorService = Executors.newFixedThreadPool(nThreads);
|
||||
THREAD_POOL_MANAGER.register(DEFAULT_NAMESPACE, group, executorService);
|
||||
return executorService;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static ExecutorService newFixedExecutorService(final String group, final int nThreads,
|
||||
final ThreadFactory threadFactory) {
|
||||
ExecutorService executorService = Executors.newFixedThreadPool(nThreads, threadFactory);
|
||||
THREAD_POOL_MANAGER.register(DEFAULT_NAMESPACE, group, executorService);
|
||||
return executorService;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static ScheduledExecutorService newSingleScheduledExecutorService(final String group,
|
||||
final ThreadFactory threadFactory) {
|
||||
ScheduledExecutorService executorService = Executors.newScheduledThreadPool(1, threadFactory);
|
||||
THREAD_POOL_MANAGER.register(DEFAULT_NAMESPACE, group, executorService);
|
||||
return executorService;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static ScheduledExecutorService newScheduledExecutorService(final String group, final int nThreads,
|
||||
final ThreadFactory threadFactory) {
|
||||
ScheduledExecutorService executorService = Executors.newScheduledThreadPool(nThreads, threadFactory);
|
||||
THREAD_POOL_MANAGER.register(DEFAULT_NAMESPACE, group, executorService);
|
||||
return executorService;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static ThreadPoolExecutor newCustomerThreadExecutor(final String group, final int coreThreads,
|
||||
final int maxThreads, final long keepAliveTimeMs, final ThreadFactory threadFactory) {
|
||||
ThreadPoolExecutor executor = new ThreadPoolExecutor(coreThreads, maxThreads, keepAliveTimeMs,
|
||||
TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(), threadFactory);
|
||||
THREAD_POOL_MANAGER.register(DEFAULT_NAMESPACE, group, executor);
|
||||
return executor;
|
||||
}
|
||||
|
||||
public static final class Managed {
|
||||
|
||||
private static final String DEFAULT_NAMESPACE = "nacos";
|
||||
|
@ -17,12 +17,12 @@
|
||||
package com.alibaba.nacos.common.http;
|
||||
|
||||
import com.alibaba.nacos.common.http.client.DefaultAsyncHttpClientRequest;
|
||||
import com.alibaba.nacos.common.http.client.DefaultHttpClientRequest;
|
||||
import com.alibaba.nacos.common.http.client.JdkHttpClientRequest;
|
||||
import com.alibaba.nacos.common.http.client.NacosAsyncRestTemplate;
|
||||
import com.alibaba.nacos.common.http.client.NacosRestTemplate;
|
||||
import org.apache.http.client.config.RequestConfig;
|
||||
import org.apache.http.impl.client.HttpClients;
|
||||
import org.apache.http.impl.nio.client.HttpAsyncClients;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
/**
|
||||
* AbstractHttpClientFactory Let the creator only specify the http client config.
|
||||
@ -33,15 +33,14 @@ public abstract class AbstractHttpClientFactory implements HttpClientFactory {
|
||||
|
||||
@Override
|
||||
public final NacosRestTemplate createNacosRestTemplate() {
|
||||
RequestConfig requestConfig = getRequestConfig();
|
||||
return new NacosRestTemplate(
|
||||
new DefaultHttpClientRequest(HttpClients.custom().setDefaultRequestConfig(requestConfig).build()));
|
||||
HttpClientConfig httpClientConfig = buildHttpClientConfig();
|
||||
return new NacosRestTemplate(assignLogger(), new JdkHttpClientRequest(httpClientConfig));
|
||||
}
|
||||
|
||||
@Override
|
||||
public final NacosAsyncRestTemplate createNacosAsyncRestTemplate() {
|
||||
RequestConfig requestConfig = getRequestConfig();
|
||||
return new NacosAsyncRestTemplate(new DefaultAsyncHttpClientRequest(
|
||||
return new NacosAsyncRestTemplate(assignLogger(), new DefaultAsyncHttpClientRequest(
|
||||
HttpAsyncClients.custom().setDefaultRequestConfig(requestConfig).build()));
|
||||
}
|
||||
|
||||
@ -58,4 +57,11 @@ public abstract class AbstractHttpClientFactory implements HttpClientFactory {
|
||||
* @return HttpClientConfig
|
||||
*/
|
||||
protected abstract HttpClientConfig buildHttpClientConfig();
|
||||
|
||||
/**
|
||||
* assign Logger.
|
||||
*
|
||||
* @return Logger
|
||||
*/
|
||||
protected abstract Logger assignLogger();
|
||||
}
|
||||
|
@ -16,6 +16,8 @@
|
||||
|
||||
package com.alibaba.nacos.common.http;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
|
||||
/**
|
||||
* default http client factory.
|
||||
*
|
||||
@ -25,8 +27,19 @@ public class DefaultHttpClientFactory extends AbstractHttpClientFactory {
|
||||
|
||||
private static final int TIMEOUT = Integer.getInteger("nacos.http.timeout", 5000);
|
||||
|
||||
private final Logger logger;
|
||||
|
||||
public DefaultHttpClientFactory(Logger logger) {
|
||||
this.logger = logger;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected HttpClientConfig buildHttpClientConfig() {
|
||||
return HttpClientConfig.builder().setConTimeOutMillis(TIMEOUT).setReadTimeOutMillis(TIMEOUT >> 1).build();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Logger assignLogger() {
|
||||
return logger;
|
||||
}
|
||||
}
|
||||
|
@ -18,15 +18,10 @@ package com.alibaba.nacos.common.http;
|
||||
|
||||
import com.alibaba.nacos.common.http.client.NacosAsyncRestTemplate;
|
||||
import com.alibaba.nacos.common.http.client.NacosRestTemplate;
|
||||
import com.alibaba.nacos.common.utils.ExceptionUtil;
|
||||
import com.alibaba.nacos.common.utils.ThreadUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
/**
|
||||
* Create a rest template to ensure that each custom client config and rest template are in one-to-one correspondence.
|
||||
@ -35,25 +30,13 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
||||
*/
|
||||
public final class HttpClientBeanHolder {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(HttpClientManager.class);
|
||||
|
||||
private static final Map<String, NacosRestTemplate> SINGLETON_REST = new HashMap<String, NacosRestTemplate>(10);
|
||||
|
||||
private static final Map<String, NacosAsyncRestTemplate> SINGLETON_ASYNC_REST = new HashMap<String, NacosAsyncRestTemplate>(10);
|
||||
private static final Map<String, NacosAsyncRestTemplate> SINGLETON_ASYNC_REST = new HashMap<String, NacosAsyncRestTemplate>(
|
||||
10);
|
||||
|
||||
private static final AtomicBoolean ALREADY_SHUTDOWN = new AtomicBoolean(false);
|
||||
|
||||
static {
|
||||
ThreadUtils.addShutdownHook(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
shutdown();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static NacosRestTemplate getNacosRestTemplate() {
|
||||
return getNacosRestTemplate(new DefaultHttpClientFactory());
|
||||
public static NacosRestTemplate getNacosRestTemplate(Logger logger) {
|
||||
return getNacosRestTemplate(new DefaultHttpClientFactory(logger));
|
||||
}
|
||||
|
||||
public static NacosRestTemplate getNacosRestTemplate(HttpClientFactory httpClientFactory) {
|
||||
@ -75,8 +58,8 @@ public final class HttpClientBeanHolder {
|
||||
return nacosRestTemplate;
|
||||
}
|
||||
|
||||
public static NacosAsyncRestTemplate getNacosAsyncRestTemplate() {
|
||||
return getNacosAsyncRestTemplate(new DefaultHttpClientFactory());
|
||||
public static NacosAsyncRestTemplate getNacosAsyncRestTemplate(Logger logger) {
|
||||
return getNacosAsyncRestTemplate(new DefaultHttpClientFactory(logger));
|
||||
}
|
||||
|
||||
public static NacosAsyncRestTemplate getNacosAsyncRestTemplate(HttpClientFactory httpClientFactory) {
|
||||
@ -99,40 +82,41 @@ public final class HttpClientBeanHolder {
|
||||
}
|
||||
|
||||
/**
|
||||
* Shutdown http client holder and close all template.
|
||||
* Shutdown http client holder and close remove template.
|
||||
*
|
||||
* @param className HttpClientFactory implement class name
|
||||
* @throws Exception ex
|
||||
*/
|
||||
public static void shutdown() {
|
||||
if (!ALREADY_SHUTDOWN.compareAndSet(false, true)) {
|
||||
return;
|
||||
}
|
||||
LOGGER.warn("[HttpClientBeanFactory] Start destroying NacosRestTemplate");
|
||||
try {
|
||||
nacostRestTemplateShutdown();
|
||||
nacosAsyncRestTemplateShutdown();
|
||||
} catch (Exception ex) {
|
||||
LOGGER.error("[HttpClientBeanFactory] An exception occurred when the HTTP client was closed : {}",
|
||||
ExceptionUtil.getStackTrace(ex));
|
||||
}
|
||||
LOGGER.warn("[HttpClientBeanFactory] Destruction of the end");
|
||||
public static void shutdown(String className) throws Exception {
|
||||
shutdownNacostSyncRest(className);
|
||||
shutdownNacosAsyncRest(className);
|
||||
}
|
||||
|
||||
private static void nacostRestTemplateShutdown() throws Exception {
|
||||
if (!SINGLETON_REST.isEmpty()) {
|
||||
Collection<NacosRestTemplate> nacosRestTemplates = SINGLETON_REST.values();
|
||||
for (NacosRestTemplate nacosRestTemplate : nacosRestTemplates) {
|
||||
nacosRestTemplate.close();
|
||||
}
|
||||
SINGLETON_REST.clear();
|
||||
/**
|
||||
* Shutdown sync http client holder and remove template.
|
||||
*
|
||||
* @param className HttpClientFactory implement class name
|
||||
* @throws Exception ex
|
||||
*/
|
||||
public static void shutdownNacostSyncRest(String className) throws Exception {
|
||||
final NacosRestTemplate nacosRestTemplate = SINGLETON_REST.get(className);
|
||||
if (nacosRestTemplate != null) {
|
||||
nacosRestTemplate.close();
|
||||
SINGLETON_REST.remove(className);
|
||||
}
|
||||
}
|
||||
|
||||
private static void nacosAsyncRestTemplateShutdown() throws Exception {
|
||||
if (!SINGLETON_ASYNC_REST.isEmpty()) {
|
||||
Collection<NacosAsyncRestTemplate> nacosAsyncRestTemplates = SINGLETON_ASYNC_REST.values();
|
||||
for (NacosAsyncRestTemplate nacosAsyncRestTemplate : nacosAsyncRestTemplates) {
|
||||
nacosAsyncRestTemplate.close();
|
||||
}
|
||||
SINGLETON_ASYNC_REST.clear();
|
||||
/**
|
||||
* Shutdown async http client holder and remove template.
|
||||
*
|
||||
* @param className HttpClientFactory implement class name
|
||||
* @throws Exception ex
|
||||
*/
|
||||
public static void shutdownNacosAsyncRest(String className) throws Exception {
|
||||
final NacosAsyncRestTemplate nacosAsyncRestTemplate = SINGLETON_ASYNC_REST.get(className);
|
||||
if (nacosAsyncRestTemplate != null) {
|
||||
nacosAsyncRestTemplate.close();
|
||||
SINGLETON_ASYNC_REST.remove(className);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -33,8 +33,8 @@ public class HttpRestResult<T> extends RestResult<T> {
|
||||
public HttpRestResult() {
|
||||
}
|
||||
|
||||
public HttpRestResult(Header header, int code, T data) {
|
||||
super(code, data);
|
||||
public HttpRestResult(Header header, int code, T data, String message) {
|
||||
super(code, message, data);
|
||||
this.header = header;
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,85 @@
|
||||
/*
|
||||
* 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.ResponseHandlerType;
|
||||
import com.alibaba.nacos.common.utils.JacksonUtils;
|
||||
import com.fasterxml.jackson.databind.JavaType;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* For NacosRestTemplate and NacosAsyncRestTemplate, provide initialization and register of response converter.
|
||||
*
|
||||
* @author mai.jh
|
||||
*/
|
||||
@SuppressWarnings("all")
|
||||
public abstract class AbstractNacosRestTemplate {
|
||||
|
||||
private final Map<String, ResponseHandler> responseHandlerMap = new HashMap<String, ResponseHandler>();
|
||||
|
||||
protected final Logger logger;
|
||||
|
||||
public AbstractNacosRestTemplate(Logger logger) {
|
||||
this.logger = logger;
|
||||
initDefaultResponseHandler();
|
||||
}
|
||||
|
||||
private void initDefaultResponseHandler() {
|
||||
// init response handler
|
||||
responseHandlerMap.put(ResponseHandlerType.STRING_TYPE, new StringResponseHandler());
|
||||
responseHandlerMap.put(ResponseHandlerType.RESTRESULT_TYPE, new RestResultResponseHandler());
|
||||
responseHandlerMap.put(ResponseHandlerType.DEFAULT_BEAN_TYPE, new BeanResponseHandler());
|
||||
}
|
||||
|
||||
/**
|
||||
* register customization Response Handler.
|
||||
*
|
||||
* @param responseHandler {@link ResponseHandler}
|
||||
*/
|
||||
public void registerResponseHandler(String responseHandlerType, ResponseHandler responseHandler) {
|
||||
responseHandlerMap.put(responseHandlerType, responseHandler);
|
||||
}
|
||||
|
||||
/**
|
||||
* Select a response handler by responseType.
|
||||
*
|
||||
* @param responseType responseType
|
||||
* @return ResponseHandler
|
||||
*/
|
||||
protected ResponseHandler selectResponseHandler(Type responseType) {
|
||||
ResponseHandler responseHandler = null;
|
||||
if (responseType == null) {
|
||||
responseHandler = responseHandlerMap.get(ResponseHandlerType.STRING_TYPE);
|
||||
}
|
||||
if (responseHandler == null) {
|
||||
JavaType javaType = JacksonUtils.constructJavaType(responseType);
|
||||
String name = javaType.getRawClass().getName();
|
||||
responseHandler = responseHandlerMap.get(name);
|
||||
}
|
||||
// When the corresponding type of response handler cannot be obtained,
|
||||
// the default bean response handler is used
|
||||
if (responseHandler == null) {
|
||||
responseHandler = responseHandlerMap.get(ResponseHandlerType.DEFAULT_BEAN_TYPE);
|
||||
}
|
||||
responseHandler.setResponseType(responseType);
|
||||
return responseHandler;
|
||||
}
|
||||
}
|
@ -0,0 +1,64 @@
|
||||
/*
|
||||
* 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.param.Header;
|
||||
import com.alibaba.nacos.common.utils.IoUtils;
|
||||
import org.apache.http.HttpStatus;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
/**
|
||||
* Abstract response handler.
|
||||
*
|
||||
* @author mai.jh
|
||||
*/
|
||||
public abstract class AbstractResponseHandler<T> implements ResponseHandler<T> {
|
||||
|
||||
private Type responseType;
|
||||
|
||||
@Override
|
||||
public final void setResponseType(Type responseType) {
|
||||
this.responseType = responseType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final HttpRestResult<T> handle(HttpClientResponse response) throws Exception {
|
||||
if (HttpStatus.SC_OK != response.getStatusCode()) {
|
||||
return handleError(response);
|
||||
}
|
||||
return convertResult(response, this.responseType);
|
||||
}
|
||||
|
||||
private HttpRestResult<T> handleError(HttpClientResponse response) throws Exception {
|
||||
Header headers = response.getHeaders();
|
||||
String message = IoUtils.toString(response.getBody(), headers.getCharset());
|
||||
return new HttpRestResult<T>(headers, response.getStatusCode(), null, message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Abstract convertResult method, Different types of converters for expansion.
|
||||
*
|
||||
* @param response http client response
|
||||
* @param responseType responseType
|
||||
* @return HttpRestResult
|
||||
* @throws Exception ex
|
||||
*/
|
||||
public abstract HttpRestResult<T> convertResult(HttpClientResponse response, Type responseType) throws Exception;
|
||||
|
||||
}
|
@ -20,7 +20,6 @@ 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;
|
||||
|
||||
/**
|
||||
@ -37,10 +36,10 @@ public interface AsyncHttpClientRequest extends Closeable {
|
||||
* @param uri http url
|
||||
* @param httpMethod http request method
|
||||
* @param requestHttpEntity http request entity
|
||||
* @param responseType http response type
|
||||
* @param responseHandler http response handler
|
||||
* @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;
|
||||
<T> void execute(URI uri, String httpMethod, RequestHttpEntity requestHttpEntity,
|
||||
final ResponseHandler<T> responseHandler, final Callback<T> callback) throws Exception;
|
||||
}
|
||||
|
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* 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.param.Header;
|
||||
import com.alibaba.nacos.common.utils.JacksonUtils;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
/**
|
||||
* bean response handler,
|
||||
* Mainly converter response type as bean type.
|
||||
*
|
||||
* @author mai.jh
|
||||
*/
|
||||
public class BeanResponseHandler<T> extends AbstractResponseHandler<T> {
|
||||
|
||||
@Override
|
||||
public HttpRestResult<T> convertResult(HttpClientResponse response, Type responseType) throws Exception {
|
||||
final Header headers = response.getHeaders();
|
||||
InputStream body = response.getBody();
|
||||
T extractBody = JacksonUtils.toObj(body, responseType);
|
||||
return new HttpRestResult<T>(headers, response.getStatusCode(), extractBody, null);
|
||||
}
|
||||
}
|
@ -18,7 +18,6 @@ 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;
|
||||
@ -26,7 +25,6 @@ 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;
|
||||
|
||||
/**
|
||||
@ -46,7 +44,7 @@ public class DefaultAsyncHttpClientRequest implements AsyncHttpClientRequest {
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> void execute(URI uri, String httpMethod, RequestHttpEntity requestHttpEntity, final Type responseType,
|
||||
public <T> void execute(URI uri, String httpMethod, RequestHttpEntity requestHttpEntity, final ResponseHandler<T> responseHandler,
|
||||
final Callback<T> callback) throws Exception {
|
||||
HttpRequestBase httpRequestBase = DefaultHttpClientRequest.build(uri, httpMethod, requestHttpEntity);
|
||||
asyncClient.execute(httpRequestBase, new FutureCallback<HttpResponse>() {
|
||||
@ -54,7 +52,7 @@ public class DefaultAsyncHttpClientRequest implements AsyncHttpClientRequest {
|
||||
public void completed(HttpResponse result) {
|
||||
DefaultClientHttpResponse response = new DefaultClientHttpResponse(result);
|
||||
try {
|
||||
HttpRestResult<T> httpRestResult = ResponseHandler.responseEntityExtractor(response, responseType);
|
||||
HttpRestResult<T> httpRestResult = responseHandler.handle(response);
|
||||
callback.onReceive(httpRestResult);
|
||||
} catch (Exception e) {
|
||||
callback.onError(e);
|
||||
|
@ -18,14 +18,14 @@ 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.HttpClientConfig;
|
||||
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.config.RequestConfig;
|
||||
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;
|
||||
@ -39,8 +39,6 @@ import java.util.Map;
|
||||
@SuppressWarnings({"unchecked", "resource"})
|
||||
public class DefaultHttpClientRequest implements HttpClientRequest {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(DefaultHttpClientRequest.class);
|
||||
|
||||
private final CloseableHttpClient client;
|
||||
|
||||
public DefaultHttpClientRequest(CloseableHttpClient client) {
|
||||
@ -52,9 +50,6 @@ public class DefaultHttpClientRequest implements HttpClientRequest {
|
||||
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);
|
||||
}
|
||||
|
||||
@ -69,7 +64,24 @@ public class DefaultHttpClientRequest implements HttpClientRequest {
|
||||
} else {
|
||||
httpMethod.initEntity(requestHttpEntity.getBody(), headers.getValue(HttpHeaderConsts.CONTENT_TYPE));
|
||||
}
|
||||
return httpMethod.getRequestBase();
|
||||
HttpRequestBase requestBase = httpMethod.getRequestBase();
|
||||
replaceDefaultConfig(requestBase, requestHttpEntity.getHttpClientConfig());
|
||||
return requestBase;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace the HTTP config created by default with the HTTP config specified in the request.
|
||||
*
|
||||
* @param requestBase requestBase
|
||||
* @param httpClientConfig http config
|
||||
*/
|
||||
private static void replaceDefaultConfig(HttpRequestBase requestBase, HttpClientConfig httpClientConfig) {
|
||||
if (httpClientConfig == null) {
|
||||
return;
|
||||
}
|
||||
requestBase.setConfig(RequestConfig.custom()
|
||||
.setConnectTimeout(httpClientConfig.getConTimeOutMillis())
|
||||
.setSocketTimeout(httpClientConfig.getReadTimeOutMillis()).build());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* 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.net.URI;
|
||||
|
||||
/**
|
||||
* Intercepts client-side HTTP requests. Implementations of this interface can be.
|
||||
*
|
||||
* @author mai.jh
|
||||
*/
|
||||
public interface HttpClientRequestInterceptor {
|
||||
|
||||
/**
|
||||
* is intercept.
|
||||
*
|
||||
* @param uri uri
|
||||
* @param httpMethod http method
|
||||
* @param requestHttpEntity request entity
|
||||
* @return boolean
|
||||
*/
|
||||
boolean isIntercept(URI uri, String httpMethod, RequestHttpEntity requestHttpEntity);
|
||||
|
||||
/**
|
||||
* if isIntercept method is true Intercept the given request, and return a response Otherwise,
|
||||
* the {@link HttpClientRequest} will be used for execution.
|
||||
*
|
||||
* @return HttpClientResponse
|
||||
*/
|
||||
HttpClientResponse intercept();
|
||||
}
|
@ -48,15 +48,17 @@ public interface HttpClientResponse extends Closeable {
|
||||
* Return the HTTP status code.
|
||||
*
|
||||
* @return the HTTP status as an integer
|
||||
* @throws IOException IOException
|
||||
*/
|
||||
int getStatusCode();
|
||||
int getStatusCode() throws IOException;
|
||||
|
||||
/**
|
||||
* Return the HTTP status text of the response.
|
||||
*
|
||||
* @return the HTTP status text
|
||||
* @throws IOException IOException
|
||||
*/
|
||||
String getStatusText();
|
||||
String getStatusText() throws IOException;
|
||||
|
||||
/**
|
||||
* close response InputStream.
|
||||
|
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* 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.IOException;
|
||||
import java.net.URI;
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* Wrap http client request and perform corresponding interception.
|
||||
*
|
||||
* @author mai.jh
|
||||
*/
|
||||
public class InterceptingHttpClientRequest implements HttpClientRequest {
|
||||
|
||||
private final HttpClientRequest httpClientRequest;
|
||||
|
||||
private final Iterator<HttpClientRequestInterceptor> interceptors;
|
||||
|
||||
public InterceptingHttpClientRequest(HttpClientRequest httpClientRequest,
|
||||
Iterator<HttpClientRequestInterceptor> interceptors) {
|
||||
this.httpClientRequest = httpClientRequest;
|
||||
this.interceptors = interceptors;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpClientResponse execute(URI uri, String httpMethod, RequestHttpEntity requestHttpEntity)
|
||||
throws Exception {
|
||||
while (interceptors.hasNext()) {
|
||||
HttpClientRequestInterceptor nextInterceptor = interceptors.next();
|
||||
if (nextInterceptor.isIntercept(uri, httpMethod, requestHttpEntity)) {
|
||||
return nextInterceptor.intercept();
|
||||
}
|
||||
}
|
||||
return httpClientRequest.execute(uri, httpMethod, requestHttpEntity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
httpClientRequest.close();
|
||||
}
|
||||
}
|
@ -0,0 +1,100 @@
|
||||
/*
|
||||
* 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.HttpClientConfig;
|
||||
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.model.RequestHttpEntity;
|
||||
import com.alibaba.nacos.common.utils.JacksonUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URI;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* JDK http client request implement.
|
||||
*
|
||||
* @author mai.jh
|
||||
*/
|
||||
public class JdkHttpClientRequest implements HttpClientRequest {
|
||||
|
||||
private HttpClientConfig httpClientConfig;
|
||||
|
||||
public JdkHttpClientRequest(HttpClientConfig httpClientConfig) {
|
||||
this.httpClientConfig = httpClientConfig;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpClientResponse execute(URI uri, String httpMethod, RequestHttpEntity requestHttpEntity)
|
||||
throws Exception {
|
||||
final Object body = requestHttpEntity.getBody();
|
||||
final Header headers = requestHttpEntity.getHeaders();
|
||||
replaceDefaultConfig(requestHttpEntity.getHttpClientConfig());
|
||||
|
||||
HttpURLConnection conn = (HttpURLConnection) uri.toURL().openConnection();
|
||||
Map<String, String> headerMap = headers.getHeader();
|
||||
if (headerMap != null && headerMap.size() > 0) {
|
||||
for (Map.Entry<String, String> entry : headerMap.entrySet()) {
|
||||
conn.setRequestProperty(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
conn.setConnectTimeout(this.httpClientConfig.getConTimeOutMillis());
|
||||
conn.setReadTimeout(this.httpClientConfig.getReadTimeOutMillis());
|
||||
conn.setRequestMethod(httpMethod);
|
||||
if (body != null) {
|
||||
String contentType = headers.getValue(HttpHeaderConsts.CONTENT_TYPE);
|
||||
String bodyStr = JacksonUtils.toJson(body);
|
||||
if (MediaType.APPLICATION_FORM_URLENCODED.equals(contentType)) {
|
||||
Map<String, String> map = JacksonUtils.toObj(bodyStr, HashMap.class);
|
||||
bodyStr = HttpUtils.encodingParams(map, headers.getCharset());
|
||||
}
|
||||
if (bodyStr != null) {
|
||||
conn.setDoOutput(true);
|
||||
byte[] b = bodyStr.getBytes();
|
||||
conn.setRequestProperty("Content-Length", String.valueOf(b.length));
|
||||
conn.getOutputStream().write(b, 0, b.length);
|
||||
conn.getOutputStream().flush();
|
||||
conn.getOutputStream().close();
|
||||
}
|
||||
}
|
||||
conn.connect();
|
||||
return new JdkHttpClientResponse(conn);
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace the HTTP config created by default with the HTTP config specified in the request.
|
||||
*
|
||||
* @param replaceConfig http config
|
||||
*/
|
||||
private void replaceDefaultConfig(HttpClientConfig replaceConfig) {
|
||||
if (replaceConfig == null) {
|
||||
return;
|
||||
}
|
||||
this.httpClientConfig = replaceConfig;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
|
||||
}
|
||||
}
|
@ -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.http.client;
|
||||
|
||||
import com.alibaba.nacos.common.http.param.Header;
|
||||
import com.alibaba.nacos.common.utils.IoUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.HttpURLConnection;
|
||||
|
||||
/**
|
||||
* JDk http client response implement.
|
||||
*
|
||||
* @author mai.jh
|
||||
*/
|
||||
public class JdkHttpClientResponse implements HttpClientResponse {
|
||||
|
||||
private final HttpURLConnection conn;
|
||||
|
||||
private InputStream responseStream;
|
||||
|
||||
private Header responseHeader;
|
||||
|
||||
public JdkHttpClientResponse(HttpURLConnection conn) {
|
||||
this.conn = conn;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Header getHeaders() {
|
||||
if (this.responseHeader == null) {
|
||||
this.responseHeader = Header.newInstance();
|
||||
}
|
||||
this.responseHeader.setOriginalResponseHeader(conn.getHeaderFields());
|
||||
return this.responseHeader;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getBody() throws IOException {
|
||||
InputStream errorStream = this.conn.getErrorStream();
|
||||
this.responseStream = (errorStream != null ? errorStream : this.conn.getInputStream());
|
||||
return this.responseStream;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getStatusCode() throws IOException {
|
||||
return this.conn.getResponseCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getStatusText() throws IOException {
|
||||
return this.conn.getResponseMessage();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
IoUtils.closeQuietly(this.responseStream);
|
||||
}
|
||||
}
|
@ -24,7 +24,6 @@ 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;
|
||||
@ -37,13 +36,12 @@ import java.util.Map;
|
||||
* @see AsyncHttpClientRequest
|
||||
* @see HttpClientResponse
|
||||
*/
|
||||
public class NacosAsyncRestTemplate {
|
||||
public class NacosAsyncRestTemplate extends AbstractNacosRestTemplate {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(NacosAsyncRestTemplate.class);
|
||||
private final AsyncHttpClientRequest clientRequest;
|
||||
|
||||
private AsyncHttpClientRequest clientRequest;
|
||||
|
||||
public NacosAsyncRestTemplate(AsyncHttpClientRequest clientRequest) {
|
||||
public NacosAsyncRestTemplate(Logger logger, AsyncHttpClientRequest clientRequest) {
|
||||
super(logger);
|
||||
this.clientRequest = clientRequest;
|
||||
}
|
||||
|
||||
@ -330,13 +328,15 @@ public class NacosAsyncRestTemplate {
|
||||
|
||||
}
|
||||
|
||||
private <T> void execute(String url, String httpMethod, RequestHttpEntity requestEntity, Type responseType,
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T> void execute(String url, String httpMethod, RequestHttpEntity requestEntity, Type type,
|
||||
Callback<T> callback) throws Exception {
|
||||
URI uri = HttpUtils.buildUri(url, requestEntity.getQuery());
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("HTTP " + httpMethod + " " + url);
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("HTTP method: {}, url: {}, body: {}", httpMethod, uri, requestEntity.getBody());
|
||||
}
|
||||
clientRequest.execute(uri, httpMethod, requestEntity, responseType, callback);
|
||||
ResponseHandler<T> responseHandler = super.selectResponseHandler(type);
|
||||
clientRequest.execute(uri, httpMethod, requestEntity, responseHandler, callback);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -16,19 +16,21 @@
|
||||
|
||||
package com.alibaba.nacos.common.http.client;
|
||||
|
||||
import com.alibaba.nacos.common.http.HttpClientConfig;
|
||||
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.CollectionUtils;
|
||||
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.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
@ -38,13 +40,14 @@ import java.util.Map;
|
||||
* @see HttpClientRequest
|
||||
* @see HttpClientResponse
|
||||
*/
|
||||
public class NacosRestTemplate {
|
||||
public class NacosRestTemplate extends AbstractNacosRestTemplate {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(NacosRestTemplate.class);
|
||||
private final HttpClientRequest requestClient;
|
||||
|
||||
private HttpClientRequest requestClient;
|
||||
private final List<HttpClientRequestInterceptor> interceptors = new ArrayList<HttpClientRequestInterceptor>();
|
||||
|
||||
public NacosRestTemplate(HttpClientRequest requestClient) {
|
||||
public NacosRestTemplate(Logger logger, HttpClientRequest requestClient) {
|
||||
super(logger);
|
||||
this.requestClient = requestClient;
|
||||
}
|
||||
|
||||
@ -83,6 +86,28 @@ public class NacosRestTemplate {
|
||||
return execute(url, HttpMethod.GET, requestHttpEntity, 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.
|
||||
*
|
||||
* <p>{@code config} Specify the request config via {@link HttpClientConfig}
|
||||
*
|
||||
* @param url url
|
||||
* @param config http config
|
||||
* @param header headers
|
||||
* @param paramValues paramValues
|
||||
* @param responseType return type
|
||||
* @return {@link HttpRestResult}
|
||||
* @throws Exception ex
|
||||
*/
|
||||
public <T> HttpRestResult<T> get(String url, HttpClientConfig config, Header header,
|
||||
Map<String, String> paramValues, Type responseType) throws Exception {
|
||||
RequestHttpEntity requestHttpEntity = new RequestHttpEntity(config, 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.
|
||||
@ -118,6 +143,27 @@ public class NacosRestTemplate {
|
||||
return execute(url, HttpMethod.DELETE, new RequestHttpEntity(header, query), 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.
|
||||
*
|
||||
* <p>{@code config} Specify the request config via {@link HttpClientConfig}
|
||||
*
|
||||
* @param url url
|
||||
* @param config http config
|
||||
* @param header http header param
|
||||
* @param paramValues http query param
|
||||
* @param responseType return type
|
||||
* @return {@link HttpRestResult}
|
||||
* @throws Exception ex
|
||||
*/
|
||||
public <T> HttpRestResult<T> delete(String url, HttpClientConfig config, Header header,
|
||||
Map<String, String> paramValues, Type responseType) throws Exception {
|
||||
return execute(url, HttpMethod.DELETE,
|
||||
new RequestHttpEntity(config, header, Query.newInstance().initParams(paramValues)), responseType);
|
||||
}
|
||||
|
||||
/**
|
||||
* http put Create a new resource by PUTting the given body to http request.
|
||||
*
|
||||
@ -208,6 +254,33 @@ public class NacosRestTemplate {
|
||||
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.
|
||||
*
|
||||
* <p>{@code config} Specify the request config via {@link HttpClientConfig}
|
||||
*
|
||||
* @param url url
|
||||
* @param config http config
|
||||
* @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> putForm(String url, HttpClientConfig config, Header header,
|
||||
Map<String, String> paramValues, Map<String, String> bodyValues, Type responseType) throws Exception {
|
||||
RequestHttpEntity requestHttpEntity = new RequestHttpEntity(config,
|
||||
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.
|
||||
*
|
||||
@ -298,6 +371,33 @@ public class NacosRestTemplate {
|
||||
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.
|
||||
*
|
||||
* <p>{@code config} Specify the request config via {@link HttpClientConfig}
|
||||
*
|
||||
* @param url url
|
||||
* @param config http config
|
||||
* @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> postForm(String url, HttpClientConfig config, Header header,
|
||||
Map<String, String> paramValues, Map<String, String> bodyValues, Type responseType) throws Exception {
|
||||
RequestHttpEntity requestHttpEntity = new RequestHttpEntity(config,
|
||||
header.setContentType(MediaType.APPLICATION_FORM_URLENCODED),
|
||||
Query.newInstance().initParams(paramValues), bodyValues);
|
||||
return execute(url, HttpMethod.POST, requestHttpEntity, responseType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the HTTP method to the given URI template, writing the given request entity to the request, and returns
|
||||
* the response as {@link HttpRestResult}.
|
||||
@ -319,16 +419,40 @@ public class NacosRestTemplate {
|
||||
return execute(url, httpMethod, requestHttpEntity, responseType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the request interceptors that this accessor should use.
|
||||
*
|
||||
* @param interceptors {@link HttpClientRequestInterceptor}
|
||||
*/
|
||||
public void setInterceptors(List<HttpClientRequestInterceptor> interceptors) {
|
||||
if (this.interceptors != interceptors) {
|
||||
this.interceptors.clear();
|
||||
this.interceptors.addAll(interceptors);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the request interceptors that this accessor uses.
|
||||
*
|
||||
* <p>The returned {@link List} is active and may get appended to.
|
||||
*/
|
||||
public List<HttpClientRequestInterceptor> getInterceptors() {
|
||||
return interceptors;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
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);
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("HTTP method: {}, url: {}, body: {}", httpMethod, uri, requestEntity.getBody());
|
||||
}
|
||||
|
||||
ResponseHandler<T> responseHandler = super.selectResponseHandler(responseType);
|
||||
HttpClientResponse response = null;
|
||||
try {
|
||||
response = requestClient.execute(uri, httpMethod, requestEntity);
|
||||
return ResponseHandler.responseEntityExtractor(response, responseType);
|
||||
response = this.requestClient().execute(uri, httpMethod, requestEntity);
|
||||
return responseHandler.handle(response);
|
||||
} finally {
|
||||
if (response != null) {
|
||||
response.close();
|
||||
@ -336,6 +460,16 @@ public class NacosRestTemplate {
|
||||
}
|
||||
}
|
||||
|
||||
private HttpClientRequest requestClient() {
|
||||
if (CollectionUtils.isNotEmpty(interceptors)) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Execute via interceptors :{}", interceptors);
|
||||
}
|
||||
return new InterceptingHttpClientRequest(requestClient, interceptors.iterator());
|
||||
}
|
||||
return requestClient;
|
||||
}
|
||||
|
||||
/**
|
||||
* close request client.
|
||||
*/
|
||||
|
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* 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 java.lang.reflect.Type;
|
||||
|
||||
/**
|
||||
* Response Handler abstract interface,
|
||||
* the actual processing of the response conversion is done by a concrete implementation class.
|
||||
*
|
||||
* @author mai.jh
|
||||
*/
|
||||
public interface ResponseHandler<T> {
|
||||
|
||||
/**
|
||||
* set response type.
|
||||
*
|
||||
* @param responseType responseType
|
||||
*/
|
||||
void setResponseType(Type responseType);
|
||||
|
||||
/**
|
||||
* handle response convert to HttpRestResult.
|
||||
*
|
||||
* @param response http response
|
||||
* @return HttpRestResult {@link HttpRestResult}
|
||||
* @throws Exception ex
|
||||
*/
|
||||
HttpRestResult<T> handle(HttpClientResponse response) throws Exception;
|
||||
|
||||
}
|
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* 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.param.Header;
|
||||
import com.alibaba.nacos.common.model.RestResult;
|
||||
import com.alibaba.nacos.common.utils.JacksonUtils;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
/**
|
||||
* RestResult response handler, Mainly converter response type as {@link RestResult} type.
|
||||
*
|
||||
* @author mai.jh
|
||||
*/
|
||||
public class RestResultResponseHandler<T> extends AbstractResponseHandler<T> {
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public HttpRestResult<T> convertResult(HttpClientResponse response, Type responseType) throws Exception {
|
||||
final Header headers = response.getHeaders();
|
||||
InputStream body = response.getBody();
|
||||
T extractBody = JacksonUtils.toObj(body, responseType);
|
||||
HttpRestResult<T> httpRestResult = convert((RestResult<T>) extractBody);
|
||||
httpRestResult.setHeader(headers);
|
||||
return httpRestResult;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* 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.param.Header;
|
||||
import com.alibaba.nacos.common.utils.IoUtils;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
/**
|
||||
* string response handler, Mainly converter response type as string type.
|
||||
*
|
||||
* @author mai.jh
|
||||
*/
|
||||
public class StringResponseHandler extends AbstractResponseHandler<String> {
|
||||
|
||||
@Override
|
||||
public HttpRestResult<String> convertResult(HttpClientResponse response, Type responseType) throws Exception {
|
||||
final Header headers = response.getHeaders();
|
||||
String extractBody = IoUtils.toString(response.getBody(), headers.getCharset());
|
||||
return new HttpRestResult<String>(headers, response.getStatusCode(), extractBody, null);
|
||||
}
|
||||
}
|
@ -16,18 +16,7 @@
|
||||
|
||||
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.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.lang.reflect.Type;
|
||||
@ -39,8 +28,6 @@ import java.lang.reflect.Type;
|
||||
*/
|
||||
public final class ResponseHandler {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(ResponseHandler.class);
|
||||
|
||||
public static <T> T convert(String s, Class<T> cls) throws Exception {
|
||||
return JacksonUtils.toObj(s, cls);
|
||||
}
|
||||
@ -52,55 +39,4 @@ public final class ResponseHandler {
|
||||
public static <T> T convert(InputStream inputStream, Type type) throws Exception {
|
||||
return JacksonUtils.toObj(inputStream, type);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract response entity to {@link HttpRestResult}.
|
||||
*
|
||||
* @param response response
|
||||
* @param type type
|
||||
* @param <T> general type
|
||||
* @return {@link HttpRestResult}
|
||||
* @throws Exception exception
|
||||
*/
|
||||
@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;
|
||||
final boolean typeToStr = String.class.toString().equals(type.toString());
|
||||
if (contentType != null && contentType.startsWith(MediaType.APPLICATION_JSON) && HttpStatus.SC_OK == response
|
||||
.getStatusCode()) {
|
||||
// When the type is string type and the response contentType is [application/json],
|
||||
// then it should be serialized as string
|
||||
if (typeToStr) {
|
||||
extractBody = (T) IoUtils.toString(body, headers.getCharset());
|
||||
} else {
|
||||
extractBody = convert(body, type);
|
||||
}
|
||||
}
|
||||
if (extractBody == null) {
|
||||
if (!typeToStr) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -37,8 +37,11 @@ public class Header {
|
||||
|
||||
private final Map<String, String> header;
|
||||
|
||||
private final Map<String, List<String>> originalResponseHeader;
|
||||
|
||||
private Header() {
|
||||
header = new LinkedHashMap<String, String>();
|
||||
originalResponseHeader = new LinkedHashMap<String, List<String>>();
|
||||
addParam(HttpHeaderConsts.CONTENT_TYPE, MediaType.APPLICATION_JSON);
|
||||
addParam(HttpHeaderConsts.ACCEPT_CHARSET, "UTF-8");
|
||||
addParam(HttpHeaderConsts.ACCEPT_ENCODING, "gzip");
|
||||
@ -120,6 +123,31 @@ public class Header {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* set original format response header.
|
||||
*
|
||||
* <p>Currently only corresponds to the response header of JDK.
|
||||
*
|
||||
* @param headers original response header
|
||||
*/
|
||||
public void setOriginalResponseHeader(Map<String, List<String>> headers) {
|
||||
this.originalResponseHeader.putAll(headers);
|
||||
for (Map.Entry<String, List<String>> entry : this.originalResponseHeader.entrySet()) {
|
||||
addParam(entry.getKey(), entry.getValue().get(0));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* get original format response header.
|
||||
*
|
||||
* <p>Currently only corresponds to the response header of JDK.
|
||||
*
|
||||
* @return Map original response header
|
||||
*/
|
||||
public Map<String, List<String>> getOriginalResponseHeader() {
|
||||
return this.originalResponseHeader;
|
||||
}
|
||||
|
||||
public String getCharset() {
|
||||
String acceptCharset = getValue(HttpHeaderConsts.ACCEPT_CHARSET);
|
||||
if (acceptCharset == null) {
|
||||
@ -145,6 +173,7 @@ public class Header {
|
||||
|
||||
public void clear() {
|
||||
header.clear();
|
||||
originalResponseHeader.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
package com.alibaba.nacos.common.model;
|
||||
|
||||
import com.alibaba.nacos.common.http.HttpClientConfig;
|
||||
import com.alibaba.nacos.common.http.param.Header;
|
||||
import com.alibaba.nacos.common.http.param.Query;
|
||||
|
||||
@ -31,17 +32,27 @@ public class RequestHttpEntity {
|
||||
|
||||
private final Header headers = Header.newInstance();
|
||||
|
||||
private final HttpClientConfig httpClientConfig;
|
||||
|
||||
private final Query query;
|
||||
|
||||
private Object body;
|
||||
|
||||
public RequestHttpEntity(Header header, Query query) {
|
||||
handleHeader(header);
|
||||
this.query = query;
|
||||
this(null, header, query);
|
||||
}
|
||||
|
||||
public RequestHttpEntity(HttpClientConfig httpClientConfig, Header header, Query query) {
|
||||
this(httpClientConfig, header, query, null);
|
||||
}
|
||||
|
||||
public RequestHttpEntity(Header header, Query query, Object body) {
|
||||
this(null, header, query, body);
|
||||
}
|
||||
|
||||
public RequestHttpEntity(HttpClientConfig httpClientConfig, Header header, Query query, Object body) {
|
||||
handleHeader(header);
|
||||
this.httpClientConfig = httpClientConfig;
|
||||
this.query = query;
|
||||
this.body = body;
|
||||
}
|
||||
@ -65,6 +76,10 @@ public class RequestHttpEntity {
|
||||
return body;
|
||||
}
|
||||
|
||||
public HttpClientConfig getHttpClientConfig() {
|
||||
return httpClientConfig;
|
||||
}
|
||||
|
||||
public boolean isEmptyBody() {
|
||||
return body == null;
|
||||
}
|
||||
|
@ -16,7 +16,6 @@
|
||||
|
||||
package com.alibaba.nacos.common.notify;
|
||||
|
||||
import com.alibaba.nacos.api.exception.NacosException;
|
||||
import com.alibaba.nacos.api.exception.runtime.NacosRuntimeException;
|
||||
import com.alibaba.nacos.common.JustForTest;
|
||||
import com.alibaba.nacos.common.notify.listener.Subscriber;
|
||||
@ -291,7 +290,9 @@ public class NotifyCenter {
|
||||
EventPublisher publisher = INSTANCE.publisherMap.get(topic);
|
||||
return publisher.publish(event);
|
||||
}
|
||||
throw new NoSuchElementException("There are no [" + topic + "] publishers for this event, please register");
|
||||
|
||||
LOGGER.warn("There are no [{}] publishers for this event, please register", topic);
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -310,8 +311,7 @@ public class NotifyCenter {
|
||||
* @param eventType class Instances type of the event type.
|
||||
* @param queueMaxSize the publisher's queue max size.
|
||||
*/
|
||||
public static EventPublisher registerToPublisher(final Class<? extends Event> eventType, final int queueMaxSize)
|
||||
throws NacosException {
|
||||
public static EventPublisher registerToPublisher(final Class<? extends Event> eventType, final int queueMaxSize) {
|
||||
if (ClassUtils.isAssignableFrom(SlowEvent.class, eventType)) {
|
||||
return INSTANCE.sharePublisher;
|
||||
}
|
||||
|
@ -22,6 +22,7 @@ import com.fasterxml.jackson.annotation.JsonInclude.Include;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||
import com.fasterxml.jackson.databind.JavaType;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.jsontype.NamedType;
|
||||
@ -264,4 +265,14 @@ public final class JacksonUtils {
|
||||
public static JsonNode transferToJsonNode(Object obj) {
|
||||
return mapper.valueToTree(obj);
|
||||
}
|
||||
|
||||
/**
|
||||
* construct java type -> Jackson Java Type.
|
||||
*
|
||||
* @param type java type
|
||||
* @return JavaType {@link JavaType}
|
||||
*/
|
||||
public static JavaType constructJavaType(Type type) {
|
||||
return mapper.constructType(type);
|
||||
}
|
||||
}
|
||||
|
@ -35,6 +35,7 @@ import java.util.concurrent.atomic.AtomicLong;
|
||||
public class NotifyCenterTest {
|
||||
|
||||
private static class TestSlowEvent extends SlowEvent {
|
||||
|
||||
}
|
||||
|
||||
private static class TestEvent extends Event {
|
||||
@ -330,9 +331,11 @@ public class NotifyCenterTest {
|
||||
}
|
||||
|
||||
private static class TestSlowEvent1 extends SlowEvent {
|
||||
|
||||
}
|
||||
|
||||
private static class TestSlowEvent2 extends SlowEvent {
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -343,10 +346,10 @@ public class NotifyCenterTest {
|
||||
|
||||
final AtomicInteger count1 = new AtomicInteger(0);
|
||||
final AtomicInteger count2 = new AtomicInteger(0);
|
||||
|
||||
|
||||
final CountDownLatch latch1 = new CountDownLatch(3);
|
||||
final CountDownLatch latch2 = new CountDownLatch(3);
|
||||
|
||||
|
||||
NotifyCenter.registerSubscriber(new Subscriber<TestSlowEvent1>() {
|
||||
@Override
|
||||
public void onEvent(TestSlowEvent1 event) {
|
||||
@ -365,7 +368,7 @@ public class NotifyCenterTest {
|
||||
public void onEvent(TestSlowEvent2 event) {
|
||||
count2.incrementAndGet();
|
||||
latch2.countDown();
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -373,26 +376,28 @@ public class NotifyCenterTest {
|
||||
return TestSlowEvent2.class;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
Assert.assertTrue(NotifyCenter.publishEvent(new TestSlowEvent1()));
|
||||
Assert.assertTrue(NotifyCenter.publishEvent(new TestSlowEvent2()));
|
||||
}
|
||||
|
||||
|
||||
ThreadUtils.sleep(2000L);
|
||||
|
||||
|
||||
latch1.await(3000L, TimeUnit.MILLISECONDS);
|
||||
latch2.await(3000L, TimeUnit.MILLISECONDS);
|
||||
|
||||
|
||||
Assert.assertEquals(3, count1.get());
|
||||
Assert.assertEquals(3, count2.get());
|
||||
|
||||
|
||||
}
|
||||
|
||||
private static class TestSlowEvent3 extends SlowEvent {
|
||||
|
||||
}
|
||||
|
||||
private static class TestSlowEvent4 extends SlowEvent {
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -408,7 +413,7 @@ public class NotifyCenterTest {
|
||||
final CountDownLatch latch2 = new CountDownLatch(3);
|
||||
|
||||
NotifyCenter.registerSubscriber(new SmartSubscriber() {
|
||||
|
||||
|
||||
@Override
|
||||
public void onEvent(Event event) {
|
||||
if (event instanceof TestSlowEvent3) {
|
||||
@ -421,7 +426,7 @@ public class NotifyCenterTest {
|
||||
latch2.countDown();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public List<Class<? extends Event>> subscribeTypes() {
|
||||
List<Class<? extends Event>> subTypes = new ArrayList<Class<? extends Event>>();
|
||||
@ -447,9 +452,11 @@ public class NotifyCenterTest {
|
||||
}
|
||||
|
||||
private static class TestSlowEvent5 extends SlowEvent {
|
||||
|
||||
}
|
||||
|
||||
private static class TestEvent6 extends Event {
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -502,4 +509,16 @@ public class NotifyCenterTest {
|
||||
Assert.assertEquals(3, count2.get());
|
||||
|
||||
}
|
||||
|
||||
private static class TestEvent7 extends Event {
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPublishEventByNoSubscriber() {
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
Assert.assertFalse(NotifyCenter.publishEvent(new TestEvent7()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -19,6 +19,7 @@ package com.alibaba.nacos.config.server.controller;
|
||||
import com.alibaba.nacos.common.model.RestResult;
|
||||
import com.alibaba.nacos.common.model.RestResultUtils;
|
||||
import com.alibaba.nacos.common.utils.Objects;
|
||||
import com.alibaba.nacos.common.notify.NotifyCenter;
|
||||
import com.alibaba.nacos.config.server.constant.Constants;
|
||||
import com.alibaba.nacos.config.server.model.event.DerbyImportEvent;
|
||||
import com.alibaba.nacos.config.server.service.datasource.DynamicDataSource;
|
||||
@ -30,7 +31,6 @@ import com.alibaba.nacos.config.server.utils.LogUtil;
|
||||
import com.alibaba.nacos.config.server.utils.PropertyUtil;
|
||||
import com.alibaba.nacos.core.auth.ActionTypes;
|
||||
import com.alibaba.nacos.core.auth.Secured;
|
||||
import com.alibaba.nacos.core.notify.NotifyCenter;
|
||||
import com.alibaba.nacos.core.utils.ApplicationUtils;
|
||||
import com.alibaba.nacos.core.utils.WebUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
@ -17,6 +17,9 @@
|
||||
package com.alibaba.nacos.config.server.filter;
|
||||
|
||||
import com.alibaba.nacos.common.utils.ExceptionUtil;
|
||||
import com.alibaba.nacos.common.notify.Event;
|
||||
import com.alibaba.nacos.common.notify.NotifyCenter;
|
||||
import com.alibaba.nacos.common.notify.listener.SmartSubscriber;
|
||||
import com.alibaba.nacos.config.server.constant.Constants;
|
||||
import com.alibaba.nacos.config.server.model.event.RaftDbErrorEvent;
|
||||
import com.alibaba.nacos.config.server.model.event.RaftDbErrorRecoverEvent;
|
||||
@ -26,9 +29,6 @@ import com.alibaba.nacos.core.cluster.Member;
|
||||
import com.alibaba.nacos.core.cluster.MemberMetaDataConstants;
|
||||
import com.alibaba.nacos.core.cluster.ServerMemberManager;
|
||||
import com.alibaba.nacos.core.code.ControllerMethodsCache;
|
||||
import com.alibaba.nacos.core.notify.Event;
|
||||
import com.alibaba.nacos.core.notify.NotifyCenter;
|
||||
import com.alibaba.nacos.core.notify.listener.SmartSubscribe;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
@ -41,6 +41,7 @@ import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.security.AccessControlException;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@ -119,7 +120,7 @@ public class CurcuitFilter implements Filter {
|
||||
}
|
||||
|
||||
private void registerSubscribe() {
|
||||
NotifyCenter.registerSubscribe(new SmartSubscribe() {
|
||||
NotifyCenter.registerSubscriber(new SmartSubscriber() {
|
||||
|
||||
@Override
|
||||
public void onEvent(Event event) {
|
||||
@ -135,8 +136,8 @@ public class CurcuitFilter implements Filter {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canNotify(Event event) {
|
||||
return (event instanceof RaftDbErrorEvent) || (event instanceof RaftDbErrorRecoverEvent);
|
||||
public List<Class<? extends Event>> subscribeTypes() {
|
||||
return Arrays.asList(RaftDbErrorRecoverEvent.class, RaftDbErrorEvent.class);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
package com.alibaba.nacos.config.server.model.event;
|
||||
|
||||
import com.alibaba.nacos.config.server.utils.event.EventDispatcher.Event;
|
||||
import com.alibaba.nacos.common.notify.Event;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
/**
|
||||
@ -24,7 +24,7 @@ import org.apache.commons.lang3.StringUtils;
|
||||
*
|
||||
* @author Nacos
|
||||
*/
|
||||
public class ConfigDataChangeEvent implements Event {
|
||||
public class ConfigDataChangeEvent extends Event {
|
||||
|
||||
public final boolean isBeta;
|
||||
|
||||
|
@ -16,14 +16,14 @@
|
||||
|
||||
package com.alibaba.nacos.config.server.model.event;
|
||||
|
||||
import com.alibaba.nacos.core.notify.Event;
|
||||
import com.alibaba.nacos.common.notify.Event;
|
||||
|
||||
/**
|
||||
* ConfigDumpEvent.
|
||||
*
|
||||
* @author <a href="mailto:liaochuntao@live.com">liaochuntao</a>
|
||||
*/
|
||||
public class ConfigDumpEvent implements Event {
|
||||
public class ConfigDumpEvent extends Event {
|
||||
|
||||
private static final long serialVersionUID = -8776888606458370294L;
|
||||
|
||||
@ -222,7 +222,7 @@ public class ConfigDumpEvent implements Event {
|
||||
this.lastModifiedTs = lastModifiedTs;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Build a configDumpEvent.
|
||||
*
|
||||
|
@ -16,14 +16,14 @@
|
||||
|
||||
package com.alibaba.nacos.config.server.model.event;
|
||||
|
||||
import com.alibaba.nacos.core.notify.SlowEvent;
|
||||
import com.alibaba.nacos.common.notify.SlowEvent;
|
||||
|
||||
/**
|
||||
* Data import event.
|
||||
*
|
||||
* @author <a href="mailto:liaochuntao@live.com">liaochuntao</a>
|
||||
*/
|
||||
public class DerbyImportEvent implements SlowEvent {
|
||||
public class DerbyImportEvent extends SlowEvent {
|
||||
|
||||
private static final long serialVersionUID = 3299565864352399053L;
|
||||
|
||||
|
@ -16,14 +16,14 @@
|
||||
|
||||
package com.alibaba.nacos.config.server.model.event;
|
||||
|
||||
import com.alibaba.nacos.core.notify.SlowEvent;
|
||||
import com.alibaba.nacos.common.notify.SlowEvent;
|
||||
|
||||
/**
|
||||
* DerbyLoadEvent.
|
||||
*
|
||||
* @author <a href="mailto:liaochuntao@live.com">liaochuntao</a>
|
||||
*/
|
||||
public class DerbyLoadEvent implements SlowEvent {
|
||||
public class DerbyLoadEvent extends SlowEvent {
|
||||
|
||||
public static final DerbyLoadEvent INSTANCE = new DerbyLoadEvent();
|
||||
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
package com.alibaba.nacos.config.server.model.event;
|
||||
|
||||
import com.alibaba.nacos.config.server.utils.event.EventDispatcher.Event;
|
||||
import com.alibaba.nacos.common.notify.Event;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@ -25,7 +25,7 @@ import java.util.List;
|
||||
*
|
||||
* @author Nacos
|
||||
*/
|
||||
public class LocalDataChangeEvent implements Event {
|
||||
public class LocalDataChangeEvent extends Event {
|
||||
|
||||
public final String groupKey;
|
||||
|
||||
|
@ -16,14 +16,14 @@
|
||||
|
||||
package com.alibaba.nacos.config.server.model.event;
|
||||
|
||||
import com.alibaba.nacos.core.notify.SlowEvent;
|
||||
import com.alibaba.nacos.common.notify.SlowEvent;
|
||||
|
||||
/**
|
||||
* RaftDBErrorEvent.
|
||||
*
|
||||
* @author <a href="mailto:liaochunyhm@live.com">liaochuntao</a>
|
||||
*/
|
||||
public class RaftDbErrorEvent implements SlowEvent {
|
||||
public class RaftDbErrorEvent extends SlowEvent {
|
||||
|
||||
private static final long serialVersionUID = 101591819161802336L;
|
||||
|
||||
|
@ -17,7 +17,7 @@
|
||||
package com.alibaba.nacos.config.server.model.event;
|
||||
|
||||
import com.alibaba.nacos.common.JustForTest;
|
||||
import com.alibaba.nacos.core.notify.Event;
|
||||
import com.alibaba.nacos.common.notify.Event;
|
||||
|
||||
/**
|
||||
* RaftDBErrorRecoverEvent.
|
||||
@ -25,6 +25,6 @@ import com.alibaba.nacos.core.notify.Event;
|
||||
* @author <a href="mailto:liaochuntao@live.com">liaochuntao</a>
|
||||
*/
|
||||
@JustForTest
|
||||
public class RaftDbErrorRecoverEvent implements Event {
|
||||
public class RaftDbErrorRecoverEvent extends Event {
|
||||
|
||||
}
|
||||
|
@ -35,13 +35,14 @@ public class MemoryMonitor {
|
||||
@Autowired
|
||||
public MemoryMonitor(AsyncNotifyService notifySingleService) {
|
||||
|
||||
ConfigExecutor.scheduleWithFixedDelay(new PrintMemoryTask(), DELAY_SECONDS, DELAY_SECONDS, TimeUnit.SECONDS);
|
||||
ConfigExecutor.scheduleConfigTask(new PrintMemoryTask(), DELAY_SECONDS, DELAY_SECONDS, TimeUnit.SECONDS);
|
||||
|
||||
ConfigExecutor.scheduleWithFixedDelay(new PrintGetConfigResponeTask(), DELAY_SECONDS, DELAY_SECONDS,
|
||||
TimeUnit.SECONDS);
|
||||
ConfigExecutor
|
||||
.scheduleConfigTask(new PrintGetConfigResponeTask(), DELAY_SECONDS, DELAY_SECONDS, TimeUnit.SECONDS);
|
||||
|
||||
ConfigExecutor.scheduleWithFixedDelay(new NotifyTaskQueueMonitorTask(notifySingleService), DELAY_SECONDS,
|
||||
DELAY_SECONDS, TimeUnit.SECONDS);
|
||||
ConfigExecutor
|
||||
.scheduleConfigTask(new NotifyTaskQueueMonitorTask(notifySingleService), DELAY_SECONDS, DELAY_SECONDS,
|
||||
TimeUnit.SECONDS);
|
||||
|
||||
}
|
||||
|
||||
|
@ -17,8 +17,7 @@
|
||||
package com.alibaba.nacos.config.server.monitor;
|
||||
|
||||
import com.alibaba.nacos.config.server.service.notify.AsyncNotifyService;
|
||||
|
||||
import java.util.concurrent.ScheduledThreadPoolExecutor;
|
||||
import com.alibaba.nacos.config.server.utils.ConfigExecutor;
|
||||
|
||||
import static com.alibaba.nacos.config.server.utils.LogUtil.MEMORY_LOG;
|
||||
|
||||
@ -37,7 +36,7 @@ public class NotifyTaskQueueMonitorTask implements Runnable {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
int size = ((ScheduledThreadPoolExecutor) notifySingleService.getExecutor()).getQueue().size();
|
||||
int size = ConfigExecutor.asyncNotifyQueueSize();
|
||||
MEMORY_LOG.info("toNotifyTaskSize = {}", size);
|
||||
MetricsMonitor.getNotifyTaskMonitor().set(size);
|
||||
}
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
package com.alibaba.nacos.config.server.service;
|
||||
|
||||
import com.alibaba.nacos.common.notify.NotifyCenter;
|
||||
import com.alibaba.nacos.common.utils.MD5Utils;
|
||||
import com.alibaba.nacos.config.server.constant.Constants;
|
||||
import com.alibaba.nacos.config.server.model.CacheItem;
|
||||
@ -26,7 +27,6 @@ import com.alibaba.nacos.config.server.utils.DiskUtil;
|
||||
import com.alibaba.nacos.config.server.utils.GroupKey;
|
||||
import com.alibaba.nacos.config.server.utils.GroupKey2;
|
||||
import com.alibaba.nacos.config.server.utils.PropertyUtil;
|
||||
import com.alibaba.nacos.config.server.utils.event.EventDispatcher;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@ -67,12 +67,12 @@ public class ConfigCacheService {
|
||||
/**
|
||||
* Save config file and update md5 value in cache.
|
||||
*
|
||||
* @param dataId dataId string value.
|
||||
* @param group group string value.
|
||||
* @param tenant tenant string value.
|
||||
* @param content content string value.
|
||||
* @param dataId dataId string value.
|
||||
* @param group group string value.
|
||||
* @param tenant tenant string value.
|
||||
* @param content content string value.
|
||||
* @param lastModifiedTs lastModifiedTs.
|
||||
* @param type file type.
|
||||
* @param type file type.
|
||||
* @return dumpChange success or not.
|
||||
*/
|
||||
public static boolean dump(String dataId, String group, String tenant, String content, long lastModifiedTs,
|
||||
@ -120,12 +120,12 @@ public class ConfigCacheService {
|
||||
/**
|
||||
* Save config file and update md5 value in cache.
|
||||
*
|
||||
* @param dataId dataId string value.
|
||||
* @param group group string value.
|
||||
* @param tenant tenant string value.
|
||||
* @param content content string value.
|
||||
* @param dataId dataId string value.
|
||||
* @param group group string value.
|
||||
* @param tenant tenant string value.
|
||||
* @param content content string value.
|
||||
* @param lastModifiedTs lastModifiedTs.
|
||||
* @param betaIps betaIps string value.
|
||||
* @param betaIps betaIps string value.
|
||||
* @return dumpChange success or not.
|
||||
*/
|
||||
public static boolean dumpBeta(String dataId, String group, String tenant, String content, long lastModifiedTs,
|
||||
@ -165,12 +165,12 @@ public class ConfigCacheService {
|
||||
/**
|
||||
* Save config file and update md5 value in cache.
|
||||
*
|
||||
* @param dataId dataId string value.
|
||||
* @param group group string value.
|
||||
* @param tenant tenant string value.
|
||||
* @param content content string value.
|
||||
* @param dataId dataId string value.
|
||||
* @param group group string value.
|
||||
* @param tenant tenant string value.
|
||||
* @param content content string value.
|
||||
* @param lastModifiedTs lastModifiedTs.
|
||||
* @param tag tag string value.
|
||||
* @param tag tag string value.
|
||||
* @return dumpChange success or not.
|
||||
*/
|
||||
public static boolean dumpTag(String dataId, String group, String tenant, String tag, String content,
|
||||
@ -209,10 +209,10 @@ public class ConfigCacheService {
|
||||
/**
|
||||
* Save config file and update md5 value in cache.
|
||||
*
|
||||
* @param dataId dataId string value.
|
||||
* @param group group string value.
|
||||
* @param tenant tenant string value.
|
||||
* @param content content string value.
|
||||
* @param dataId dataId string value.
|
||||
* @param group group string value.
|
||||
* @param tenant tenant string value.
|
||||
* @param content content string value.
|
||||
* @param lastModifiedTs lastModifiedTs.
|
||||
* @return dumpChange success or not.
|
||||
*/
|
||||
@ -313,6 +313,7 @@ public class ConfigCacheService {
|
||||
|
||||
/**
|
||||
* Check md5.
|
||||
*
|
||||
* @return return diff result list.
|
||||
*/
|
||||
public static List<String> checkMd5() {
|
||||
@ -343,20 +344,20 @@ public class ConfigCacheService {
|
||||
* Delete config file, and delete cache.
|
||||
*
|
||||
* @param dataId dataId string value.
|
||||
* @param group group string value.
|
||||
* @param group group string value.
|
||||
* @param tenant tenant string value.
|
||||
* @return remove success or not.
|
||||
*/
|
||||
public static boolean remove(String dataId, String group, String tenant) {
|
||||
final String groupKey = GroupKey2.getKey(dataId, group, tenant);
|
||||
final int lockResult = tryWriteLock(groupKey);
|
||||
|
||||
|
||||
// If data is non-existent.
|
||||
if (0 == lockResult) {
|
||||
DUMP_LOG.info("[remove-ok] {} not exist.", groupKey);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// try to lock failed
|
||||
if (lockResult < 0) {
|
||||
DUMP_LOG.warn("[remove-error] write lock failed. {}", groupKey);
|
||||
@ -368,7 +369,7 @@ public class ConfigCacheService {
|
||||
DiskUtil.removeConfigInfo(dataId, group, tenant);
|
||||
}
|
||||
CACHE.remove(groupKey);
|
||||
EventDispatcher.fireEvent(new LocalDataChangeEvent(groupKey));
|
||||
NotifyCenter.publishEvent(new LocalDataChangeEvent(groupKey));
|
||||
|
||||
return true;
|
||||
} finally {
|
||||
@ -380,7 +381,7 @@ public class ConfigCacheService {
|
||||
* Delete beta config file, and delete cache.
|
||||
*
|
||||
* @param dataId dataId string value.
|
||||
* @param group group string value.
|
||||
* @param group group string value.
|
||||
* @param tenant tenant string value.
|
||||
* @return remove success or not.
|
||||
*/
|
||||
@ -393,7 +394,7 @@ public class ConfigCacheService {
|
||||
DUMP_LOG.info("[remove-ok] {} not exist.", groupKey);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// try to lock failed
|
||||
if (lockResult < 0) {
|
||||
DUMP_LOG.warn("[remove-error] write lock failed. {}", groupKey);
|
||||
@ -404,7 +405,7 @@ public class ConfigCacheService {
|
||||
if (!PropertyUtil.isDirectRead()) {
|
||||
DiskUtil.removeConfigInfo4Beta(dataId, group, tenant);
|
||||
}
|
||||
EventDispatcher.fireEvent(new LocalDataChangeEvent(groupKey, true, CACHE.get(groupKey).getIps4Beta()));
|
||||
NotifyCenter.publishEvent(new LocalDataChangeEvent(groupKey, true, CACHE.get(groupKey).getIps4Beta()));
|
||||
CACHE.get(groupKey).setBeta(false);
|
||||
CACHE.get(groupKey).setIps4Beta(null);
|
||||
CACHE.get(groupKey).setMd54Beta(Constants.NULL);
|
||||
@ -418,21 +419,21 @@ public class ConfigCacheService {
|
||||
* Delete tag config file, and delete cache.
|
||||
*
|
||||
* @param dataId dataId string value.
|
||||
* @param group group string value.
|
||||
* @param group group string value.
|
||||
* @param tenant tenant string value.
|
||||
* @param tag tag string value.
|
||||
* @param tag tag string value.
|
||||
* @return remove success or not.
|
||||
*/
|
||||
public static boolean removeTag(String dataId, String group, String tenant, String tag) {
|
||||
final String groupKey = GroupKey2.getKey(dataId, group, tenant);
|
||||
final int lockResult = tryWriteLock(groupKey);
|
||||
|
||||
|
||||
// If data is non-existent.
|
||||
if (0 == lockResult) {
|
||||
DUMP_LOG.info("[remove-ok] {} not exist.", groupKey);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// try to lock failed
|
||||
if (lockResult < 0) {
|
||||
DUMP_LOG.warn("[remove-error] write lock failed. {}", groupKey);
|
||||
@ -447,7 +448,7 @@ public class ConfigCacheService {
|
||||
CacheItem ci = CACHE.get(groupKey);
|
||||
ci.tagMd5.remove(tag);
|
||||
ci.tagLastModifiedTs.remove(tag);
|
||||
EventDispatcher.fireEvent(new LocalDataChangeEvent(groupKey, false, null, tag));
|
||||
NotifyCenter.publishEvent(new LocalDataChangeEvent(groupKey, false, null, tag));
|
||||
return true;
|
||||
} finally {
|
||||
releaseWriteLock(groupKey);
|
||||
@ -457,8 +458,8 @@ public class ConfigCacheService {
|
||||
/**
|
||||
* Update md5 value.
|
||||
*
|
||||
* @param groupKey groupKey string value.
|
||||
* @param md5 md5 string value.
|
||||
* @param groupKey groupKey string value.
|
||||
* @param md5 md5 string value.
|
||||
* @param lastModifiedTs lastModifiedTs long value.
|
||||
*/
|
||||
public static void updateMd5(String groupKey, String md5, long lastModifiedTs) {
|
||||
@ -466,16 +467,16 @@ public class ConfigCacheService {
|
||||
if (cache.md5 == null || !cache.md5.equals(md5)) {
|
||||
cache.md5 = md5;
|
||||
cache.lastModifiedTs = lastModifiedTs;
|
||||
EventDispatcher.fireEvent(new LocalDataChangeEvent(groupKey));
|
||||
NotifyCenter.publishEvent(new LocalDataChangeEvent(groupKey));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update Beta md5 value.
|
||||
*
|
||||
* @param groupKey groupKey string value.
|
||||
* @param md5 md5 string value.
|
||||
* @param ips4Beta ips4Beta List.
|
||||
* @param groupKey groupKey string value.
|
||||
* @param md5 md5 string value.
|
||||
* @param ips4Beta ips4Beta List.
|
||||
* @param lastModifiedTs lastModifiedTs long value.
|
||||
*/
|
||||
public static void updateBetaMd5(String groupKey, String md5, List<String> ips4Beta, long lastModifiedTs) {
|
||||
@ -485,16 +486,16 @@ public class ConfigCacheService {
|
||||
cache.md54Beta = md5;
|
||||
cache.lastModifiedTs4Beta = lastModifiedTs;
|
||||
cache.ips4Beta = ips4Beta;
|
||||
EventDispatcher.fireEvent(new LocalDataChangeEvent(groupKey, true, ips4Beta));
|
||||
NotifyCenter.publishEvent(new LocalDataChangeEvent(groupKey, true, ips4Beta));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update tag md5 value.
|
||||
*
|
||||
* @param groupKey groupKey string value.
|
||||
* @param tag tag string value.
|
||||
* @param md5 md5 string value.
|
||||
* @param groupKey groupKey string value.
|
||||
* @param tag tag string value.
|
||||
* @param md5 md5 string value.
|
||||
* @param lastModifiedTs lastModifiedTs long value.
|
||||
*/
|
||||
public static void updateTagMd5(String groupKey, String tag, String md5, long lastModifiedTs) {
|
||||
@ -510,13 +511,13 @@ public class ConfigCacheService {
|
||||
} else {
|
||||
cache.tagLastModifiedTs.put(tag, lastModifiedTs);
|
||||
}
|
||||
EventDispatcher.fireEvent(new LocalDataChangeEvent(groupKey, false, null, tag));
|
||||
NotifyCenter.publishEvent(new LocalDataChangeEvent(groupKey, false, null, tag));
|
||||
return;
|
||||
}
|
||||
if (cache.tagMd5.get(tag) == null || !cache.tagMd5.get(tag).equals(md5)) {
|
||||
cache.tagMd5.put(tag, md5);
|
||||
cache.tagLastModifiedTs.put(tag, lastModifiedTs);
|
||||
EventDispatcher.fireEvent(new LocalDataChangeEvent(groupKey, false, null, tag));
|
||||
NotifyCenter.publishEvent(new LocalDataChangeEvent(groupKey, false, null, tag));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -16,9 +16,9 @@
|
||||
|
||||
package com.alibaba.nacos.config.server.service;
|
||||
|
||||
import com.alibaba.nacos.common.notify.NotifyCenter;
|
||||
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;
|
||||
|
||||
/**
|
||||
@ -30,13 +30,14 @@ public class ConfigChangePublisher {
|
||||
|
||||
/**
|
||||
* Notify ConfigChange.
|
||||
*
|
||||
* @param event ConfigDataChangeEvent instance.
|
||||
*/
|
||||
public static void notifyConfigChange(ConfigDataChangeEvent event) {
|
||||
if (PropertyUtil.isEmbeddedStorage() && !ApplicationUtils.getStandaloneMode()) {
|
||||
return;
|
||||
}
|
||||
EventDispatcher.fireEvent(event);
|
||||
NotifyCenter.publishEvent(event);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -16,17 +16,17 @@
|
||||
|
||||
package com.alibaba.nacos.config.server.service;
|
||||
|
||||
import com.alibaba.nacos.common.utils.ThreadUtils;
|
||||
import com.alibaba.nacos.config.server.constant.Constants;
|
||||
import com.alibaba.nacos.config.server.model.SampleResult;
|
||||
import com.alibaba.nacos.config.server.service.notify.NotifyService;
|
||||
import com.alibaba.nacos.config.server.utils.ConfigExecutor;
|
||||
import com.alibaba.nacos.config.server.utils.JSONUtils;
|
||||
import com.alibaba.nacos.config.server.utils.LogUtil;
|
||||
import com.alibaba.nacos.core.cluster.Member;
|
||||
import com.alibaba.nacos.core.cluster.ServerMemberManager;
|
||||
import com.alibaba.nacos.core.utils.ApplicationUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@ -37,18 +37,15 @@ import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CompletionService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.LinkedBlockingDeque;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.CompletionService;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.ExecutorCompletionService;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.LinkedBlockingDeque;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
/**
|
||||
* Config sub service.
|
||||
@ -58,24 +55,12 @@ import java.util.concurrent.ExecutorCompletionService;
|
||||
@Service
|
||||
public class ConfigSubService {
|
||||
|
||||
private ScheduledExecutorService scheduler;
|
||||
|
||||
private ServerMemberManager memberManager;
|
||||
|
||||
@Autowired
|
||||
@SuppressWarnings("PMD.ThreadPoolCreationRule")
|
||||
public ConfigSubService(ServerMemberManager memberManager) {
|
||||
this.memberManager = memberManager;
|
||||
|
||||
scheduler = Executors.newScheduledThreadPool(ThreadUtils.getSuitableThreadCount(), new ThreadFactory() {
|
||||
@Override
|
||||
public Thread newThread(Runnable r) {
|
||||
Thread t = new Thread(r);
|
||||
t.setDaemon(true);
|
||||
t.setName("com.alibaba.nacos.ConfigSubService");
|
||||
return t;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected ConfigSubService() {
|
||||
@ -140,7 +125,7 @@ public class ConfigSubService {
|
||||
* Merge SampleResult.
|
||||
*
|
||||
* @param sampleCollectResult sampleCollectResult.
|
||||
* @param sampleResults sampleResults.
|
||||
* @param sampleResults sampleResults.
|
||||
* @return SampleResult.
|
||||
*/
|
||||
public SampleResult mergeSampleResult(SampleResult sampleCollectResult, List<SampleResult> sampleResults) {
|
||||
@ -195,7 +180,7 @@ public class ConfigSubService {
|
||||
String urlAll = getUrl(ip, url) + "?" + paramUrl;
|
||||
com.alibaba.nacos.config.server.service.notify.NotifyService.HttpResult result = NotifyService
|
||||
.invokeURL(urlAll, null, Constants.ENCODE);
|
||||
|
||||
|
||||
// Http code 200
|
||||
if (result.code == HttpURLConnection.HTTP_OK) {
|
||||
String json = result.content;
|
||||
@ -227,8 +212,8 @@ public class ConfigSubService {
|
||||
}
|
||||
BlockingQueue<Future<SampleResult>> queue = new LinkedBlockingDeque<Future<SampleResult>>(
|
||||
memberManager.getServerList().size());
|
||||
CompletionService<SampleResult> completionService = new ExecutorCompletionService<SampleResult>(scheduler,
|
||||
queue);
|
||||
CompletionService<SampleResult> completionService = new ExecutorCompletionService<SampleResult>(
|
||||
ConfigExecutor.getConfigSubServiceExecutor(), queue);
|
||||
|
||||
SampleResult sampleCollectResult = new SampleResult();
|
||||
for (int i = 0; i < sampleTime; i++) {
|
||||
@ -247,8 +232,8 @@ public class ConfigSubService {
|
||||
params.put("ip", ip);
|
||||
BlockingQueue<Future<SampleResult>> queue = new LinkedBlockingDeque<Future<SampleResult>>(
|
||||
memberManager.getServerList().size());
|
||||
CompletionService<SampleResult> completionService = new ExecutorCompletionService<SampleResult>(scheduler,
|
||||
queue);
|
||||
CompletionService<SampleResult> completionService = new ExecutorCompletionService<SampleResult>(
|
||||
ConfigExecutor.getConfigSubServiceExecutor(), queue);
|
||||
|
||||
SampleResult sampleCollectResult = new SampleResult();
|
||||
for (int i = 0; i < sampleTime; i++) {
|
||||
|
@ -17,17 +17,20 @@
|
||||
package com.alibaba.nacos.config.server.service;
|
||||
|
||||
import com.alibaba.nacos.api.config.remote.response.ConfigChangeNotifyResponse;
|
||||
import com.alibaba.nacos.common.notify.Event;
|
||||
import com.alibaba.nacos.common.notify.NotifyCenter;
|
||||
import com.alibaba.nacos.common.notify.listener.Subscriber;
|
||||
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;
|
||||
import com.alibaba.nacos.config.server.utils.ConfigExecutor;
|
||||
import com.alibaba.nacos.config.server.utils.GroupKey;
|
||||
import com.alibaba.nacos.config.server.utils.LogUtil;
|
||||
import com.alibaba.nacos.config.server.utils.MD5Util;
|
||||
import com.alibaba.nacos.config.server.utils.RequestUtil;
|
||||
import com.alibaba.nacos.config.server.utils.event.EventDispatcher.AbstractEventListener;
|
||||
import com.alibaba.nacos.config.server.utils.event.EventDispatcher.Event;
|
||||
|
||||
import com.alibaba.nacos.core.remote.DataChangeListenerNotifier;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@ -48,10 +51,7 @@ import java.util.Queue;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static com.alibaba.nacos.config.server.utils.LogUtil.MEMORY_LOG;
|
||||
@ -63,7 +63,7 @@ import static com.alibaba.nacos.config.server.utils.LogUtil.PULL_LOG;
|
||||
* @author Nacos
|
||||
*/
|
||||
@Service
|
||||
public class LongPollingService extends AbstractEventListener {
|
||||
public class LongPollingService {
|
||||
|
||||
private static final int FIXED_POLLING_INTERVAL_MS = 10000;
|
||||
|
||||
@ -251,7 +251,7 @@ public class LongPollingService extends AbstractEventListener {
|
||||
String appName = req.getHeader(RequestUtil.CLIENT_APPNAME_HEADER);
|
||||
String tag = req.getHeader("Vipserver-Tag");
|
||||
int delayTime = SwitchService.getSwitchInteger(SwitchService.FIXED_DELAY_TIME, 500);
|
||||
|
||||
|
||||
// Add delay time for LoadBalance, and one response is returned 500 ms in advance to avoid client timeout.
|
||||
long timeout = Math.max(10000, Long.parseLong(str) - delayTime);
|
||||
if (isFixedPolling()) {
|
||||
@ -281,29 +281,10 @@ public class LongPollingService extends AbstractEventListener {
|
||||
// AsyncContext.setTimeout() is incorrect, Control by oneself
|
||||
asyncContext.setTimeout(0L);
|
||||
|
||||
scheduler.execute(
|
||||
ConfigExecutor.executeLongPolling(
|
||||
new ClientLongPolling(asyncContext, clientMd5Map, ip, probeRequestSize, timeout, appName, tag));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Class<? extends Event>> interest() {
|
||||
List<Class<? extends Event>> eventTypes = new ArrayList<Class<? extends Event>>();
|
||||
eventTypes.add(LocalDataChangeEvent.class);
|
||||
return eventTypes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEvent(Event event) {
|
||||
if (isFixedPolling()) {
|
||||
// Ignore.
|
||||
} else {
|
||||
if (event instanceof LocalDataChangeEvent) {
|
||||
LocalDataChangeEvent evt = (LocalDataChangeEvent) event;
|
||||
scheduler.execute(new DataChangeTask(evt.groupKey, evt.isBeta, evt.betaIps));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isSupportLongPolling(HttpServletRequest req) {
|
||||
return null != req.getHeader(LONG_POLLING_HEADER);
|
||||
}
|
||||
@ -312,24 +293,38 @@ public class LongPollingService extends AbstractEventListener {
|
||||
public LongPollingService() {
|
||||
allSubs = new ConcurrentLinkedQueue<ClientLongPolling>();
|
||||
|
||||
scheduler = Executors.newScheduledThreadPool(1, new ThreadFactory() {
|
||||
ConfigExecutor.scheduleLongPolling(new StatTask(), 0L, 10L, TimeUnit.SECONDS);
|
||||
|
||||
// Register LocalDataChangeEvent to NotifyCenter.
|
||||
NotifyCenter.registerToPublisher(LocalDataChangeEvent.class, NotifyCenter.ringBufferSize);
|
||||
|
||||
// Register A Subscriber to subscribe LocalDataChangeEvent.
|
||||
NotifyCenter.registerSubscriber(new Subscriber() {
|
||||
|
||||
@Override
|
||||
public Thread newThread(Runnable r) {
|
||||
Thread t = new Thread(r);
|
||||
t.setDaemon(true);
|
||||
t.setName("com.alibaba.nacos.LongPolling");
|
||||
return t;
|
||||
public void onEvent(Event event) {
|
||||
if (isFixedPolling()) {
|
||||
// Ignore.
|
||||
} else {
|
||||
if (event instanceof LocalDataChangeEvent) {
|
||||
LocalDataChangeEvent evt = (LocalDataChangeEvent) event;
|
||||
ConfigExecutor.executeLongPolling(new DataChangeTask(evt.groupKey, evt.isBeta, evt.betaIps));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends Event> subscribeType() {
|
||||
return LocalDataChangeEvent.class;
|
||||
}
|
||||
});
|
||||
scheduler.scheduleWithFixedDelay(new StatTask(), 0L, 10L, TimeUnit.SECONDS);
|
||||
|
||||
}
|
||||
|
||||
public static final String LONG_POLLING_HEADER = "Long-Pulling-Timeout";
|
||||
|
||||
public static final String LONG_POLLING_NO_HANG_UP_HEADER = "Long-Pulling-Timeout-No-Hangup";
|
||||
|
||||
final ScheduledExecutorService scheduler;
|
||||
|
||||
/**
|
||||
* ClientLongPolling subscibers.
|
||||
*/
|
||||
@ -413,12 +408,12 @@ public class LongPollingService extends AbstractEventListener {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
asyncTimeoutFuture = scheduler.schedule(new Runnable() {
|
||||
asyncTimeoutFuture = ConfigExecutor.scheduleLongPolling(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
getRetainIps().put(ClientLongPolling.this.ip, System.currentTimeMillis());
|
||||
|
||||
|
||||
// Delete subsciber's relations.
|
||||
allSubs.remove(ClientLongPolling.this);
|
||||
|
||||
@ -454,7 +449,7 @@ public class LongPollingService extends AbstractEventListener {
|
||||
}
|
||||
|
||||
void sendResponse(List<String> changedGroups) {
|
||||
|
||||
|
||||
// Cancel time out task.
|
||||
if (null != asyncTimeoutFuture) {
|
||||
asyncTimeoutFuture.cancel(false);
|
||||
@ -464,7 +459,7 @@ public class LongPollingService extends AbstractEventListener {
|
||||
|
||||
void generateResponse(List<String> changedGroups) {
|
||||
if (null == changedGroups) {
|
||||
|
||||
|
||||
// Tell web container to send http response.
|
||||
asyncContext.complete();
|
||||
return;
|
||||
|
@ -21,11 +21,11 @@ import com.alibaba.nacos.config.server.model.capacity.Capacity;
|
||||
import com.alibaba.nacos.config.server.model.capacity.GroupCapacity;
|
||||
import com.alibaba.nacos.config.server.model.capacity.TenantCapacity;
|
||||
import com.alibaba.nacos.config.server.service.repository.PersistService;
|
||||
import com.alibaba.nacos.config.server.utils.ConfigExecutor;
|
||||
import com.alibaba.nacos.config.server.utils.LogUtil;
|
||||
import com.alibaba.nacos.config.server.utils.PropertyUtil;
|
||||
import com.alibaba.nacos.config.server.utils.TimeUtils;
|
||||
import com.google.common.base.Stopwatch;
|
||||
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@ -34,12 +34,8 @@ import org.springframework.dao.DuplicateKeyException;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import javax.annotation.PreDestroy;
|
||||
import java.sql.Timestamp;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
@ -66,8 +62,6 @@ public class CapacityService {
|
||||
@Autowired
|
||||
private PersistService persistService;
|
||||
|
||||
private ScheduledExecutorService scheduledExecutorService;
|
||||
|
||||
/**
|
||||
* Init.
|
||||
*/
|
||||
@ -75,10 +69,7 @@ public class CapacityService {
|
||||
@SuppressWarnings("PMD.ThreadPoolCreationRule")
|
||||
public void init() {
|
||||
// All servers have jobs that modify usage, idempotent.
|
||||
ThreadFactory threadFactory = new ThreadFactoryBuilder()
|
||||
.setNameFormat("com.alibaba.nacos.CapacityManagement-%d").setDaemon(true).build();
|
||||
scheduledExecutorService = Executors.newSingleThreadScheduledExecutor(threadFactory);
|
||||
scheduledExecutorService.scheduleWithFixedDelay(new Runnable() {
|
||||
ConfigExecutor.scheduleCorrectUsageTask(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
LOGGER.info("[capacityManagement] start correct usage");
|
||||
@ -90,11 +81,6 @@ public class CapacityService {
|
||||
}, PropertyUtil.getCorrectUsageDelay(), PropertyUtil.getCorrectUsageDelay(), TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
@PreDestroy
|
||||
public void destroy() {
|
||||
scheduledExecutorService.shutdown();
|
||||
}
|
||||
|
||||
public void correctUsage() {
|
||||
correctGroupUsage();
|
||||
correctTenantUsage();
|
||||
@ -192,11 +178,10 @@ public class CapacityService {
|
||||
}
|
||||
|
||||
/**
|
||||
* To Cluster.
|
||||
* 1.If the capacity information does not exist, initialize the capacity information.
|
||||
* 2.Update capacity usage, plus or minus one.
|
||||
* To Cluster. 1.If the capacity information does not exist, initialize the capacity information. 2.Update capacity
|
||||
* usage, plus or minus one.
|
||||
*
|
||||
* @param counterMode increase or decrease mode.
|
||||
* @param counterMode increase or decrease mode.
|
||||
* @param ignoreQuotaLimit ignoreQuotaLimit flag.
|
||||
* @return
|
||||
*/
|
||||
@ -215,12 +200,11 @@ public class CapacityService {
|
||||
}
|
||||
|
||||
/**
|
||||
* It is used for counting when the limit check function of capacity management is turned off.
|
||||
* 1.If the capacity information does not exist, initialize the capacity information.
|
||||
* 2.Update capacity usage, plus or minus one.
|
||||
* It is used for counting when the limit check function of capacity management is turned off. 1.If the capacity
|
||||
* information does not exist, initialize the capacity information. 2.Update capacity usage, plus or minus one.
|
||||
*
|
||||
* @param counterMode increase or decrease mode.
|
||||
* @param group tenant string value.
|
||||
* @param counterMode increase or decrease mode.
|
||||
* @param group tenant string value.
|
||||
* @param ignoreQuotaLimit ignoreQuotaLimit flag.
|
||||
* @return operate successfully or not.
|
||||
*/
|
||||
@ -260,8 +244,8 @@ public class CapacityService {
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the capacity information of the group.
|
||||
* If the quota is reached, the capacity will be automatically expanded to reduce the operation and maintenance cost.
|
||||
* Initialize the capacity information of the group. If the quota is reached, the capacity will be automatically
|
||||
* expanded to reduce the operation and maintenance cost.
|
||||
*
|
||||
* @param group group string value.
|
||||
* @return init result.
|
||||
@ -271,14 +255,14 @@ public class CapacityService {
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the capacity information of the group. If the quota is reached,
|
||||
* the capacity will be automatically expanded to reduce the operation and maintenance cost.
|
||||
* Initialize the capacity information of the group. If the quota is reached, the capacity will be automatically
|
||||
* expanded to reduce the operation and maintenance cost.
|
||||
*
|
||||
* @param group group string value.
|
||||
* @param quota quota int value.
|
||||
* @param maxSize maxSize int value.
|
||||
* @param group group string value.
|
||||
* @param quota quota int value.
|
||||
* @param maxSize maxSize int value.
|
||||
* @param maxAggrCount maxAggrCount int value.
|
||||
* @param maxAggrSize maxAggrSize int value.
|
||||
* @param maxAggrSize maxAggrSize int value.
|
||||
* @return init result.
|
||||
*/
|
||||
private boolean initGroupCapacity(String group, Integer quota, Integer maxSize, Integer maxAggrCount,
|
||||
@ -290,11 +274,11 @@ public class CapacityService {
|
||||
autoExpansion(group, null);
|
||||
return insertSuccess;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Expand capacity automatically.
|
||||
*
|
||||
* @param group group string value.
|
||||
* @param group group string value.
|
||||
* @param tenant tenant string value.
|
||||
*/
|
||||
private void autoExpansion(String group, String tenant) {
|
||||
@ -377,7 +361,7 @@ public class CapacityService {
|
||||
/**
|
||||
* Init capacity.
|
||||
*
|
||||
* @param group group string value.
|
||||
* @param group group string value.
|
||||
* @param tenant tenant string value.
|
||||
* @return init result.
|
||||
*/
|
||||
@ -423,12 +407,11 @@ public class CapacityService {
|
||||
}
|
||||
|
||||
/**
|
||||
* It is used for counting when the limit check function of capacity management is turned off.
|
||||
* 1.If the capacity information does not exist, initialize the capacity information.
|
||||
* 2.Update capacity usage, plus or minus one.
|
||||
* It is used for counting when the limit check function of capacity management is turned off. 1.If the capacity
|
||||
* information does not exist, initialize the capacity information. 2.Update capacity usage, plus or minus one.
|
||||
*
|
||||
* @param counterMode increase or decrease mode.
|
||||
* @param tenant tenant string value.
|
||||
* @param counterMode increase or decrease mode.
|
||||
* @param tenant tenant string value.
|
||||
* @param ignoreQuotaLimit ignoreQuotaLimit flag.
|
||||
* @return operate successfully or not.
|
||||
*/
|
||||
@ -464,8 +447,8 @@ public class CapacityService {
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the capacity information of the tenant. If the quota is reached,
|
||||
* the capacity will be automatically expanded to reduce the operation and maintenance cos.
|
||||
* Initialize the capacity information of the tenant. If the quota is reached, the capacity will be automatically
|
||||
* expanded to reduce the operation and maintenance cos.
|
||||
*
|
||||
* @param tenant tenant string value.
|
||||
* @return init result.
|
||||
@ -475,14 +458,14 @@ public class CapacityService {
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the capacity information of the tenant. If the quota is reached,
|
||||
* the capacity will be automatically expanded to reduce the operation and maintenance cost
|
||||
* Initialize the capacity information of the tenant. If the quota is reached, the capacity will be automatically
|
||||
* expanded to reduce the operation and maintenance cost
|
||||
*
|
||||
* @param tenant tenant string value.
|
||||
* @param quota quota int value.
|
||||
* @param maxSize maxSize int value.
|
||||
* @param tenant tenant string value.
|
||||
* @param quota quota int value.
|
||||
* @param maxSize maxSize int value.
|
||||
* @param maxAggrCount maxAggrCount int value.
|
||||
* @param maxAggrSize maxAggrSize int value.
|
||||
* @param maxAggrSize maxAggrSize int value.
|
||||
* @return
|
||||
*/
|
||||
public boolean initTenantCapacity(String tenant, Integer quota, Integer maxSize, Integer maxAggrCount,
|
||||
@ -530,15 +513,15 @@ public class CapacityService {
|
||||
}
|
||||
|
||||
/**
|
||||
* Support for API interface, Tenant: initialize if the record does not exist,
|
||||
* and update the capacity quota or content size directly if it exists.
|
||||
* Support for API interface, Tenant: initialize if the record does not exist, and update the capacity quota or
|
||||
* content size directly if it exists.
|
||||
*
|
||||
* @param group group string value.
|
||||
* @param tenant tenant string value.
|
||||
* @param quota quota int value.
|
||||
* @param maxSize maxSize int value.
|
||||
* @param group group string value.
|
||||
* @param tenant tenant string value.
|
||||
* @param quota quota int value.
|
||||
* @param maxSize maxSize int value.
|
||||
* @param maxAggrCount maxAggrCount int value.
|
||||
* @param maxAggrSize maxAggrSize int value.
|
||||
* @param maxAggrSize maxAggrSize int value.
|
||||
* @return operate successfully or not.
|
||||
*/
|
||||
public boolean insertOrUpdateCapacity(String group, String tenant, Integer quota, Integer maxSize,
|
||||
|
@ -45,7 +45,7 @@ public class ExternalDataSourceProperties {
|
||||
|
||||
public static final int DEFAULT_MAX_POOL_SIZE = 20;
|
||||
|
||||
public static final int DEFAULT_MINIMUM_IDLE = 50;
|
||||
public static final int DEFAULT_MINIMUM_IDLE = 20;
|
||||
|
||||
private Integer num;
|
||||
|
||||
|
@ -101,13 +101,13 @@ public class ExternalDataSourceServiceImpl implements DataSourceService {
|
||||
testMasterWritableJT.setQueryTimeout(1);
|
||||
|
||||
// Database health check
|
||||
|
||||
|
||||
testJtList = new ArrayList<JdbcTemplate>();
|
||||
isHealthList = new ArrayList<Boolean>();
|
||||
|
||||
tm = new DataSourceTransactionManager();
|
||||
tjt = new TransactionTemplate(tm);
|
||||
|
||||
|
||||
// Transaction timeout needs to be distinguished from ordinary operations.
|
||||
tjt.setTimeout(TRANSACTION_QUERY_TIMEOUT);
|
||||
if (PropertyUtil.isUseExternalDB()) {
|
||||
@ -118,8 +118,8 @@ public class ExternalDataSourceServiceImpl implements DataSourceService {
|
||||
throw new RuntimeException(DB_LOAD_ERROR_MSG);
|
||||
}
|
||||
|
||||
ConfigExecutor.scheduleWithFixedDelay(new SelectMasterTask(), 10, 10, TimeUnit.SECONDS);
|
||||
ConfigExecutor.scheduleWithFixedDelay(new CheckDbHealthTask(), 10, 10, TimeUnit.SECONDS);
|
||||
ConfigExecutor.scheduleConfigTask(new SelectMasterTask(), 10, 10, TimeUnit.SECONDS);
|
||||
ConfigExecutor.scheduleConfigTask(new CheckDbHealthTask(), 10, 10, TimeUnit.SECONDS);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -17,28 +17,27 @@
|
||||
package com.alibaba.nacos.config.server.service.dump;
|
||||
|
||||
import com.alibaba.nacos.common.utils.StringUtils;
|
||||
import com.alibaba.nacos.common.notify.Event;
|
||||
import com.alibaba.nacos.common.notify.listener.Subscriber;
|
||||
import com.alibaba.nacos.config.server.model.event.ConfigDumpEvent;
|
||||
import com.alibaba.nacos.config.server.service.AggrWhitelist;
|
||||
import com.alibaba.nacos.config.server.service.ClientIpWhiteList;
|
||||
import com.alibaba.nacos.config.server.service.ConfigCacheService;
|
||||
import com.alibaba.nacos.config.server.service.SwitchService;
|
||||
import com.alibaba.nacos.config.server.service.trace.ConfigTraceService;
|
||||
import com.alibaba.nacos.core.notify.Event;
|
||||
import com.alibaba.nacos.core.notify.listener.Subscribe;
|
||||
|
||||
/**
|
||||
* Dump config subscriber.
|
||||
*
|
||||
* @author <a href="mailto:liaochuntao@live.com">liaochuntao</a>
|
||||
*/
|
||||
public class DumpConfigHandler implements Subscribe<ConfigDumpEvent> {
|
||||
public class DumpConfigHandler extends Subscriber<ConfigDumpEvent> {
|
||||
|
||||
/**
|
||||
* trigger config dump event.
|
||||
*
|
||||
* @param event {@link ConfigDumpEvent}
|
||||
* @return {@code true} if the config dump task success , else
|
||||
* {@code false}
|
||||
* @return {@code true} if the config dump task success , else {@code false}
|
||||
*/
|
||||
public static boolean configDump(ConfigDumpEvent event) {
|
||||
final String dataId = event.getDataId();
|
||||
|
@ -152,7 +152,8 @@ public abstract class DumpService {
|
||||
if (totalCount > 0) {
|
||||
int pageSize = 1000;
|
||||
int removeTime = (totalCount + pageSize - 1) / pageSize;
|
||||
LOGGER.warn("clearConfigHistory, getBeforeStamp:{}, totalCount:{}, pageSize:{}, removeTime:{}",
|
||||
LOGGER.warn(
|
||||
"clearConfigHistory, getBeforeStamp:{}, totalCount:{}, pageSize:{}, removeTime:{}",
|
||||
startTime, totalCount, pageSize, removeTime);
|
||||
while (removeTime > 0) {
|
||||
// delete paging to avoid reporting errors in batches
|
||||
@ -212,22 +213,21 @@ public abstract class DumpService {
|
||||
}
|
||||
};
|
||||
|
||||
ConfigExecutor.scheduleWithFixedDelay(heartbeat, 0, 10, TimeUnit.SECONDS);
|
||||
ConfigExecutor.scheduleConfigTask(heartbeat, 0, 10, TimeUnit.SECONDS);
|
||||
|
||||
long initialDelay = new Random().nextInt(INITIAL_DELAY_IN_MINUTE) + 10;
|
||||
LogUtil.DEFAULT_LOG.warn("initialDelay:{}", initialDelay);
|
||||
|
||||
ConfigExecutor.scheduleConfigTask(dumpAll, initialDelay, DUMP_ALL_INTERVAL_IN_MINUTE, TimeUnit.MINUTES);
|
||||
|
||||
ConfigExecutor
|
||||
.scheduleWithFixedDelay(dumpAll, initialDelay, DUMP_ALL_INTERVAL_IN_MINUTE, TimeUnit.MINUTES);
|
||||
.scheduleConfigTask(dumpAllBeta, initialDelay, DUMP_ALL_INTERVAL_IN_MINUTE, TimeUnit.MINUTES);
|
||||
|
||||
ConfigExecutor.scheduleWithFixedDelay(dumpAllBeta, initialDelay, DUMP_ALL_INTERVAL_IN_MINUTE,
|
||||
TimeUnit.MINUTES);
|
||||
|
||||
ConfigExecutor.scheduleWithFixedDelay(dumpAllTag, initialDelay, DUMP_ALL_INTERVAL_IN_MINUTE,
|
||||
TimeUnit.MINUTES);
|
||||
ConfigExecutor
|
||||
.scheduleConfigTask(dumpAllTag, initialDelay, DUMP_ALL_INTERVAL_IN_MINUTE, TimeUnit.MINUTES);
|
||||
}
|
||||
|
||||
ConfigExecutor.scheduleWithFixedDelay(clearConfigHistory, 10, 10, TimeUnit.MINUTES);
|
||||
ConfigExecutor.scheduleConfigTask(clearConfigHistory, 10, 10, TimeUnit.MINUTES);
|
||||
} finally {
|
||||
TimerContext.end(LogUtil.DUMP_LOG);
|
||||
}
|
||||
@ -276,7 +276,7 @@ public abstract class DumpService {
|
||||
}
|
||||
LogUtil.DEFAULT_LOG.error("end checkMd5Task");
|
||||
};
|
||||
ConfigExecutor.scheduleWithFixedDelay(checkMd5Task, 0, 12, TimeUnit.HOURS);
|
||||
ConfigExecutor.scheduleConfigTask(checkMd5Task, 0, 12, TimeUnit.HOURS);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
LogUtil.FATAL_LOG.error("dump config fail" + e.getMessage());
|
||||
@ -420,8 +420,9 @@ public abstract class DumpService {
|
||||
} else {
|
||||
// remove config info
|
||||
persistService.removeConfigInfo(dataId, group, tenant, InetUtils.getSelfIp(), null);
|
||||
LOGGER.warn("[merge-delete] delete config info because no datum. dataId=" + dataId + ", groupId="
|
||||
+ group);
|
||||
LOGGER.warn(
|
||||
"[merge-delete] delete config info because no datum. dataId=" + dataId + ", groupId="
|
||||
+ group);
|
||||
}
|
||||
|
||||
} catch (Throwable e) {
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
package com.alibaba.nacos.config.server.service.merge;
|
||||
|
||||
import com.alibaba.nacos.common.notify.NotifyCenter;
|
||||
import com.alibaba.nacos.config.server.constant.Constants;
|
||||
import com.alibaba.nacos.config.server.manager.AbstractTask;
|
||||
import com.alibaba.nacos.config.server.manager.TaskProcessor;
|
||||
@ -27,7 +28,6 @@ import com.alibaba.nacos.config.server.service.repository.PersistService;
|
||||
import com.alibaba.nacos.config.server.service.trace.ConfigTraceService;
|
||||
import com.alibaba.nacos.config.server.utils.ContentUtils;
|
||||
import com.alibaba.nacos.config.server.utils.TimeUtils;
|
||||
import com.alibaba.nacos.config.server.utils.event.EventDispatcher;
|
||||
import com.alibaba.nacos.core.utils.InetUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
@ -79,8 +79,9 @@ public class MergeTaskProcessor implements TaskProcessor {
|
||||
|
||||
persistService.insertOrUpdate(null, null, cf, time, null);
|
||||
|
||||
LOGGER.info("[merge-ok] {}, {}, size={}, length={}, md5={}, content={}", dataId, group, datumList.size(),
|
||||
cf.getContent().length(), cf.getMd5(), ContentUtils.truncateContent(cf.getContent()));
|
||||
LOGGER.info("[merge-ok] {}, {}, size={}, length={}, md5={}, content={}", dataId, group,
|
||||
datumList.size(), cf.getContent().length(), cf.getMd5(),
|
||||
ContentUtils.truncateContent(cf.getContent()));
|
||||
|
||||
ConfigTraceService
|
||||
.logPersistenceEvent(dataId, group, tenant, null, time.getTime(), InetUtils.getSelfIp(),
|
||||
@ -93,14 +94,14 @@ public class MergeTaskProcessor implements TaskProcessor {
|
||||
persistService.removeConfigInfoTag(dataId, group, tenant, tag, clientIp, null);
|
||||
}
|
||||
|
||||
LOGGER.warn("[merge-delete] delete config info because no datum. dataId=" + dataId + ", groupId=" + group);
|
||||
LOGGER.warn(
|
||||
"[merge-delete] delete config info because no datum. dataId=" + dataId + ", groupId=" + group);
|
||||
|
||||
ConfigTraceService
|
||||
.logPersistenceEvent(dataId, group, tenant, null, time.getTime(), InetUtils.getSelfIp(),
|
||||
ConfigTraceService.PERSISTENCE_EVENT_REMOVE, null);
|
||||
}
|
||||
|
||||
EventDispatcher.fireEvent(new ConfigDataChangeEvent(false, dataId, group, tenant, tag, time.getTime()));
|
||||
NotifyCenter.publishEvent(new ConfigDataChangeEvent(false, dataId, group, tenant, tag, time.getTime()));
|
||||
|
||||
} catch (Exception e) {
|
||||
mergeService.addMergeTask(dataId, group, tenant, mergeTask.getClientIp());
|
||||
@ -113,9 +114,9 @@ public class MergeTaskProcessor implements TaskProcessor {
|
||||
/**
|
||||
* merge datumList {@link ConfigInfoAggr}.
|
||||
*
|
||||
* @param dataId data id
|
||||
* @param group group
|
||||
* @param tenant tenant
|
||||
* @param dataId data id
|
||||
* @param group group
|
||||
* @param tenant tenant
|
||||
* @param datumList datumList
|
||||
* @return {@link ConfigInfo}
|
||||
*/
|
||||
|
@ -16,14 +16,16 @@
|
||||
|
||||
package com.alibaba.nacos.config.server.service.notify;
|
||||
|
||||
import com.alibaba.nacos.common.notify.Event;
|
||||
import com.alibaba.nacos.common.notify.NotifyCenter;
|
||||
import com.alibaba.nacos.common.notify.listener.Subscriber;
|
||||
import com.alibaba.nacos.config.server.constant.Constants;
|
||||
import com.alibaba.nacos.config.server.monitor.MetricsMonitor;
|
||||
import com.alibaba.nacos.config.server.model.event.ConfigDataChangeEvent;
|
||||
import com.alibaba.nacos.config.server.monitor.MetricsMonitor;
|
||||
import com.alibaba.nacos.config.server.service.trace.ConfigTraceService;
|
||||
import com.alibaba.nacos.config.server.utils.ConfigExecutor;
|
||||
import com.alibaba.nacos.config.server.utils.LogUtil;
|
||||
import com.alibaba.nacos.config.server.utils.PropertyUtil;
|
||||
import com.alibaba.nacos.config.server.utils.event.EventDispatcher.AbstractEventListener;
|
||||
import com.alibaba.nacos.config.server.utils.event.EventDispatcher.Event;
|
||||
import com.alibaba.nacos.core.cluster.Member;
|
||||
import com.alibaba.nacos.core.cluster.ServerMemberManager;
|
||||
import com.alibaba.nacos.core.utils.ApplicationUtils;
|
||||
@ -45,15 +47,9 @@ import org.springframework.stereotype.Service;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLEncoder;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Queue;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledThreadPoolExecutor;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
@ -62,51 +58,48 @@ import java.util.concurrent.TimeUnit;
|
||||
* @author Nacos
|
||||
*/
|
||||
@Service
|
||||
public class AsyncNotifyService extends AbstractEventListener {
|
||||
|
||||
@Override
|
||||
public List<Class<? extends Event>> interest() {
|
||||
List<Class<? extends Event>> types = new ArrayList<Class<? extends Event>>();
|
||||
// Trigger configuration change synchronization notification
|
||||
types.add(ConfigDataChangeEvent.class);
|
||||
return types;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEvent(Event event) {
|
||||
|
||||
// Generate ConfigDataChangeEvent concurrently
|
||||
if (event instanceof ConfigDataChangeEvent) {
|
||||
ConfigDataChangeEvent evt = (ConfigDataChangeEvent) event;
|
||||
long dumpTs = evt.lastModifiedTs;
|
||||
String dataId = evt.dataId;
|
||||
String group = evt.group;
|
||||
String tenant = evt.tenant;
|
||||
String tag = evt.tag;
|
||||
Collection<Member> ipList = memberManager.allMembers();
|
||||
|
||||
// In fact, any type of queue here can be
|
||||
Queue<NotifySingleTask> queue = new LinkedList<NotifySingleTask>();
|
||||
for (Member member : ipList) {
|
||||
queue.add(new NotifySingleTask(dataId, group, tenant, tag, dumpTs, member.getAddress(), evt.isBeta));
|
||||
}
|
||||
EXECUTOR.execute(new AsyncTask(httpclient, queue));
|
||||
}
|
||||
}
|
||||
public class AsyncNotifyService {
|
||||
|
||||
@Autowired
|
||||
public AsyncNotifyService(ServerMemberManager memberManager) {
|
||||
this.memberManager = memberManager;
|
||||
httpclient.start();
|
||||
|
||||
// Register ConfigDataChangeEvent to NotifyCenter.
|
||||
NotifyCenter.registerToPublisher(ConfigDataChangeEvent.class, NotifyCenter.ringBufferSize);
|
||||
|
||||
// Register A Subscriber to subscribe ConfigDataChangeEvent.
|
||||
NotifyCenter.registerSubscriber(new Subscriber() {
|
||||
|
||||
@Override
|
||||
public void onEvent(Event event) {
|
||||
// Generate ConfigDataChangeEvent concurrently
|
||||
if (event instanceof ConfigDataChangeEvent) {
|
||||
ConfigDataChangeEvent evt = (ConfigDataChangeEvent) event;
|
||||
long dumpTs = evt.lastModifiedTs;
|
||||
String dataId = evt.dataId;
|
||||
String group = evt.group;
|
||||
String tenant = evt.tenant;
|
||||
String tag = evt.tag;
|
||||
Collection<Member> ipList = memberManager.allMembers();
|
||||
|
||||
// In fact, any type of queue here can be
|
||||
Queue<NotifySingleTask> queue = new LinkedList<NotifySingleTask>();
|
||||
for (Member member : ipList) {
|
||||
queue.add(new NotifySingleTask(dataId, group, tenant, tag, dumpTs, member.getAddress(),
|
||||
evt.isBeta));
|
||||
}
|
||||
ConfigExecutor.executeAsyncNotify(new AsyncTask(httpclient, queue));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends Event> subscribeType() {
|
||||
return ConfigDataChangeEvent.class;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public Executor getExecutor() {
|
||||
return EXECUTOR;
|
||||
}
|
||||
|
||||
@SuppressWarnings("PMD.ThreadPoolCreationRule")
|
||||
private static final Executor EXECUTOR = Executors.newScheduledThreadPool(100, new NotifyThreadFactory());
|
||||
|
||||
private RequestConfig requestConfig = RequestConfig.custom()
|
||||
.setConnectTimeout(PropertyUtil.getNotifyConnectTimeout())
|
||||
.setSocketTimeout(PropertyUtil.getNotifySocketTimeout()).build();
|
||||
@ -169,7 +162,7 @@ public class AsyncNotifyService extends AbstractEventListener {
|
||||
Queue<NotifySingleTask> queue = new LinkedList<NotifySingleTask>();
|
||||
queue.add(task);
|
||||
AsyncTask asyncTask = new AsyncTask(httpclient, queue);
|
||||
((ScheduledThreadPoolExecutor) EXECUTOR).schedule(asyncTask, delay, TimeUnit.MILLISECONDS);
|
||||
ConfigExecutor.scheduleAsyncNotify(asyncTask, delay, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
class AsyncNotifyCallBack implements FutureCallback<HttpResponse> {
|
||||
@ -310,16 +303,6 @@ public class AsyncNotifyService extends AbstractEventListener {
|
||||
|
||||
}
|
||||
|
||||
static class NotifyThreadFactory implements ThreadFactory {
|
||||
|
||||
@Override
|
||||
public Thread newThread(Runnable r) {
|
||||
Thread thread = new Thread(r, "com.alibaba.nacos.AsyncNotifyServiceThread");
|
||||
thread.setDaemon(true);
|
||||
return thread;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* get delayTime and also set failCount to task; The failure time index increases, so as not to retry invalid tasks
|
||||
* in the offline scene, which affects the normal synchronization.
|
||||
|
@ -16,6 +16,8 @@
|
||||
|
||||
package com.alibaba.nacos.config.server.service.notify;
|
||||
|
||||
import com.alibaba.nacos.common.executor.ExecutorFactory;
|
||||
import com.alibaba.nacos.common.executor.NameThreadFactory;
|
||||
import com.alibaba.nacos.config.server.manager.AbstractTask;
|
||||
import com.alibaba.nacos.config.server.utils.GroupKey2;
|
||||
import com.alibaba.nacos.config.server.utils.LogUtil;
|
||||
@ -28,9 +30,7 @@ import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledThreadPoolExecutor;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@ -102,22 +102,6 @@ public class NotifySingleService {
|
||||
}
|
||||
}
|
||||
|
||||
static class NotifyThreadFactory implements ThreadFactory {
|
||||
|
||||
private final String notifyTarget;
|
||||
|
||||
NotifyThreadFactory(String notifyTarget) {
|
||||
this.notifyTarget = notifyTarget;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Thread newThread(Runnable r) {
|
||||
Thread thread = new Thread(r, "com.alibaba.nacos.NotifySingleServiceThread-" + notifyTarget);
|
||||
thread.setDaemon(true);
|
||||
return thread;
|
||||
}
|
||||
}
|
||||
|
||||
@Autowired
|
||||
public NotifySingleService(ServerMemberManager memberManager) {
|
||||
this.memberManager = memberManager;
|
||||
@ -141,8 +125,8 @@ public class NotifySingleService {
|
||||
* there will be no continuous task accumulation,
|
||||
* there is occasional instantaneous pressure)
|
||||
*/
|
||||
@SuppressWarnings("PMD.ThreadPoolCreationRule") Executor executor = Executors
|
||||
.newScheduledThreadPool(1, new NotifyThreadFactory(address));
|
||||
Executor executor = ExecutorFactory.newSingleScheduledExecutorService(
|
||||
new NameThreadFactory("com.alibaba.nacos.config.NotifySingleServiceThread-" + address));
|
||||
|
||||
if (null == executors.putIfAbsent(address, executor)) {
|
||||
LOGGER.warn("[notify-thread-pool] setup thread target ip {} ok.", address);
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
package com.alibaba.nacos.config.server.service.repository.embedded;
|
||||
|
||||
import com.alibaba.nacos.common.notify.NotifyCenter;
|
||||
import com.alibaba.nacos.config.server.model.event.DerbyLoadEvent;
|
||||
import com.alibaba.nacos.config.server.service.datasource.DataSourceService;
|
||||
import com.alibaba.nacos.config.server.service.datasource.DynamicDataSource;
|
||||
@ -27,7 +28,6 @@ import com.alibaba.nacos.consistency.snapshot.SnapshotOperation;
|
||||
import com.alibaba.nacos.consistency.snapshot.Writer;
|
||||
import com.alibaba.nacos.core.distributed.raft.utils.RaftExecutor;
|
||||
import com.alibaba.nacos.core.utils.DiskUtils;
|
||||
import com.alibaba.nacos.core.notify.NotifyCenter;
|
||||
import com.alibaba.nacos.core.utils.ApplicationUtils;
|
||||
import com.alibaba.nacos.core.utils.TimerContext;
|
||||
import com.alipay.sofa.jraft.util.CRC64;
|
||||
|
@ -21,6 +21,9 @@ import com.alibaba.nacos.api.exception.runtime.NacosRuntimeException;
|
||||
import com.alibaba.nacos.common.JustForTest;
|
||||
import com.alibaba.nacos.common.model.RestResult;
|
||||
import com.alibaba.nacos.common.model.RestResultUtils;
|
||||
import com.alibaba.nacos.common.notify.Event;
|
||||
import com.alibaba.nacos.common.notify.NotifyCenter;
|
||||
import com.alibaba.nacos.common.notify.listener.Subscriber;
|
||||
import com.alibaba.nacos.common.utils.ExceptionUtil;
|
||||
import com.alibaba.nacos.common.utils.JacksonUtils;
|
||||
import com.alibaba.nacos.common.utils.LoggerUtils;
|
||||
@ -53,9 +56,6 @@ import com.alibaba.nacos.consistency.exception.ConsistencyException;
|
||||
import com.alibaba.nacos.consistency.snapshot.SnapshotOperation;
|
||||
import com.alibaba.nacos.core.cluster.ServerMemberManager;
|
||||
import com.alibaba.nacos.core.distributed.ProtocolManager;
|
||||
import com.alibaba.nacos.core.notify.Event;
|
||||
import com.alibaba.nacos.core.notify.NotifyCenter;
|
||||
import com.alibaba.nacos.core.notify.listener.Subscribe;
|
||||
import com.alibaba.nacos.core.utils.ClassUtils;
|
||||
import com.alibaba.nacos.core.utils.DiskUtils;
|
||||
import com.alibaba.nacos.core.utils.GenericType;
|
||||
@ -190,7 +190,7 @@ public class DistributedDatabaseOperateImpl extends LogProcessor4CP implements B
|
||||
// Register the snapshot load event
|
||||
NotifyCenter.registerToSharePublisher(DerbyLoadEvent.class);
|
||||
|
||||
NotifyCenter.registerSubscribe(new Subscribe<RaftDbErrorEvent>() {
|
||||
NotifyCenter.registerSubscriber(new Subscriber<RaftDbErrorEvent>() {
|
||||
@Override
|
||||
public void onEvent(RaftDbErrorEvent event) {
|
||||
dataSourceService.setHealthStatus("DOWN");
|
||||
@ -202,8 +202,8 @@ public class DistributedDatabaseOperateImpl extends LogProcessor4CP implements B
|
||||
}
|
||||
});
|
||||
|
||||
NotifyCenter.registerToPublisher(ConfigDumpEvent.class, NotifyCenter.RING_BUFFER_SIZE);
|
||||
NotifyCenter.registerSubscribe(new DumpConfigHandler());
|
||||
NotifyCenter.registerToPublisher(ConfigDumpEvent.class, NotifyCenter.ringBufferSize);
|
||||
NotifyCenter.registerSubscriber(new DumpConfigHandler());
|
||||
|
||||
this.protocol.addLogProcessors(Collections.singletonList(this));
|
||||
LogUtil.DEFAULT_LOG.info("use DistributedTransactionServicesImpl");
|
||||
|
@ -18,6 +18,7 @@ package com.alibaba.nacos.config.server.service.repository.embedded;
|
||||
|
||||
import com.alibaba.nacos.api.exception.NacosException;
|
||||
import com.alibaba.nacos.common.utils.MD5Utils;
|
||||
import com.alibaba.nacos.common.notify.NotifyCenter;
|
||||
import com.alibaba.nacos.config.server.configuration.ConditionOnEmbeddedStorage;
|
||||
import com.alibaba.nacos.config.server.constant.Constants;
|
||||
import com.alibaba.nacos.config.server.enums.FileTypeEnum;
|
||||
@ -48,7 +49,6 @@ import com.alibaba.nacos.config.server.service.sql.EmbeddedStorageContextUtils;
|
||||
import com.alibaba.nacos.config.server.utils.LogUtil;
|
||||
import com.alibaba.nacos.config.server.utils.ParamUtils;
|
||||
import com.alibaba.nacos.core.distributed.id.IdGeneratorManager;
|
||||
import com.alibaba.nacos.core.notify.NotifyCenter;
|
||||
import com.google.common.base.Joiner;
|
||||
import com.google.common.collect.Lists;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
|
@ -18,10 +18,14 @@ package com.alibaba.nacos.config.server.utils;
|
||||
|
||||
import com.alibaba.nacos.common.executor.ExecutorFactory;
|
||||
import com.alibaba.nacos.common.executor.NameThreadFactory;
|
||||
import com.alibaba.nacos.common.utils.ThreadUtils;
|
||||
import com.alibaba.nacos.config.server.Config;
|
||||
import com.alibaba.nacos.core.utils.ClassUtils;
|
||||
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.ScheduledThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
@ -31,15 +35,32 @@ import java.util.concurrent.TimeUnit;
|
||||
*/
|
||||
public final class ConfigExecutor {
|
||||
|
||||
private static final Executor DUMP_EXECUTOR = ExecutorFactory
|
||||
.newFixedExecutorService(Config.class.getCanonicalName(), 1,
|
||||
new NameThreadFactory("nacos.config.embedded.dump"));
|
||||
private static final Executor DUMP_EXECUTOR = ExecutorFactory.Managed
|
||||
.newSingleExecutorService(ClassUtils.getCanonicalName(Config.class),
|
||||
new NameThreadFactory("com.alibaba.nacos.config.embedded.dump"));
|
||||
|
||||
private static final ScheduledExecutorService TIMER_EXECUTOR = ExecutorFactory
|
||||
.newScheduledExecutorService(Config.class.getCanonicalName(), 10,
|
||||
new NameThreadFactory("com.alibaba.nacos.server.Timer"));
|
||||
private static final ScheduledExecutorService TIMER_EXECUTOR = ExecutorFactory.Managed
|
||||
.newScheduledExecutorService(ClassUtils.getCanonicalName(Config.class), 10,
|
||||
new NameThreadFactory("com.alibaba.nacos.config.server.timer"));
|
||||
|
||||
public static void scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit) {
|
||||
private static final ScheduledExecutorService CAPACITY_MANAGEMENT_EXECUTOR = ExecutorFactory.Managed
|
||||
.newSingleScheduledExecutorService(ClassUtils.getCanonicalName(Config.class),
|
||||
new NameThreadFactory("com.alibaba.nacos.config.CapacityManagement"));
|
||||
|
||||
private static final ScheduledExecutorService ASYNC_NOTIFY_EXECUTOR = ExecutorFactory.Managed
|
||||
.newScheduledExecutorService(ClassUtils.getCanonicalName(Config.class), 100,
|
||||
new NameThreadFactory("com.alibaba.nacos.config.AsyncNotifyService"));
|
||||
|
||||
private static final ScheduledExecutorService CONFIG_SUB_SERVICE_EXECUTOR = ExecutorFactory.Managed
|
||||
.newScheduledExecutorService(ClassUtils.getCanonicalName(Config.class),
|
||||
ThreadUtils.getSuitableThreadCount(),
|
||||
new NameThreadFactory("com.alibaba.nacos.config.ConfigSubService"));
|
||||
|
||||
private static final ScheduledExecutorService LONG_POLLING_EXECUTOR = ExecutorFactory.Managed
|
||||
.newSingleScheduledExecutorService(ClassUtils.getCanonicalName(Config.class),
|
||||
new NameThreadFactory("com.alibaba.nacos.config.LongPolling"));
|
||||
|
||||
public static void scheduleConfigTask(Runnable command, long initialDelay, long delay, TimeUnit unit) {
|
||||
TIMER_EXECUTOR.scheduleWithFixedDelay(command, initialDelay, delay, unit);
|
||||
}
|
||||
|
||||
@ -47,4 +68,35 @@ public final class ConfigExecutor {
|
||||
DUMP_EXECUTOR.execute(runnable);
|
||||
}
|
||||
|
||||
public static void scheduleCorrectUsageTask(Runnable runnable, long initialDelay, long delay, TimeUnit unit) {
|
||||
CAPACITY_MANAGEMENT_EXECUTOR.scheduleWithFixedDelay(runnable, initialDelay, delay, unit);
|
||||
}
|
||||
|
||||
public static void executeAsyncNotify(Runnable runnable) {
|
||||
ASYNC_NOTIFY_EXECUTOR.execute(runnable);
|
||||
}
|
||||
|
||||
public static void scheduleAsyncNotify(Runnable command, long delay, TimeUnit unit) {
|
||||
ASYNC_NOTIFY_EXECUTOR.schedule(command, delay, unit);
|
||||
}
|
||||
|
||||
public static int asyncNotifyQueueSize() {
|
||||
return ((ScheduledThreadPoolExecutor) ASYNC_NOTIFY_EXECUTOR).getQueue().size();
|
||||
}
|
||||
|
||||
public static ScheduledExecutorService getConfigSubServiceExecutor() {
|
||||
return CONFIG_SUB_SERVICE_EXECUTOR;
|
||||
}
|
||||
|
||||
public static void scheduleLongPolling(Runnable runnable, long initialDelay, long period, TimeUnit unit) {
|
||||
LONG_POLLING_EXECUTOR.scheduleWithFixedDelay(runnable, initialDelay, period, unit);
|
||||
}
|
||||
|
||||
public static ScheduledFuture<?> scheduleLongPolling(Runnable runnable, long period, TimeUnit unit) {
|
||||
return LONG_POLLING_EXECUTOR.schedule(runnable, period, unit);
|
||||
}
|
||||
|
||||
public static void executeLongPolling(Runnable runnable) {
|
||||
LONG_POLLING_EXECUTOR.execute(runnable);
|
||||
}
|
||||
}
|
||||
|
@ -16,9 +16,12 @@
|
||||
|
||||
package com.alibaba.nacos.config.server.utils;
|
||||
|
||||
import java.util.concurrent.Executors;
|
||||
import com.alibaba.nacos.common.executor.ExecutorFactory;
|
||||
import com.alibaba.nacos.common.executor.NameThreadFactory;
|
||||
import com.alibaba.nacos.config.server.Config;
|
||||
import com.alibaba.nacos.core.utils.ClassUtils;
|
||||
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
@ -37,18 +40,9 @@ public class SimpleFlowData {
|
||||
|
||||
private int slotCount;
|
||||
|
||||
@SuppressWarnings("PMD.ThreadPoolCreationRule")
|
||||
private ScheduledExecutorService timer = Executors.newSingleThreadScheduledExecutor(new ThreadFactory() {
|
||||
|
||||
@Override
|
||||
public Thread newThread(Runnable r) {
|
||||
Thread t = new Thread(r);
|
||||
t.setName("nacos flow control thread");
|
||||
t.setDaemon(true);
|
||||
return t;
|
||||
}
|
||||
|
||||
});
|
||||
private ScheduledExecutorService timer = ExecutorFactory.Managed
|
||||
.newSingleScheduledExecutorService(ClassUtils.getCanonicalName(Config.class),
|
||||
new NameThreadFactory("com.alibaba.nacos.config.flow.control"));
|
||||
|
||||
public SimpleFlowData(int slotCount, int interval) {
|
||||
this.slotCount = slotCount;
|
||||
|
@ -16,9 +16,12 @@
|
||||
|
||||
package com.alibaba.nacos.config.server.utils;
|
||||
|
||||
import java.util.concurrent.Executors;
|
||||
import com.alibaba.nacos.common.executor.ExecutorFactory;
|
||||
import com.alibaba.nacos.common.executor.NameThreadFactory;
|
||||
import com.alibaba.nacos.config.server.Config;
|
||||
import com.alibaba.nacos.core.utils.ClassUtils;
|
||||
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
@ -35,18 +38,9 @@ public class SimpleIpFlowData {
|
||||
|
||||
private int averageCount;
|
||||
|
||||
@SuppressWarnings("PMD.ThreadPoolCreationRule")
|
||||
private ScheduledExecutorService timer = Executors.newSingleThreadScheduledExecutor(new ThreadFactory() {
|
||||
|
||||
@Override
|
||||
public Thread newThread(Runnable r) {
|
||||
Thread t = new Thread(r);
|
||||
t.setName("nacos ip flow control thread");
|
||||
t.setDaemon(true);
|
||||
return t;
|
||||
}
|
||||
|
||||
});
|
||||
private ScheduledExecutorService timer = ExecutorFactory.Managed
|
||||
.newSingleScheduledExecutorService(ClassUtils.getCanonicalName(Config.class),
|
||||
new NameThreadFactory("com.alibaba.nacos.config.flow.control.ip"));
|
||||
|
||||
class DefaultIpFlowDataManagerTask implements Runnable {
|
||||
|
||||
|
@ -1,143 +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.config.server.utils.event;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
/**
|
||||
* Event dispatcher.
|
||||
*
|
||||
* @author Nacos
|
||||
*/
|
||||
public class EventDispatcher {
|
||||
|
||||
/**
|
||||
* add event listener.
|
||||
*/
|
||||
public static void addEventListener(AbstractEventListener listener) {
|
||||
for (Class<? extends Event> type : listener.interest()) {
|
||||
getEntry(type).listeners.addIfAbsent(listener);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* fire event, notify listeners.
|
||||
*/
|
||||
public static void fireEvent(Event event) {
|
||||
if (null == event) {
|
||||
throw new IllegalArgumentException("event is null");
|
||||
}
|
||||
|
||||
for (AbstractEventListener listener : getEntry(event.getClass()).listeners) {
|
||||
try {
|
||||
listener.onEvent(event);
|
||||
} catch (Exception e) {
|
||||
LOGGER.error(e.toString(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* For only test purpose.
|
||||
*/
|
||||
public static void clear() {
|
||||
LISTENER_HUB.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get event listener for eventType. Add Entry if not exist.
|
||||
*/
|
||||
static Entry getEntry(Class<? extends Event> eventType) {
|
||||
for (; ; ) {
|
||||
for (Entry entry : LISTENER_HUB) {
|
||||
if (entry.eventType == eventType) {
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
|
||||
Entry tmp = new Entry(eventType);
|
||||
// false means already exists
|
||||
if (LISTENER_HUB.addIfAbsent(tmp)) {
|
||||
return tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class Entry {
|
||||
|
||||
final Class<? extends Event> eventType;
|
||||
|
||||
final CopyOnWriteArrayList<AbstractEventListener> listeners;
|
||||
|
||||
Entry(Class<? extends Event> type) {
|
||||
eventType = type;
|
||||
listeners = new CopyOnWriteArrayList<AbstractEventListener>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (null == obj || obj.getClass() != getClass()) {
|
||||
return false;
|
||||
}
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
return eventType == ((Entry) obj).eventType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return super.hashCode();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(EventDispatcher.class);
|
||||
|
||||
static final CopyOnWriteArrayList<Entry> LISTENER_HUB = new CopyOnWriteArrayList<Entry>();
|
||||
|
||||
public interface Event {
|
||||
|
||||
}
|
||||
|
||||
public abstract static class AbstractEventListener {
|
||||
|
||||
public AbstractEventListener() {
|
||||
// automatic register
|
||||
EventDispatcher.addEventListener(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* List of events of interest.
|
||||
*
|
||||
* @return event list
|
||||
*/
|
||||
public abstract List<Class<? extends Event>> interest();
|
||||
|
||||
/**
|
||||
* Handle events.
|
||||
*
|
||||
* @param event event
|
||||
*/
|
||||
public abstract void onEvent(Event event);
|
||||
}
|
||||
|
||||
}
|
@ -16,33 +16,35 @@
|
||||
|
||||
package com.alibaba.nacos.config.server.service;
|
||||
|
||||
import com.alibaba.nacos.common.notify.Event;
|
||||
import com.alibaba.nacos.common.notify.NotifyCenter;
|
||||
import com.alibaba.nacos.common.notify.listener.Subscriber;
|
||||
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() {
|
||||
public void testConfigChangeNotify() throws InterruptedException {
|
||||
|
||||
AtomicReference<ConfigDataChangeEvent> reference = new AtomicReference<>();
|
||||
|
||||
EventDispatcher.addEventListener(new EventDispatcher.AbstractEventListener() {
|
||||
NotifyCenter.registerToPublisher(ConfigDataChangeEvent.class, NotifyCenter.ringBufferSize);
|
||||
NotifyCenter.registerSubscriber(new Subscriber() {
|
||||
|
||||
@Override
|
||||
public List<Class<? extends EventDispatcher.Event>> interest() {
|
||||
return Collections.singletonList(ConfigDataChangeEvent.class);
|
||||
public void onEvent(Event event) {
|
||||
reference.set((ConfigDataChangeEvent) event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEvent(EventDispatcher.Event event) {
|
||||
reference.set((ConfigDataChangeEvent) event);
|
||||
public Class<? extends Event> subscribeType() {
|
||||
return ConfigDataChangeEvent.class;
|
||||
}
|
||||
});
|
||||
|
||||
@ -52,33 +54,34 @@ public class ConfigChangePublisherTest {
|
||||
|
||||
ConfigChangePublisher
|
||||
.notifyConfigChange(new ConfigDataChangeEvent("chuntaojun", "chuntaojun", System.currentTimeMillis()));
|
||||
Thread.sleep(2000);
|
||||
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()));
|
||||
Thread.sleep(2000);
|
||||
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()));
|
||||
Thread.sleep(2000);
|
||||
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()));
|
||||
Thread.sleep(2000);
|
||||
Assert.assertNotNull(reference.get());
|
||||
reference.set(null);
|
||||
}
|
||||
|
@ -97,6 +97,20 @@ public class ExternalDataSourcePropertiesTest {
|
||||
}));
|
||||
Assert.assertEquals(dataSources.size(), 2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void externalDatasourceToAssertMinIdle() {
|
||||
MockEnvironment environment = new MockEnvironment();
|
||||
environment.setProperty("db.num", "1");
|
||||
environment.setProperty("db.user", USERNAME);
|
||||
environment.setProperty("db.password", PASSWORD);
|
||||
environment.setProperty("db.url.0", JDBC_URL);
|
||||
List<HikariDataSource> dataSources = new ExternalDataSourceProperties().build(environment, (dataSource -> {
|
||||
dataSource.validate();
|
||||
Assert.assertEquals(dataSource.getMinimumIdle(), ExternalDataSourceProperties.DEFAULT_MINIMUM_IDLE);
|
||||
}));
|
||||
Assert.assertEquals(dataSources.size(), 1);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void externalDatasourceFailureWithLarkInfo() {
|
||||
|
@ -1,98 +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.config.server.utils.event;
|
||||
|
||||
import com.alibaba.nacos.config.server.utils.event.EventDispatcher.AbstractEventListener;
|
||||
import com.alibaba.nacos.config.server.utils.event.EventDispatcher.Event;
|
||||
import org.junit.After;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.test.context.web.WebAppConfiguration;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@WebAppConfiguration
|
||||
public class EventDispatcherTest {
|
||||
|
||||
@After
|
||||
public void after() {
|
||||
EventDispatcher.clear();
|
||||
}
|
||||
|
||||
@Ignore
|
||||
@Test
|
||||
public void testAddListener() throws Exception {
|
||||
final AbstractEventListener listener = new MockListener();
|
||||
|
||||
int vusers = 1000;
|
||||
final CountDownLatch latch = new CountDownLatch(vusers);
|
||||
|
||||
for (int i = 0; i < vusers; ++i) {
|
||||
new Thread(new Runnable() {
|
||||
public void run() {
|
||||
latch.countDown();
|
||||
EventDispatcher.addEventListener(listener);
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
|
||||
latch.await();
|
||||
assertEquals(1, EventDispatcher.LISTENER_HUB.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFireEvent() {
|
||||
EventDispatcher.fireEvent(new MockEvent());
|
||||
assertEquals(0, MockListener.count);
|
||||
|
||||
EventDispatcher.addEventListener(new MockListener());
|
||||
|
||||
EventDispatcher.fireEvent(new MockEvent());
|
||||
assertEquals(1, MockListener.count);
|
||||
|
||||
EventDispatcher.fireEvent(new MockEvent());
|
||||
assertEquals(2, MockListener.count);
|
||||
}
|
||||
|
||||
private static class MockEvent implements Event {
|
||||
|
||||
}
|
||||
|
||||
private static class MockListener extends AbstractEventListener {
|
||||
|
||||
static int count = 0;
|
||||
|
||||
@Override
|
||||
public List<Class<? extends Event>> interest() {
|
||||
List<Class<? extends Event>> types = new ArrayList<Class<? extends Event>>();
|
||||
types.add(MockEvent.class);
|
||||
return types;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEvent(Event event) {
|
||||
++count;
|
||||
}
|
||||
}
|
||||
}
|
@ -16,15 +16,16 @@
|
||||
|
||||
package com.alibaba.nacos.core.cluster;
|
||||
|
||||
import com.alibaba.nacos.core.notify.Event;
|
||||
import com.alibaba.nacos.core.notify.listener.Subscribe;
|
||||
import com.alibaba.nacos.common.notify.Event;
|
||||
import com.alibaba.nacos.common.notify.listener.Subscriber;
|
||||
|
||||
/**
|
||||
* Node change listeners.
|
||||
*
|
||||
* @author <a href="mailto:liaochuntao@live.com">liaochuntao</a>
|
||||
*/
|
||||
public interface MemberChangeListener extends Subscribe<MembersChangeEvent> {
|
||||
@SuppressWarnings("PMD.AbstractClassShouldStartWithAbstractNamingRule")
|
||||
public abstract class MemberChangeListener extends Subscriber<MembersChangeEvent> {
|
||||
|
||||
/**
|
||||
* return NodeChangeEvent.class info.
|
||||
@ -32,7 +33,7 @@ public interface MemberChangeListener extends Subscribe<MembersChangeEvent> {
|
||||
* @return {@link MembersChangeEvent#getClass()}
|
||||
*/
|
||||
@Override
|
||||
default Class<? extends Event> subscribeType() {
|
||||
public Class<? extends Event> subscribeType() {
|
||||
return MembersChangeEvent.class;
|
||||
}
|
||||
|
||||
@ -42,7 +43,7 @@ public interface MemberChangeListener extends Subscribe<MembersChangeEvent> {
|
||||
* @return default value is {@link Boolean#TRUE}
|
||||
*/
|
||||
@Override
|
||||
default boolean ignoreExpireEvent() {
|
||||
public boolean ignoreExpireEvent() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -16,10 +16,9 @@
|
||||
|
||||
package com.alibaba.nacos.core.cluster;
|
||||
|
||||
import com.alibaba.nacos.core.notify.Event;
|
||||
import com.alibaba.nacos.common.notify.Event;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
/**
|
||||
* Publish this event when the node list changes,All interested in the node list change event can listen to this event.
|
||||
@ -32,16 +31,12 @@ import java.util.concurrent.atomic.AtomicLong;
|
||||
*
|
||||
* @author <a href="mailto:liaochuntao@live.com">liaochuntao</a>
|
||||
*/
|
||||
public class MembersChangeEvent implements Event {
|
||||
|
||||
private static final AtomicLong SEQUENCE = new AtomicLong(0);
|
||||
public class MembersChangeEvent extends Event {
|
||||
|
||||
private static final long serialVersionUID = 7308126651076668976L;
|
||||
|
||||
private Collection<Member> members;
|
||||
|
||||
private long no = SEQUENCE.getAndIncrement();
|
||||
|
||||
public static MemberChangeEventBuilder builder() {
|
||||
return new MemberChangeEventBuilder();
|
||||
}
|
||||
@ -54,14 +49,9 @@ public class MembersChangeEvent implements Event {
|
||||
this.members = members;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long sequence() {
|
||||
return no;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "MembersChangeEvent{" + "members=" + members + ", no=" + no + '}';
|
||||
return "MembersChangeEvent{" + "members=" + members + ", no=" + sequence() + '}';
|
||||
}
|
||||
|
||||
public static final class MemberChangeEventBuilder {
|
||||
|
@ -25,13 +25,13 @@ import com.alibaba.nacos.common.http.NAsyncHttpClient;
|
||||
import com.alibaba.nacos.common.http.param.Header;
|
||||
import com.alibaba.nacos.common.http.param.Query;
|
||||
import com.alibaba.nacos.common.model.RestResult;
|
||||
import com.alibaba.nacos.common.notify.Event;
|
||||
import com.alibaba.nacos.common.notify.NotifyCenter;
|
||||
import com.alibaba.nacos.common.notify.listener.Subscriber;
|
||||
import com.alibaba.nacos.common.utils.ConcurrentHashSet;
|
||||
import com.alibaba.nacos.common.utils.ExceptionUtil;
|
||||
import com.alibaba.nacos.common.utils.VersionUtils;
|
||||
import com.alibaba.nacos.core.cluster.lookup.LookupFactory;
|
||||
import com.alibaba.nacos.core.notify.Event;
|
||||
import com.alibaba.nacos.core.notify.NotifyCenter;
|
||||
import com.alibaba.nacos.core.notify.listener.Subscribe;
|
||||
import com.alibaba.nacos.core.utils.ApplicationUtils;
|
||||
import com.alibaba.nacos.core.utils.Commons;
|
||||
import com.alibaba.nacos.core.utils.Constants;
|
||||
@ -166,7 +166,7 @@ public class ServerMemberManager implements ApplicationListener<WebServerInitial
|
||||
|
||||
// The address information of this node needs to be dynamically modified
|
||||
// when registering the IP change of this node
|
||||
NotifyCenter.registerSubscribe(new Subscribe<InetUtils.IPChangeEvent>() {
|
||||
NotifyCenter.registerSubscriber(new Subscriber<InetUtils.IPChangeEvent>() {
|
||||
@Override
|
||||
public void onEvent(InetUtils.IPChangeEvent event) {
|
||||
String newAddress = event.getNewIp() + ":" + port;
|
||||
|
@ -20,8 +20,8 @@ import com.alibaba.nacos.common.executor.ExecutorFactory;
|
||||
import com.alibaba.nacos.common.executor.NameThreadFactory;
|
||||
import com.alibaba.nacos.common.executor.ThreadPoolManager;
|
||||
import com.alibaba.nacos.common.http.HttpClientManager;
|
||||
import com.alibaba.nacos.common.notify.NotifyCenter;
|
||||
import com.alibaba.nacos.core.file.WatchFileCenter;
|
||||
import com.alibaba.nacos.core.notify.NotifyCenter;
|
||||
import com.alibaba.nacos.core.utils.ApplicationUtils;
|
||||
import com.alibaba.nacos.core.utils.DiskUtils;
|
||||
import com.alibaba.nacos.core.utils.InetUtils;
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
package com.alibaba.nacos.core.distributed;
|
||||
|
||||
import com.alibaba.nacos.common.notify.NotifyCenter;
|
||||
import com.alibaba.nacos.consistency.Config;
|
||||
import com.alibaba.nacos.consistency.ap.APProtocol;
|
||||
import com.alibaba.nacos.consistency.cp.CPProtocol;
|
||||
@ -25,7 +26,6 @@ import com.alibaba.nacos.core.cluster.MemberChangeListener;
|
||||
import com.alibaba.nacos.core.cluster.MemberMetaDataConstants;
|
||||
import com.alibaba.nacos.core.cluster.MemberUtils;
|
||||
import com.alibaba.nacos.core.cluster.ServerMemberManager;
|
||||
import com.alibaba.nacos.core.notify.NotifyCenter;
|
||||
import com.alibaba.nacos.core.utils.ApplicationUtils;
|
||||
import com.alibaba.nacos.core.utils.ClassUtils;
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
@ -49,7 +49,7 @@ import java.util.Set;
|
||||
@SuppressWarnings("all")
|
||||
@Component(value = "ProtocolManager")
|
||||
@DependsOn("serverMemberManager")
|
||||
public class ProtocolManager implements ApplicationListener<ContextStartedEvent>, DisposableBean, MemberChangeListener {
|
||||
public class ProtocolManager extends MemberChangeListener implements ApplicationListener<ContextStartedEvent>, DisposableBean {
|
||||
|
||||
private CPProtocol cpProtocol;
|
||||
|
||||
@ -85,7 +85,7 @@ public class ProtocolManager implements ApplicationListener<ContextStartedEvent>
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
this.memberManager = memberManager;
|
||||
NotifyCenter.registerSubscribe(this);
|
||||
NotifyCenter.registerSubscriber(this);
|
||||
}
|
||||
|
||||
public CPProtocol getCpProtocol() {
|
||||
|
@ -17,6 +17,9 @@
|
||||
package com.alibaba.nacos.core.distributed.raft;
|
||||
|
||||
import com.alibaba.nacos.common.model.RestResult;
|
||||
import com.alibaba.nacos.common.notify.NotifyCenter;
|
||||
import com.alibaba.nacos.common.notify.listener.Subscriber;
|
||||
import com.alibaba.nacos.common.notify.Event;
|
||||
import com.alibaba.nacos.common.utils.MapUtils;
|
||||
import com.alibaba.nacos.common.utils.ThreadUtils;
|
||||
import com.alibaba.nacos.consistency.ProtocolMetaData;
|
||||
@ -32,9 +35,6 @@ import com.alibaba.nacos.core.cluster.Member;
|
||||
import com.alibaba.nacos.core.cluster.ServerMemberManager;
|
||||
import com.alibaba.nacos.core.distributed.AbstractConsistencyProtocol;
|
||||
import com.alibaba.nacos.core.distributed.raft.exception.NoSuchRaftGroupException;
|
||||
import com.alibaba.nacos.core.notify.Event;
|
||||
import com.alibaba.nacos.core.notify.NotifyCenter;
|
||||
import com.alibaba.nacos.core.notify.listener.Subscribe;
|
||||
import com.alibaba.nacos.core.utils.Loggers;
|
||||
import com.alipay.sofa.jraft.Node;
|
||||
|
||||
@ -123,7 +123,7 @@ public class JRaftProtocol extends AbstractConsistencyProtocol<RaftConfig, LogPr
|
||||
|
||||
// There is only one consumer to ensure that the internal consumption
|
||||
// is sequential and there is no concurrent competition
|
||||
NotifyCenter.registerSubscribe(new Subscribe<RaftEvent>() {
|
||||
NotifyCenter.registerSubscriber(new Subscriber<RaftEvent>() {
|
||||
@Override
|
||||
public void onEvent(RaftEvent event) {
|
||||
Loggers.RAFT.info("This Raft event changes : {}", event);
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
package com.alibaba.nacos.core.distributed.raft;
|
||||
|
||||
import com.alibaba.nacos.common.notify.NotifyCenter;
|
||||
import com.alibaba.nacos.common.utils.ExceptionUtil;
|
||||
import com.alibaba.nacos.common.utils.JacksonUtils;
|
||||
import com.alibaba.nacos.common.utils.LoggerUtils;
|
||||
@ -30,7 +31,6 @@ import com.alibaba.nacos.consistency.snapshot.Reader;
|
||||
import com.alibaba.nacos.consistency.snapshot.SnapshotOperation;
|
||||
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.alipay.sofa.jraft.Closure;
|
||||
import com.alipay.sofa.jraft.Iterator;
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
package com.alibaba.nacos.core.distributed.raft;
|
||||
|
||||
import com.alibaba.nacos.core.notify.Event;
|
||||
import com.alibaba.nacos.common.notify.Event;
|
||||
|
||||
/**
|
||||
* The RAFT protocol runs an exception event. If this event is published, it means that the current raft Group cannot
|
||||
@ -24,7 +24,7 @@ import com.alibaba.nacos.core.notify.Event;
|
||||
*
|
||||
* @author <a href="mailto:liaochuntao@live.com">liaochuntao</a>
|
||||
*/
|
||||
public class RaftErrorEvent implements Event {
|
||||
public class RaftErrorEvent extends Event {
|
||||
|
||||
private static final long serialVersionUID = 3016514657754158167L;
|
||||
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
package com.alibaba.nacos.core.distributed.raft;
|
||||
|
||||
import com.alibaba.nacos.core.notify.SlowEvent;
|
||||
import com.alibaba.nacos.common.notify.SlowEvent;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
@ -27,7 +27,7 @@ import java.util.List;
|
||||
* @author <a href="mailto:liaochuntao@live.com">liaochuntao</a>
|
||||
*/
|
||||
@SuppressWarnings("all")
|
||||
public class RaftEvent implements SlowEvent {
|
||||
public class RaftEvent extends SlowEvent {
|
||||
|
||||
private static final long serialVersionUID = -4304258594602886451L;
|
||||
|
||||
|
@ -1,211 +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.core.notify;
|
||||
|
||||
import com.alibaba.nacos.common.utils.ConcurrentHashSet;
|
||||
import com.alibaba.nacos.common.utils.ThreadUtils;
|
||||
import com.alibaba.nacos.core.notify.listener.SmartSubscribe;
|
||||
import com.alibaba.nacos.core.notify.listener.Subscribe;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.ArrayBlockingQueue;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
|
||||
|
||||
import static com.alibaba.nacos.core.notify.NotifyCenter.RING_BUFFER_SIZE;
|
||||
|
||||
/**
|
||||
* The default event publisher implementation. Internally, use {@link ArrayBlockingQueue} as a message staging queue
|
||||
*
|
||||
* @author <a href="mailto:liaochuntao@live.com">liaochuntao</a>
|
||||
*/
|
||||
public class DefaultPublisher extends Thread implements EventPublisher {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(NotifyCenter.class);
|
||||
|
||||
private final ConcurrentHashSet<Subscribe> subscribes = new ConcurrentHashSet<>();
|
||||
|
||||
private final AtomicReferenceFieldUpdater<DefaultPublisher, Long> updater = AtomicReferenceFieldUpdater
|
||||
.newUpdater(DefaultPublisher.class, Long.class, "lastEventSequence");
|
||||
|
||||
private volatile boolean initialized = false;
|
||||
|
||||
private volatile boolean canOpen = false;
|
||||
|
||||
private volatile boolean shutdown = false;
|
||||
|
||||
private Class<? extends Event> eventType;
|
||||
|
||||
private int queueMaxSize = -1;
|
||||
|
||||
private BlockingQueue<Event> queue;
|
||||
|
||||
private volatile Long lastEventSequence = -1L;
|
||||
|
||||
@Override
|
||||
public void init(Class<? extends Event> type, int bufferSize) {
|
||||
setDaemon(true);
|
||||
setName("nacos.publisher-" + type.getName());
|
||||
this.eventType = type;
|
||||
this.queueMaxSize = bufferSize;
|
||||
this.queue = new ArrayBlockingQueue<>(bufferSize);
|
||||
start();
|
||||
}
|
||||
|
||||
public ConcurrentHashSet<Subscribe> getSubscribes() {
|
||||
return subscribes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void start() {
|
||||
super.start();
|
||||
if (!initialized) {
|
||||
if (queueMaxSize == -1) {
|
||||
queueMaxSize = RING_BUFFER_SIZE;
|
||||
}
|
||||
initialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public long currentEventSize() {
|
||||
return queue.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
openEventHandler();
|
||||
}
|
||||
|
||||
void openEventHandler() {
|
||||
try {
|
||||
int waitTimes = 60;
|
||||
// To ensure that messages are not lost, enable EventHandler when
|
||||
// waiting for the first Subscriber to register
|
||||
for (; ; ) {
|
||||
if (shutdown || canOpen || waitTimes <= 0) {
|
||||
break;
|
||||
}
|
||||
ThreadUtils.sleep(1_000L);
|
||||
waitTimes--;
|
||||
}
|
||||
|
||||
for (; ; ) {
|
||||
if (shutdown) {
|
||||
break;
|
||||
}
|
||||
final Event event = queue.take();
|
||||
receiveEvent(event);
|
||||
updater.compareAndSet(this, lastEventSequence, Math.max(lastEventSequence, event.sequence()));
|
||||
}
|
||||
} catch (Throwable ex) {
|
||||
LOGGER.error("Event listener exception : {}", ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addSubscribe(Subscribe subscribe) {
|
||||
subscribes.add(subscribe);
|
||||
canOpen = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unSubscribe(Subscribe subscribe) {
|
||||
subscribes.remove(subscribe);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean publish(Event event) {
|
||||
checkIsStart();
|
||||
boolean success = this.queue.offer(event);
|
||||
if (!success) {
|
||||
LOGGER.warn("Unable to plug in due to interruption, synchronize sending time, event : {}", event);
|
||||
receiveEvent(event);
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void checkIsStart() {
|
||||
if (!initialized) {
|
||||
throw new IllegalStateException("Publisher does not start");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shutdown() {
|
||||
this.shutdown = true;
|
||||
this.queue.clear();
|
||||
}
|
||||
|
||||
public boolean isInitialized() {
|
||||
return initialized;
|
||||
}
|
||||
|
||||
void receiveEvent(Event event) {
|
||||
final long currentEventSequence = event.sequence();
|
||||
final String sourceName = event.getClass().getName();
|
||||
|
||||
// Notification single event listener
|
||||
for (Subscribe subscribe : subscribes) {
|
||||
// Whether to ignore expiration events
|
||||
if (subscribe.ignoreExpireEvent() && lastEventSequence > currentEventSequence) {
|
||||
LOGGER.debug("[NotifyCenter] the {} is unacceptable to this subscriber, because had expire",
|
||||
event.getClass());
|
||||
continue;
|
||||
}
|
||||
|
||||
final String targetName = subscribe.subscribeType().getName();
|
||||
if (!Objects.equals(sourceName, targetName)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
notifySubscriber(subscribe, event);
|
||||
}
|
||||
|
||||
// Notification multi-event event listener
|
||||
for (SmartSubscribe subscribe : SMART_SUBSCRIBES) {
|
||||
// If you are a multi-event listener, you need to make additional logical judgments
|
||||
if (!subscribe.canNotify(event)) {
|
||||
LOGGER.debug("[NotifyCenter] the {} is unacceptable to this multi-event subscriber", event.getClass());
|
||||
continue;
|
||||
}
|
||||
notifySubscriber(subscribe, event);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifySubscriber(final Subscribe subscribe, final Event event) {
|
||||
|
||||
LOGGER.debug("[NotifyCenter] the {} will received by {}", event, subscribe);
|
||||
|
||||
final Runnable job = () -> subscribe.onEvent(event);
|
||||
final Executor executor = subscribe.executor();
|
||||
if (Objects.nonNull(executor)) {
|
||||
executor.execute(job);
|
||||
} else {
|
||||
try {
|
||||
job.run();
|
||||
} catch (Throwable e) {
|
||||
LOGGER.error("Event callback exception : {}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,86 +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.core.notify;
|
||||
|
||||
import com.alibaba.nacos.common.utils.ConcurrentHashSet;
|
||||
import com.alibaba.nacos.core.notify.listener.SmartSubscribe;
|
||||
import com.alibaba.nacos.core.notify.listener.Subscribe;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Event publisher.
|
||||
*
|
||||
* @author <a href="mailto:liaochuntao@live.com">liaochuntao</a>
|
||||
*/
|
||||
public interface EventPublisher {
|
||||
|
||||
/**
|
||||
* Multi-event listener collection list.
|
||||
*/
|
||||
Set<SmartSubscribe> SMART_SUBSCRIBES = new ConcurrentHashSet<>();
|
||||
|
||||
/**
|
||||
* Initializes the event publisher.
|
||||
*
|
||||
* @param type {@link Class}
|
||||
* @param bufferSize Message staging queue size
|
||||
*/
|
||||
void init(Class<? extends Event> type, int bufferSize);
|
||||
|
||||
/**
|
||||
* The number of currently staged events.
|
||||
*
|
||||
* @return event size
|
||||
*/
|
||||
long currentEventSize();
|
||||
|
||||
/**
|
||||
* Add listener.
|
||||
*
|
||||
* @param subscribe {@link Subscribe}
|
||||
*/
|
||||
void addSubscribe(Subscribe subscribe);
|
||||
|
||||
/**
|
||||
* Remove listener.
|
||||
*
|
||||
* @param subscribe {@link Subscribe}
|
||||
*/
|
||||
void unSubscribe(Subscribe subscribe);
|
||||
|
||||
/**
|
||||
* publish event.
|
||||
*
|
||||
* @param event {@link Event}
|
||||
* @return publish event is success
|
||||
*/
|
||||
boolean publish(Event event);
|
||||
|
||||
/**
|
||||
* Notify listener.
|
||||
*
|
||||
* @param subscribe {@link Subscribe}
|
||||
* @param event {@link Event}
|
||||
*/
|
||||
void notifySubscriber(Subscribe subscribe, Event event);
|
||||
|
||||
/**
|
||||
* shutdown this publisher.
|
||||
*/
|
||||
void shutdown();
|
||||
}
|
@ -1,280 +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.core.notify;
|
||||
|
||||
import com.alibaba.nacos.common.JustForTest;
|
||||
import com.alibaba.nacos.common.utils.ConcurrentHashSet;
|
||||
import com.alibaba.nacos.common.utils.ThreadUtils;
|
||||
import com.alibaba.nacos.core.notify.listener.SmartSubscribe;
|
||||
import com.alibaba.nacos.core.notify.listener.Subscribe;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.ServiceLoader;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
/**
|
||||
* notify center.
|
||||
*
|
||||
* @author <a href="mailto:liaochuntao@live.com">liaochuntao</a>
|
||||
*/
|
||||
@SuppressWarnings("all")
|
||||
public class NotifyCenter {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(NotifyCenter.class);
|
||||
|
||||
private static final AtomicBoolean CLOSED = new AtomicBoolean(false);
|
||||
|
||||
private static final NotifyCenter INSTANCE = new NotifyCenter();
|
||||
|
||||
private static final AtomicBoolean closed = new AtomicBoolean(false);
|
||||
|
||||
public static int RING_BUFFER_SIZE = 16384;
|
||||
|
||||
public static int SHATE_BUFFER_SIZE = 1024;
|
||||
|
||||
private static BiFunction<Class<? extends Event>, Integer, EventPublisher> BUILD_FACTORY = null;
|
||||
|
||||
static {
|
||||
// Internal ArrayBlockingQueue buffer size. For applications with high write throughput,
|
||||
// this value needs to be increased appropriately. default value is 16384
|
||||
String ringBufferSizeProperty = "nacos.core.notify.ring-buffer-size";
|
||||
RING_BUFFER_SIZE = Integer.getInteger(ringBufferSizeProperty, 16384);
|
||||
|
||||
// The size of the public publisher's message staging queue buffer
|
||||
String shareBufferSizeProperty = "nacos.core.notify.share-buffer-size";
|
||||
SHATE_BUFFER_SIZE = Integer.getInteger(shareBufferSizeProperty, 1024);
|
||||
|
||||
ServiceLoader<EventPublisher> loader = ServiceLoader.load(EventPublisher.class);
|
||||
Iterator<EventPublisher> iterator = loader.iterator();
|
||||
|
||||
if (iterator.hasNext()) {
|
||||
BUILD_FACTORY = (cls, buffer) -> {
|
||||
loader.reload();
|
||||
EventPublisher publisher = ServiceLoader.load(EventPublisher.class).iterator().next();
|
||||
publisher.init(cls, buffer);
|
||||
return publisher;
|
||||
};
|
||||
} else {
|
||||
BUILD_FACTORY = (cls, buffer) -> {
|
||||
EventPublisher publisher = new DefaultPublisher();
|
||||
publisher.init(cls, buffer);
|
||||
return publisher;
|
||||
};
|
||||
}
|
||||
|
||||
INSTANCE.sharePublisher = BUILD_FACTORY.apply(SlowEvent.class, SHATE_BUFFER_SIZE);
|
||||
ThreadUtils.addShutdownHook(new Thread(() -> {
|
||||
shutdown();
|
||||
}));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Publisher management container
|
||||
*/
|
||||
private final Map<String, EventPublisher> publisherMap = new ConcurrentHashMap<>(16);
|
||||
|
||||
/**
|
||||
* Multi-event listening list
|
||||
*/
|
||||
private final Set<SmartSubscribe> smartSubscribes = new ConcurrentHashSet<>();
|
||||
|
||||
private EventPublisher sharePublisher;
|
||||
|
||||
@JustForTest
|
||||
public static Map<String, EventPublisher> getPublisherMap() {
|
||||
return INSTANCE.publisherMap;
|
||||
}
|
||||
|
||||
@JustForTest
|
||||
public static EventPublisher getPublisher(Class<? extends Event> topic) {
|
||||
if (SlowEvent.class.isAssignableFrom(topic)) {
|
||||
return INSTANCE.sharePublisher;
|
||||
}
|
||||
return INSTANCE.publisherMap.get(topic.getCanonicalName());
|
||||
}
|
||||
|
||||
@JustForTest
|
||||
public static Set<SmartSubscribe> getSmartSubscribes() {
|
||||
return EventPublisher.SMART_SUBSCRIBES;
|
||||
}
|
||||
|
||||
@JustForTest
|
||||
public static EventPublisher getSharePublisher() {
|
||||
return INSTANCE.sharePublisher;
|
||||
}
|
||||
|
||||
public static void shutdown() {
|
||||
if (!closed.compareAndSet(false, true)) {
|
||||
return;
|
||||
}
|
||||
LOGGER.warn("[NotifyCenter] Start destroying Publisher");
|
||||
try {
|
||||
INSTANCE.publisherMap.forEach(new BiConsumer<String, EventPublisher>() {
|
||||
@Override
|
||||
public void accept(String s, EventPublisher publisher) {
|
||||
publisher.shutdown();
|
||||
}
|
||||
});
|
||||
|
||||
INSTANCE.sharePublisher.shutdown();
|
||||
} catch (Throwable e) {
|
||||
LOGGER.error("NotifyCenter shutdown has error : {}", e);
|
||||
}
|
||||
LOGGER.warn("[NotifyCenter] Destruction of the end");
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a Subscriber. If the Publisher concerned by the Subscriber does not exist, then PublihserMap will
|
||||
* preempt a placeholder Publisher first. not call {@link Publisher#start()}
|
||||
*
|
||||
* @param eventType Types of events that Subscriber cares about
|
||||
* @param consumer subscriber
|
||||
* @param <T> event type
|
||||
*/
|
||||
public static <T> void registerSubscribe(final Subscribe consumer) {
|
||||
final Class<? extends Event> cls = consumer.subscribeType();
|
||||
// If you want to listen to multiple events, you do it separately,
|
||||
// without automatically registering the appropriate publisher
|
||||
if (consumer instanceof SmartSubscribe) {
|
||||
EventPublisher.SMART_SUBSCRIBES.add((SmartSubscribe) consumer);
|
||||
return;
|
||||
}
|
||||
// If the event does not require additional queue resources,
|
||||
// go to share-publisher to reduce resource waste
|
||||
if (SlowEvent.class.isAssignableFrom(cls)) {
|
||||
INSTANCE.sharePublisher.addSubscribe(consumer);
|
||||
return;
|
||||
}
|
||||
final String topic = consumer.subscribeType().getCanonicalName();
|
||||
INSTANCE.publisherMap.computeIfAbsent(topic, s -> BUILD_FACTORY.apply(cls, RING_BUFFER_SIZE));
|
||||
EventPublisher publisher = INSTANCE.publisherMap.get(topic);
|
||||
publisher.addSubscribe(consumer);
|
||||
}
|
||||
|
||||
/**
|
||||
* deregister subscriber
|
||||
*
|
||||
* @param consumer subscriber
|
||||
* @param <T>
|
||||
*/
|
||||
public static <T> void deregisterSubscribe(final Subscribe consumer) {
|
||||
final Class<? extends Event> cls = consumer.subscribeType();
|
||||
if (consumer instanceof SmartSubscribe) {
|
||||
EventPublisher.SMART_SUBSCRIBES.remove((SmartSubscribe) consumer);
|
||||
return;
|
||||
}
|
||||
if (SlowEvent.class.isAssignableFrom(cls)) {
|
||||
INSTANCE.sharePublisher.unSubscribe(consumer);
|
||||
return;
|
||||
}
|
||||
final String topic = consumer.subscribeType().getCanonicalName();
|
||||
if (INSTANCE.publisherMap.containsKey(topic)) {
|
||||
EventPublisher publisher = INSTANCE.publisherMap.get(topic);
|
||||
publisher.unSubscribe(consumer);
|
||||
return;
|
||||
}
|
||||
throw new NoSuchElementException("The subcriber has no event publisher");
|
||||
}
|
||||
|
||||
/**
|
||||
* request publisher publish event Publishers load lazily, calling publisher. Start () only when the event is
|
||||
* actually published
|
||||
*
|
||||
* @param event
|
||||
*/
|
||||
public static boolean publishEvent(final Event event) {
|
||||
try {
|
||||
return publishEvent(event.getClass(), event);
|
||||
} catch (Throwable ex) {
|
||||
LOGGER.error("There was an exception to the message publishing : {}", ex);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* request publisher publish event Publishers load lazily, calling publisher. Start () only when the event is
|
||||
* actually published
|
||||
*
|
||||
* @param eventType
|
||||
* @param event
|
||||
*/
|
||||
private static boolean publishEvent(final Class<? extends Event> eventType, final Event event) {
|
||||
final String topic = eventType.getCanonicalName();
|
||||
if (SlowEvent.class.isAssignableFrom(eventType)) {
|
||||
return INSTANCE.sharePublisher.publish(event);
|
||||
}
|
||||
|
||||
if (INSTANCE.publisherMap.containsKey(topic)) {
|
||||
EventPublisher publisher = INSTANCE.publisherMap.get(topic);
|
||||
return publisher.publish(event);
|
||||
}
|
||||
throw new NoSuchElementException("There are no [" + topic + "] publishers for this event, please register");
|
||||
}
|
||||
|
||||
/**
|
||||
* register to share-publisher
|
||||
*
|
||||
* @param supplier
|
||||
* @param eventType
|
||||
* @return
|
||||
*/
|
||||
public static EventPublisher registerToSharePublisher(final Class<? extends SlowEvent> eventType) {
|
||||
return INSTANCE.sharePublisher;
|
||||
}
|
||||
|
||||
/**
|
||||
* register publisher
|
||||
*
|
||||
* @param supplier
|
||||
* @param eventType
|
||||
* @param queueMaxSize
|
||||
* @return
|
||||
*/
|
||||
public static EventPublisher registerToPublisher(final Class<? extends Event> eventType, final int queueMaxSize) {
|
||||
|
||||
if (SlowEvent.class.isAssignableFrom(eventType)) {
|
||||
return INSTANCE.sharePublisher;
|
||||
}
|
||||
|
||||
final String topic = eventType.getCanonicalName();
|
||||
INSTANCE.publisherMap.computeIfAbsent(topic, s -> BUILD_FACTORY.apply(eventType, queueMaxSize));
|
||||
EventPublisher publisher = INSTANCE.publisherMap.get(topic);
|
||||
return publisher;
|
||||
}
|
||||
|
||||
/**
|
||||
* deregister publisher
|
||||
*
|
||||
* @param eventType
|
||||
* @return
|
||||
*/
|
||||
public static void deregisterPublisher(final Class<? extends Event> eventType) {
|
||||
final String topic = eventType.getCanonicalName();
|
||||
EventPublisher publisher = INSTANCE.publisherMap.remove(topic);
|
||||
publisher.shutdown();
|
||||
}
|
||||
|
||||
}
|
@ -1,46 +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.core.notify.listener;
|
||||
|
||||
import com.alibaba.nacos.core.notify.Event;
|
||||
|
||||
/**
|
||||
* Subscribers to multiple events can be listened to.
|
||||
*
|
||||
* @author <a href="mailto:liaochuntao@live.com">liaochuntao</a>
|
||||
*/
|
||||
@SuppressWarnings("PMD.AbstractClassShouldStartWithAbstractNamingRule")
|
||||
public abstract class SmartSubscribe implements Subscribe<Event> {
|
||||
|
||||
/**
|
||||
* Determines if the processing message is acceptable.
|
||||
*
|
||||
* @param event {@link Event}
|
||||
* @return Determines if the processing message is acceptable
|
||||
*/
|
||||
public abstract boolean canNotify(Event event);
|
||||
|
||||
@Override
|
||||
public final Class<? extends Event> subscribeType() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean ignoreExpireEvent() {
|
||||
return false;
|
||||
}
|
||||
}
|
@ -1,62 +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.core.notify.listener;
|
||||
|
||||
import com.alibaba.nacos.core.notify.Event;
|
||||
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
/**
|
||||
* subscriber.
|
||||
*
|
||||
* @author <a href="mailto:liaochuntao@live.com">liaochuntao</a>
|
||||
*/
|
||||
public interface Subscribe<T extends Event> {
|
||||
|
||||
/**
|
||||
* Event callback.
|
||||
*
|
||||
* @param event {@link Event}
|
||||
*/
|
||||
void onEvent(T event);
|
||||
|
||||
/**
|
||||
* Type of this subscriber's subscription.
|
||||
*
|
||||
* @return Class which extends {@link Event}
|
||||
*/
|
||||
Class<? extends Event> subscribeType();
|
||||
|
||||
/**
|
||||
* It is up to the listener to determine whether the callback is asynchronous or synchronous.
|
||||
*
|
||||
* @return {@link Executor}
|
||||
*/
|
||||
default Executor executor() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether to ignore expired events.
|
||||
*
|
||||
* @return default value is {@link Boolean#FALSE}
|
||||
*/
|
||||
default boolean ignoreExpireEvent() {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
@ -16,8 +16,8 @@
|
||||
|
||||
package com.alibaba.nacos.core.utils;
|
||||
|
||||
import com.alibaba.nacos.core.notify.NotifyCenter;
|
||||
import com.alibaba.nacos.core.notify.SlowEvent;
|
||||
import com.alibaba.nacos.common.notify.NotifyCenter;
|
||||
import com.alibaba.nacos.common.notify.SlowEvent;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@ -229,7 +229,7 @@ public class InetUtils {
|
||||
* {@link com.alibaba.nacos.core.cluster.ServerMemberManager} is listener.
|
||||
*/
|
||||
@SuppressWarnings({"PMD.ClassNamingShouldBeCamelRule", "checkstyle:AbbreviationAsWordInName"})
|
||||
public static class IPChangeEvent implements SlowEvent {
|
||||
public static class IPChangeEvent extends SlowEvent {
|
||||
|
||||
private String oldIp;
|
||||
|
||||
|
@ -244,7 +244,7 @@
|
||||
<level value="INFO"/>
|
||||
</logger>
|
||||
|
||||
<logger name="com.alibaba.nacos.core.notify.NotifyCenter">
|
||||
<logger name="com.alibaba.nacos.common.notify.NotifyCenter">
|
||||
<appender-ref ref="CONSOLE"/>
|
||||
<level value="INFO"/>
|
||||
</logger>
|
||||
|
@ -665,7 +665,7 @@
|
||||
<level value="INFO"/>
|
||||
</logger>
|
||||
|
||||
<logger name="com.alibaba.nacos.core.notify.NotifyCenter">
|
||||
<logger name="com.alibaba.nacos.common.notify.NotifyCenter">
|
||||
<appender-ref ref="CONSOLE"/>
|
||||
<level value="INFO"/>
|
||||
</logger>
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
package com.alibaba.nacos.naming.cluster;
|
||||
|
||||
import com.alibaba.nacos.common.notify.NotifyCenter;
|
||||
import com.alibaba.nacos.common.utils.JacksonUtils;
|
||||
import com.alibaba.nacos.core.cluster.Member;
|
||||
import com.alibaba.nacos.core.cluster.MembersChangeEvent;
|
||||
@ -23,7 +24,6 @@ import com.alibaba.nacos.core.cluster.MemberChangeListener;
|
||||
import com.alibaba.nacos.core.cluster.MemberMetaDataConstants;
|
||||
import com.alibaba.nacos.core.cluster.NodeState;
|
||||
import com.alibaba.nacos.core.cluster.ServerMemberManager;
|
||||
import com.alibaba.nacos.core.notify.NotifyCenter;
|
||||
import com.alibaba.nacos.core.utils.ApplicationUtils;
|
||||
import com.alibaba.nacos.naming.consistency.persistent.raft.RaftPeer;
|
||||
import com.alibaba.nacos.naming.misc.GlobalExecutor;
|
||||
@ -54,7 +54,7 @@ import java.util.Optional;
|
||||
* @deprecated 1.3.0 This object will be deleted sometime after version 1.3.0
|
||||
*/
|
||||
@Component("serverListManager")
|
||||
public class ServerListManager implements MemberChangeListener {
|
||||
public class ServerListManager extends MemberChangeListener {
|
||||
|
||||
private static final String LOCALHOST_SITE = UtilsAndCommons.UNKNOWN_SITE;
|
||||
|
||||
@ -69,7 +69,7 @@ public class ServerListManager implements MemberChangeListener {
|
||||
public ServerListManager(final SwitchDomain switchDomain, final ServerMemberManager memberManager) {
|
||||
this.switchDomain = switchDomain;
|
||||
this.memberManager = memberManager;
|
||||
NotifyCenter.registerSubscribe(this);
|
||||
NotifyCenter.registerSubscriber(this);
|
||||
this.servers = new ArrayList<>(memberManager.allMembers());
|
||||
}
|
||||
|
||||
|
@ -16,12 +16,12 @@
|
||||
|
||||
package com.alibaba.nacos.naming.consistency.persistent.raft;
|
||||
|
||||
import com.alibaba.nacos.common.notify.NotifyCenter;
|
||||
import com.alibaba.nacos.common.utils.JacksonUtils;
|
||||
import com.alibaba.nacos.core.cluster.Member;
|
||||
import com.alibaba.nacos.core.cluster.MemberChangeListener;
|
||||
import com.alibaba.nacos.core.cluster.MembersChangeEvent;
|
||||
import com.alibaba.nacos.core.cluster.ServerMemberManager;
|
||||
import com.alibaba.nacos.core.notify.NotifyCenter;
|
||||
import com.alibaba.nacos.core.utils.ApplicationUtils;
|
||||
import com.alibaba.nacos.naming.misc.HttpClient;
|
||||
import com.alibaba.nacos.naming.misc.Loggers;
|
||||
@ -53,7 +53,7 @@ import java.util.concurrent.atomic.AtomicLong;
|
||||
*/
|
||||
@Component
|
||||
@DependsOn("ProtocolManager")
|
||||
public class RaftPeerSet implements MemberChangeListener {
|
||||
public class RaftPeerSet extends MemberChangeListener {
|
||||
|
||||
private final ServerMemberManager memberManager;
|
||||
|
||||
@ -75,7 +75,7 @@ public class RaftPeerSet implements MemberChangeListener {
|
||||
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
NotifyCenter.registerSubscribe(this);
|
||||
NotifyCenter.registerSubscriber(this);
|
||||
changePeers(memberManager.allMembers());
|
||||
}
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user