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:
KomachiSion 2020-07-18 16:28:00 +08:00
commit 79c8521bde
111 changed files with 2897 additions and 2879 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,73 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.nacos.common.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);
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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