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 OVER_THRESHOLD = 503;
public static final int RESOURCE_NOT_FOUND = -404; 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.MetricsHttpAgent;
import com.alibaba.nacos.client.config.http.ServerHttpAgent; import com.alibaba.nacos.client.config.http.ServerHttpAgent;
import com.alibaba.nacos.client.config.impl.ClientWorker; import com.alibaba.nacos.client.config.impl.ClientWorker;
import com.alibaba.nacos.client.config.impl.HttpSimpleClient.HttpResult;
import com.alibaba.nacos.client.config.impl.LocalConfigInfoProcessor; import com.alibaba.nacos.client.config.impl.LocalConfigInfoProcessor;
import com.alibaba.nacos.client.config.utils.ContentUtils; import com.alibaba.nacos.client.config.utils.ContentUtils;
import com.alibaba.nacos.client.config.utils.ParamUtils; import com.alibaba.nacos.client.config.utils.ParamUtils;
import com.alibaba.nacos.client.utils.LogUtils; import com.alibaba.nacos.client.utils.LogUtils;
import com.alibaba.nacos.client.utils.ParamUtil; import com.alibaba.nacos.client.utils.ParamUtil;
import com.alibaba.nacos.client.utils.ValidatorUtils; import com.alibaba.nacos.client.utils.ValidatorUtils;
import com.alibaba.nacos.common.http.HttpRestResult;
import com.alibaba.nacos.common.utils.StringUtils; import com.alibaba.nacos.common.utils.StringUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import java.io.IOException;
import java.net.HttpURLConnection; import java.net.HttpURLConnection;
import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.HashMap;
import java.util.Map;
import java.util.Properties; import java.util.Properties;
/** /**
@ -181,42 +180,39 @@ public class NacosConfigService implements ConfigService {
group = null2defaultGroup(group); group = null2defaultGroup(group);
ParamUtils.checkKeyParam(dataId, group); ParamUtils.checkKeyParam(dataId, group);
String url = Constants.CONFIG_CONTROLLER_PATH; String url = Constants.CONFIG_CONTROLLER_PATH;
List<String> params = new ArrayList<String>(); Map<String, String> params = new HashMap<String, String>(4);
params.add("dataId"); params.put("dataId", dataId);
params.add(dataId); params.put("group", group);
params.add("group");
params.add(group);
if (StringUtils.isNotEmpty(tenant)) { if (StringUtils.isNotEmpty(tenant)) {
params.add("tenant"); params.put("tenant", tenant);
params.add(tenant);
} }
if (StringUtils.isNotEmpty(tag)) { if (StringUtils.isNotEmpty(tag)) {
params.add("tag"); params.put("tag", tag);
params.add(tag);
} }
if (!ParamUtils.useHttpSwitch()) { if (!ParamUtils.useHttpSwitch()) {
return removeConfigInRpc(tenant, dataId, group, tag); return removeConfigInRpc(tenant, dataId, group, tag);
} }
HttpResult result = null; HttpRestResult<String> result = null;
try { try {
result = agent.httpDelete(url, null, params, encode, POST_TIMEOUT); result = agent.httpDelete(url, null, params, encode, POST_TIMEOUT);
} catch (IOException ioe) { } catch (Exception ex) {
LOGGER.warn("[remove] error, " + dataId + ", " + group + ", " + tenant + ", msg: " + ioe.toString()); LOGGER.warn("[remove] error, " + dataId + ", " + group + ", " + tenant + ", msg: " + ex.toString());
return false; return false;
} }
if (HttpURLConnection.HTTP_OK == result.code) { if (result.ok()) {
LOGGER.info("[{}] [remove] ok, dataId={}, group={}, tenant={}", agent.getName(), dataId, group, tenant); LOGGER.info("[{}] [remove] ok, dataId={}, group={}, tenant={}", agent.getName(), dataId, group, tenant);
return true; 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, LOGGER.warn("[{}] [remove] error, dataId={}, group={}, tenant={}, code={}, msg={}", agent.getName(), dataId,
group, tenant, result.code, result.content); group, tenant, result.getCode(), result.getMessage());
throw new NacosException(result.code, result.content); throw new NacosException(result.getCode(), result.getMessage());
} else { } else {
LOGGER.warn("[{}] [remove] error, dataId={}, group={}, tenant={}, code={}, msg={}", agent.getName(), dataId, 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; return false;
} }
} }
@ -248,56 +244,48 @@ public class NacosConfigService implements ConfigService {
content = cr.getContent(); content = cr.getContent();
String url = Constants.CONFIG_CONTROLLER_PATH; String url = Constants.CONFIG_CONTROLLER_PATH;
List<String> params = new ArrayList<String>(); Map<String, String> params = new HashMap<String, String>(6);
params.add("dataId"); params.put("dataId", dataId);
params.add(dataId); params.put("group", group);
params.add("group"); params.put("content", content);
params.add(group);
params.add("content");
params.add(content);
if (StringUtils.isNotEmpty(tenant)) { if (StringUtils.isNotEmpty(tenant)) {
params.add("tenant"); params.put("tenant", tenant);
params.add(tenant);
} }
if (StringUtils.isNotEmpty(appName)) { if (StringUtils.isNotEmpty(appName)) {
params.add("appName"); params.put("appName", appName);
params.add(appName);
} }
if (StringUtils.isNotEmpty(tag)) { if (StringUtils.isNotEmpty(tag)) {
params.add("tag"); params.put("tag", tag);
params.add(tag);
} }
Map<String, String> headers = new HashMap<String, String>(1);
List<String> headers = new ArrayList<String>();
if (StringUtils.isNotEmpty(betaIps)) { if (StringUtils.isNotEmpty(betaIps)) {
headers.add("betaIps"); headers.put("betaIps", betaIps);
headers.add(betaIps);
} }
if (!ParamUtils.useHttpSwitch()) { if (!ParamUtils.useHttpSwitch()) {
return publishConfigWithRpc(dataId, group, tenant, content); return publishConfigWithRpc(dataId, group, tenant, content);
} }
HttpResult result = null; HttpRestResult<String> result = null;
try { try {
result = agent.httpPost(url, headers, params, encode, POST_TIMEOUT); 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, LOGGER.warn("[{}] [publish-single] exception, dataId={}, group={}, msg={}", agent.getName(), dataId, group,
ioe.toString()); ex.toString());
return false; return false;
} }
if (HttpURLConnection.HTTP_OK == result.code) { if (result.ok()) {
LOGGER.info("[{}] [publish-single] ok, dataId={}, group={}, tenant={}, config={}", agent.getName(), dataId, LOGGER.info("[{}] [publish-single] ok, dataId={}, group={}, tenant={}, config={}", agent.getName(), dataId,
group, tenant, ContentUtils.truncateContent(content)); group, tenant, ContentUtils.truncateContent(content));
return true; 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(), 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());
throw new NacosException(result.code, result.content); throw new NacosException(result.getCode(), result.getMessage());
} else { } else {
LOGGER.warn("[{}] [publish-single] error, dataId={}, group={}, tenant={}, code={}, msg={}", agent.getName(), 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; return false;
} }

View File

@ -17,12 +17,11 @@
package com.alibaba.nacos.client.config.http; package com.alibaba.nacos.client.config.http;
import com.alibaba.nacos.api.exception.NacosException; 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.client.config.impl.ServerListManager;
import com.alibaba.nacos.common.lifecycle.Closeable; import com.alibaba.nacos.common.lifecycle.Closeable;
import java.io.IOException; import java.util.Map;
import java.util.List;
/** /**
* HttpAgent. * HttpAgent.
@ -54,11 +53,11 @@ public interface HttpAgent extends Closeable {
* @param encoding http encode * @param encoding http encode
* @param readTimeoutMs http timeout * @param readTimeoutMs http timeout
* @return HttpResult http response * @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) HttpRestResult<String> httpGet(String path, Map<String, String> headers, Map<String, String> paramValues,
throws IOException; String encoding, long readTimeoutMs) throws Exception;
/** /**
* invoke http post method. * invoke http post method.
@ -69,10 +68,10 @@ public interface HttpAgent extends Closeable {
* @param encoding http encode * @param encoding http encode
* @param readTimeoutMs http timeout * @param readTimeoutMs http timeout
* @return HttpResult http response * @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, HttpRestResult<String> httpPost(String path, Map<String, String> headers, Map<String, String> paramValues,
long readTimeoutMs) throws IOException; String encoding, long readTimeoutMs) throws Exception;
/** /**
* invoke http delete method. * invoke http delete method.
@ -83,10 +82,10 @@ public interface HttpAgent extends Closeable {
* @param encoding http encode * @param encoding http encode
* @param readTimeoutMs http timeout * @param readTimeoutMs http timeout
* @return HttpResult http response * @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, HttpRestResult<String> httpDelete(String path, Map<String, String> headers, Map<String, String> paramValues,
long readTimeoutMs) throws IOException; String encoding, long readTimeoutMs) throws Exception;
/** /**
* get name. * get name.

View File

@ -17,13 +17,13 @@
package com.alibaba.nacos.client.config.http; package com.alibaba.nacos.client.config.http;
import com.alibaba.nacos.api.exception.NacosException; 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.config.impl.ServerListManager;
import com.alibaba.nacos.client.monitor.MetricsMonitor; import com.alibaba.nacos.client.monitor.MetricsMonitor;
import com.alibaba.nacos.common.http.HttpRestResult;
import io.prometheus.client.Histogram; import io.prometheus.client.Histogram;
import java.io.IOException; import java.io.IOException;
import java.util.List; import java.util.Map;
/** /**
* MetricsHttpAgent. * MetricsHttpAgent.
@ -49,12 +49,12 @@ public class MetricsHttpAgent implements HttpAgent {
} }
@Override @Override
public HttpResult httpGet(String path, List<String> headers, List<String> paramValues, String encoding, public HttpRestResult<String> httpGet(String path, Map<String, String> headers, Map<String, String> paramValues,
long readTimeoutMs) throws IOException { String encode, long readTimeoutMs) throws Exception {
Histogram.Timer timer = MetricsMonitor.getConfigRequestMonitor("GET", path, "NA"); Histogram.Timer timer = MetricsMonitor.getConfigRequestMonitor("GET", path, "NA");
HttpResult result; HttpRestResult<String> result;
try { try {
result = httpAgent.httpGet(path, headers, paramValues, encoding, readTimeoutMs); result = httpAgent.httpGet(path, headers, paramValues, encode, readTimeoutMs);
} catch (IOException e) { } catch (IOException e) {
throw e; throw e;
} finally { } finally {
@ -66,12 +66,12 @@ public class MetricsHttpAgent implements HttpAgent {
} }
@Override @Override
public HttpResult httpPost(String path, List<String> headers, List<String> paramValues, String encoding, public HttpRestResult<String> httpPost(String path, Map<String, String> headers, Map<String, String> paramValues,
long readTimeoutMs) throws IOException { String encode, long readTimeoutMs) throws Exception {
Histogram.Timer timer = MetricsMonitor.getConfigRequestMonitor("POST", path, "NA"); Histogram.Timer timer = MetricsMonitor.getConfigRequestMonitor("POST", path, "NA");
HttpResult result; HttpRestResult<String> result;
try { try {
result = httpAgent.httpPost(path, headers, paramValues, encoding, readTimeoutMs); result = httpAgent.httpPost(path, headers, paramValues, encode, readTimeoutMs);
} catch (IOException e) { } catch (IOException e) {
throw e; throw e;
} finally { } finally {
@ -83,12 +83,12 @@ public class MetricsHttpAgent implements HttpAgent {
} }
@Override @Override
public HttpResult httpDelete(String path, List<String> headers, List<String> paramValues, String encoding, public HttpRestResult<String> httpDelete(String path, Map<String, String> headers, Map<String, String> paramValues,
long readTimeoutMs) throws IOException { String encode, long readTimeoutMs) throws Exception {
Histogram.Timer timer = MetricsMonitor.getConfigRequestMonitor("DELETE", path, "NA"); Histogram.Timer timer = MetricsMonitor.getConfigRequestMonitor("DELETE", path, "NA");
HttpResult result; HttpRestResult<String> result;
try { try {
result = httpAgent.httpDelete(path, headers, paramValues, encoding, readTimeoutMs); result = httpAgent.httpDelete(path, headers, paramValues, encode, readTimeoutMs);
} catch (IOException e) { } catch (IOException e) {
throw 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.PropertyKeyConst;
import com.alibaba.nacos.api.common.Constants; import com.alibaba.nacos.api.common.Constants;
import com.alibaba.nacos.api.exception.NacosException; import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.client.config.impl.HttpSimpleClient; import com.alibaba.nacos.client.config.impl.ConfigHttpClientManager;
import com.alibaba.nacos.client.config.impl.HttpSimpleClient.HttpResult;
import com.alibaba.nacos.client.config.impl.ServerListManager; import com.alibaba.nacos.client.config.impl.ServerListManager;
import com.alibaba.nacos.client.config.impl.SpasAdapter; import com.alibaba.nacos.client.config.impl.SpasAdapter;
import com.alibaba.nacos.client.identify.StsConfig; 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.LogUtils;
import com.alibaba.nacos.client.utils.ParamUtil; import com.alibaba.nacos.client.utils.ParamUtil;
import com.alibaba.nacos.client.utils.TemplateUtils; 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.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.JacksonUtils;
import com.alibaba.nacos.common.utils.MD5Utils;
import com.alibaba.nacos.common.utils.StringUtils; import com.alibaba.nacos.common.utils.StringUtils;
import com.alibaba.nacos.common.utils.ThreadUtils; 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.annotation.JsonProperty;
import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.core.type.TypeReference;
import org.slf4j.Logger; import org.slf4j.Logger;
import java.io.IOException;
import java.net.ConnectException; import java.net.ConnectException;
import java.net.HttpURLConnection; import java.net.HttpURLConnection;
import java.net.SocketTimeoutException; import java.net.SocketTimeoutException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.HashMap;
import java.util.Map;
import java.util.Properties; import java.util.Properties;
import java.util.concurrent.Callable;
import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.Callable;
/** /**
* Server Agent. * Server Agent.
@ -61,6 +67,9 @@ public class ServerHttpAgent implements HttpAgent {
private static final Logger LOGGER = LogUtils.logger(ServerHttpAgent.class); private static final Logger LOGGER = LogUtils.logger(ServerHttpAgent.class);
private static final NacosRestTemplate NACOS_RESTTEMPLATE = ConfigHttpClientManager.getInstance()
.getNacosRestTemplate();
private SecurityProxy securityProxy; private SecurityProxy securityProxy;
private String namespaceId; private String namespaceId;
@ -69,40 +78,28 @@ public class ServerHttpAgent implements HttpAgent {
private ScheduledExecutorService executorService; 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 @Override
public HttpResult httpGet(String path, List<String> headers, List<String> paramValues, String encoding, public HttpRestResult<String> httpGet(String path, Map<String, String> headers, Map<String, String> paramValues,
long readTimeoutMs) throws IOException { String encode, long readTimeoutMs) throws Exception {
final long endTime = System.currentTimeMillis() + readTimeoutMs; final long endTime = System.currentTimeMillis() + readTimeoutMs;
final boolean isSsl = false;
injectSecurityInfo(paramValues); injectSecurityInfo(paramValues);
String currentServerAddr = serverListMgr.getCurrentServerAddr(); String currentServerAddr = serverListMgr.getCurrentServerAddr();
int maxRetry = this.maxRetry; int maxRetry = this.maxRetry;
HttpClientConfig httpConfig = HttpClientConfig.builder()
.setReadTimeOutMillis(Long.valueOf(readTimeoutMs).intValue())
.setConTimeOutMillis(ConfigHttpClientManager.getInstance().getConnectTimeoutOrDefault(100)).build();
do { do {
try { try {
List<String> newHeaders = getSpasHeaders(paramValues); Header newHeaders = getSpasHeaders(paramValues, encode);
if (headers != null) { if (headers != null) {
newHeaders.addAll(headers); newHeaders.addAll(headers);
} }
HttpResult result = HttpSimpleClient
.httpGet(getUrl(currentServerAddr, path), newHeaders, paramValues, encoding, readTimeoutMs, HttpRestResult<String> result = NACOS_RESTTEMPLATE
isSsl); .get(getUrl(currentServerAddr, path), httpConfig, newHeaders, paramValues, String.class);
if (result.code == HttpURLConnection.HTTP_INTERNAL_ERROR if (isFail(result)) {
|| result.code == HttpURLConnection.HTTP_BAD_GATEWAY
|| result.code == HttpURLConnection.HTTP_UNAVAILABLE) {
LOGGER.error("[NACOS ConnectException] currentServerAddr: {}, httpCode: {}", LOGGER.error("[NACOS ConnectException] currentServerAddr: {}, httpCode: {}",
serverListMgr.getCurrentServerAddr(), result.code); serverListMgr.getCurrentServerAddr(), result.getCode());
} else { } else {
// Update the currently available server addr // Update the currently available server addr
serverListMgr.updateCurrentServerAddr(currentServerAddr); serverListMgr.updateCurrentServerAddr(currentServerAddr);
@ -114,10 +111,10 @@ public class ServerHttpAgent implements HttpAgent {
} catch (SocketTimeoutException socketTimeoutException) { } catch (SocketTimeoutException socketTimeoutException) {
LOGGER.error("[NACOS SocketTimeoutException httpGet] currentServerAddr:{} err : {}", LOGGER.error("[NACOS SocketTimeoutException httpGet] currentServerAddr:{} err : {}",
serverListMgr.getCurrentServerAddr(), socketTimeoutException.getMessage()); serverListMgr.getCurrentServerAddr(), socketTimeoutException.getMessage());
} catch (IOException ioException) { } catch (Exception ex) {
LOGGER.error("[NACOS IOException httpGet] currentServerAddr: " + serverListMgr.getCurrentServerAddr(), LOGGER.error("[NACOS Exception httpGet] currentServerAddr: " + serverListMgr.getCurrentServerAddr(),
ioException); ex);
throw ioException; throw ex;
} }
if (serverListMgr.getIterator().hasNext()) { if (serverListMgr.getIterator().hasNext()) {
@ -138,30 +135,29 @@ public class ServerHttpAgent implements HttpAgent {
} }
@Override @Override
public HttpResult httpPost(String path, List<String> headers, List<String> paramValues, String encoding, public HttpRestResult<String> httpPost(String path, Map<String, String> headers, Map<String, String> paramValues,
long readTimeoutMs) throws IOException { String encode, long readTimeoutMs) throws Exception {
final long endTime = System.currentTimeMillis() + readTimeoutMs; final long endTime = System.currentTimeMillis() + readTimeoutMs;
boolean isSsl = false;
injectSecurityInfo(paramValues); injectSecurityInfo(paramValues);
String currentServerAddr = serverListMgr.getCurrentServerAddr(); String currentServerAddr = serverListMgr.getCurrentServerAddr();
int maxRetry = this.maxRetry; int maxRetry = this.maxRetry;
HttpClientConfig httpConfig = HttpClientConfig.builder()
.setReadTimeOutMillis(Long.valueOf(readTimeoutMs).intValue())
.setConTimeOutMillis(ConfigHttpClientManager.getInstance().getConnectTimeoutOrDefault(3000)).build();
do { do {
try { try {
List<String> newHeaders = getSpasHeaders(paramValues); Header newHeaders = getSpasHeaders(paramValues, encode);
if (headers != null) { if (headers != null) {
newHeaders.addAll(headers); 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 if (isFail(result)) {
.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) {
LOGGER.error("[NACOS ConnectException] currentServerAddr: {}, httpCode: {}", currentServerAddr, LOGGER.error("[NACOS ConnectException] currentServerAddr: {}, httpCode: {}", currentServerAddr,
result.code); result.getCode());
} else { } else {
// Update the currently available server addr // Update the currently available server addr
serverListMgr.updateCurrentServerAddr(currentServerAddr); serverListMgr.updateCurrentServerAddr(currentServerAddr);
@ -173,9 +169,9 @@ public class ServerHttpAgent implements HttpAgent {
} catch (SocketTimeoutException socketTimeoutException) { } catch (SocketTimeoutException socketTimeoutException) {
LOGGER.error("[NACOS SocketTimeoutException httpPost] currentServerAddr: {} err : {}", LOGGER.error("[NACOS SocketTimeoutException httpPost] currentServerAddr: {} err : {}",
currentServerAddr, socketTimeoutException.getMessage()); currentServerAddr, socketTimeoutException.getMessage());
} catch (IOException ioe) { } catch (Exception ex) {
LOGGER.error("[NACOS IOException httpPost] currentServerAddr: " + currentServerAddr, ioe); LOGGER.error("[NACOS Exception httpPost] currentServerAddr: " + currentServerAddr, ex);
throw ioe; throw ex;
} }
if (serverListMgr.getIterator().hasNext()) { if (serverListMgr.getIterator().hasNext()) {
@ -196,46 +192,42 @@ public class ServerHttpAgent implements HttpAgent {
} }
@Override @Override
public HttpResult httpDelete(String path, List<String> headers, List<String> paramValues, String encoding, public HttpRestResult<String> httpDelete(String path, Map<String, String> headers, Map<String, String> paramValues,
long readTimeoutMs) throws IOException { String encode, long readTimeoutMs) throws Exception {
final long endTime = System.currentTimeMillis() + readTimeoutMs; final long endTime = System.currentTimeMillis() + readTimeoutMs;
boolean isSsl = false;
injectSecurityInfo(paramValues); injectSecurityInfo(paramValues);
String currentServerAddr = serverListMgr.getCurrentServerAddr(); String currentServerAddr = serverListMgr.getCurrentServerAddr();
int maxRetry = this.maxRetry; int maxRetry = this.maxRetry;
HttpClientConfig httpConfig = HttpClientConfig.builder()
.setReadTimeOutMillis(Long.valueOf(readTimeoutMs).intValue())
.setConTimeOutMillis(ConfigHttpClientManager.getInstance().getConnectTimeoutOrDefault(100)).build();
do { do {
try { try {
List<String> newHeaders = getSpasHeaders(paramValues); Header newHeaders = getSpasHeaders(paramValues, encode);
if (headers != null) { if (headers != null) {
newHeaders.addAll(headers); newHeaders.addAll(headers);
} }
HttpResult result = HttpSimpleClient HttpRestResult<String> result = NACOS_RESTTEMPLATE
.httpDelete(getUrl(currentServerAddr, path), newHeaders, paramValues, encoding, readTimeoutMs, .delete(getUrl(currentServerAddr, path), httpConfig, newHeaders, paramValues, String.class);
isSsl); if (isFail(result)) {
if (result.code == HttpURLConnection.HTTP_INTERNAL_ERROR
|| result.code == HttpURLConnection.HTTP_BAD_GATEWAY
|| result.code == HttpURLConnection.HTTP_UNAVAILABLE) {
LOGGER.error("[NACOS ConnectException] currentServerAddr: {}, httpCode: {}", LOGGER.error("[NACOS ConnectException] currentServerAddr: {}, httpCode: {}",
serverListMgr.getCurrentServerAddr(), result.code); serverListMgr.getCurrentServerAddr(), result.getCode());
} else { } else {
// Update the currently available server addr // Update the currently available server addr
serverListMgr.updateCurrentServerAddr(currentServerAddr); serverListMgr.updateCurrentServerAddr(currentServerAddr);
return result; return result;
} }
} catch (ConnectException connectException) { } catch (ConnectException connectException) {
connectException.printStackTrace();
LOGGER.error("[NACOS ConnectException httpDelete] currentServerAddr:{}, err : {}", LOGGER.error("[NACOS ConnectException httpDelete] currentServerAddr:{}, err : {}",
serverListMgr.getCurrentServerAddr(), connectException.getMessage()); serverListMgr.getCurrentServerAddr(), ExceptionUtil.getStackTrace(connectException));
} catch (SocketTimeoutException stoe) { } catch (SocketTimeoutException stoe) {
stoe.printStackTrace();
LOGGER.error("[NACOS SocketTimeoutException httpDelete] currentServerAddr:{} err : {}", LOGGER.error("[NACOS SocketTimeoutException httpDelete] currentServerAddr:{} err : {}",
serverListMgr.getCurrentServerAddr(), stoe.getMessage()); serverListMgr.getCurrentServerAddr(), ExceptionUtil.getStackTrace(stoe));
} catch (IOException ioe) { } catch (Exception ex) {
LOGGER.error( LOGGER.error(
"[NACOS IOException httpDelete] currentServerAddr: " + serverListMgr.getCurrentServerAddr(), "[NACOS Exception httpDelete] currentServerAddr: " + serverListMgr.getCurrentServerAddr(),
ioe); ex);
throw ioe; throw ex;
} }
if (serverListMgr.getIterator().hasNext()) { if (serverListMgr.getIterator().hasNext()) {
@ -261,6 +253,12 @@ public class ServerHttpAgent implements HttpAgent {
return serverAddr + contextPath + relativePath; 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() { public static String getAppname() {
return ParamUtil.getAppName(); return ParamUtil.getAppName();
} }
@ -276,7 +274,7 @@ public class ServerHttpAgent implements HttpAgent {
public ServerHttpAgent(Properties properties) throws NacosException { public ServerHttpAgent(Properties properties) throws NacosException {
this.serverListMgr = new ServerListManager(properties); this.serverListMgr = new ServerListManager(properties);
this.securityProxy = new SecurityProxy(properties); this.securityProxy = new SecurityProxy(properties, NACOS_RESTTEMPLATE);
this.namespaceId = properties.getProperty(PropertyKeyConst.NAMESPACE); this.namespaceId = properties.getProperty(PropertyKeyConst.NAMESPACE);
init(properties); init(properties);
this.securityProxy.login(this.serverListMgr.getServerUrls()); 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())) { if (StringUtils.isNotBlank(securityProxy.getAccessToken())) {
params.add(Constants.ACCESS_TOKEN); params.put(Constants.ACCESS_TOKEN, securityProxy.getAccessToken());
params.add(securityProxy.getAccessToken());
} }
if (StringUtils.isNotBlank(namespaceId) && !params.contains(SpasAdapter.TENANT_KEY)) { if (StringUtils.isNotBlank(namespaceId) && !params.containsKey(SpasAdapter.TENANT_KEY)) {
params.add(SpasAdapter.TENANT_KEY); params.put(SpasAdapter.TENANT_KEY, namespaceId);
params.add(namespaceId);
} }
} }
@ -363,29 +359,37 @@ public class ServerHttpAgent implements HttpAgent {
serverListMgr.start(); serverListMgr.start();
} }
private List<String> getSpasHeaders(List<String> paramValues) throws IOException { private Header getSpasHeaders(Map<String, String> paramValues, String encode) throws Exception {
List<String> newHeaders = new ArrayList<String>(); Header header = Header.newInstance();
// STS 临时凭证鉴权的优先级高于 AK/SK 鉴权 // STS 临时凭证鉴权的优先级高于 AK/SK 鉴权
if (StsConfig.getInstance().isStsOn()) { if (StsConfig.getInstance().isStsOn()) {
StsCredential stsCredential = getStsCredential(); StsCredential stsCredential = getStsCredential();
accessKey = stsCredential.accessKeyId; accessKey = stsCredential.accessKeyId;
secretKey = stsCredential.accessKeySecret; secretKey = stsCredential.accessKeySecret;
newHeaders.add("Spas-SecurityToken"); header.addParam("Spas-SecurityToken", stsCredential.securityToken);
newHeaders.add(stsCredential.securityToken);
} }
if (StringUtils.isNotEmpty(accessKey) && StringUtils.isNotEmpty(secretKey)) { if (StringUtils.isNotEmpty(accessKey) && StringUtils.isNotEmpty(secretKey)) {
newHeaders.add("Spas-AccessKey"); header.addParam("Spas-AccessKey", accessKey);
newHeaders.add(accessKey); Map<String, String> signHeaders = SpasAdapter.getSignHeaders(paramValues, secretKey);
List<String> signHeaders = SpasAdapter.getSignHeaders(paramValues, secretKey);
if (signHeaders != null) { 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(); boolean cacheSecurityCredentials = StsConfig.getInstance().isCacheSecurityCredentials();
if (cacheSecurityCredentials && stsCredential != null) { if (cacheSecurityCredentials && stsCredential != null) {
long currentTime = System.currentTimeMillis(); long currentTime = System.currentTimeMillis();
@ -405,40 +409,29 @@ public class ServerHttpAgent implements HttpAgent {
return stsCredential; return stsCredential;
} }
private static String getStsResponse() throws IOException { private static String getStsResponse() throws Exception {
String securityCredentials = StsConfig.getInstance().getSecurityCredentials(); String securityCredentials = StsConfig.getInstance().getSecurityCredentials();
if (securityCredentials != null) { if (securityCredentials != null) {
return securityCredentials; return securityCredentials;
} }
String securityCredentialsUrl = StsConfig.getInstance().getSecurityCredentialsUrl(); String securityCredentialsUrl = StsConfig.getInstance().getSecurityCredentialsUrl();
HttpURLConnection conn = null;
int respCode;
String response;
try { try {
conn = (HttpURLConnection) new URL(securityCredentialsUrl).openConnection(); HttpRestResult<String> result = NACOS_RESTTEMPLATE
conn.setRequestMethod("GET"); .get(securityCredentialsUrl, Header.EMPTY, Query.EMPTY, String.class);
conn.setConnectTimeout(ParamUtil.getConnectTimeout() > 100 ? ParamUtil.getConnectTimeout() : 100);
conn.setReadTimeout(1000); if (!result.ok()) {
conn.connect(); LOGGER.error(
respCode = conn.getResponseCode(); "can not get security credentials, securityCredentialsUrl: {}, responseCode: {}, response: {}",
if (HttpURLConnection.HTTP_OK == respCode) { securityCredentialsUrl, result.getCode(), result.getMessage());
response = IoUtils.toString(conn.getInputStream(), Constants.ENCODE); throw new NacosException(NacosException.SERVER_ERROR,
} else { "can not get security credentials, responseCode: " + result.getCode() + ", response: " + result
response = IoUtils.toString(conn.getErrorStream(), Constants.ENCODE); .getMessage());
} }
} catch (IOException e) { return result.getData();
} catch (Exception e) {
LOGGER.error("can not get security credentials", e); LOGGER.error("can not get security credentials", e);
throw 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 @Override
@ -466,6 +459,7 @@ public class ServerHttpAgent implements HttpAgent {
String className = this.getClass().getName(); String className = this.getClass().getName();
LOGGER.info("{} do shutdown begin", className); LOGGER.info("{} do shutdown begin", className);
ThreadUtils.shutdownThreadPool(executorService, LOGGER); ThreadUtils.shutdownThreadPool(executorService, LOGGER);
ConfigHttpClientManager.getInstance().shutdown();
LOGGER.info("{} do shutdown stop", className); 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.common.Constants;
import com.alibaba.nacos.api.config.ConfigType; import com.alibaba.nacos.api.config.ConfigType;
import com.alibaba.nacos.api.config.listener.Listener; 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.ConfigChangeNotifyResponse;
import com.alibaba.nacos.api.config.remote.response.ConfigQueryResponse; import com.alibaba.nacos.api.config.remote.response.ConfigQueryResponse;
import com.alibaba.nacos.api.exception.NacosException; 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.common.GroupKey;
import com.alibaba.nacos.client.config.filter.impl.ConfigFilterChainManager; import com.alibaba.nacos.client.config.filter.impl.ConfigFilterChainManager;
import com.alibaba.nacos.client.config.http.HttpAgent; 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.remote.ConfigGrpcClientProxy;
import com.alibaba.nacos.client.config.utils.ContentUtils; import com.alibaba.nacos.client.config.utils.ContentUtils;
import com.alibaba.nacos.client.config.utils.ParamUtils; 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.LogUtils;
import com.alibaba.nacos.client.utils.ParamUtil; import com.alibaba.nacos.client.utils.ParamUtil;
import com.alibaba.nacos.client.utils.TenantUtil; 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.lifecycle.Closeable;
import com.alibaba.nacos.common.utils.ConvertUtils; import com.alibaba.nacos.common.utils.ConvertUtils;
import com.alibaba.nacos.common.utils.MD5Utils; import com.alibaba.nacos.common.utils.MD5Utils;
@ -52,7 +51,6 @@ import java.io.IOException;
import java.net.HttpURLConnection; import java.net.HttpURLConnection;
import java.net.URLDecoder; import java.net.URLDecoder;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
@ -330,29 +328,32 @@ public class ClientWorker implements Closeable {
return getServerConfigInRpc(dataId, group, tenant, readTimeout); return getServerConfigInRpc(dataId, group, tenant, readTimeout);
} }
HttpResult result = null; HttpRestResult<String> result = null;
try { try {
List<String> params = null; Map<String, String> params = new HashMap<String, String>(3);
if (StringUtils.isBlank(tenant)) { if (StringUtils.isBlank(tenant)) {
params = new ArrayList<String>(Arrays.asList("dataId", dataId, "group", group)); params.put("dataId", dataId);
params.put("group", group);
} else { } 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); result = agent.httpGet(Constants.CONFIG_CONTROLLER_PATH, null, params, agent.getEncode(), readTimeout);
} catch (IOException e) { } catch (Exception ex) {
String message = String String message = String
.format("[%s] [sub-server] get server config exception, dataId=%s, group=%s, tenant=%s", .format("[%s] [sub-server] get server config exception, dataId=%s, group=%s, tenant=%s",
agent.getName(), dataId, group, tenant); agent.getName(), dataId, group, tenant);
LOGGER.error(message, e); LOGGER.error(message, ex);
throw new NacosException(NacosException.SERVER_ERROR, e); throw new NacosException(NacosException.SERVER_ERROR, ex);
} }
switch (result.code) { switch (result.getCode()) {
case HttpURLConnection.HTTP_OK: case HttpURLConnection.HTTP_OK:
LocalConfigInfoProcessor.saveSnapshot(agent.getName(), dataId, group, tenant, result.content); LocalConfigInfoProcessor.saveSnapshot(agent.getName(), dataId, group, tenant, result.getData());
ct[0] = result.content; ct[0] = result.getData();
if (result.headers.containsKey(CONFIG_TYPE)) { if (result.getHeader().getValue(CONFIG_TYPE) != null) {
ct[1] = result.headers.get(CONFIG_TYPE).get(0); ct[1] = result.getHeader().getValue(CONFIG_TYPE);
} else { } else {
ct[1] = ConfigType.TEXT.getType(); ct[1] = ConfigType.TEXT.getType();
} }
@ -370,13 +371,13 @@ public class ClientWorker implements Closeable {
case HttpURLConnection.HTTP_FORBIDDEN: { case HttpURLConnection.HTTP_FORBIDDEN: {
LOGGER.error("[{}] [sub-server-error] no right, dataId={}, group={}, tenant={}", agent.getName(), LOGGER.error("[{}] [sub-server-error] no right, dataId={}, group={}, tenant={}", agent.getName(),
dataId, group, tenant); dataId, group, tenant);
throw new NacosException(result.code, result.content); throw new NacosException(result.getCode(), result.getMessage());
} }
default: { default: {
LOGGER.error("[{}] [sub-server-error] dataId={}, group={}, tenant={}, code={}", agent.getName(), LOGGER.error("[{}] [sub-server-error] dataId={}, group={}, tenant={}, code={}", agent.getName(),
dataId, group, tenant, result.code); dataId, group, tenant, result.getCode());
throw new NacosException(result.code, throw new NacosException(result.getCode(),
"http error, code=" + result.code + ",dataId=" + dataId + ",group=" + group + ",tenant=" "http error, code=" + result.getCode() + ",dataId=" + dataId + ",group=" + group + ",tenant="
+ tenant); + tenant);
} }
} }
@ -481,10 +482,9 @@ public class ClientWorker implements Closeable {
* @param cacheDatas CacheDatas for config infomations. * @param cacheDatas CacheDatas for config infomations.
* @param inInitializingCacheList initial cache lists. * @param inInitializingCacheList initial cache lists.
* @return String include dataId and group (ps: it maybe null). * @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) List<String> checkUpdateDataIds(List<CacheData> cacheDatas, List<String> inInitializingCacheList) throws Exception {
throws IOException {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
for (CacheData cacheData : cacheDatas) { for (CacheData cacheData : cacheDatas) {
if (!cacheData.isUseLocalConfigInfo()) { if (!cacheData.isUseLocalConfigInfo()) {
@ -515,20 +515,16 @@ public class ClientWorker implements Closeable {
* @return The updated dataId list(ps: it maybe null). * @return The updated dataId list(ps: it maybe null).
* @throws IOException Exception. * @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); Map<String, String> params = new HashMap<String, String>(2);
params.add(Constants.PROBE_MODIFY_REQUEST); params.put(Constants.PROBE_MODIFY_REQUEST, probeUpdateString);
params.add(probeUpdateString); Map<String, String> headers = new HashMap<String, String>(2);
headers.put("Long-Pulling-Timeout", "" + timeout);
List<String> headers = new ArrayList<String>(2);
headers.add("Long-Pulling-Timeout");
headers.add("" + timeout);
// told server do not hang me up if new initializing cacheData added in // told server do not hang me up if new initializing cacheData added in
if (isInitializingCacheList) { if (isInitializingCacheList) {
headers.add("Long-Pulling-Timeout-No-Hangup"); headers.put("Long-Pulling-Timeout-No-Hangup", "true");
headers.add("true");
} }
if (StringUtils.isBlank(probeUpdateString)) { if (StringUtils.isBlank(probeUpdateString)) {
@ -540,18 +536,19 @@ public class ClientWorker implements Closeable {
// increase the client's read timeout to avoid this problem. // increase the client's read timeout to avoid this problem.
long readTimeoutMs = timeout + (long) Math.round(timeout >> 1); 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(), .httpPost(Constants.CONFIG_CONTROLLER_PATH + "/listener", headers, params, agent.getEncode(),
readTimeoutMs); readTimeoutMs);
if (HttpURLConnection.HTTP_OK == result.code) { if (result.ok()) {
setHealthServer(true); setHealthServer(true);
return parseUpdateDataIdResponse(result.content); return parseUpdateDataIdResponse(result.getData());
} else { } else {
setHealthServer(false); 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); setHealthServer(false);
LOGGER.error("[" + agent.getName() + "] [check-update] get changed dataId exception", e); LOGGER.error("[" + agent.getName() + "] [check-update] get changed dataId exception", e);
throw 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.api.exception.NacosException;
import com.alibaba.nacos.client.utils.ParamUtil; import com.alibaba.nacos.client.utils.ParamUtil;
import com.alibaba.nacos.common.constant.HttpHeaderConsts; 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.IoUtils;
import com.alibaba.nacos.common.utils.MD5Utils; import com.alibaba.nacos.common.utils.MD5Utils;
import com.alibaba.nacos.common.utils.UuidUtils; import com.alibaba.nacos.common.utils.UuidUtils;
@ -39,7 +40,9 @@ import java.util.Map;
* Http tool. * Http tool.
* *
* @author Nacos * @author Nacos
* @deprecated Use NacosRestTemplate{@link NacosRestTemplate} unified http client
*/ */
@Deprecated
public class HttpSimpleClient { 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.PropertyKeyConst;
import com.alibaba.nacos.api.SystemPropertyKeyConst; import com.alibaba.nacos.api.SystemPropertyKeyConst;
import com.alibaba.nacos.api.exception.NacosException; 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.EnvUtil;
import com.alibaba.nacos.client.utils.LogUtils; import com.alibaba.nacos.client.utils.LogUtils;
import com.alibaba.nacos.client.utils.ParamUtil; import com.alibaba.nacos.client.utils.ParamUtil;
import com.alibaba.nacos.client.utils.TemplateUtils; 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.lifecycle.Closeable;
import com.alibaba.nacos.common.notify.NotifyCenter;
import com.alibaba.nacos.common.utils.IoUtils; import com.alibaba.nacos.common.utils.IoUtils;
import com.alibaba.nacos.common.utils.StringUtils; import com.alibaba.nacos.common.utils.StringUtils;
import com.alibaba.nacos.common.utils.ThreadUtils; import com.alibaba.nacos.common.utils.ThreadUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import java.io.IOException;
import java.io.StringReader; import java.io.StringReader;
import java.net.HttpURLConnection;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.Iterator; import java.util.Iterator;
@ -59,6 +60,8 @@ public class ServerListManager implements Closeable {
private static final String HTTP = "http://"; private static final String HTTP = "http://";
private final NacosRestTemplate nacosRestTemplate = ConfigHttpClientManager.getInstance().getNacosRestTemplate();
private final ScheduledExecutorService executorService = new ScheduledThreadPoolExecutor(1, new ThreadFactory() { private final ScheduledExecutorService executorService = new ScheduledThreadPoolExecutor(1, new ThreadFactory() {
@Override @Override
public Thread newThread(Runnable r) { public Thread newThread(Runnable r) {
@ -335,19 +338,20 @@ public class ServerListManager implements Closeable {
iterator = iterator(); iterator = iterator();
currentServerAddr = iterator.next(); 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); LOGGER.info("[{}] [update-serverlist] serverlist updated to {}", name, serverUrls);
} }
private List<String> getApacheServerList(String url, String name) { private List<String> getApacheServerList(String url, String name) {
try { try {
HttpResult httpResult = HttpSimpleClient.httpGet(url, null, null, null, 3000); HttpRestResult<String> httpResult = nacosRestTemplate.get(url, Header.EMPTY, Query.EMPTY, String.class);
if (HttpURLConnection.HTTP_OK == httpResult.code) { if (httpResult.ok()) {
if (DEFAULT_NAME.equals(name)) { 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()); List<String> result = new ArrayList<String>(lines.size());
for (String serverAddr : lines) { for (String serverAddr : lines) {
if (StringUtils.isNotBlank(serverAddr)) { if (StringUtils.isNotBlank(serverAddr)) {
@ -363,10 +367,10 @@ public class ServerListManager implements Closeable {
return result; return result;
} else { } else {
LOGGER.error("[check-serverlist] error. addressServerUrl: {}, code: {}", addressServerUrl, LOGGER.error("[check-serverlist] error. addressServerUrl: {}, code: {}", addressServerUrl,
httpResult.code); httpResult.getCode());
return null; return null;
} }
} catch (IOException e) { } catch (Exception e) {
LOGGER.error("[check-serverlist] exception. url: " + url, e); LOGGER.error("[check-serverlist] exception. url: " + url, e);
return null; return null;
} }

View File

@ -14,13 +14,14 @@
* limitations under the License. * 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.Mac;
import javax.crypto.SecretKey; import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec; import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map; import java.util.Map;
/** /**
@ -38,43 +34,33 @@ import java.util.Map;
*/ */
public class SpasAdapter { public class SpasAdapter {
public static List<String> getSignHeaders(String resource, String secretKey) { public static Map<String, String> getSignHeaders(String resource, String secretKey) {
List<String> header = new ArrayList<String>(); Map<String, String> header = new HashMap<String, String>(2);
String timeStamp = String.valueOf(System.currentTimeMillis()); String timeStamp = String.valueOf(System.currentTimeMillis());
header.add("Timestamp"); header.put("Timestamp", timeStamp);
header.add(timeStamp);
if (secretKey != null) { if (secretKey != null) {
header.add("Spas-Signature");
String signature = ""; String signature = "";
if (StringUtils.isBlank(resource)) { if (StringUtils.isBlank(resource)) {
signature = signWithHmacSha1Encrypt(timeStamp, secretKey); signature = signWithHmacSha1Encrypt(timeStamp, secretKey);
} else { } else {
signature = signWithHmacSha1Encrypt(resource + "+" + timeStamp, secretKey); signature = signWithHmacSha1Encrypt(resource + "+" + timeStamp, secretKey);
} }
header.add(signature); header.put("Spas-Signature", signature);
} }
return header; 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) { if (null == paramValues) {
return null; 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 = ""; String resource = "";
if (signMap.size() > 1) { if (paramValues.containsKey(TENANT_KEY) && paramValues.containsKey(GROUP_KEY)) {
resource = signMap.get(TENANT_KEY) + "+" + signMap.get(GROUP_KEY); resource = paramValues.get(TENANT_KEY) + "+" + paramValues.get(GROUP_KEY);
} else { } else {
if (!StringUtils.isBlank(signMap.get(GROUP_KEY))) { if (!StringUtils.isBlank(paramValues.get(GROUP_KEY))) {
resource = signMap.get(GROUP_KEY); resource = paramValues.get(GROUP_KEY);
} }
} }
return getSignHeaders(resource, secretKey); return getSignHeaders(resource, secretKey);
@ -97,14 +83,14 @@ public class SpasAdapter {
*/ */
public static String signWithHmacSha1Encrypt(String encryptText, String encryptKey) { public static String signWithHmacSha1Encrypt(String encryptText, String encryptKey) {
try { try {
byte[] data = encryptKey.getBytes(StandardCharsets.UTF_8); byte[] data = encryptKey.getBytes(Constants.ENCODE);
// 根据给定的字节数组构造一个密钥,第二参数指定一个密钥算法的名称 // 根据给定的字节数组构造一个密钥,第二参数指定一个密钥算法的名称
SecretKey secretKey = new SecretKeySpec(data, "HmacSHA1"); SecretKey secretKey = new SecretKeySpec(data, "HmacSHA1");
// 生成一个指定 Mac 算法 Mac 对象 // 生成一个指定 Mac 算法 Mac 对象
Mac mac = Mac.getInstance("HmacSHA1"); Mac mac = Mac.getInstance("HmacSHA1");
// 用给定密钥初始化 Mac 对象 // 用给定密钥初始化 Mac 对象
mac.init(secretKey); mac.init(secretKey);
byte[] text = encryptText.getBytes(StandardCharsets.UTF_8); byte[] text = encryptText.getBytes(Constants.ENCODE);
byte[] textFinal = mac.doFinal(text); byte[] textFinal = mac.doFinal(text);
// 完成 Mac 操作, base64编码将byte数组转换为字符串 // 完成 Mac 操作, base64编码将byte数组转换为字符串
return new String(Base64.encodeBase64(textFinal), Constants.ENCODE); return new String(Base64.encodeBase64(textFinal), Constants.ENCODE);

View File

@ -165,7 +165,7 @@ public class BeatReactor implements Closeable {
long nextTime = beatInfo.getPeriod(); long nextTime = beatInfo.getPeriod();
try { try {
JsonNode result = serverProxy.sendBeat(beatInfo, BeatReactor.this.lightBeatEnabled); JsonNode result = serverProxy.sendBeat(beatInfo, BeatReactor.this.lightBeatEnabled);
long interval = result.get("clientBeatInterval").asInt(); long interval = result.get("clientBeatInterval").asLong();
boolean lightBeatEnabled = false; boolean lightBeatEnabled = false;
if (result.has(CommonParams.LIGHT_BEAT_ENABLED)) { if (result.has(CommonParams.LIGHT_BEAT_ENABLED)) {
lightBeatEnabled = result.get(CommonParams.LIGHT_BEAT_ENABLED).asBoolean(); lightBeatEnabled = result.get(CommonParams.LIGHT_BEAT_ENABLED).asBoolean();

View File

@ -16,18 +16,24 @@
package com.alibaba.nacos.client.naming.net; 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.AbstractHttpClientFactory;
import com.alibaba.nacos.common.http.HttpClientBeanHolder; import com.alibaba.nacos.common.http.HttpClientBeanHolder;
import com.alibaba.nacos.common.http.HttpClientConfig; import com.alibaba.nacos.common.http.HttpClientConfig;
import com.alibaba.nacos.common.http.HttpClientFactory; import com.alibaba.nacos.common.http.HttpClientFactory;
import com.alibaba.nacos.common.http.client.NacosRestTemplate; 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. * http Manager.
* *
* @author mai.jh * @author mai.jh
*/ */
public class NamingHttpClientManager { public class NamingHttpClientManager implements Closeable {
private static final int READ_TIME_OUT_MILLIS = Integer private static final int READ_TIME_OUT_MILLIS = Integer
.getInteger("com.alibaba.nacos.client.naming.rtimeout", 50000); .getInteger("com.alibaba.nacos.client.naming.rtimeout", 50000);
@ -40,17 +46,38 @@ public class NamingHttpClientManager {
private static final HttpClientFactory HTTP_CLIENT_FACTORY = new NamingHttpClientFactory(); 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) { if (ENABLE_HTTPS) {
return "https://"; return "https://";
} }
return "http://"; return "http://";
} }
public static NacosRestTemplate getNacosRestTemplate() { public NacosRestTemplate getNacosRestTemplate() {
return HttpClientBeanHolder.getNacosRestTemplate(HTTP_CLIENT_FACTORY); 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 { private static class NamingHttpClientFactory extends AbstractHttpClientFactory {
@Override @Override
@ -58,5 +85,10 @@ public class NamingHttpClientManager {
return HttpClientConfig.builder().setConTimeOutMillis(CON_TIME_OUT_MILLIS) return HttpClientConfig.builder().setConTimeOutMillis(CON_TIME_OUT_MILLIS)
.setReadTimeOutMillis(READ_TIME_OUT_MILLIS).setMaxRedirects(MAX_REDIRECTS).build(); .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 { 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; 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) { 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.properties = properties;
this.setServerPort(DEFAULT_SERVER_PORT); this.setServerPort(DEFAULT_SERVER_PORT);
this.namespaceId = namespaceId; this.namespaceId = namespaceId;
@ -592,7 +592,7 @@ public class NamingProxy implements Closeable {
if (!curServer.contains(UtilAndComs.SERVER_ADDR_IP_SPLITER)) { if (!curServer.contains(UtilAndComs.SERVER_ADDR_IP_SPLITER)) {
curServer = curServer + UtilAndComs.SERVER_ADDR_IP_SPLITER + serverPort; curServer = curServer + UtilAndComs.SERVER_ADDR_IP_SPLITER + serverPort;
} }
url = NamingHttpClientManager.getPrefix() + curServer + api; url = NamingHttpClientManager.getInstance().getPrefix() + curServer + api;
} }
try { try {
@ -609,7 +609,7 @@ public class NamingProxy implements Closeable {
if (HttpStatus.SC_NOT_MODIFIED == restResult.getCode()) { if (HttpStatus.SC_NOT_MODIFIED == restResult.getCode()) {
return StringUtils.EMPTY; return StringUtils.EMPTY;
} }
throw new NacosException(restResult.getCode(), restResult.getData()); throw new NacosException(restResult.getCode(), restResult.getMessage());
} catch (Exception e) { } catch (Exception e) {
NAMING_LOGGER.error("[NA] failed to request", e); NAMING_LOGGER.error("[NA] failed to request", e);
throw new NacosException(NacosException.SERVER_ERROR, e); throw new NacosException(NacosException.SERVER_ERROR, e);
@ -715,6 +715,7 @@ public class NamingProxy implements Closeable {
String className = this.getClass().getName(); String className = this.getClass().getName();
NAMING_LOGGER.info("{} do shutdown begin", className); NAMING_LOGGER.info("{} do shutdown begin", className);
ThreadUtils.shutdownThreadPool(executorService, NAMING_LOGGER); ThreadUtils.shutdownThreadPool(executorService, NAMING_LOGGER);
NamingHttpClientManager.getInstance().shutdown();
NAMING_LOGGER.info("{} do shutdown stop", className); 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.PropertyKeyConst;
import com.alibaba.nacos.api.common.Constants; 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.HttpRestResult;
import com.alibaba.nacos.common.http.client.NacosRestTemplate; import com.alibaba.nacos.common.http.client.NacosRestTemplate;
import com.alibaba.nacos.common.http.param.Header; 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 static final String LOGIN_URL = "/v1/auth/users/login";
private final NacosRestTemplate nacosRestTemplate = NamingHttpClientManager.getNacosRestTemplate(); private final NacosRestTemplate nacosRestTemplate;
private String contextPath; private String contextPath;
@ -85,11 +84,12 @@ public class SecurityProxy {
* *
* @param properties a bunch of properties to read * @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); username = properties.getProperty(PropertyKeyConst.USERNAME, StringUtils.EMPTY);
password = properties.getProperty(PropertyKeyConst.PASSWORD, StringUtils.EMPTY); password = properties.getProperty(PropertyKeyConst.PASSWORD, StringUtils.EMPTY);
contextPath = properties.getProperty(PropertyKeyConst.CONTEXT_PATH, "/nacos"); contextPath = properties.getProperty(PropertyKeyConst.CONTEXT_PATH, "/nacos");
contextPath = contextPath.startsWith("/") ? contextPath : "/" + contextPath; 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.PropertyKeyConst;
import com.alibaba.nacos.api.SystemPropertyKeyConst; import com.alibaba.nacos.api.SystemPropertyKeyConst;
import com.alibaba.nacos.api.common.Constants; import com.alibaba.nacos.api.common.Constants;
import com.alibaba.nacos.client.config.impl.HttpSimpleClient;
import com.alibaba.nacos.common.utils.StringUtils; import com.alibaba.nacos.common.utils.StringUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
@ -82,7 +81,7 @@ public class ParamUtil {
LOGGER.info("[settings] [http-client] connect timeout:{}", connectTimeout); LOGGER.info("[settings] [http-client] connect timeout:{}", connectTimeout);
try { try {
InputStream in = HttpSimpleClient.class.getClassLoader().getResourceAsStream("application.properties"); InputStream in = ValidatorUtils.class.getClassLoader().getResourceAsStream("application.properties");
Properties props = new Properties(); Properties props = new Properties();
props.load(in); props.load(in);
String val = null; 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.core.SwitchAndOptions;
import com.alibaba.nacos.cmdb.service.CmdbReader; import com.alibaba.nacos.cmdb.service.CmdbReader;
import com.alibaba.nacos.cmdb.service.CmdbWriter; 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.Loggers;
import com.alibaba.nacos.cmdb.utils.UtilsAndCommons;
import com.alibaba.nacos.common.utils.JacksonUtils; import com.alibaba.nacos.common.utils.JacksonUtils;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@ -117,11 +117,9 @@ public class CmdbProvider implements CmdbReader, CmdbWriter {
initCmdbService(); initCmdbService();
load(); load();
UtilsAndCommons.GLOBAL_EXECUTOR.schedule(new CmdbDumpTask(), switches.getDumpTaskInterval(), TimeUnit.SECONDS); CmdbExecutor.scheduleCmdbTask(new CmdbDumpTask(), switches.getDumpTaskInterval(), TimeUnit.SECONDS);
UtilsAndCommons.GLOBAL_EXECUTOR CmdbExecutor.scheduleCmdbTask(new CmdbLabelTask(), switches.getLabelTaskInterval(), TimeUnit.SECONDS);
.schedule(new CmdbLabelTask(), switches.getLabelTaskInterval(), TimeUnit.SECONDS); CmdbExecutor.scheduleCmdbTask(new CmdbEventTask(), switches.getEventTaskInterval(), TimeUnit.SECONDS);
UtilsAndCommons.GLOBAL_EXECUTOR
.schedule(new CmdbEventTask(), switches.getEventTaskInterval(), TimeUnit.SECONDS);
} }
@Override @Override
@ -205,7 +203,7 @@ public class CmdbProvider implements CmdbReader, CmdbWriter {
} catch (Exception e) { } catch (Exception e) {
Loggers.MAIN.error("CMDB-LABEL-TASK {}", "dump failed!", e); Loggers.MAIN.error("CMDB-LABEL-TASK {}", "dump failed!", e);
} finally { } 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) { } catch (Exception e) {
Loggers.MAIN.error("DUMP-TASK {}", "dump failed!", e); Loggers.MAIN.error("DUMP-TASK {}", "dump failed!", e);
} finally { } 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) { } catch (Exception e) {
Loggers.MAIN.error("CMDB-EVENT {}", "event task failed!", e); Loggers.MAIN.error("CMDB-EVENT {}", "event task failed!", e);
} finally { } 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; package com.alibaba.nacos.cmdb.utils;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadFactory;
/** /**
* Utils and constants. * Utils and constants.
* *
@ -32,19 +28,4 @@ public class UtilsAndCommons {
public static final String NACOS_CMDB_CONTEXT = NACOS_SERVER_VERSION + "/cmdb"; 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. * limitations under the License.
*/ */
package com.alibaba.nacos.core.notify; package com.alibaba.nacos.common.constant;
import java.io.Serializable;
/** /**
* 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 {
/** public static final String STRING_TYPE = "java.lang.String";
* Event sequence number, which can be used to handle the sequence of events.
* public static final String RESTRESULT_TYPE = "com.alibaba.nacos.common.model.RestResult";
* @return sequence num, It's best to make sure it's monotone
*/ public static final String DEFAULT_BEAN_TYPE = "default_bean_handler";
default long sequence() {
return System.currentTimeMillis();
}
} }

View File

@ -38,10 +38,6 @@ import java.util.concurrent.TimeUnit;
"checkstyle:missingjavadocmethod"}) "checkstyle:missingjavadocmethod"})
public final class ExecutorFactory { public final class ExecutorFactory {
private static final String DEFAULT_NAMESPACE = "nacos";
private static final ThreadPoolManager THREAD_POOL_MANAGER = ThreadPoolManager.getInstance();
public static ExecutorService newSingleExecutorService() { public static ExecutorService newSingleExecutorService() {
return Executors.newFixedThreadPool(1); return Executors.newFixedThreadPool(1);
} }
@ -73,61 +69,6 @@ public final class ExecutorFactory {
new LinkedBlockingQueue<Runnable>(), threadFactory); 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 { public static final class Managed {
private static final String DEFAULT_NAMESPACE = "nacos"; private static final String DEFAULT_NAMESPACE = "nacos";

View File

@ -17,12 +17,12 @@
package com.alibaba.nacos.common.http; package com.alibaba.nacos.common.http;
import com.alibaba.nacos.common.http.client.DefaultAsyncHttpClientRequest; 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.NacosAsyncRestTemplate;
import com.alibaba.nacos.common.http.client.NacosRestTemplate; import com.alibaba.nacos.common.http.client.NacosRestTemplate;
import org.apache.http.client.config.RequestConfig; import org.apache.http.client.config.RequestConfig;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.nio.client.HttpAsyncClients; import org.apache.http.impl.nio.client.HttpAsyncClients;
import org.slf4j.Logger;
/** /**
* AbstractHttpClientFactory Let the creator only specify the http client config. * AbstractHttpClientFactory Let the creator only specify the http client config.
@ -33,15 +33,14 @@ public abstract class AbstractHttpClientFactory implements HttpClientFactory {
@Override @Override
public final NacosRestTemplate createNacosRestTemplate() { public final NacosRestTemplate createNacosRestTemplate() {
RequestConfig requestConfig = getRequestConfig(); HttpClientConfig httpClientConfig = buildHttpClientConfig();
return new NacosRestTemplate( return new NacosRestTemplate(assignLogger(), new JdkHttpClientRequest(httpClientConfig));
new DefaultHttpClientRequest(HttpClients.custom().setDefaultRequestConfig(requestConfig).build()));
} }
@Override @Override
public final NacosAsyncRestTemplate createNacosAsyncRestTemplate() { public final NacosAsyncRestTemplate createNacosAsyncRestTemplate() {
RequestConfig requestConfig = getRequestConfig(); RequestConfig requestConfig = getRequestConfig();
return new NacosAsyncRestTemplate(new DefaultAsyncHttpClientRequest( return new NacosAsyncRestTemplate(assignLogger(), new DefaultAsyncHttpClientRequest(
HttpAsyncClients.custom().setDefaultRequestConfig(requestConfig).build())); HttpAsyncClients.custom().setDefaultRequestConfig(requestConfig).build()));
} }
@ -58,4 +57,11 @@ public abstract class AbstractHttpClientFactory implements HttpClientFactory {
* @return HttpClientConfig * @return HttpClientConfig
*/ */
protected abstract HttpClientConfig buildHttpClientConfig(); protected abstract HttpClientConfig buildHttpClientConfig();
/**
* assign Logger.
*
* @return Logger
*/
protected abstract Logger assignLogger();
} }

View File

@ -16,6 +16,8 @@
package com.alibaba.nacos.common.http; package com.alibaba.nacos.common.http;
import org.slf4j.Logger;
/** /**
* default http client factory. * 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 static final int TIMEOUT = Integer.getInteger("nacos.http.timeout", 5000);
private final Logger logger;
public DefaultHttpClientFactory(Logger logger) {
this.logger = logger;
}
@Override @Override
protected HttpClientConfig buildHttpClientConfig() { protected HttpClientConfig buildHttpClientConfig() {
return HttpClientConfig.builder().setConTimeOutMillis(TIMEOUT).setReadTimeOutMillis(TIMEOUT >> 1).build(); 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.NacosAsyncRestTemplate;
import com.alibaba.nacos.common.http.client.NacosRestTemplate; 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.Logger;
import org.slf4j.LoggerFactory;
import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; 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. * 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 { 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, 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); public static NacosRestTemplate getNacosRestTemplate(Logger logger) {
return getNacosRestTemplate(new DefaultHttpClientFactory(logger));
static {
ThreadUtils.addShutdownHook(new Runnable() {
@Override
public void run() {
shutdown();
}
});
}
public static NacosRestTemplate getNacosRestTemplate() {
return getNacosRestTemplate(new DefaultHttpClientFactory());
} }
public static NacosRestTemplate getNacosRestTemplate(HttpClientFactory httpClientFactory) { public static NacosRestTemplate getNacosRestTemplate(HttpClientFactory httpClientFactory) {
@ -75,8 +58,8 @@ public final class HttpClientBeanHolder {
return nacosRestTemplate; return nacosRestTemplate;
} }
public static NacosAsyncRestTemplate getNacosAsyncRestTemplate() { public static NacosAsyncRestTemplate getNacosAsyncRestTemplate(Logger logger) {
return getNacosAsyncRestTemplate(new DefaultHttpClientFactory()); return getNacosAsyncRestTemplate(new DefaultHttpClientFactory(logger));
} }
public static NacosAsyncRestTemplate getNacosAsyncRestTemplate(HttpClientFactory httpClientFactory) { 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() { public static void shutdown(String className) throws Exception {
if (!ALREADY_SHUTDOWN.compareAndSet(false, true)) { shutdownNacostSyncRest(className);
return; shutdownNacosAsyncRest(className);
}
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");
} }
private static void nacostRestTemplateShutdown() throws Exception { /**
if (!SINGLETON_REST.isEmpty()) { * Shutdown sync http client holder and remove template.
Collection<NacosRestTemplate> nacosRestTemplates = SINGLETON_REST.values(); *
for (NacosRestTemplate nacosRestTemplate : nacosRestTemplates) { * @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(); nacosRestTemplate.close();
} SINGLETON_REST.remove(className);
SINGLETON_REST.clear();
} }
} }
private static void nacosAsyncRestTemplateShutdown() throws Exception { /**
if (!SINGLETON_ASYNC_REST.isEmpty()) { * Shutdown async http client holder and remove template.
Collection<NacosAsyncRestTemplate> nacosAsyncRestTemplates = SINGLETON_ASYNC_REST.values(); *
for (NacosAsyncRestTemplate nacosAsyncRestTemplate : nacosAsyncRestTemplates) { * @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(); nacosAsyncRestTemplate.close();
} SINGLETON_ASYNC_REST.remove(className);
SINGLETON_ASYNC_REST.clear();
} }
} }
} }

View File

@ -33,8 +33,8 @@ public class HttpRestResult<T> extends RestResult<T> {
public HttpRestResult() { public HttpRestResult() {
} }
public HttpRestResult(Header header, int code, T data) { public HttpRestResult(Header header, int code, T data, String message) {
super(code, data); super(code, message, data);
this.header = header; 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 com.alibaba.nacos.common.model.RequestHttpEntity;
import java.io.Closeable; import java.io.Closeable;
import java.lang.reflect.Type;
import java.net.URI; import java.net.URI;
/** /**
@ -37,10 +36,10 @@ public interface AsyncHttpClientRequest extends Closeable {
* @param uri http url * @param uri http url
* @param httpMethod http request method * @param httpMethod http request method
* @param requestHttpEntity http request entity * @param requestHttpEntity http request entity
* @param responseType http response type * @param responseHandler http response handler
* @param callback http response callback * @param callback http response callback
* @throws Exception ex * @throws Exception ex
*/ */
<T> void execute(URI uri, String httpMethod, RequestHttpEntity requestHttpEntity, final Type responseType, <T> void execute(URI uri, String httpMethod, RequestHttpEntity requestHttpEntity,
final Callback<T> callback) throws Exception; 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.Callback;
import com.alibaba.nacos.common.http.HttpRestResult; import com.alibaba.nacos.common.http.HttpRestResult;
import com.alibaba.nacos.common.http.handler.ResponseHandler;
import com.alibaba.nacos.common.model.RequestHttpEntity; import com.alibaba.nacos.common.model.RequestHttpEntity;
import org.apache.http.HttpResponse; import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpRequestBase; 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 org.apache.http.impl.nio.client.CloseableHttpAsyncClient;
import java.io.IOException; import java.io.IOException;
import java.lang.reflect.Type;
import java.net.URI; import java.net.URI;
/** /**
@ -46,7 +44,7 @@ public class DefaultAsyncHttpClientRequest implements AsyncHttpClientRequest {
} }
@Override @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 { final Callback<T> callback) throws Exception {
HttpRequestBase httpRequestBase = DefaultHttpClientRequest.build(uri, httpMethod, requestHttpEntity); HttpRequestBase httpRequestBase = DefaultHttpClientRequest.build(uri, httpMethod, requestHttpEntity);
asyncClient.execute(httpRequestBase, new FutureCallback<HttpResponse>() { asyncClient.execute(httpRequestBase, new FutureCallback<HttpResponse>() {
@ -54,7 +52,7 @@ public class DefaultAsyncHttpClientRequest implements AsyncHttpClientRequest {
public void completed(HttpResponse result) { public void completed(HttpResponse result) {
DefaultClientHttpResponse response = new DefaultClientHttpResponse(result); DefaultClientHttpResponse response = new DefaultClientHttpResponse(result);
try { try {
HttpRestResult<T> httpRestResult = ResponseHandler.responseEntityExtractor(response, responseType); HttpRestResult<T> httpRestResult = responseHandler.handle(response);
callback.onReceive(httpRestResult); callback.onReceive(httpRestResult);
} catch (Exception e) { } catch (Exception e) {
callback.onError(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.constant.HttpHeaderConsts;
import com.alibaba.nacos.common.http.BaseHttpMethod; 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.Header;
import com.alibaba.nacos.common.http.param.MediaType; import com.alibaba.nacos.common.http.param.MediaType;
import com.alibaba.nacos.common.model.RequestHttpEntity; 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.CloseableHttpResponse;
import org.apache.http.client.methods.HttpRequestBase; import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.CloseableHttpClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException; import java.io.IOException;
import java.net.URI; import java.net.URI;
@ -39,8 +39,6 @@ import java.util.Map;
@SuppressWarnings({"unchecked", "resource"}) @SuppressWarnings({"unchecked", "resource"})
public class DefaultHttpClientRequest implements HttpClientRequest { public class DefaultHttpClientRequest implements HttpClientRequest {
private static final Logger LOGGER = LoggerFactory.getLogger(DefaultHttpClientRequest.class);
private final CloseableHttpClient client; private final CloseableHttpClient client;
public DefaultHttpClientRequest(CloseableHttpClient client) { public DefaultHttpClientRequest(CloseableHttpClient client) {
@ -52,9 +50,6 @@ public class DefaultHttpClientRequest implements HttpClientRequest {
throws Exception { throws Exception {
HttpRequestBase request = build(uri, httpMethod, requestHttpEntity); HttpRequestBase request = build(uri, httpMethod, requestHttpEntity);
CloseableHttpResponse response = client.execute(request); CloseableHttpResponse response = client.execute(request);
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Request from server: " + request.getURI().toString());
}
return new DefaultClientHttpResponse(response); return new DefaultClientHttpResponse(response);
} }
@ -69,7 +64,24 @@ public class DefaultHttpClientRequest implements HttpClientRequest {
} else { } else {
httpMethod.initEntity(requestHttpEntity.getBody(), headers.getValue(HttpHeaderConsts.CONTENT_TYPE)); 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 @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 code.
* *
* @return the HTTP status as an integer * @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 of the response.
* *
* @return the HTTP status text * @return the HTTP status text
* @throws IOException IOException
*/ */
String getStatusText(); String getStatusText() throws IOException;
/** /**
* close response InputStream. * 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.model.RequestHttpEntity;
import com.alibaba.nacos.common.utils.HttpMethod; import com.alibaba.nacos.common.utils.HttpMethod;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.reflect.Type; import java.lang.reflect.Type;
import java.net.URI; import java.net.URI;
@ -37,13 +36,12 @@ import java.util.Map;
* @see AsyncHttpClientRequest * @see AsyncHttpClientRequest
* @see HttpClientResponse * @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(Logger logger, AsyncHttpClientRequest clientRequest) {
super(logger);
public NacosAsyncRestTemplate(AsyncHttpClientRequest clientRequest) {
this.clientRequest = clientRequest; 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 { Callback<T> callback) throws Exception {
URI uri = HttpUtils.buildUri(url, requestEntity.getQuery()); URI uri = HttpUtils.buildUri(url, requestEntity.getQuery());
if (LOGGER.isDebugEnabled()) { if (logger.isDebugEnabled()) {
LOGGER.debug("HTTP " + httpMethod + " " + url); 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; 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.HttpRestResult;
import com.alibaba.nacos.common.http.HttpUtils; 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.Header;
import com.alibaba.nacos.common.http.param.MediaType; import com.alibaba.nacos.common.http.param.MediaType;
import com.alibaba.nacos.common.http.param.Query; import com.alibaba.nacos.common.http.param.Query;
import com.alibaba.nacos.common.model.RequestHttpEntity; import com.alibaba.nacos.common.model.RequestHttpEntity;
import com.alibaba.nacos.common.utils.CollectionUtils;
import com.alibaba.nacos.common.utils.HttpMethod; import com.alibaba.nacos.common.utils.HttpMethod;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.reflect.Type; import java.lang.reflect.Type;
import java.net.URI; import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import java.util.Map; import java.util.Map;
/** /**
@ -38,13 +40,14 @@ import java.util.Map;
* @see HttpClientRequest * @see HttpClientRequest
* @see HttpClientResponse * @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; this.requestClient = requestClient;
} }
@ -83,6 +86,28 @@ public class NacosRestTemplate {
return execute(url, HttpMethod.GET, requestHttpEntity, responseType); 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}, * 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. * 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); 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. * 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); 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. * 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); 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 * Execute the HTTP method to the given URI template, writing the given request entity to the request, and returns
* the response as {@link HttpRestResult}. * the response as {@link HttpRestResult}.
@ -319,16 +419,40 @@ public class NacosRestTemplate {
return execute(url, httpMethod, requestHttpEntity, responseType); 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, private <T> HttpRestResult<T> execute(String url, String httpMethod, RequestHttpEntity requestEntity,
Type responseType) throws Exception { Type responseType) throws Exception {
URI uri = HttpUtils.buildUri(url, requestEntity.getQuery()); URI uri = HttpUtils.buildUri(url, requestEntity.getQuery());
if (LOGGER.isDebugEnabled()) { if (logger.isDebugEnabled()) {
LOGGER.debug("HTTP " + httpMethod + " " + url); logger.debug("HTTP method: {}, url: {}, body: {}", httpMethod, uri, requestEntity.getBody());
} }
ResponseHandler<T> responseHandler = super.selectResponseHandler(responseType);
HttpClientResponse response = null; HttpClientResponse response = null;
try { try {
response = requestClient.execute(uri, httpMethod, requestEntity); response = this.requestClient().execute(uri, httpMethod, requestEntity);
return ResponseHandler.responseEntityExtractor(response, responseType); return responseHandler.handle(response);
} finally { } finally {
if (response != null) { if (response != null) {
response.close(); 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. * 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; 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 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.io.InputStream;
import java.lang.reflect.Type; import java.lang.reflect.Type;
@ -39,8 +28,6 @@ import java.lang.reflect.Type;
*/ */
public final class ResponseHandler { 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 { public static <T> T convert(String s, Class<T> cls) throws Exception {
return JacksonUtils.toObj(s, cls); return JacksonUtils.toObj(s, cls);
} }
@ -52,55 +39,4 @@ public final class ResponseHandler {
public static <T> T convert(InputStream inputStream, Type type) throws Exception { public static <T> T convert(InputStream inputStream, Type type) throws Exception {
return JacksonUtils.toObj(inputStream, type); 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, String> header;
private final Map<String, List<String>> originalResponseHeader;
private Header() { private Header() {
header = new LinkedHashMap<String, String>(); header = new LinkedHashMap<String, String>();
originalResponseHeader = new LinkedHashMap<String, List<String>>();
addParam(HttpHeaderConsts.CONTENT_TYPE, MediaType.APPLICATION_JSON); addParam(HttpHeaderConsts.CONTENT_TYPE, MediaType.APPLICATION_JSON);
addParam(HttpHeaderConsts.ACCEPT_CHARSET, "UTF-8"); addParam(HttpHeaderConsts.ACCEPT_CHARSET, "UTF-8");
addParam(HttpHeaderConsts.ACCEPT_ENCODING, "gzip"); 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() { public String getCharset() {
String acceptCharset = getValue(HttpHeaderConsts.ACCEPT_CHARSET); String acceptCharset = getValue(HttpHeaderConsts.ACCEPT_CHARSET);
if (acceptCharset == null) { if (acceptCharset == null) {
@ -145,6 +173,7 @@ public class Header {
public void clear() { public void clear() {
header.clear(); header.clear();
originalResponseHeader.clear();
} }
@Override @Override

View File

@ -16,6 +16,7 @@
package com.alibaba.nacos.common.model; 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.Header;
import com.alibaba.nacos.common.http.param.Query; import com.alibaba.nacos.common.http.param.Query;
@ -31,17 +32,27 @@ public class RequestHttpEntity {
private final Header headers = Header.newInstance(); private final Header headers = Header.newInstance();
private final HttpClientConfig httpClientConfig;
private final Query query; private final Query query;
private Object body; private Object body;
public RequestHttpEntity(Header header, Query query) { public RequestHttpEntity(Header header, Query query) {
handleHeader(header); this(null, header, query);
this.query = query; }
public RequestHttpEntity(HttpClientConfig httpClientConfig, Header header, Query query) {
this(httpClientConfig, header, query, null);
} }
public RequestHttpEntity(Header header, Query query, Object body) { 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); handleHeader(header);
this.httpClientConfig = httpClientConfig;
this.query = query; this.query = query;
this.body = body; this.body = body;
} }
@ -65,6 +76,10 @@ public class RequestHttpEntity {
return body; return body;
} }
public HttpClientConfig getHttpClientConfig() {
return httpClientConfig;
}
public boolean isEmptyBody() { public boolean isEmptyBody() {
return body == null; return body == null;
} }

View File

@ -16,7 +16,6 @@
package com.alibaba.nacos.common.notify; 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.api.exception.runtime.NacosRuntimeException;
import com.alibaba.nacos.common.JustForTest; import com.alibaba.nacos.common.JustForTest;
import com.alibaba.nacos.common.notify.listener.Subscriber; import com.alibaba.nacos.common.notify.listener.Subscriber;
@ -291,7 +290,9 @@ public class NotifyCenter {
EventPublisher publisher = INSTANCE.publisherMap.get(topic); EventPublisher publisher = INSTANCE.publisherMap.get(topic);
return publisher.publish(event); 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 eventType class Instances type of the event type.
* @param queueMaxSize the publisher's queue max size. * @param queueMaxSize the publisher's queue max size.
*/ */
public static EventPublisher registerToPublisher(final Class<? extends Event> eventType, final int queueMaxSize) public static EventPublisher registerToPublisher(final Class<? extends Event> eventType, final int queueMaxSize) {
throws NacosException {
if (ClassUtils.isAssignableFrom(SlowEvent.class, eventType)) { if (ClassUtils.isAssignableFrom(SlowEvent.class, eventType)) {
return INSTANCE.sharePublisher; 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.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.jsontype.NamedType; import com.fasterxml.jackson.databind.jsontype.NamedType;
@ -264,4 +265,14 @@ public final class JacksonUtils {
public static JsonNode transferToJsonNode(Object obj) { public static JsonNode transferToJsonNode(Object obj) {
return mapper.valueToTree(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 { public class NotifyCenterTest {
private static class TestSlowEvent extends SlowEvent { private static class TestSlowEvent extends SlowEvent {
} }
private static class TestEvent extends Event { private static class TestEvent extends Event {
@ -330,9 +331,11 @@ public class NotifyCenterTest {
} }
private static class TestSlowEvent1 extends SlowEvent { private static class TestSlowEvent1 extends SlowEvent {
} }
private static class TestSlowEvent2 extends SlowEvent { private static class TestSlowEvent2 extends SlowEvent {
} }
@Test @Test
@ -390,9 +393,11 @@ public class NotifyCenterTest {
} }
private static class TestSlowEvent3 extends SlowEvent { private static class TestSlowEvent3 extends SlowEvent {
} }
private static class TestSlowEvent4 extends SlowEvent { private static class TestSlowEvent4 extends SlowEvent {
} }
@Test @Test
@ -447,9 +452,11 @@ public class NotifyCenterTest {
} }
private static class TestSlowEvent5 extends SlowEvent { private static class TestSlowEvent5 extends SlowEvent {
} }
private static class TestEvent6 extends Event { private static class TestEvent6 extends Event {
} }
@Test @Test
@ -502,4 +509,16 @@ public class NotifyCenterTest {
Assert.assertEquals(3, count2.get()); 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.RestResult;
import com.alibaba.nacos.common.model.RestResultUtils; import com.alibaba.nacos.common.model.RestResultUtils;
import com.alibaba.nacos.common.utils.Objects; 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.constant.Constants;
import com.alibaba.nacos.config.server.model.event.DerbyImportEvent; import com.alibaba.nacos.config.server.model.event.DerbyImportEvent;
import com.alibaba.nacos.config.server.service.datasource.DynamicDataSource; 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.config.server.utils.PropertyUtil;
import com.alibaba.nacos.core.auth.ActionTypes; import com.alibaba.nacos.core.auth.ActionTypes;
import com.alibaba.nacos.core.auth.Secured; 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.ApplicationUtils;
import com.alibaba.nacos.core.utils.WebUtils; import com.alibaba.nacos.core.utils.WebUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;

View File

@ -17,6 +17,9 @@
package com.alibaba.nacos.config.server.filter; package com.alibaba.nacos.config.server.filter;
import com.alibaba.nacos.common.utils.ExceptionUtil; 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.constant.Constants;
import com.alibaba.nacos.config.server.model.event.RaftDbErrorEvent; import com.alibaba.nacos.config.server.model.event.RaftDbErrorEvent;
import com.alibaba.nacos.config.server.model.event.RaftDbErrorRecoverEvent; 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.MemberMetaDataConstants;
import com.alibaba.nacos.core.cluster.ServerMemberManager; import com.alibaba.nacos.core.cluster.ServerMemberManager;
import com.alibaba.nacos.core.code.ControllerMethodsCache; 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 org.springframework.beans.factory.annotation.Autowired;
import javax.annotation.PostConstruct; import javax.annotation.PostConstruct;
@ -41,6 +41,7 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import java.io.IOException; import java.io.IOException;
import java.security.AccessControlException; import java.security.AccessControlException;
import java.util.Arrays;
import java.util.List; import java.util.List;
/** /**
@ -119,7 +120,7 @@ public class CurcuitFilter implements Filter {
} }
private void registerSubscribe() { private void registerSubscribe() {
NotifyCenter.registerSubscribe(new SmartSubscribe() { NotifyCenter.registerSubscriber(new SmartSubscriber() {
@Override @Override
public void onEvent(Event event) { public void onEvent(Event event) {
@ -135,8 +136,8 @@ public class CurcuitFilter implements Filter {
} }
@Override @Override
public boolean canNotify(Event event) { public List<Class<? extends Event>> subscribeTypes() {
return (event instanceof RaftDbErrorEvent) || (event instanceof RaftDbErrorRecoverEvent); return Arrays.asList(RaftDbErrorRecoverEvent.class, RaftDbErrorEvent.class);
} }
}); });
} }

View File

@ -16,7 +16,7 @@
package com.alibaba.nacos.config.server.model.event; 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; import org.apache.commons.lang3.StringUtils;
/** /**
@ -24,7 +24,7 @@ import org.apache.commons.lang3.StringUtils;
* *
* @author Nacos * @author Nacos
*/ */
public class ConfigDataChangeEvent implements Event { public class ConfigDataChangeEvent extends Event {
public final boolean isBeta; public final boolean isBeta;

View File

@ -16,14 +16,14 @@
package com.alibaba.nacos.config.server.model.event; package com.alibaba.nacos.config.server.model.event;
import com.alibaba.nacos.core.notify.Event; import com.alibaba.nacos.common.notify.Event;
/** /**
* ConfigDumpEvent. * ConfigDumpEvent.
* *
* @author <a href="mailto:liaochuntao@live.com">liaochuntao</a> * @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; private static final long serialVersionUID = -8776888606458370294L;

View File

@ -16,14 +16,14 @@
package com.alibaba.nacos.config.server.model.event; 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. * Data import event.
* *
* @author <a href="mailto:liaochuntao@live.com">liaochuntao</a> * @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; private static final long serialVersionUID = 3299565864352399053L;

View File

@ -16,14 +16,14 @@
package com.alibaba.nacos.config.server.model.event; package com.alibaba.nacos.config.server.model.event;
import com.alibaba.nacos.core.notify.SlowEvent; import com.alibaba.nacos.common.notify.SlowEvent;
/** /**
* DerbyLoadEvent. * DerbyLoadEvent.
* *
* @author <a href="mailto:liaochuntao@live.com">liaochuntao</a> * @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(); public static final DerbyLoadEvent INSTANCE = new DerbyLoadEvent();

View File

@ -16,7 +16,7 @@
package com.alibaba.nacos.config.server.model.event; 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; import java.util.List;
@ -25,7 +25,7 @@ import java.util.List;
* *
* @author Nacos * @author Nacos
*/ */
public class LocalDataChangeEvent implements Event { public class LocalDataChangeEvent extends Event {
public final String groupKey; public final String groupKey;

View File

@ -16,14 +16,14 @@
package com.alibaba.nacos.config.server.model.event; package com.alibaba.nacos.config.server.model.event;
import com.alibaba.nacos.core.notify.SlowEvent; import com.alibaba.nacos.common.notify.SlowEvent;
/** /**
* RaftDBErrorEvent. * RaftDBErrorEvent.
* *
* @author <a href="mailto:liaochunyhm@live.com">liaochuntao</a> * @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; private static final long serialVersionUID = 101591819161802336L;

View File

@ -17,7 +17,7 @@
package com.alibaba.nacos.config.server.model.event; package com.alibaba.nacos.config.server.model.event;
import com.alibaba.nacos.common.JustForTest; import com.alibaba.nacos.common.JustForTest;
import com.alibaba.nacos.core.notify.Event; import com.alibaba.nacos.common.notify.Event;
/** /**
* RaftDBErrorRecoverEvent. * RaftDBErrorRecoverEvent.
@ -25,6 +25,6 @@ import com.alibaba.nacos.core.notify.Event;
* @author <a href="mailto:liaochuntao@live.com">liaochuntao</a> * @author <a href="mailto:liaochuntao@live.com">liaochuntao</a>
*/ */
@JustForTest @JustForTest
public class RaftDbErrorRecoverEvent implements Event { public class RaftDbErrorRecoverEvent extends Event {
} }

View File

@ -35,14 +35,15 @@ public class MemoryMonitor {
@Autowired @Autowired
public MemoryMonitor(AsyncNotifyService notifySingleService) { 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, ConfigExecutor
.scheduleConfigTask(new PrintGetConfigResponeTask(), DELAY_SECONDS, DELAY_SECONDS, TimeUnit.SECONDS);
ConfigExecutor
.scheduleConfigTask(new NotifyTaskQueueMonitorTask(notifySingleService), DELAY_SECONDS, DELAY_SECONDS,
TimeUnit.SECONDS); TimeUnit.SECONDS);
ConfigExecutor.scheduleWithFixedDelay(new NotifyTaskQueueMonitorTask(notifySingleService), DELAY_SECONDS,
DELAY_SECONDS, TimeUnit.SECONDS);
} }
private static final long DELAY_SECONDS = 10; private static final long DELAY_SECONDS = 10;

View File

@ -17,8 +17,7 @@
package com.alibaba.nacos.config.server.monitor; package com.alibaba.nacos.config.server.monitor;
import com.alibaba.nacos.config.server.service.notify.AsyncNotifyService; import com.alibaba.nacos.config.server.service.notify.AsyncNotifyService;
import com.alibaba.nacos.config.server.utils.ConfigExecutor;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import static com.alibaba.nacos.config.server.utils.LogUtil.MEMORY_LOG; import static com.alibaba.nacos.config.server.utils.LogUtil.MEMORY_LOG;
@ -37,7 +36,7 @@ public class NotifyTaskQueueMonitorTask implements Runnable {
@Override @Override
public void run() { public void run() {
int size = ((ScheduledThreadPoolExecutor) notifySingleService.getExecutor()).getQueue().size(); int size = ConfigExecutor.asyncNotifyQueueSize();
MEMORY_LOG.info("toNotifyTaskSize = {}", size); MEMORY_LOG.info("toNotifyTaskSize = {}", size);
MetricsMonitor.getNotifyTaskMonitor().set(size); MetricsMonitor.getNotifyTaskMonitor().set(size);
} }

View File

@ -16,6 +16,7 @@
package com.alibaba.nacos.config.server.service; 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.common.utils.MD5Utils;
import com.alibaba.nacos.config.server.constant.Constants; import com.alibaba.nacos.config.server.constant.Constants;
import com.alibaba.nacos.config.server.model.CacheItem; 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.GroupKey;
import com.alibaba.nacos.config.server.utils.GroupKey2; import com.alibaba.nacos.config.server.utils.GroupKey2;
import com.alibaba.nacos.config.server.utils.PropertyUtil; 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.apache.commons.lang3.StringUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -313,6 +313,7 @@ public class ConfigCacheService {
/** /**
* Check md5. * Check md5.
*
* @return return diff result list. * @return return diff result list.
*/ */
public static List<String> checkMd5() { public static List<String> checkMd5() {
@ -368,7 +369,7 @@ public class ConfigCacheService {
DiskUtil.removeConfigInfo(dataId, group, tenant); DiskUtil.removeConfigInfo(dataId, group, tenant);
} }
CACHE.remove(groupKey); CACHE.remove(groupKey);
EventDispatcher.fireEvent(new LocalDataChangeEvent(groupKey)); NotifyCenter.publishEvent(new LocalDataChangeEvent(groupKey));
return true; return true;
} finally { } finally {
@ -404,7 +405,7 @@ public class ConfigCacheService {
if (!PropertyUtil.isDirectRead()) { if (!PropertyUtil.isDirectRead()) {
DiskUtil.removeConfigInfo4Beta(dataId, group, tenant); 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).setBeta(false);
CACHE.get(groupKey).setIps4Beta(null); CACHE.get(groupKey).setIps4Beta(null);
CACHE.get(groupKey).setMd54Beta(Constants.NULL); CACHE.get(groupKey).setMd54Beta(Constants.NULL);
@ -447,7 +448,7 @@ public class ConfigCacheService {
CacheItem ci = CACHE.get(groupKey); CacheItem ci = CACHE.get(groupKey);
ci.tagMd5.remove(tag); ci.tagMd5.remove(tag);
ci.tagLastModifiedTs.remove(tag); ci.tagLastModifiedTs.remove(tag);
EventDispatcher.fireEvent(new LocalDataChangeEvent(groupKey, false, null, tag)); NotifyCenter.publishEvent(new LocalDataChangeEvent(groupKey, false, null, tag));
return true; return true;
} finally { } finally {
releaseWriteLock(groupKey); releaseWriteLock(groupKey);
@ -466,7 +467,7 @@ public class ConfigCacheService {
if (cache.md5 == null || !cache.md5.equals(md5)) { if (cache.md5 == null || !cache.md5.equals(md5)) {
cache.md5 = md5; cache.md5 = md5;
cache.lastModifiedTs = lastModifiedTs; cache.lastModifiedTs = lastModifiedTs;
EventDispatcher.fireEvent(new LocalDataChangeEvent(groupKey)); NotifyCenter.publishEvent(new LocalDataChangeEvent(groupKey));
} }
} }
@ -485,7 +486,7 @@ public class ConfigCacheService {
cache.md54Beta = md5; cache.md54Beta = md5;
cache.lastModifiedTs4Beta = lastModifiedTs; cache.lastModifiedTs4Beta = lastModifiedTs;
cache.ips4Beta = ips4Beta; cache.ips4Beta = ips4Beta;
EventDispatcher.fireEvent(new LocalDataChangeEvent(groupKey, true, ips4Beta)); NotifyCenter.publishEvent(new LocalDataChangeEvent(groupKey, true, ips4Beta));
} }
} }
@ -510,13 +511,13 @@ public class ConfigCacheService {
} else { } else {
cache.tagLastModifiedTs.put(tag, lastModifiedTs); cache.tagLastModifiedTs.put(tag, lastModifiedTs);
} }
EventDispatcher.fireEvent(new LocalDataChangeEvent(groupKey, false, null, tag)); NotifyCenter.publishEvent(new LocalDataChangeEvent(groupKey, false, null, tag));
return; return;
} }
if (cache.tagMd5.get(tag) == null || !cache.tagMd5.get(tag).equals(md5)) { if (cache.tagMd5.get(tag) == null || !cache.tagMd5.get(tag).equals(md5)) {
cache.tagMd5.put(tag, md5); cache.tagMd5.put(tag, md5);
cache.tagLastModifiedTs.put(tag, lastModifiedTs); 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; 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.model.event.ConfigDataChangeEvent;
import com.alibaba.nacos.config.server.utils.PropertyUtil; 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 com.alibaba.nacos.core.utils.ApplicationUtils;
/** /**
@ -30,13 +30,14 @@ public class ConfigChangePublisher {
/** /**
* Notify ConfigChange. * Notify ConfigChange.
*
* @param event ConfigDataChangeEvent instance. * @param event ConfigDataChangeEvent instance.
*/ */
public static void notifyConfigChange(ConfigDataChangeEvent event) { public static void notifyConfigChange(ConfigDataChangeEvent event) {
if (PropertyUtil.isEmbeddedStorage() && !ApplicationUtils.getStandaloneMode()) { if (PropertyUtil.isEmbeddedStorage() && !ApplicationUtils.getStandaloneMode()) {
return; return;
} }
EventDispatcher.fireEvent(event); NotifyCenter.publishEvent(event);
} }
} }

View File

@ -16,17 +16,17 @@
package com.alibaba.nacos.config.server.service; 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.constant.Constants;
import com.alibaba.nacos.config.server.model.SampleResult; import com.alibaba.nacos.config.server.model.SampleResult;
import com.alibaba.nacos.config.server.service.notify.NotifyService; 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.JSONUtils;
import com.alibaba.nacos.config.server.utils.LogUtil; import com.alibaba.nacos.config.server.utils.LogUtil;
import com.alibaba.nacos.core.cluster.Member; import com.alibaba.nacos.core.cluster.Member;
import com.alibaba.nacos.core.cluster.ServerMemberManager; import com.alibaba.nacos.core.cluster.ServerMemberManager;
import com.alibaba.nacos.core.utils.ApplicationUtils; import com.alibaba.nacos.core.utils.ApplicationUtils;
import org.apache.commons.lang3.StringUtils;
import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.core.type.TypeReference;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@ -37,18 +37,15 @@ import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; 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.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.ExecutorCompletionService;
import java.util.concurrent.Future;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
/** /**
* Config sub service. * Config sub service.
@ -58,24 +55,12 @@ import java.util.concurrent.ExecutorCompletionService;
@Service @Service
public class ConfigSubService { public class ConfigSubService {
private ScheduledExecutorService scheduler;
private ServerMemberManager memberManager; private ServerMemberManager memberManager;
@Autowired @Autowired
@SuppressWarnings("PMD.ThreadPoolCreationRule") @SuppressWarnings("PMD.ThreadPoolCreationRule")
public ConfigSubService(ServerMemberManager memberManager) { public ConfigSubService(ServerMemberManager memberManager) {
this.memberManager = 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() { protected ConfigSubService() {
@ -227,8 +212,8 @@ public class ConfigSubService {
} }
BlockingQueue<Future<SampleResult>> queue = new LinkedBlockingDeque<Future<SampleResult>>( BlockingQueue<Future<SampleResult>> queue = new LinkedBlockingDeque<Future<SampleResult>>(
memberManager.getServerList().size()); memberManager.getServerList().size());
CompletionService<SampleResult> completionService = new ExecutorCompletionService<SampleResult>(scheduler, CompletionService<SampleResult> completionService = new ExecutorCompletionService<SampleResult>(
queue); ConfigExecutor.getConfigSubServiceExecutor(), queue);
SampleResult sampleCollectResult = new SampleResult(); SampleResult sampleCollectResult = new SampleResult();
for (int i = 0; i < sampleTime; i++) { for (int i = 0; i < sampleTime; i++) {
@ -247,8 +232,8 @@ public class ConfigSubService {
params.put("ip", ip); params.put("ip", ip);
BlockingQueue<Future<SampleResult>> queue = new LinkedBlockingDeque<Future<SampleResult>>( BlockingQueue<Future<SampleResult>> queue = new LinkedBlockingDeque<Future<SampleResult>>(
memberManager.getServerList().size()); memberManager.getServerList().size());
CompletionService<SampleResult> completionService = new ExecutorCompletionService<SampleResult>(scheduler, CompletionService<SampleResult> completionService = new ExecutorCompletionService<SampleResult>(
queue); ConfigExecutor.getConfigSubServiceExecutor(), queue);
SampleResult sampleCollectResult = new SampleResult(); SampleResult sampleCollectResult = new SampleResult();
for (int i = 0; i < sampleTime; i++) { for (int i = 0; i < sampleTime; i++) {

View File

@ -17,17 +17,20 @@
package com.alibaba.nacos.config.server.service; package com.alibaba.nacos.config.server.service;
import com.alibaba.nacos.api.config.remote.response.ConfigChangeNotifyResponse; 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.CollectionUtils;
import com.alibaba.nacos.common.utils.ExceptionUtil; import com.alibaba.nacos.common.utils.ExceptionUtil;
import com.alibaba.nacos.config.server.model.SampleResult; import com.alibaba.nacos.config.server.model.SampleResult;
import com.alibaba.nacos.config.server.model.event.LocalDataChangeEvent; import com.alibaba.nacos.config.server.model.event.LocalDataChangeEvent;
import com.alibaba.nacos.config.server.monitor.MetricsMonitor; 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.GroupKey;
import com.alibaba.nacos.config.server.utils.LogUtil; import com.alibaba.nacos.config.server.utils.LogUtil;
import com.alibaba.nacos.config.server.utils.MD5Util; import com.alibaba.nacos.config.server.utils.MD5Util;
import com.alibaba.nacos.config.server.utils.RequestUtil; 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 com.alibaba.nacos.core.remote.DataChangeListenerNotifier;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@ -48,10 +51,7 @@ import java.util.Queue;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.Executors;
import java.util.concurrent.Future; import java.util.concurrent.Future;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import static com.alibaba.nacos.config.server.utils.LogUtil.MEMORY_LOG; 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 * @author Nacos
*/ */
@Service @Service
public class LongPollingService extends AbstractEventListener { public class LongPollingService {
private static final int FIXED_POLLING_INTERVAL_MS = 10000; private static final int FIXED_POLLING_INTERVAL_MS = 10000;
@ -281,29 +281,10 @@ public class LongPollingService extends AbstractEventListener {
// AsyncContext.setTimeout() is incorrect, Control by oneself // AsyncContext.setTimeout() is incorrect, Control by oneself
asyncContext.setTimeout(0L); asyncContext.setTimeout(0L);
scheduler.execute( ConfigExecutor.executeLongPolling(
new ClientLongPolling(asyncContext, clientMd5Map, ip, probeRequestSize, timeout, appName, tag)); 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) { public static boolean isSupportLongPolling(HttpServletRequest req) {
return null != req.getHeader(LONG_POLLING_HEADER); return null != req.getHeader(LONG_POLLING_HEADER);
} }
@ -312,24 +293,38 @@ public class LongPollingService extends AbstractEventListener {
public LongPollingService() { public LongPollingService() {
allSubs = new ConcurrentLinkedQueue<ClientLongPolling>(); 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 @Override
public Thread newThread(Runnable r) { public void onEvent(Event event) {
Thread t = new Thread(r); if (isFixedPolling()) {
t.setDaemon(true); // Ignore.
t.setName("com.alibaba.nacos.LongPolling"); } else {
return t; 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_HEADER = "Long-Pulling-Timeout";
public static final String LONG_POLLING_NO_HANG_UP_HEADER = "Long-Pulling-Timeout-No-Hangup"; public static final String LONG_POLLING_NO_HANG_UP_HEADER = "Long-Pulling-Timeout-No-Hangup";
final ScheduledExecutorService scheduler;
/** /**
* ClientLongPolling subscibers. * ClientLongPolling subscibers.
*/ */
@ -413,7 +408,7 @@ public class LongPollingService extends AbstractEventListener {
@Override @Override
public void run() { public void run() {
asyncTimeoutFuture = scheduler.schedule(new Runnable() { asyncTimeoutFuture = ConfigExecutor.scheduleLongPolling(new Runnable() {
@Override @Override
public void run() { public void run() {
try { try {

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.GroupCapacity;
import com.alibaba.nacos.config.server.model.capacity.TenantCapacity; import com.alibaba.nacos.config.server.model.capacity.TenantCapacity;
import com.alibaba.nacos.config.server.service.repository.PersistService; 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.LogUtil;
import com.alibaba.nacos.config.server.utils.PropertyUtil; import com.alibaba.nacos.config.server.utils.PropertyUtil;
import com.alibaba.nacos.config.server.utils.TimeUtils; import com.alibaba.nacos.config.server.utils.TimeUtils;
import com.google.common.base.Stopwatch; import com.google.common.base.Stopwatch;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -34,12 +34,8 @@ import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct; import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.sql.Timestamp; import java.sql.Timestamp;
import java.util.List; import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
/** /**
@ -66,8 +62,6 @@ public class CapacityService {
@Autowired @Autowired
private PersistService persistService; private PersistService persistService;
private ScheduledExecutorService scheduledExecutorService;
/** /**
* Init. * Init.
*/ */
@ -75,10 +69,7 @@ public class CapacityService {
@SuppressWarnings("PMD.ThreadPoolCreationRule") @SuppressWarnings("PMD.ThreadPoolCreationRule")
public void init() { public void init() {
// All servers have jobs that modify usage, idempotent. // All servers have jobs that modify usage, idempotent.
ThreadFactory threadFactory = new ThreadFactoryBuilder() ConfigExecutor.scheduleCorrectUsageTask(new Runnable() {
.setNameFormat("com.alibaba.nacos.CapacityManagement-%d").setDaemon(true).build();
scheduledExecutorService = Executors.newSingleThreadScheduledExecutor(threadFactory);
scheduledExecutorService.scheduleWithFixedDelay(new Runnable() {
@Override @Override
public void run() { public void run() {
LOGGER.info("[capacityManagement] start correct usage"); LOGGER.info("[capacityManagement] start correct usage");
@ -90,11 +81,6 @@ public class CapacityService {
}, PropertyUtil.getCorrectUsageDelay(), PropertyUtil.getCorrectUsageDelay(), TimeUnit.SECONDS); }, PropertyUtil.getCorrectUsageDelay(), PropertyUtil.getCorrectUsageDelay(), TimeUnit.SECONDS);
} }
@PreDestroy
public void destroy() {
scheduledExecutorService.shutdown();
}
public void correctUsage() { public void correctUsage() {
correctGroupUsage(); correctGroupUsage();
correctTenantUsage(); correctTenantUsage();
@ -192,9 +178,8 @@ public class CapacityService {
} }
/** /**
* To Cluster. * To Cluster. 1.If the capacity information does not exist, initialize the capacity information. 2.Update capacity
* 1.If the capacity information does not exist, initialize the capacity information. * usage, plus or minus one.
* 2.Update capacity usage, plus or minus one.
* *
* @param counterMode increase or decrease mode. * @param counterMode increase or decrease mode.
* @param ignoreQuotaLimit ignoreQuotaLimit flag. * @param ignoreQuotaLimit ignoreQuotaLimit flag.
@ -215,9 +200,8 @@ public class CapacityService {
} }
/** /**
* It is used for counting when the limit check function of capacity management is turned off. * It is used for counting when the limit check function of capacity management is turned off. 1.If the capacity
* 1.If the capacity information does not exist, initialize the capacity information. * information does not exist, initialize the capacity information. 2.Update capacity usage, plus or minus one.
* 2.Update capacity usage, plus or minus one.
* *
* @param counterMode increase or decrease mode. * @param counterMode increase or decrease mode.
* @param group tenant string value. * @param group tenant string value.
@ -260,8 +244,8 @@ public class CapacityService {
} }
/** /**
* Initialize the capacity information of the group. * Initialize the capacity information of the group. If the quota is reached, the capacity will be automatically
* If the quota is reached, the capacity will be automatically expanded to reduce the operation and maintenance cost. * expanded to reduce the operation and maintenance cost.
* *
* @param group group string value. * @param group group string value.
* @return init result. * @return init result.
@ -271,8 +255,8 @@ public class CapacityService {
} }
/** /**
* Initialize the capacity information of the group. If the quota is reached, * Initialize the capacity information of the group. If the quota is reached, the capacity will be automatically
* the capacity will be automatically expanded to reduce the operation and maintenance cost. * expanded to reduce the operation and maintenance cost.
* *
* @param group group string value. * @param group group string value.
* @param quota quota int value. * @param quota quota int value.
@ -423,9 +407,8 @@ public class CapacityService {
} }
/** /**
* It is used for counting when the limit check function of capacity management is turned off. * It is used for counting when the limit check function of capacity management is turned off. 1.If the capacity
* 1.If the capacity information does not exist, initialize the capacity information. * information does not exist, initialize the capacity information. 2.Update capacity usage, plus or minus one.
* 2.Update capacity usage, plus or minus one.
* *
* @param counterMode increase or decrease mode. * @param counterMode increase or decrease mode.
* @param tenant tenant string value. * @param tenant tenant string value.
@ -464,8 +447,8 @@ public class CapacityService {
} }
/** /**
* Initialize the capacity information of the tenant. If the quota is reached, * Initialize the capacity information of the tenant. If the quota is reached, the capacity will be automatically
* the capacity will be automatically expanded to reduce the operation and maintenance cos. * expanded to reduce the operation and maintenance cos.
* *
* @param tenant tenant string value. * @param tenant tenant string value.
* @return init result. * @return init result.
@ -475,8 +458,8 @@ public class CapacityService {
} }
/** /**
* Initialize the capacity information of the tenant. If the quota is reached, * Initialize the capacity information of the tenant. If the quota is reached, the capacity will be automatically
* the capacity will be automatically expanded to reduce the operation and maintenance cost * expanded to reduce the operation and maintenance cost
* *
* @param tenant tenant string value. * @param tenant tenant string value.
* @param quota quota int value. * @param quota quota int value.
@ -530,8 +513,8 @@ public class CapacityService {
} }
/** /**
* Support for API interface, Tenant: initialize if the record does not exist, * Support for API interface, Tenant: initialize if the record does not exist, and update the capacity quota or
* and update the capacity quota or content size directly if it exists. * content size directly if it exists.
* *
* @param group group string value. * @param group group string value.
* @param tenant tenant string value. * @param tenant tenant string value.

View File

@ -45,7 +45,7 @@ public class ExternalDataSourceProperties {
public static final int DEFAULT_MAX_POOL_SIZE = 20; 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; private Integer num;

View File

@ -118,8 +118,8 @@ public class ExternalDataSourceServiceImpl implements DataSourceService {
throw new RuntimeException(DB_LOAD_ERROR_MSG); throw new RuntimeException(DB_LOAD_ERROR_MSG);
} }
ConfigExecutor.scheduleWithFixedDelay(new SelectMasterTask(), 10, 10, TimeUnit.SECONDS); ConfigExecutor.scheduleConfigTask(new SelectMasterTask(), 10, 10, TimeUnit.SECONDS);
ConfigExecutor.scheduleWithFixedDelay(new CheckDbHealthTask(), 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; package com.alibaba.nacos.config.server.service.dump;
import com.alibaba.nacos.common.utils.StringUtils; 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.model.event.ConfigDumpEvent;
import com.alibaba.nacos.config.server.service.AggrWhitelist; import com.alibaba.nacos.config.server.service.AggrWhitelist;
import com.alibaba.nacos.config.server.service.ClientIpWhiteList; import com.alibaba.nacos.config.server.service.ClientIpWhiteList;
import com.alibaba.nacos.config.server.service.ConfigCacheService; import com.alibaba.nacos.config.server.service.ConfigCacheService;
import com.alibaba.nacos.config.server.service.SwitchService; import com.alibaba.nacos.config.server.service.SwitchService;
import com.alibaba.nacos.config.server.service.trace.ConfigTraceService; 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. * Dump config subscriber.
* *
* @author <a href="mailto:liaochuntao@live.com">liaochuntao</a> * @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. * trigger config dump event.
* *
* @param event {@link ConfigDumpEvent} * @param event {@link ConfigDumpEvent}
* @return {@code true} if the config dump task success , else * @return {@code true} if the config dump task success , else {@code false}
* {@code false}
*/ */
public static boolean configDump(ConfigDumpEvent event) { public static boolean configDump(ConfigDumpEvent event) {
final String dataId = event.getDataId(); final String dataId = event.getDataId();

View File

@ -152,7 +152,8 @@ public abstract class DumpService {
if (totalCount > 0) { if (totalCount > 0) {
int pageSize = 1000; int pageSize = 1000;
int removeTime = (totalCount + pageSize - 1) / pageSize; int removeTime = (totalCount + pageSize - 1) / pageSize;
LOGGER.warn("clearConfigHistory, getBeforeStamp:{}, totalCount:{}, pageSize:{}, removeTime:{}", LOGGER.warn(
"clearConfigHistory, getBeforeStamp:{}, totalCount:{}, pageSize:{}, removeTime:{}",
startTime, totalCount, pageSize, removeTime); startTime, totalCount, pageSize, removeTime);
while (removeTime > 0) { while (removeTime > 0) {
// delete paging to avoid reporting errors in batches // 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; long initialDelay = new Random().nextInt(INITIAL_DELAY_IN_MINUTE) + 10;
LogUtil.DEFAULT_LOG.warn("initialDelay:{}", initialDelay); LogUtil.DEFAULT_LOG.warn("initialDelay:{}", initialDelay);
ConfigExecutor.scheduleConfigTask(dumpAll, initialDelay, DUMP_ALL_INTERVAL_IN_MINUTE, TimeUnit.MINUTES);
ConfigExecutor 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, ConfigExecutor
TimeUnit.MINUTES); .scheduleConfigTask(dumpAllTag, initialDelay, DUMP_ALL_INTERVAL_IN_MINUTE, TimeUnit.MINUTES);
ConfigExecutor.scheduleWithFixedDelay(dumpAllTag, initialDelay, DUMP_ALL_INTERVAL_IN_MINUTE,
TimeUnit.MINUTES);
} }
ConfigExecutor.scheduleWithFixedDelay(clearConfigHistory, 10, 10, TimeUnit.MINUTES); ConfigExecutor.scheduleConfigTask(clearConfigHistory, 10, 10, TimeUnit.MINUTES);
} finally { } finally {
TimerContext.end(LogUtil.DUMP_LOG); TimerContext.end(LogUtil.DUMP_LOG);
} }
@ -276,7 +276,7 @@ public abstract class DumpService {
} }
LogUtil.DEFAULT_LOG.error("end checkMd5Task"); LogUtil.DEFAULT_LOG.error("end checkMd5Task");
}; };
ConfigExecutor.scheduleWithFixedDelay(checkMd5Task, 0, 12, TimeUnit.HOURS); ConfigExecutor.scheduleConfigTask(checkMd5Task, 0, 12, TimeUnit.HOURS);
} }
} catch (IOException e) { } catch (IOException e) {
LogUtil.FATAL_LOG.error("dump config fail" + e.getMessage()); LogUtil.FATAL_LOG.error("dump config fail" + e.getMessage());
@ -420,7 +420,8 @@ public abstract class DumpService {
} else { } else {
// remove config info // remove config info
persistService.removeConfigInfo(dataId, group, tenant, InetUtils.getSelfIp(), null); persistService.removeConfigInfo(dataId, group, tenant, InetUtils.getSelfIp(), null);
LOGGER.warn("[merge-delete] delete config info because no datum. dataId=" + dataId + ", groupId=" LOGGER.warn(
"[merge-delete] delete config info because no datum. dataId=" + dataId + ", groupId="
+ group); + group);
} }

View File

@ -16,6 +16,7 @@
package com.alibaba.nacos.config.server.service.merge; 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.constant.Constants;
import com.alibaba.nacos.config.server.manager.AbstractTask; import com.alibaba.nacos.config.server.manager.AbstractTask;
import com.alibaba.nacos.config.server.manager.TaskProcessor; 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.service.trace.ConfigTraceService;
import com.alibaba.nacos.config.server.utils.ContentUtils; import com.alibaba.nacos.config.server.utils.ContentUtils;
import com.alibaba.nacos.config.server.utils.TimeUtils; 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 com.alibaba.nacos.core.utils.InetUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
@ -79,8 +79,9 @@ public class MergeTaskProcessor implements TaskProcessor {
persistService.insertOrUpdate(null, null, cf, time, null); persistService.insertOrUpdate(null, null, cf, time, null);
LOGGER.info("[merge-ok] {}, {}, size={}, length={}, md5={}, content={}", dataId, group, datumList.size(), LOGGER.info("[merge-ok] {}, {}, size={}, length={}, md5={}, content={}", dataId, group,
cf.getContent().length(), cf.getMd5(), ContentUtils.truncateContent(cf.getContent())); datumList.size(), cf.getContent().length(), cf.getMd5(),
ContentUtils.truncateContent(cf.getContent()));
ConfigTraceService ConfigTraceService
.logPersistenceEvent(dataId, group, tenant, null, time.getTime(), InetUtils.getSelfIp(), .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); 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 ConfigTraceService
.logPersistenceEvent(dataId, group, tenant, null, time.getTime(), InetUtils.getSelfIp(), .logPersistenceEvent(dataId, group, tenant, null, time.getTime(), InetUtils.getSelfIp(),
ConfigTraceService.PERSISTENCE_EVENT_REMOVE, null); ConfigTraceService.PERSISTENCE_EVENT_REMOVE, null);
} }
NotifyCenter.publishEvent(new ConfigDataChangeEvent(false, dataId, group, tenant, tag, time.getTime()));
EventDispatcher.fireEvent(new ConfigDataChangeEvent(false, dataId, group, tenant, tag, time.getTime()));
} catch (Exception e) { } catch (Exception e) {
mergeService.addMergeTask(dataId, group, tenant, mergeTask.getClientIp()); mergeService.addMergeTask(dataId, group, tenant, mergeTask.getClientIp());

View File

@ -16,14 +16,16 @@
package com.alibaba.nacos.config.server.service.notify; 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.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.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.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.LogUtil;
import com.alibaba.nacos.config.server.utils.PropertyUtil; 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.Member;
import com.alibaba.nacos.core.cluster.ServerMemberManager; import com.alibaba.nacos.core.cluster.ServerMemberManager;
import com.alibaba.nacos.core.utils.ApplicationUtils; import com.alibaba.nacos.core.utils.ApplicationUtils;
@ -45,15 +47,9 @@ import org.springframework.stereotype.Service;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.net.URLEncoder; import java.net.URLEncoder;
import java.text.MessageFormat; import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List;
import java.util.Queue; 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; import java.util.concurrent.TimeUnit;
/** /**
@ -62,19 +58,21 @@ import java.util.concurrent.TimeUnit;
* @author Nacos * @author Nacos
*/ */
@Service @Service
public class AsyncNotifyService extends AbstractEventListener { public class AsyncNotifyService {
@Override @Autowired
public List<Class<? extends Event>> interest() { public AsyncNotifyService(ServerMemberManager memberManager) {
List<Class<? extends Event>> types = new ArrayList<Class<? extends Event>>(); this.memberManager = memberManager;
// Trigger configuration change synchronization notification httpclient.start();
types.add(ConfigDataChangeEvent.class);
return types; // Register ConfigDataChangeEvent to NotifyCenter.
} NotifyCenter.registerToPublisher(ConfigDataChangeEvent.class, NotifyCenter.ringBufferSize);
// Register A Subscriber to subscribe ConfigDataChangeEvent.
NotifyCenter.registerSubscriber(new Subscriber() {
@Override @Override
public void onEvent(Event event) { public void onEvent(Event event) {
// Generate ConfigDataChangeEvent concurrently // Generate ConfigDataChangeEvent concurrently
if (event instanceof ConfigDataChangeEvent) { if (event instanceof ConfigDataChangeEvent) {
ConfigDataChangeEvent evt = (ConfigDataChangeEvent) event; ConfigDataChangeEvent evt = (ConfigDataChangeEvent) event;
@ -88,25 +86,20 @@ public class AsyncNotifyService extends AbstractEventListener {
// In fact, any type of queue here can be // In fact, any type of queue here can be
Queue<NotifySingleTask> queue = new LinkedList<NotifySingleTask>(); Queue<NotifySingleTask> queue = new LinkedList<NotifySingleTask>();
for (Member member : ipList) { for (Member member : ipList) {
queue.add(new NotifySingleTask(dataId, group, tenant, tag, dumpTs, member.getAddress(), evt.isBeta)); queue.add(new NotifySingleTask(dataId, group, tenant, tag, dumpTs, member.getAddress(),
evt.isBeta));
} }
EXECUTOR.execute(new AsyncTask(httpclient, queue)); ConfigExecutor.executeAsyncNotify(new AsyncTask(httpclient, queue));
} }
} }
@Autowired @Override
public AsyncNotifyService(ServerMemberManager memberManager) { public Class<? extends Event> subscribeType() {
this.memberManager = memberManager; return ConfigDataChangeEvent.class;
httpclient.start();
} }
});
public Executor getExecutor() {
return EXECUTOR;
} }
@SuppressWarnings("PMD.ThreadPoolCreationRule")
private static final Executor EXECUTOR = Executors.newScheduledThreadPool(100, new NotifyThreadFactory());
private RequestConfig requestConfig = RequestConfig.custom() private RequestConfig requestConfig = RequestConfig.custom()
.setConnectTimeout(PropertyUtil.getNotifyConnectTimeout()) .setConnectTimeout(PropertyUtil.getNotifyConnectTimeout())
.setSocketTimeout(PropertyUtil.getNotifySocketTimeout()).build(); .setSocketTimeout(PropertyUtil.getNotifySocketTimeout()).build();
@ -169,7 +162,7 @@ public class AsyncNotifyService extends AbstractEventListener {
Queue<NotifySingleTask> queue = new LinkedList<NotifySingleTask>(); Queue<NotifySingleTask> queue = new LinkedList<NotifySingleTask>();
queue.add(task); queue.add(task);
AsyncTask asyncTask = new AsyncTask(httpclient, queue); AsyncTask asyncTask = new AsyncTask(httpclient, queue);
((ScheduledThreadPoolExecutor) EXECUTOR).schedule(asyncTask, delay, TimeUnit.MILLISECONDS); ConfigExecutor.scheduleAsyncNotify(asyncTask, delay, TimeUnit.MILLISECONDS);
} }
class AsyncNotifyCallBack implements FutureCallback<HttpResponse> { 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 * 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. * in the offline scene, which affects the normal synchronization.

View File

@ -16,6 +16,8 @@
package com.alibaba.nacos.config.server.service.notify; 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.manager.AbstractTask;
import com.alibaba.nacos.config.server.utils.GroupKey2; import com.alibaba.nacos.config.server.utils.GroupKey2;
import com.alibaba.nacos.config.server.utils.LogUtil; import com.alibaba.nacos.config.server.utils.LogUtil;
@ -28,9 +30,7 @@ import java.util.Collection;
import java.util.Map; import java.util.Map;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit; 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 @Autowired
public NotifySingleService(ServerMemberManager memberManager) { public NotifySingleService(ServerMemberManager memberManager) {
this.memberManager = memberManager; this.memberManager = memberManager;
@ -141,8 +125,8 @@ public class NotifySingleService {
* there will be no continuous task accumulation, * there will be no continuous task accumulation,
* there is occasional instantaneous pressure) * there is occasional instantaneous pressure)
*/ */
@SuppressWarnings("PMD.ThreadPoolCreationRule") Executor executor = Executors Executor executor = ExecutorFactory.newSingleScheduledExecutorService(
.newScheduledThreadPool(1, new NotifyThreadFactory(address)); new NameThreadFactory("com.alibaba.nacos.config.NotifySingleServiceThread-" + address));
if (null == executors.putIfAbsent(address, executor)) { if (null == executors.putIfAbsent(address, executor)) {
LOGGER.warn("[notify-thread-pool] setup thread target ip {} ok.", address); 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; 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.model.event.DerbyLoadEvent;
import com.alibaba.nacos.config.server.service.datasource.DataSourceService; import com.alibaba.nacos.config.server.service.datasource.DataSourceService;
import com.alibaba.nacos.config.server.service.datasource.DynamicDataSource; import com.alibaba.nacos.config.server.service.datasource.DynamicDataSource;
@ -27,7 +28,6 @@ import com.alibaba.nacos.consistency.snapshot.SnapshotOperation;
import com.alibaba.nacos.consistency.snapshot.Writer; import com.alibaba.nacos.consistency.snapshot.Writer;
import com.alibaba.nacos.core.distributed.raft.utils.RaftExecutor; import com.alibaba.nacos.core.distributed.raft.utils.RaftExecutor;
import com.alibaba.nacos.core.utils.DiskUtils; 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.ApplicationUtils;
import com.alibaba.nacos.core.utils.TimerContext; import com.alibaba.nacos.core.utils.TimerContext;
import com.alipay.sofa.jraft.util.CRC64; 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.JustForTest;
import com.alibaba.nacos.common.model.RestResult; import com.alibaba.nacos.common.model.RestResult;
import com.alibaba.nacos.common.model.RestResultUtils; 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.ExceptionUtil;
import com.alibaba.nacos.common.utils.JacksonUtils; import com.alibaba.nacos.common.utils.JacksonUtils;
import com.alibaba.nacos.common.utils.LoggerUtils; 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.consistency.snapshot.SnapshotOperation;
import com.alibaba.nacos.core.cluster.ServerMemberManager; import com.alibaba.nacos.core.cluster.ServerMemberManager;
import com.alibaba.nacos.core.distributed.ProtocolManager; 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.ClassUtils;
import com.alibaba.nacos.core.utils.DiskUtils; import com.alibaba.nacos.core.utils.DiskUtils;
import com.alibaba.nacos.core.utils.GenericType; import com.alibaba.nacos.core.utils.GenericType;
@ -190,7 +190,7 @@ public class DistributedDatabaseOperateImpl extends LogProcessor4CP implements B
// Register the snapshot load event // Register the snapshot load event
NotifyCenter.registerToSharePublisher(DerbyLoadEvent.class); NotifyCenter.registerToSharePublisher(DerbyLoadEvent.class);
NotifyCenter.registerSubscribe(new Subscribe<RaftDbErrorEvent>() { NotifyCenter.registerSubscriber(new Subscriber<RaftDbErrorEvent>() {
@Override @Override
public void onEvent(RaftDbErrorEvent event) { public void onEvent(RaftDbErrorEvent event) {
dataSourceService.setHealthStatus("DOWN"); dataSourceService.setHealthStatus("DOWN");
@ -202,8 +202,8 @@ public class DistributedDatabaseOperateImpl extends LogProcessor4CP implements B
} }
}); });
NotifyCenter.registerToPublisher(ConfigDumpEvent.class, NotifyCenter.RING_BUFFER_SIZE); NotifyCenter.registerToPublisher(ConfigDumpEvent.class, NotifyCenter.ringBufferSize);
NotifyCenter.registerSubscribe(new DumpConfigHandler()); NotifyCenter.registerSubscriber(new DumpConfigHandler());
this.protocol.addLogProcessors(Collections.singletonList(this)); this.protocol.addLogProcessors(Collections.singletonList(this));
LogUtil.DEFAULT_LOG.info("use DistributedTransactionServicesImpl"); 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.api.exception.NacosException;
import com.alibaba.nacos.common.utils.MD5Utils; 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.configuration.ConditionOnEmbeddedStorage;
import com.alibaba.nacos.config.server.constant.Constants; import com.alibaba.nacos.config.server.constant.Constants;
import com.alibaba.nacos.config.server.enums.FileTypeEnum; 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.LogUtil;
import com.alibaba.nacos.config.server.utils.ParamUtils; import com.alibaba.nacos.config.server.utils.ParamUtils;
import com.alibaba.nacos.core.distributed.id.IdGeneratorManager; 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.base.Joiner;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import org.apache.commons.collections.CollectionUtils; 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.ExecutorFactory;
import com.alibaba.nacos.common.executor.NameThreadFactory; 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.config.server.Config;
import com.alibaba.nacos.core.utils.ClassUtils;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
/** /**
@ -31,15 +35,32 @@ import java.util.concurrent.TimeUnit;
*/ */
public final class ConfigExecutor { public final class ConfigExecutor {
private static final Executor DUMP_EXECUTOR = ExecutorFactory private static final Executor DUMP_EXECUTOR = ExecutorFactory.Managed
.newFixedExecutorService(Config.class.getCanonicalName(), 1, .newSingleExecutorService(ClassUtils.getCanonicalName(Config.class),
new NameThreadFactory("nacos.config.embedded.dump")); new NameThreadFactory("com.alibaba.nacos.config.embedded.dump"));
private static final ScheduledExecutorService TIMER_EXECUTOR = ExecutorFactory private static final ScheduledExecutorService TIMER_EXECUTOR = ExecutorFactory.Managed
.newScheduledExecutorService(Config.class.getCanonicalName(), 10, .newScheduledExecutorService(ClassUtils.getCanonicalName(Config.class), 10,
new NameThreadFactory("com.alibaba.nacos.server.Timer")); 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); TIMER_EXECUTOR.scheduleWithFixedDelay(command, initialDelay, delay, unit);
} }
@ -47,4 +68,35 @@ public final class ConfigExecutor {
DUMP_EXECUTOR.execute(runnable); 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; 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.ScheduledExecutorService;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
@ -37,18 +40,9 @@ public class SimpleFlowData {
private int slotCount; private int slotCount;
@SuppressWarnings("PMD.ThreadPoolCreationRule") private ScheduledExecutorService timer = ExecutorFactory.Managed
private ScheduledExecutorService timer = Executors.newSingleThreadScheduledExecutor(new ThreadFactory() { .newSingleScheduledExecutorService(ClassUtils.getCanonicalName(Config.class),
new NameThreadFactory("com.alibaba.nacos.config.flow.control"));
@Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r);
t.setName("nacos flow control thread");
t.setDaemon(true);
return t;
}
});
public SimpleFlowData(int slotCount, int interval) { public SimpleFlowData(int slotCount, int interval) {
this.slotCount = slotCount; this.slotCount = slotCount;

View File

@ -16,9 +16,12 @@
package com.alibaba.nacos.config.server.utils; 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.ScheduledExecutorService;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
@ -35,18 +38,9 @@ public class SimpleIpFlowData {
private int averageCount; private int averageCount;
@SuppressWarnings("PMD.ThreadPoolCreationRule") private ScheduledExecutorService timer = ExecutorFactory.Managed
private ScheduledExecutorService timer = Executors.newSingleThreadScheduledExecutor(new ThreadFactory() { .newSingleScheduledExecutorService(ClassUtils.getCanonicalName(Config.class),
new NameThreadFactory("com.alibaba.nacos.config.flow.control.ip"));
@Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r);
t.setName("nacos ip flow control thread");
t.setDaemon(true);
return t;
}
});
class DefaultIpFlowDataManagerTask implements Runnable { 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; 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.model.event.ConfigDataChangeEvent;
import com.alibaba.nacos.config.server.utils.PropertyUtil; 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 com.alibaba.nacos.core.utils.ApplicationUtils;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Test; import org.junit.Test;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
public class ConfigChangePublisherTest { public class ConfigChangePublisherTest {
@Test @Test
public void testConfigChangeNotify() { public void testConfigChangeNotify() throws InterruptedException {
AtomicReference<ConfigDataChangeEvent> reference = new AtomicReference<>(); AtomicReference<ConfigDataChangeEvent> reference = new AtomicReference<>();
EventDispatcher.addEventListener(new EventDispatcher.AbstractEventListener() { NotifyCenter.registerToPublisher(ConfigDataChangeEvent.class, NotifyCenter.ringBufferSize);
NotifyCenter.registerSubscriber(new Subscriber() {
@Override @Override
public List<Class<? extends EventDispatcher.Event>> interest() { public void onEvent(Event event) {
return Collections.singletonList(ConfigDataChangeEvent.class); reference.set((ConfigDataChangeEvent) event);
} }
@Override @Override
public void onEvent(EventDispatcher.Event event) { public Class<? extends Event> subscribeType() {
reference.set((ConfigDataChangeEvent) event); return ConfigDataChangeEvent.class;
} }
}); });
@ -52,33 +54,34 @@ public class ConfigChangePublisherTest {
ConfigChangePublisher ConfigChangePublisher
.notifyConfigChange(new ConfigDataChangeEvent("chuntaojun", "chuntaojun", System.currentTimeMillis())); .notifyConfigChange(new ConfigDataChangeEvent("chuntaojun", "chuntaojun", System.currentTimeMillis()));
Thread.sleep(2000);
Assert.assertNotNull(reference.get()); Assert.assertNotNull(reference.get());
reference.set(null); reference.set(null);
// nacos is standalone mode and use external storage // nacos is standalone mode and use external storage
ApplicationUtils.setIsStandalone(true); ApplicationUtils.setIsStandalone(true);
PropertyUtil.setEmbeddedStorage(false); PropertyUtil.setEmbeddedStorage(false);
ConfigChangePublisher ConfigChangePublisher
.notifyConfigChange(new ConfigDataChangeEvent("chuntaojun", "chuntaojun", System.currentTimeMillis())); .notifyConfigChange(new ConfigDataChangeEvent("chuntaojun", "chuntaojun", System.currentTimeMillis()));
Thread.sleep(2000);
Assert.assertNotNull(reference.get()); Assert.assertNotNull(reference.get());
reference.set(null); reference.set(null);
// nacos is cluster mode and use embedded storage // nacos is cluster mode and use embedded storage
ApplicationUtils.setIsStandalone(false); ApplicationUtils.setIsStandalone(false);
PropertyUtil.setEmbeddedStorage(true); PropertyUtil.setEmbeddedStorage(true);
ConfigChangePublisher ConfigChangePublisher
.notifyConfigChange(new ConfigDataChangeEvent("chuntaojun", "chuntaojun", System.currentTimeMillis())); .notifyConfigChange(new ConfigDataChangeEvent("chuntaojun", "chuntaojun", System.currentTimeMillis()));
Thread.sleep(2000);
Assert.assertNull(reference.get()); Assert.assertNull(reference.get());
reference.set(null); reference.set(null);
// nacos is cluster mode and use external storage // nacos is cluster mode and use external storage
ApplicationUtils.setIsStandalone(false); ApplicationUtils.setIsStandalone(false);
PropertyUtil.setEmbeddedStorage(false); PropertyUtil.setEmbeddedStorage(false);
ConfigChangePublisher ConfigChangePublisher
.notifyConfigChange(new ConfigDataChangeEvent("chuntaojun", "chuntaojun", System.currentTimeMillis())); .notifyConfigChange(new ConfigDataChangeEvent("chuntaojun", "chuntaojun", System.currentTimeMillis()));
Thread.sleep(2000);
Assert.assertNotNull(reference.get()); Assert.assertNotNull(reference.get());
reference.set(null); reference.set(null);
} }

View File

@ -98,6 +98,20 @@ public class ExternalDataSourcePropertiesTest {
Assert.assertEquals(dataSources.size(), 2); 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) @Test(expected = IllegalArgumentException.class)
public void externalDatasourceFailureWithLarkInfo() { 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; package com.alibaba.nacos.core.cluster;
import com.alibaba.nacos.core.notify.Event; import com.alibaba.nacos.common.notify.Event;
import com.alibaba.nacos.core.notify.listener.Subscribe; import com.alibaba.nacos.common.notify.listener.Subscriber;
/** /**
* Node change listeners. * Node change listeners.
* *
* @author <a href="mailto:liaochuntao@live.com">liaochuntao</a> * @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. * return NodeChangeEvent.class info.
@ -32,7 +33,7 @@ public interface MemberChangeListener extends Subscribe<MembersChangeEvent> {
* @return {@link MembersChangeEvent#getClass()} * @return {@link MembersChangeEvent#getClass()}
*/ */
@Override @Override
default Class<? extends Event> subscribeType() { public Class<? extends Event> subscribeType() {
return MembersChangeEvent.class; return MembersChangeEvent.class;
} }
@ -42,7 +43,7 @@ public interface MemberChangeListener extends Subscribe<MembersChangeEvent> {
* @return default value is {@link Boolean#TRUE} * @return default value is {@link Boolean#TRUE}
*/ */
@Override @Override
default boolean ignoreExpireEvent() { public boolean ignoreExpireEvent() {
return true; return true;
} }
} }

View File

@ -16,10 +16,9 @@
package com.alibaba.nacos.core.cluster; 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.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. * 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> * @author <a href="mailto:liaochuntao@live.com">liaochuntao</a>
*/ */
public class MembersChangeEvent implements Event { public class MembersChangeEvent extends Event {
private static final AtomicLong SEQUENCE = new AtomicLong(0);
private static final long serialVersionUID = 7308126651076668976L; private static final long serialVersionUID = 7308126651076668976L;
private Collection<Member> members; private Collection<Member> members;
private long no = SEQUENCE.getAndIncrement();
public static MemberChangeEventBuilder builder() { public static MemberChangeEventBuilder builder() {
return new MemberChangeEventBuilder(); return new MemberChangeEventBuilder();
} }
@ -54,14 +49,9 @@ public class MembersChangeEvent implements Event {
this.members = members; this.members = members;
} }
@Override
public long sequence() {
return no;
}
@Override @Override
public String toString() { public String toString() {
return "MembersChangeEvent{" + "members=" + members + ", no=" + no + '}'; return "MembersChangeEvent{" + "members=" + members + ", no=" + sequence() + '}';
} }
public static final class MemberChangeEventBuilder { 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.Header;
import com.alibaba.nacos.common.http.param.Query; import com.alibaba.nacos.common.http.param.Query;
import com.alibaba.nacos.common.model.RestResult; 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.ConcurrentHashSet;
import com.alibaba.nacos.common.utils.ExceptionUtil; import com.alibaba.nacos.common.utils.ExceptionUtil;
import com.alibaba.nacos.common.utils.VersionUtils; import com.alibaba.nacos.common.utils.VersionUtils;
import com.alibaba.nacos.core.cluster.lookup.LookupFactory; 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.ApplicationUtils;
import com.alibaba.nacos.core.utils.Commons; import com.alibaba.nacos.core.utils.Commons;
import com.alibaba.nacos.core.utils.Constants; 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 // The address information of this node needs to be dynamically modified
// when registering the IP change of this node // when registering the IP change of this node
NotifyCenter.registerSubscribe(new Subscribe<InetUtils.IPChangeEvent>() { NotifyCenter.registerSubscriber(new Subscriber<InetUtils.IPChangeEvent>() {
@Override @Override
public void onEvent(InetUtils.IPChangeEvent event) { public void onEvent(InetUtils.IPChangeEvent event) {
String newAddress = event.getNewIp() + ":" + port; 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.NameThreadFactory;
import com.alibaba.nacos.common.executor.ThreadPoolManager; import com.alibaba.nacos.common.executor.ThreadPoolManager;
import com.alibaba.nacos.common.http.HttpClientManager; 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.file.WatchFileCenter;
import com.alibaba.nacos.core.notify.NotifyCenter;
import com.alibaba.nacos.core.utils.ApplicationUtils; import com.alibaba.nacos.core.utils.ApplicationUtils;
import com.alibaba.nacos.core.utils.DiskUtils; import com.alibaba.nacos.core.utils.DiskUtils;
import com.alibaba.nacos.core.utils.InetUtils; import com.alibaba.nacos.core.utils.InetUtils;

View File

@ -16,6 +16,7 @@
package com.alibaba.nacos.core.distributed; package com.alibaba.nacos.core.distributed;
import com.alibaba.nacos.common.notify.NotifyCenter;
import com.alibaba.nacos.consistency.Config; import com.alibaba.nacos.consistency.Config;
import com.alibaba.nacos.consistency.ap.APProtocol; import com.alibaba.nacos.consistency.ap.APProtocol;
import com.alibaba.nacos.consistency.cp.CPProtocol; 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.MemberMetaDataConstants;
import com.alibaba.nacos.core.cluster.MemberUtils; import com.alibaba.nacos.core.cluster.MemberUtils;
import com.alibaba.nacos.core.cluster.ServerMemberManager; 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.ApplicationUtils;
import com.alibaba.nacos.core.utils.ClassUtils; import com.alibaba.nacos.core.utils.ClassUtils;
import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.DisposableBean;
@ -49,7 +49,7 @@ import java.util.Set;
@SuppressWarnings("all") @SuppressWarnings("all")
@Component(value = "ProtocolManager") @Component(value = "ProtocolManager")
@DependsOn("serverMemberManager") @DependsOn("serverMemberManager")
public class ProtocolManager implements ApplicationListener<ContextStartedEvent>, DisposableBean, MemberChangeListener { public class ProtocolManager extends MemberChangeListener implements ApplicationListener<ContextStartedEvent>, DisposableBean {
private CPProtocol cpProtocol; private CPProtocol cpProtocol;
@ -85,7 +85,7 @@ public class ProtocolManager implements ApplicationListener<ContextStartedEvent>
@PostConstruct @PostConstruct
public void init() { public void init() {
this.memberManager = memberManager; this.memberManager = memberManager;
NotifyCenter.registerSubscribe(this); NotifyCenter.registerSubscriber(this);
} }
public CPProtocol getCpProtocol() { public CPProtocol getCpProtocol() {

View File

@ -17,6 +17,9 @@
package com.alibaba.nacos.core.distributed.raft; package com.alibaba.nacos.core.distributed.raft;
import com.alibaba.nacos.common.model.RestResult; 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.MapUtils;
import com.alibaba.nacos.common.utils.ThreadUtils; import com.alibaba.nacos.common.utils.ThreadUtils;
import com.alibaba.nacos.consistency.ProtocolMetaData; 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.cluster.ServerMemberManager;
import com.alibaba.nacos.core.distributed.AbstractConsistencyProtocol; import com.alibaba.nacos.core.distributed.AbstractConsistencyProtocol;
import com.alibaba.nacos.core.distributed.raft.exception.NoSuchRaftGroupException; 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.alibaba.nacos.core.utils.Loggers;
import com.alipay.sofa.jraft.Node; 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 // There is only one consumer to ensure that the internal consumption
// is sequential and there is no concurrent competition // is sequential and there is no concurrent competition
NotifyCenter.registerSubscribe(new Subscribe<RaftEvent>() { NotifyCenter.registerSubscriber(new Subscriber<RaftEvent>() {
@Override @Override
public void onEvent(RaftEvent event) { public void onEvent(RaftEvent event) {
Loggers.RAFT.info("This Raft event changes : {}", event); Loggers.RAFT.info("This Raft event changes : {}", event);

View File

@ -16,6 +16,7 @@
package com.alibaba.nacos.core.distributed.raft; 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.ExceptionUtil;
import com.alibaba.nacos.common.utils.JacksonUtils; import com.alibaba.nacos.common.utils.JacksonUtils;
import com.alibaba.nacos.common.utils.LoggerUtils; 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.SnapshotOperation;
import com.alibaba.nacos.consistency.snapshot.Writer; import com.alibaba.nacos.consistency.snapshot.Writer;
import com.alibaba.nacos.core.distributed.raft.utils.JRaftUtils; import com.alibaba.nacos.core.distributed.raft.utils.JRaftUtils;
import com.alibaba.nacos.core.notify.NotifyCenter;
import com.alibaba.nacos.core.utils.Loggers; import com.alibaba.nacos.core.utils.Loggers;
import com.alipay.sofa.jraft.Closure; import com.alipay.sofa.jraft.Closure;
import com.alipay.sofa.jraft.Iterator; import com.alipay.sofa.jraft.Iterator;

View File

@ -16,7 +16,7 @@
package com.alibaba.nacos.core.distributed.raft; 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 * 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> * @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; private static final long serialVersionUID = 3016514657754158167L;

View File

@ -16,7 +16,7 @@
package com.alibaba.nacos.core.distributed.raft; 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.Collections;
import java.util.List; import java.util.List;
@ -27,7 +27,7 @@ import java.util.List;
* @author <a href="mailto:liaochuntao@live.com">liaochuntao</a> * @author <a href="mailto:liaochuntao@live.com">liaochuntao</a>
*/ */
@SuppressWarnings("all") @SuppressWarnings("all")
public class RaftEvent implements SlowEvent { public class RaftEvent extends SlowEvent {
private static final long serialVersionUID = -4304258594602886451L; 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; package com.alibaba.nacos.core.utils;
import com.alibaba.nacos.core.notify.NotifyCenter; import com.alibaba.nacos.common.notify.NotifyCenter;
import com.alibaba.nacos.core.notify.SlowEvent; import com.alibaba.nacos.common.notify.SlowEvent;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -229,7 +229,7 @@ public class InetUtils {
* {@link com.alibaba.nacos.core.cluster.ServerMemberManager} is listener. * {@link com.alibaba.nacos.core.cluster.ServerMemberManager} is listener.
*/ */
@SuppressWarnings({"PMD.ClassNamingShouldBeCamelRule", "checkstyle:AbbreviationAsWordInName"}) @SuppressWarnings({"PMD.ClassNamingShouldBeCamelRule", "checkstyle:AbbreviationAsWordInName"})
public static class IPChangeEvent implements SlowEvent { public static class IPChangeEvent extends SlowEvent {
private String oldIp; private String oldIp;

View File

@ -244,7 +244,7 @@
<level value="INFO"/> <level value="INFO"/>
</logger> </logger>
<logger name="com.alibaba.nacos.core.notify.NotifyCenter"> <logger name="com.alibaba.nacos.common.notify.NotifyCenter">
<appender-ref ref="CONSOLE"/> <appender-ref ref="CONSOLE"/>
<level value="INFO"/> <level value="INFO"/>
</logger> </logger>

View File

@ -665,7 +665,7 @@
<level value="INFO"/> <level value="INFO"/>
</logger> </logger>
<logger name="com.alibaba.nacos.core.notify.NotifyCenter"> <logger name="com.alibaba.nacos.common.notify.NotifyCenter">
<appender-ref ref="CONSOLE"/> <appender-ref ref="CONSOLE"/>
<level value="INFO"/> <level value="INFO"/>
</logger> </logger>

View File

@ -16,6 +16,7 @@
package com.alibaba.nacos.naming.cluster; package com.alibaba.nacos.naming.cluster;
import com.alibaba.nacos.common.notify.NotifyCenter;
import com.alibaba.nacos.common.utils.JacksonUtils; import com.alibaba.nacos.common.utils.JacksonUtils;
import com.alibaba.nacos.core.cluster.Member; import com.alibaba.nacos.core.cluster.Member;
import com.alibaba.nacos.core.cluster.MembersChangeEvent; 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.MemberMetaDataConstants;
import com.alibaba.nacos.core.cluster.NodeState; import com.alibaba.nacos.core.cluster.NodeState;
import com.alibaba.nacos.core.cluster.ServerMemberManager; 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.ApplicationUtils;
import com.alibaba.nacos.naming.consistency.persistent.raft.RaftPeer; import com.alibaba.nacos.naming.consistency.persistent.raft.RaftPeer;
import com.alibaba.nacos.naming.misc.GlobalExecutor; 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 * @deprecated 1.3.0 This object will be deleted sometime after version 1.3.0
*/ */
@Component("serverListManager") @Component("serverListManager")
public class ServerListManager implements MemberChangeListener { public class ServerListManager extends MemberChangeListener {
private static final String LOCALHOST_SITE = UtilsAndCommons.UNKNOWN_SITE; 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) { public ServerListManager(final SwitchDomain switchDomain, final ServerMemberManager memberManager) {
this.switchDomain = switchDomain; this.switchDomain = switchDomain;
this.memberManager = memberManager; this.memberManager = memberManager;
NotifyCenter.registerSubscribe(this); NotifyCenter.registerSubscriber(this);
this.servers = new ArrayList<>(memberManager.allMembers()); this.servers = new ArrayList<>(memberManager.allMembers());
} }

View File

@ -16,12 +16,12 @@
package com.alibaba.nacos.naming.consistency.persistent.raft; 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.common.utils.JacksonUtils;
import com.alibaba.nacos.core.cluster.Member; import com.alibaba.nacos.core.cluster.Member;
import com.alibaba.nacos.core.cluster.MemberChangeListener; import com.alibaba.nacos.core.cluster.MemberChangeListener;
import com.alibaba.nacos.core.cluster.MembersChangeEvent; import com.alibaba.nacos.core.cluster.MembersChangeEvent;
import com.alibaba.nacos.core.cluster.ServerMemberManager; 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.ApplicationUtils;
import com.alibaba.nacos.naming.misc.HttpClient; import com.alibaba.nacos.naming.misc.HttpClient;
import com.alibaba.nacos.naming.misc.Loggers; import com.alibaba.nacos.naming.misc.Loggers;
@ -53,7 +53,7 @@ import java.util.concurrent.atomic.AtomicLong;
*/ */
@Component @Component
@DependsOn("ProtocolManager") @DependsOn("ProtocolManager")
public class RaftPeerSet implements MemberChangeListener { public class RaftPeerSet extends MemberChangeListener {
private final ServerMemberManager memberManager; private final ServerMemberManager memberManager;
@ -75,7 +75,7 @@ public class RaftPeerSet implements MemberChangeListener {
@PostConstruct @PostConstruct
public void init() { public void init() {
NotifyCenter.registerSubscribe(this); NotifyCenter.registerSubscriber(this);
changePeers(memberManager.allMembers()); changePeers(memberManager.allMembers());
} }

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