Merge pull request #3519 from alibaba/develop

Upgrade to 1.3.2
This commit is contained in:
杨翊 SionYang 2020-08-04 19:23:08 +08:00 committed by GitHub
commit a341b65151
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
161 changed files with 3693 additions and 3234 deletions

41
.github/ISSUE_TEMPLATE/bug-report.md vendored Normal file
View File

@ -0,0 +1,41 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: ''
assignees: ''
---
<!-- Here is for bug reports and feature requests ONLY!
If you're looking for help, please check our mail list、WeChat group and the Gitter room.
Please try to use English to describe your issue, or at least provide a snippet of English translation.
我们鼓励使用英文,如果不能直接使用,可以使用翻译软件,您仍旧可以保留中文原文。
-->
**Describe the bug**
A clear and concise description of what the bug is.
**Expected behavior**
A clear and concise description of what you expected to happen.
**Acutally behavior**
A clear and concise description of what you actually to happen.
**How to Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Desktop (please complete the following information):**
- OS: [e.g. Centos]
- Version [e.g. nacos-server 1.3.1, nacos-client 1.3.1]
- Module [e.g. naming/config]
- SDK [e.g. original, spring-cloud-alibaba-nacos, dubbo]
**Additional context**
Add any other context about the problem here.

View File

@ -0,0 +1,28 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: ''
assignees: ''
---
<!-- Here is for bug reports and feature requests ONLY!
If you're looking for help, please check our mail list、WeChat group and the Gitter room.
Please try to use English to describe your issue, or at least provide a snippet of English translation.
我们鼓励使用英文,如果不能直接使用,可以使用翻译软件,您仍旧可以保留中文原文。
-->
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.

View File

@ -0,0 +1,37 @@
---
name: Old issue template
about: Describe this issue template's purpose here.
title: ''
labels: ''
assignees: ''
---
<!-- Here is for bug reports and feature requests ONLY!
If you're looking for help, please check our mail list、WeChat group and the Gitter room.
Please try to use English to describe your issue, or at least provide a snippet of English translation.
我们鼓励使用英文,如果不能直接使用,可以使用翻译软件,您仍旧可以保留中文原文。
-->
## Issue Description
Type: *bug report* or *feature request*
### Describe what happened (or what feature you want)
### Describe what you expected to happen
### How to reproduce it (as minimally and precisely as possible)
1.
2.
3.
### Tell us your environment
### Anything else we need to know?

View File

@ -19,7 +19,7 @@
<parent>
<artifactId>nacos-all</artifactId>
<groupId>com.alibaba.nacos</groupId>
<version>1.3.1</version>
<version>1.3.2</version>
</parent>
<modelVersion>4.0.0</modelVersion>

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.address.auth;
import com.alibaba.nacos.core.auth.AccessException;
import com.alibaba.nacos.core.auth.AuthManager;
import com.alibaba.nacos.core.auth.Permission;
import com.alibaba.nacos.core.auth.User;
/**
* Address server auth manager.
*
* <p>For #3091, Only implement an empty auth manager so that address server can startup.</p>
*
* @author xiweng.yy
*/
public class AddressServerAuthManager implements AuthManager {
@Override
public User login(Object request) throws AccessException {
User result = new User();
result.setUserName("nacos");
return result;
}
@Override
public void auth(Permission permission, User user) throws AccessException {
}
}

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.address.configuration;
import com.alibaba.nacos.address.auth.AddressServerAuthManager;
import com.alibaba.nacos.core.auth.AuthManager;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* Address server spring configuration.
*
* @author xiweng.yy
*/
@Configuration
public class AddressServerSpringConfiguration {
@Bean
@ConditionalOnMissingBean(value = AuthManager.class)
public AuthManager getAuthManager() {
return new AddressServerAuthManager();
}
}

View File

@ -19,7 +19,7 @@
<parent>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-all</artifactId>
<version>1.3.1</version>
<version>1.3.2</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -154,4 +154,10 @@ public class NacosException extends Exception {
public static final int OVER_THRESHOLD = 503;
public static final int RESOURCE_NOT_FOUND = -404;
/**
* http client error code,
* ome exceptions that occurred when the use the Nacos RestTemplate and Nacos AsyncRestTemplate.
*/
public static final int HTTP_CLIENT_ERROR_CODE = -500;
}

View File

@ -231,6 +231,19 @@ public class Instance {
Constants.DEFAULT_INSTANCE_ID_GENERATOR);
}
/**
* Returns {@code true} if this metadata contains the specified key.
*
* @param key metadata key
* @return {@code true} if this metadata contains the specified key
*/
public boolean containsMetadata(final String key) {
if (getMetadata() == null || getMetadata().isEmpty()) {
return false;
}
return getMetadata().containsKey(key);
}
private long getMetaDataByKeyWithDefault(final String key, final long defaultValue) {
if (getMetadata() == null || getMetadata().isEmpty()) {
return defaultValue;

View File

@ -19,7 +19,7 @@
<parent>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-all</artifactId>
<version>1.3.1</version>
<version>1.3.2</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -28,21 +28,20 @@ import com.alibaba.nacos.client.config.http.HttpAgent;
import com.alibaba.nacos.client.config.http.MetricsHttpAgent;
import com.alibaba.nacos.client.config.http.ServerHttpAgent;
import com.alibaba.nacos.client.config.impl.ClientWorker;
import com.alibaba.nacos.client.config.impl.HttpSimpleClient.HttpResult;
import com.alibaba.nacos.client.config.impl.LocalConfigInfoProcessor;
import com.alibaba.nacos.client.config.utils.ContentUtils;
import com.alibaba.nacos.client.config.utils.ParamUtils;
import com.alibaba.nacos.client.utils.LogUtils;
import com.alibaba.nacos.client.utils.ParamUtil;
import com.alibaba.nacos.client.utils.ValidatorUtils;
import com.alibaba.nacos.common.http.HttpRestResult;
import com.alibaba.nacos.common.utils.StringUtils;
import org.slf4j.Logger;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
/**
@ -179,37 +178,34 @@ public class NacosConfigService implements ConfigService {
group = null2defaultGroup(group);
ParamUtils.checkKeyParam(dataId, group);
String url = Constants.CONFIG_CONTROLLER_PATH;
List<String> params = new ArrayList<String>();
params.add("dataId");
params.add(dataId);
params.add("group");
params.add(group);
Map<String, String> params = new HashMap<String, String>(4);
params.put("dataId", dataId);
params.put("group", group);
if (StringUtils.isNotEmpty(tenant)) {
params.add("tenant");
params.add(tenant);
params.put("tenant", tenant);
}
if (StringUtils.isNotEmpty(tag)) {
params.add("tag");
params.add(tag);
params.put("tag", tag);
}
HttpResult result = null;
HttpRestResult<String> result = null;
try {
result = agent.httpDelete(url, null, params, encode, POST_TIMEOUT);
} catch (IOException ioe) {
LOGGER.warn("[remove] error, " + dataId + ", " + group + ", " + tenant + ", msg: " + ioe.toString());
} catch (Exception ex) {
LOGGER.warn("[remove] error, " + dataId + ", " + group + ", " + tenant + ", msg: " + ex.toString());
return false;
}
if (HttpURLConnection.HTTP_OK == result.code) {
if (result.ok()) {
LOGGER.info("[{}] [remove] ok, dataId={}, group={}, tenant={}", agent.getName(), dataId, group, tenant);
return true;
} else if (HttpURLConnection.HTTP_FORBIDDEN == result.code) {
} else if (HttpURLConnection.HTTP_FORBIDDEN == result.getCode()) {
LOGGER.warn("[{}] [remove] error, dataId={}, group={}, tenant={}, code={}, msg={}", agent.getName(), dataId,
group, tenant, result.code, result.content);
throw new NacosException(result.code, result.content);
group, tenant, result.getCode(), result.getMessage());
throw new NacosException(result.getCode(), result.getMessage());
} else {
LOGGER.warn("[{}] [remove] error, dataId={}, group={}, tenant={}, code={}, msg={}", agent.getName(), dataId,
group, tenant, result.code, result.content);
group, tenant, result.getCode(), result.getMessage());
return false;
}
}
@ -228,52 +224,44 @@ public class NacosConfigService implements ConfigService {
content = cr.getContent();
String url = Constants.CONFIG_CONTROLLER_PATH;
List<String> params = new ArrayList<String>();
params.add("dataId");
params.add(dataId);
params.add("group");
params.add(group);
params.add("content");
params.add(content);
Map<String, String> params = new HashMap<String, String>(6);
params.put("dataId", dataId);
params.put("group", group);
params.put("content", content);
if (StringUtils.isNotEmpty(tenant)) {
params.add("tenant");
params.add(tenant);
params.put("tenant", tenant);
}
if (StringUtils.isNotEmpty(appName)) {
params.add("appName");
params.add(appName);
params.put("appName", appName);
}
if (StringUtils.isNotEmpty(tag)) {
params.add("tag");
params.add(tag);
params.put("tag", tag);
}
List<String> headers = new ArrayList<String>();
Map<String, String> headers = new HashMap<String, String>(1);
if (StringUtils.isNotEmpty(betaIps)) {
headers.add("betaIps");
headers.add(betaIps);
headers.put("betaIps", betaIps);
}
HttpResult result = null;
HttpRestResult<String> result = null;
try {
result = agent.httpPost(url, headers, params, encode, POST_TIMEOUT);
} catch (IOException ioe) {
} catch (Exception ex) {
LOGGER.warn("[{}] [publish-single] exception, dataId={}, group={}, msg={}", agent.getName(), dataId, group,
ioe.toString());
ex.toString());
return false;
}
if (HttpURLConnection.HTTP_OK == result.code) {
if (result.ok()) {
LOGGER.info("[{}] [publish-single] ok, dataId={}, group={}, tenant={}, config={}", agent.getName(), dataId,
group, tenant, ContentUtils.truncateContent(content));
return true;
} else if (HttpURLConnection.HTTP_FORBIDDEN == result.code) {
} else if (HttpURLConnection.HTTP_FORBIDDEN == result.getCode()) {
LOGGER.warn("[{}] [publish-single] error, dataId={}, group={}, tenant={}, code={}, msg={}", agent.getName(),
dataId, group, tenant, result.code, result.content);
throw new NacosException(result.code, result.content);
dataId, group, tenant, result.getCode(), result.getMessage());
throw new NacosException(result.getCode(), result.getMessage());
} else {
LOGGER.warn("[{}] [publish-single] error, dataId={}, group={}, tenant={}, code={}, msg={}", agent.getName(),
dataId, group, tenant, result.code, result.content);
dataId, group, tenant, result.getCode(), result.getMessage());
return false;
}

View File

@ -17,11 +17,10 @@
package com.alibaba.nacos.client.config.http;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.client.config.impl.HttpSimpleClient.HttpResult;
import com.alibaba.nacos.common.http.HttpRestResult;
import com.alibaba.nacos.common.lifecycle.Closeable;
import java.io.IOException;
import java.util.List;
import java.util.Map;
/**
* HttpAgent.
@ -46,11 +45,11 @@ public interface HttpAgent extends Closeable {
* @param encoding http encode
* @param readTimeoutMs http timeout
* @return HttpResult http response
* @throws IOException If an input or output exception occurred
* @throws Exception If an input or output exception occurred
*/
HttpResult httpGet(String path, List<String> headers, List<String> paramValues, String encoding, long readTimeoutMs)
throws IOException;
HttpRestResult<String> httpGet(String path, Map<String, String> headers, Map<String, String> paramValues,
String encoding, long readTimeoutMs) throws Exception;
/**
* invoke http post method.
@ -61,10 +60,10 @@ public interface HttpAgent extends Closeable {
* @param encoding http encode
* @param readTimeoutMs http timeout
* @return HttpResult http response
* @throws IOException If an input or output exception occurred
* @throws Exception If an input or output exception occurred
*/
HttpResult httpPost(String path, List<String> headers, List<String> paramValues, String encoding,
long readTimeoutMs) throws IOException;
HttpRestResult<String> httpPost(String path, Map<String, String> headers, Map<String, String> paramValues,
String encoding, long readTimeoutMs) throws Exception;
/**
* invoke http delete method.
@ -75,10 +74,10 @@ public interface HttpAgent extends Closeable {
* @param encoding http encode
* @param readTimeoutMs http timeout
* @return HttpResult http response
* @throws IOException If an input or output exception occurred
* @throws Exception If an input or output exception occurred
*/
HttpResult httpDelete(String path, List<String> headers, List<String> paramValues, String encoding,
long readTimeoutMs) throws IOException;
HttpRestResult<String> httpDelete(String path, Map<String, String> headers, Map<String, String> paramValues,
String encoding, long readTimeoutMs) throws Exception;
/**
* get name.

View File

@ -17,12 +17,12 @@
package com.alibaba.nacos.client.config.http;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.client.config.impl.HttpSimpleClient.HttpResult;
import com.alibaba.nacos.client.monitor.MetricsMonitor;
import com.alibaba.nacos.common.http.HttpRestResult;
import io.prometheus.client.Histogram;
import java.io.IOException;
import java.util.List;
import java.util.Map;
/**
* MetricsHttpAgent.
@ -43,12 +43,12 @@ public class MetricsHttpAgent implements HttpAgent {
}
@Override
public HttpResult httpGet(String path, List<String> headers, List<String> paramValues, String encoding,
long readTimeoutMs) throws IOException {
public HttpRestResult<String> httpGet(String path, Map<String, String> headers, Map<String, String> paramValues,
String encode, long readTimeoutMs) throws Exception {
Histogram.Timer timer = MetricsMonitor.getConfigRequestMonitor("GET", path, "NA");
HttpResult result;
HttpRestResult<String> result;
try {
result = httpAgent.httpGet(path, headers, paramValues, encoding, readTimeoutMs);
result = httpAgent.httpGet(path, headers, paramValues, encode, readTimeoutMs);
} catch (IOException e) {
throw e;
} finally {
@ -60,12 +60,12 @@ public class MetricsHttpAgent implements HttpAgent {
}
@Override
public HttpResult httpPost(String path, List<String> headers, List<String> paramValues, String encoding,
long readTimeoutMs) throws IOException {
public HttpRestResult<String> httpPost(String path, Map<String, String> headers, Map<String, String> paramValues,
String encode, long readTimeoutMs) throws Exception {
Histogram.Timer timer = MetricsMonitor.getConfigRequestMonitor("POST", path, "NA");
HttpResult result;
HttpRestResult<String> result;
try {
result = httpAgent.httpPost(path, headers, paramValues, encoding, readTimeoutMs);
result = httpAgent.httpPost(path, headers, paramValues, encode, readTimeoutMs);
} catch (IOException e) {
throw e;
} finally {
@ -77,12 +77,12 @@ public class MetricsHttpAgent implements HttpAgent {
}
@Override
public HttpResult httpDelete(String path, List<String> headers, List<String> paramValues, String encoding,
long readTimeoutMs) throws IOException {
public HttpRestResult<String> httpDelete(String path, Map<String, String> headers, Map<String, String> paramValues,
String encode, long readTimeoutMs) throws Exception {
Histogram.Timer timer = MetricsMonitor.getConfigRequestMonitor("DELETE", path, "NA");
HttpResult result;
HttpRestResult<String> result;
try {
result = httpAgent.httpDelete(path, headers, paramValues, encoding, readTimeoutMs);
result = httpAgent.httpDelete(path, headers, paramValues, encode, readTimeoutMs);
} catch (IOException e) {
throw e;

View File

@ -19,8 +19,7 @@ package com.alibaba.nacos.client.config.http;
import com.alibaba.nacos.api.PropertyKeyConst;
import com.alibaba.nacos.api.common.Constants;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.client.config.impl.HttpSimpleClient;
import com.alibaba.nacos.client.config.impl.HttpSimpleClient.HttpResult;
import com.alibaba.nacos.client.config.impl.ConfigHttpClientManager;
import com.alibaba.nacos.client.config.impl.ServerListManager;
import com.alibaba.nacos.client.config.impl.SpasAdapter;
import com.alibaba.nacos.client.identify.StsConfig;
@ -28,29 +27,36 @@ import com.alibaba.nacos.client.security.SecurityProxy;
import com.alibaba.nacos.client.utils.LogUtils;
import com.alibaba.nacos.client.utils.ParamUtil;
import com.alibaba.nacos.client.utils.TemplateUtils;
import com.alibaba.nacos.common.constant.HttpHeaderConsts;
import com.alibaba.nacos.common.http.HttpClientConfig;
import com.alibaba.nacos.common.http.HttpRestResult;
import com.alibaba.nacos.common.http.client.NacosRestTemplate;
import com.alibaba.nacos.common.http.param.Header;
import com.alibaba.nacos.common.http.param.Query;
import com.alibaba.nacos.common.utils.ConvertUtils;
import com.alibaba.nacos.common.utils.IoUtils;
import com.alibaba.nacos.common.utils.ExceptionUtil;
import com.alibaba.nacos.common.utils.JacksonUtils;
import com.alibaba.nacos.common.utils.MD5Utils;
import com.alibaba.nacos.common.utils.StringUtils;
import com.alibaba.nacos.common.utils.ThreadUtils;
import com.alibaba.nacos.common.utils.UuidUtils;
import com.alibaba.nacos.common.utils.VersionUtils;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.type.TypeReference;
import org.slf4j.Logger;
import java.io.IOException;
import java.net.ConnectException;
import java.net.HttpURLConnection;
import java.net.SocketTimeoutException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.Callable;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.Callable;
/**
* Server Agent.
@ -61,6 +67,9 @@ public class ServerHttpAgent implements HttpAgent {
private static final Logger LOGGER = LogUtils.logger(ServerHttpAgent.class);
private static final NacosRestTemplate NACOS_RESTTEMPLATE = ConfigHttpClientManager.getInstance()
.getNacosRestTemplate();
private SecurityProxy securityProxy;
private String namespaceId;
@ -69,40 +78,28 @@ public class ServerHttpAgent implements HttpAgent {
private ScheduledExecutorService executorService;
/**
* Invoke http get method.
*
* @param path 相对于web应用根/开头
* @param headers headers
* @param paramValues parameters
* @param encoding encoding
* @param readTimeoutMs time out milliseconds
* @return http result
* @throws IOException io exception
*/
@Override
public HttpResult httpGet(String path, List<String> headers, List<String> paramValues, String encoding,
long readTimeoutMs) throws IOException {
public HttpRestResult<String> httpGet(String path, Map<String, String> headers, Map<String, String> paramValues,
String encode, long readTimeoutMs) throws Exception {
final long endTime = System.currentTimeMillis() + readTimeoutMs;
final boolean isSsl = false;
injectSecurityInfo(paramValues);
String currentServerAddr = serverListMgr.getCurrentServerAddr();
int maxRetry = this.maxRetry;
HttpClientConfig httpConfig = HttpClientConfig.builder()
.setReadTimeOutMillis(Long.valueOf(readTimeoutMs).intValue())
.setConTimeOutMillis(ConfigHttpClientManager.getInstance().getConnectTimeoutOrDefault(100)).build();
do {
try {
List<String> newHeaders = getSpasHeaders(paramValues);
Header newHeaders = getSpasHeaders(paramValues, encode);
if (headers != null) {
newHeaders.addAll(headers);
}
HttpResult result = HttpSimpleClient
.httpGet(getUrl(currentServerAddr, path), newHeaders, paramValues, encoding, readTimeoutMs,
isSsl);
if (result.code == HttpURLConnection.HTTP_INTERNAL_ERROR
|| result.code == HttpURLConnection.HTTP_BAD_GATEWAY
|| result.code == HttpURLConnection.HTTP_UNAVAILABLE) {
HttpRestResult<String> result = NACOS_RESTTEMPLATE
.get(getUrl(currentServerAddr, path), httpConfig, newHeaders, paramValues, String.class);
if (isFail(result)) {
LOGGER.error("[NACOS ConnectException] currentServerAddr: {}, httpCode: {}",
serverListMgr.getCurrentServerAddr(), result.code);
serverListMgr.getCurrentServerAddr(), result.getCode());
} else {
// Update the currently available server addr
serverListMgr.updateCurrentServerAddr(currentServerAddr);
@ -114,10 +111,10 @@ public class ServerHttpAgent implements HttpAgent {
} catch (SocketTimeoutException socketTimeoutException) {
LOGGER.error("[NACOS SocketTimeoutException httpGet] currentServerAddr:{} err : {}",
serverListMgr.getCurrentServerAddr(), socketTimeoutException.getMessage());
} catch (IOException ioException) {
LOGGER.error("[NACOS IOException httpGet] currentServerAddr: " + serverListMgr.getCurrentServerAddr(),
ioException);
throw ioException;
} catch (Exception ex) {
LOGGER.error("[NACOS Exception httpGet] currentServerAddr: " + serverListMgr.getCurrentServerAddr(),
ex);
throw ex;
}
if (serverListMgr.getIterator().hasNext()) {
@ -138,30 +135,29 @@ public class ServerHttpAgent implements HttpAgent {
}
@Override
public HttpResult httpPost(String path, List<String> headers, List<String> paramValues, String encoding,
long readTimeoutMs) throws IOException {
public HttpRestResult<String> httpPost(String path, Map<String, String> headers, Map<String, String> paramValues,
String encode, long readTimeoutMs) throws Exception {
final long endTime = System.currentTimeMillis() + readTimeoutMs;
boolean isSsl = false;
injectSecurityInfo(paramValues);
String currentServerAddr = serverListMgr.getCurrentServerAddr();
int maxRetry = this.maxRetry;
HttpClientConfig httpConfig = HttpClientConfig.builder()
.setReadTimeOutMillis(Long.valueOf(readTimeoutMs).intValue())
.setConTimeOutMillis(ConfigHttpClientManager.getInstance().getConnectTimeoutOrDefault(3000)).build();
do {
try {
List<String> newHeaders = getSpasHeaders(paramValues);
Header newHeaders = getSpasHeaders(paramValues, encode);
if (headers != null) {
newHeaders.addAll(headers);
}
HttpRestResult<String> result = NACOS_RESTTEMPLATE
.postForm(getUrl(currentServerAddr, path), httpConfig, newHeaders,
new HashMap<String, String>(0), paramValues, String.class);
HttpResult result = HttpSimpleClient
.httpPost(getUrl(currentServerAddr, path), newHeaders, paramValues, encoding, readTimeoutMs,
isSsl);
if (result.code == HttpURLConnection.HTTP_INTERNAL_ERROR
|| result.code == HttpURLConnection.HTTP_BAD_GATEWAY
|| result.code == HttpURLConnection.HTTP_UNAVAILABLE) {
if (isFail(result)) {
LOGGER.error("[NACOS ConnectException] currentServerAddr: {}, httpCode: {}", currentServerAddr,
result.code);
result.getCode());
} else {
// Update the currently available server addr
serverListMgr.updateCurrentServerAddr(currentServerAddr);
@ -173,9 +169,9 @@ public class ServerHttpAgent implements HttpAgent {
} catch (SocketTimeoutException socketTimeoutException) {
LOGGER.error("[NACOS SocketTimeoutException httpPost] currentServerAddr: {} err : {}",
currentServerAddr, socketTimeoutException.getMessage());
} catch (IOException ioe) {
LOGGER.error("[NACOS IOException httpPost] currentServerAddr: " + currentServerAddr, ioe);
throw ioe;
} catch (Exception ex) {
LOGGER.error("[NACOS Exception httpPost] currentServerAddr: " + currentServerAddr, ex);
throw ex;
}
if (serverListMgr.getIterator().hasNext()) {
@ -196,46 +192,42 @@ public class ServerHttpAgent implements HttpAgent {
}
@Override
public HttpResult httpDelete(String path, List<String> headers, List<String> paramValues, String encoding,
long readTimeoutMs) throws IOException {
public HttpRestResult<String> httpDelete(String path, Map<String, String> headers, Map<String, String> paramValues,
String encode, long readTimeoutMs) throws Exception {
final long endTime = System.currentTimeMillis() + readTimeoutMs;
boolean isSsl = false;
injectSecurityInfo(paramValues);
String currentServerAddr = serverListMgr.getCurrentServerAddr();
int maxRetry = this.maxRetry;
HttpClientConfig httpConfig = HttpClientConfig.builder()
.setReadTimeOutMillis(Long.valueOf(readTimeoutMs).intValue())
.setConTimeOutMillis(ConfigHttpClientManager.getInstance().getConnectTimeoutOrDefault(100)).build();
do {
try {
List<String> newHeaders = getSpasHeaders(paramValues);
Header newHeaders = getSpasHeaders(paramValues, encode);
if (headers != null) {
newHeaders.addAll(headers);
}
HttpResult result = HttpSimpleClient
.httpDelete(getUrl(currentServerAddr, path), newHeaders, paramValues, encoding, readTimeoutMs,
isSsl);
if (result.code == HttpURLConnection.HTTP_INTERNAL_ERROR
|| result.code == HttpURLConnection.HTTP_BAD_GATEWAY
|| result.code == HttpURLConnection.HTTP_UNAVAILABLE) {
HttpRestResult<String> result = NACOS_RESTTEMPLATE
.delete(getUrl(currentServerAddr, path), httpConfig, newHeaders, paramValues, String.class);
if (isFail(result)) {
LOGGER.error("[NACOS ConnectException] currentServerAddr: {}, httpCode: {}",
serverListMgr.getCurrentServerAddr(), result.code);
serverListMgr.getCurrentServerAddr(), result.getCode());
} else {
// Update the currently available server addr
serverListMgr.updateCurrentServerAddr(currentServerAddr);
return result;
}
} catch (ConnectException connectException) {
connectException.printStackTrace();
LOGGER.error("[NACOS ConnectException httpDelete] currentServerAddr:{}, err : {}",
serverListMgr.getCurrentServerAddr(), connectException.getMessage());
serverListMgr.getCurrentServerAddr(), ExceptionUtil.getStackTrace(connectException));
} catch (SocketTimeoutException stoe) {
stoe.printStackTrace();
LOGGER.error("[NACOS SocketTimeoutException httpDelete] currentServerAddr:{} err : {}",
serverListMgr.getCurrentServerAddr(), stoe.getMessage());
} catch (IOException ioe) {
serverListMgr.getCurrentServerAddr(), ExceptionUtil.getStackTrace(stoe));
} catch (Exception ex) {
LOGGER.error(
"[NACOS IOException httpDelete] currentServerAddr: " + serverListMgr.getCurrentServerAddr(),
ioe);
throw ioe;
"[NACOS Exception httpDelete] currentServerAddr: " + serverListMgr.getCurrentServerAddr(),
ex);
throw ex;
}
if (serverListMgr.getIterator().hasNext()) {
@ -261,6 +253,12 @@ public class ServerHttpAgent implements HttpAgent {
return serverAddr + contextPath + relativePath;
}
private boolean isFail(HttpRestResult<String> result) {
return result.getCode() == HttpURLConnection.HTTP_INTERNAL_ERROR
|| result.getCode() == HttpURLConnection.HTTP_BAD_GATEWAY
|| result.getCode() == HttpURLConnection.HTTP_UNAVAILABLE;
}
public static String getAppname() {
return ParamUtil.getAppName();
}
@ -276,7 +274,7 @@ public class ServerHttpAgent implements HttpAgent {
public ServerHttpAgent(Properties properties) throws NacosException {
this.serverListMgr = new ServerListManager(properties);
this.securityProxy = new SecurityProxy(properties);
this.securityProxy = new SecurityProxy(properties, NACOS_RESTTEMPLATE);
this.namespaceId = properties.getProperty(PropertyKeyConst.NAMESPACE);
init(properties);
this.securityProxy.login(this.serverListMgr.getServerUrls());
@ -301,14 +299,12 @@ public class ServerHttpAgent implements HttpAgent {
}
private void injectSecurityInfo(List<String> params) {
private void injectSecurityInfo(Map<String, String> params) {
if (StringUtils.isNotBlank(securityProxy.getAccessToken())) {
params.add(Constants.ACCESS_TOKEN);
params.add(securityProxy.getAccessToken());
params.put(Constants.ACCESS_TOKEN, securityProxy.getAccessToken());
}
if (StringUtils.isNotBlank(namespaceId) && !params.contains(SpasAdapter.TENANT_KEY)) {
params.add(SpasAdapter.TENANT_KEY);
params.add(namespaceId);
if (StringUtils.isNotBlank(namespaceId) && !params.containsKey(SpasAdapter.TENANT_KEY)) {
params.put(SpasAdapter.TENANT_KEY, namespaceId);
}
}
@ -358,29 +354,37 @@ public class ServerHttpAgent implements HttpAgent {
serverListMgr.start();
}
private List<String> getSpasHeaders(List<String> paramValues) throws IOException {
List<String> newHeaders = new ArrayList<String>();
private Header getSpasHeaders(Map<String, String> paramValues, String encode) throws Exception {
Header header = Header.newInstance();
// STS 临时凭证鉴权的优先级高于 AK/SK 鉴权
if (StsConfig.getInstance().isStsOn()) {
StsCredential stsCredential = getStsCredential();
accessKey = stsCredential.accessKeyId;
secretKey = stsCredential.accessKeySecret;
newHeaders.add("Spas-SecurityToken");
newHeaders.add(stsCredential.securityToken);
header.addParam("Spas-SecurityToken", stsCredential.securityToken);
}
if (StringUtils.isNotEmpty(accessKey) && StringUtils.isNotEmpty(secretKey)) {
newHeaders.add("Spas-AccessKey");
newHeaders.add(accessKey);
List<String> signHeaders = SpasAdapter.getSignHeaders(paramValues, secretKey);
header.addParam("Spas-AccessKey", accessKey);
Map<String, String> signHeaders = SpasAdapter.getSignHeaders(paramValues, secretKey);
if (signHeaders != null) {
newHeaders.addAll(signHeaders);
header.addAll(signHeaders);
}
}
return newHeaders;
String ts = String.valueOf(System.currentTimeMillis());
String token = MD5Utils.md5Hex(ts + ParamUtil.getAppKey(), Constants.ENCODE);
header.addParam(Constants.CLIENT_APPNAME_HEADER, ParamUtil.getAppName());
header.addParam(Constants.CLIENT_REQUEST_TS_HEADER, ts);
header.addParam(Constants.CLIENT_REQUEST_TOKEN_HEADER, token);
header.addParam(HttpHeaderConsts.CLIENT_VERSION_HEADER, VersionUtils.version);
header.addParam("exConfigInfo", "true");
header.addParam(HttpHeaderConsts.REQUEST_ID, UuidUtils.generateUuid());
header.addParam(HttpHeaderConsts.ACCEPT_CHARSET, encode);
return header;
}
private StsCredential getStsCredential() throws IOException {
private StsCredential getStsCredential() throws Exception {
boolean cacheSecurityCredentials = StsConfig.getInstance().isCacheSecurityCredentials();
if (cacheSecurityCredentials && stsCredential != null) {
long currentTime = System.currentTimeMillis();
@ -400,40 +404,29 @@ public class ServerHttpAgent implements HttpAgent {
return stsCredential;
}
private static String getStsResponse() throws IOException {
private static String getStsResponse() throws Exception {
String securityCredentials = StsConfig.getInstance().getSecurityCredentials();
if (securityCredentials != null) {
return securityCredentials;
}
String securityCredentialsUrl = StsConfig.getInstance().getSecurityCredentialsUrl();
HttpURLConnection conn = null;
int respCode;
String response;
try {
conn = (HttpURLConnection) new URL(securityCredentialsUrl).openConnection();
conn.setRequestMethod("GET");
conn.setConnectTimeout(ParamUtil.getConnectTimeout() > 100 ? ParamUtil.getConnectTimeout() : 100);
conn.setReadTimeout(1000);
conn.connect();
respCode = conn.getResponseCode();
if (HttpURLConnection.HTTP_OK == respCode) {
response = IoUtils.toString(conn.getInputStream(), Constants.ENCODE);
} else {
response = IoUtils.toString(conn.getErrorStream(), Constants.ENCODE);
HttpRestResult<String> result = NACOS_RESTTEMPLATE
.get(securityCredentialsUrl, Header.EMPTY, Query.EMPTY, String.class);
if (!result.ok()) {
LOGGER.error(
"can not get security credentials, securityCredentialsUrl: {}, responseCode: {}, response: {}",
securityCredentialsUrl, result.getCode(), result.getMessage());
throw new NacosException(NacosException.SERVER_ERROR,
"can not get security credentials, responseCode: " + result.getCode() + ", response: " + result
.getMessage());
}
} catch (IOException e) {
return result.getData();
} catch (Exception e) {
LOGGER.error("can not get security credentials", e);
throw e;
} finally {
IoUtils.closeQuietly(conn);
}
if (HttpURLConnection.HTTP_OK == respCode) {
return response;
}
LOGGER.error("can not get security credentials, securityCredentialsUrl: {}, responseCode: {}, response: {}",
securityCredentialsUrl, respCode, response);
throw new IOException(
"can not get security credentials, responseCode: " + respCode + ", response: " + response);
}
@Override
@ -461,6 +454,7 @@ public class ServerHttpAgent implements HttpAgent {
String className = this.getClass().getName();
LOGGER.info("{} do shutdown begin", className);
ThreadUtils.shutdownThreadPool(executorService, LOGGER);
ConfigHttpClientManager.getInstance().shutdown();
LOGGER.info("{} do shutdown stop", className);
}

View File

@ -24,13 +24,13 @@ import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.client.config.common.GroupKey;
import com.alibaba.nacos.client.config.filter.impl.ConfigFilterChainManager;
import com.alibaba.nacos.client.config.http.HttpAgent;
import com.alibaba.nacos.client.config.impl.HttpSimpleClient.HttpResult;
import com.alibaba.nacos.client.config.utils.ContentUtils;
import com.alibaba.nacos.client.monitor.MetricsMonitor;
import com.alibaba.nacos.client.naming.utils.CollectionUtils;
import com.alibaba.nacos.client.utils.LogUtils;
import com.alibaba.nacos.client.utils.ParamUtil;
import com.alibaba.nacos.client.utils.TenantUtil;
import com.alibaba.nacos.common.http.HttpRestResult;
import com.alibaba.nacos.common.lifecycle.Closeable;
import com.alibaba.nacos.common.utils.ConvertUtils;
import com.alibaba.nacos.common.utils.MD5Utils;
@ -43,7 +43,6 @@ import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
@ -285,29 +284,32 @@ public class ClientWorker implements Closeable {
group = Constants.DEFAULT_GROUP;
}
HttpResult result = null;
HttpRestResult<String> result = null;
try {
List<String> params = null;
Map<String, String> params = new HashMap<String, String>(3);
if (StringUtils.isBlank(tenant)) {
params = new ArrayList<String>(Arrays.asList("dataId", dataId, "group", group));
params.put("dataId", dataId);
params.put("group", group);
} else {
params = new ArrayList<String>(Arrays.asList("dataId", dataId, "group", group, "tenant", tenant));
params.put("dataId", dataId);
params.put("group", group);
params.put("tenant", tenant);
}
result = agent.httpGet(Constants.CONFIG_CONTROLLER_PATH, null, params, agent.getEncode(), readTimeout);
} catch (IOException e) {
} catch (Exception ex) {
String message = String
.format("[%s] [sub-server] get server config exception, dataId=%s, group=%s, tenant=%s",
agent.getName(), dataId, group, tenant);
LOGGER.error(message, e);
throw new NacosException(NacosException.SERVER_ERROR, e);
LOGGER.error(message, ex);
throw new NacosException(NacosException.SERVER_ERROR, ex);
}
switch (result.code) {
switch (result.getCode()) {
case HttpURLConnection.HTTP_OK:
LocalConfigInfoProcessor.saveSnapshot(agent.getName(), dataId, group, tenant, result.content);
ct[0] = result.content;
if (result.headers.containsKey(CONFIG_TYPE)) {
ct[1] = result.headers.get(CONFIG_TYPE).get(0);
LocalConfigInfoProcessor.saveSnapshot(agent.getName(), dataId, group, tenant, result.getData());
ct[0] = result.getData();
if (result.getHeader().getValue(CONFIG_TYPE) != null) {
ct[1] = result.getHeader().getValue(CONFIG_TYPE);
} else {
ct[1] = ConfigType.TEXT.getType();
}
@ -325,13 +327,13 @@ public class ClientWorker implements Closeable {
case HttpURLConnection.HTTP_FORBIDDEN: {
LOGGER.error("[{}] [sub-server-error] no right, dataId={}, group={}, tenant={}", agent.getName(),
dataId, group, tenant);
throw new NacosException(result.code, result.content);
throw new NacosException(result.getCode(), result.getMessage());
}
default: {
LOGGER.error("[{}] [sub-server-error] dataId={}, group={}, tenant={}, code={}", agent.getName(),
dataId, group, tenant, result.code);
throw new NacosException(result.code,
"http error, code=" + result.code + ",dataId=" + dataId + ",group=" + group + ",tenant="
dataId, group, tenant, result.getCode());
throw new NacosException(result.getCode(),
"http error, code=" + result.getCode() + ",dataId=" + dataId + ",group=" + group + ",tenant="
+ tenant);
}
}
@ -405,10 +407,9 @@ public class ClientWorker implements Closeable {
* @param cacheDatas CacheDatas for config infomations.
* @param inInitializingCacheList initial cache lists.
* @return String include dataId and group (ps: it maybe null).
* @throws IOException Exception.
* @throws Exception Exception.
*/
List<String> checkUpdateDataIds(List<CacheData> cacheDatas, List<String> inInitializingCacheList)
throws IOException {
List<String> checkUpdateDataIds(List<CacheData> cacheDatas, List<String> inInitializingCacheList) throws Exception {
StringBuilder sb = new StringBuilder();
for (CacheData cacheData : cacheDatas) {
if (!cacheData.isUseLocalConfigInfo()) {
@ -439,20 +440,16 @@ public class ClientWorker implements Closeable {
* @return The updated dataId list(ps: it maybe null).
* @throws IOException Exception.
*/
List<String> checkUpdateConfigStr(String probeUpdateString, boolean isInitializingCacheList) throws IOException {
List<String> checkUpdateConfigStr(String probeUpdateString, boolean isInitializingCacheList) throws Exception {
List<String> params = new ArrayList<String>(2);
params.add(Constants.PROBE_MODIFY_REQUEST);
params.add(probeUpdateString);
List<String> headers = new ArrayList<String>(2);
headers.add("Long-Pulling-Timeout");
headers.add("" + timeout);
Map<String, String> params = new HashMap<String, String>(2);
params.put(Constants.PROBE_MODIFY_REQUEST, probeUpdateString);
Map<String, String> headers = new HashMap<String, String>(2);
headers.put("Long-Pulling-Timeout", "" + timeout);
// told server do not hang me up if new initializing cacheData added in
if (isInitializingCacheList) {
headers.add("Long-Pulling-Timeout-No-Hangup");
headers.add("true");
headers.put("Long-Pulling-Timeout-No-Hangup", "true");
}
if (StringUtils.isBlank(probeUpdateString)) {
@ -464,18 +461,19 @@ public class ClientWorker implements Closeable {
// increase the client's read timeout to avoid this problem.
long readTimeoutMs = timeout + (long) Math.round(timeout >> 1);
HttpResult result = agent
HttpRestResult<String> result = agent
.httpPost(Constants.CONFIG_CONTROLLER_PATH + "/listener", headers, params, agent.getEncode(),
readTimeoutMs);
if (HttpURLConnection.HTTP_OK == result.code) {
if (result.ok()) {
setHealthServer(true);
return parseUpdateDataIdResponse(result.content);
return parseUpdateDataIdResponse(result.getData());
} else {
setHealthServer(false);
LOGGER.error("[{}] [check-update] get changed dataId error, code: {}", agent.getName(), result.code);
LOGGER.error("[{}] [check-update] get changed dataId error, code: {}", agent.getName(),
result.getCode());
}
} catch (IOException e) {
} catch (Exception e) {
setHealthServer(false);
LOGGER.error("[" + agent.getName() + "] [check-update] get changed dataId exception", e);
throw e;

View File

@ -0,0 +1,171 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.nacos.client.config.impl;
import com.alibaba.nacos.api.common.Constants;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.client.utils.LogUtils;
import com.alibaba.nacos.client.utils.ParamUtil;
import com.alibaba.nacos.common.http.AbstractHttpClientFactory;
import com.alibaba.nacos.common.http.HttpClientBeanHolder;
import com.alibaba.nacos.common.http.HttpClientConfig;
import com.alibaba.nacos.common.http.HttpClientFactory;
import com.alibaba.nacos.common.http.client.HttpClientRequestInterceptor;
import com.alibaba.nacos.common.http.client.NacosRestTemplate;
import com.alibaba.nacos.common.http.client.response.HttpClientResponse;
import com.alibaba.nacos.common.http.param.Header;
import com.alibaba.nacos.common.lifecycle.Closeable;
import com.alibaba.nacos.common.model.RequestHttpEntity;
import com.alibaba.nacos.common.utils.ExceptionUtil;
import com.alibaba.nacos.common.utils.JacksonUtils;
import com.alibaba.nacos.common.utils.MD5Utils;
import org.slf4j.Logger;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import static com.alibaba.nacos.client.utils.LogUtils.NAMING_LOGGER;
/**
* config http Manager.
*
* @author mai.jh
*/
public class ConfigHttpClientManager implements Closeable {
private static final Logger LOGGER = LogUtils.logger(ConfigHttpClientManager.class);
private static final HttpClientFactory HTTP_CLIENT_FACTORY = new ConfigHttpClientFactory();
private static final int CON_TIME_OUT_MILLIS = ParamUtil.getConnectTimeout();
private static final int READ_TIME_OUT_MILLIS = 3000;
private static final NacosRestTemplate NACOS_REST_TEMPLATE;
static {
NACOS_REST_TEMPLATE = HttpClientBeanHolder.getNacosRestTemplate(HTTP_CLIENT_FACTORY);
NACOS_REST_TEMPLATE.getInterceptors().add(new LimiterHttpClientRequestInterceptor());
}
private static class ConfigHttpClientManagerInstance {
private static final ConfigHttpClientManager INSTANCE = new ConfigHttpClientManager();
}
public static ConfigHttpClientManager getInstance() {
return ConfigHttpClientManagerInstance.INSTANCE;
}
@Override
public void shutdown() throws NacosException {
NAMING_LOGGER.warn("[ConfigHttpClientManager] Start destroying NacosRestTemplate");
try {
HttpClientBeanHolder.shutdownNacostSyncRest(HTTP_CLIENT_FACTORY.getClass().getName());
} catch (Exception ex) {
NAMING_LOGGER.error("[ConfigHttpClientManager] An exception occurred when the HTTP client was closed : {}",
ExceptionUtil.getStackTrace(ex));
}
NAMING_LOGGER.warn("[ConfigHttpClientManager] Destruction of the end");
}
/**
* get connectTimeout.
*
* @param connectTimeout connectTimeout
* @return int return max timeout
*/
public int getConnectTimeoutOrDefault(int connectTimeout) {
return Math.max(CON_TIME_OUT_MILLIS, connectTimeout);
}
/**
* get NacosRestTemplate Instance.
*
* @return NacosRestTemplate
*/
public NacosRestTemplate getNacosRestTemplate() {
return NACOS_REST_TEMPLATE;
}
/**
* ConfigHttpClientFactory.
*/
private static class ConfigHttpClientFactory extends AbstractHttpClientFactory {
@Override
protected HttpClientConfig buildHttpClientConfig() {
return HttpClientConfig.builder().setConTimeOutMillis(CON_TIME_OUT_MILLIS)
.setReadTimeOutMillis(READ_TIME_OUT_MILLIS).build();
}
@Override
protected Logger assignLogger() {
return LOGGER;
}
}
/**
* config Limiter implement.
*/
private static class LimiterHttpClientRequestInterceptor implements HttpClientRequestInterceptor {
@Override
public boolean isIntercept(URI uri, String httpMethod, RequestHttpEntity requestHttpEntity) {
final String body = requestHttpEntity.getBody() == null ? "" : JacksonUtils.toJson(requestHttpEntity.getBody());
return Limiter.isLimit(MD5Utils.md5Hex(uri + body, Constants.ENCODE));
}
@Override
public HttpClientResponse intercept() {
return new LimitResponse();
}
}
/**
* Limit Interrupt response.
*/
private static class LimitResponse implements HttpClientResponse {
@Override
public Header getHeaders() {
return Header.EMPTY;
}
@Override
public InputStream getBody() throws IOException {
return new ByteArrayInputStream("More than client-side current limit threshold".getBytes());
}
@Override
public int getStatusCode() {
return NacosException.CLIENT_OVER_THRESHOLD;
}
@Override
public String getStatusText() {
return null;
}
@Override
public void close() throws IOException {
}
}
}

View File

@ -1,128 +0,0 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.nacos.client.config.impl;
import com.alibaba.nacos.client.utils.LogUtils;
import org.slf4j.Logger;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArrayList;
/**
* Event subscription and publishing tools.
*
* @author Nacos
*/
public class EventDispatcher {
private static final Logger LOGGER = LogUtils.logger(EventDispatcher.class);
/**
* 添加事件监听器.
*/
public static void addEventListener(AbstractEventListener listener) {
for (Class<? extends AbstractEvent> type : listener.interest()) {
getListenerList(type).addIfAbsent(listener);
}
}
/**
* 发布事件首先发布该事件暗示的其他事件最后通知所有对应的监听器.
*/
public static void fireEvent(AbstractEvent abstractEvent) {
if (null == abstractEvent) {
return;
}
// 发布该事件暗示的其他事件
for (AbstractEvent implyEvent : abstractEvent.implyEvents()) {
try {
// 避免死循环
if (abstractEvent != implyEvent) {
fireEvent(implyEvent);
}
} catch (Exception e) {
LOGGER.warn(e.toString(), e);
}
}
for (AbstractEventListener listener : getListenerList(abstractEvent.getClass())) {
try {
listener.onEvent(abstractEvent);
} catch (Exception e) {
LOGGER.warn(e.toString(), e);
}
}
}
static synchronized CopyOnWriteArrayList<AbstractEventListener> getListenerList(
Class<? extends AbstractEvent> eventType) {
CopyOnWriteArrayList<AbstractEventListener> listeners = LISTENER_MAP.get(eventType);
if (null == listeners) {
listeners = new CopyOnWriteArrayList<AbstractEventListener>();
LISTENER_MAP.put(eventType, listeners);
}
return listeners;
}
@SuppressWarnings("checkstyle:linelength")
static final Map<Class<? extends AbstractEvent>, CopyOnWriteArrayList<AbstractEventListener>> LISTENER_MAP = new HashMap<Class<? extends AbstractEvent>, CopyOnWriteArrayList<AbstractEventListener>>();
/**
* Client事件.
*/
public abstract static class AbstractEvent {
@SuppressWarnings("unchecked")
protected List<AbstractEvent> implyEvents() {
return Collections.EMPTY_LIST;
}
}
/**
* 事件监听器.
*/
public abstract static class AbstractEventListener {
public AbstractEventListener() {
EventDispatcher.addEventListener(this);
}
/**
* 感兴趣的事件列表.
*
* @return event list
*/
public abstract List<Class<? extends AbstractEvent>> interest();
/**
* 处理事件.
*
* @param abstractEvent event to do
*/
public abstract void onEvent(AbstractEvent abstractEvent);
}
/**
* serverList has changed.
*/
public static class ServerlistChangeEvent extends AbstractEvent {
}
}

View File

@ -20,6 +20,7 @@ import com.alibaba.nacos.api.common.Constants;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.client.utils.ParamUtil;
import com.alibaba.nacos.common.constant.HttpHeaderConsts;
import com.alibaba.nacos.common.http.client.NacosRestTemplate;
import com.alibaba.nacos.common.utils.IoUtils;
import com.alibaba.nacos.common.utils.MD5Utils;
import com.alibaba.nacos.common.utils.UuidUtils;
@ -39,7 +40,9 @@ import java.util.Map;
* Http tool.
*
* @author Nacos
* @deprecated Use NacosRestTemplate{@link NacosRestTemplate} unified http client
*/
@Deprecated
public class HttpSimpleClient {
/**

View File

@ -19,21 +19,22 @@ package com.alibaba.nacos.client.config.impl;
import com.alibaba.nacos.api.PropertyKeyConst;
import com.alibaba.nacos.api.SystemPropertyKeyConst;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.client.config.impl.EventDispatcher.ServerlistChangeEvent;
import com.alibaba.nacos.client.config.impl.HttpSimpleClient.HttpResult;
import com.alibaba.nacos.client.utils.EnvUtil;
import com.alibaba.nacos.client.utils.LogUtils;
import com.alibaba.nacos.client.utils.ParamUtil;
import com.alibaba.nacos.client.utils.TemplateUtils;
import com.alibaba.nacos.common.http.HttpRestResult;
import com.alibaba.nacos.common.http.client.NacosRestTemplate;
import com.alibaba.nacos.common.http.param.Header;
import com.alibaba.nacos.common.http.param.Query;
import com.alibaba.nacos.common.lifecycle.Closeable;
import com.alibaba.nacos.common.notify.NotifyCenter;
import com.alibaba.nacos.common.utils.IoUtils;
import com.alibaba.nacos.common.utils.StringUtils;
import com.alibaba.nacos.common.utils.ThreadUtils;
import org.slf4j.Logger;
import java.io.IOException;
import java.io.StringReader;
import java.net.HttpURLConnection;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
@ -59,6 +60,8 @@ public class ServerListManager implements Closeable {
private static final String HTTP = "http://";
private final NacosRestTemplate nacosRestTemplate = ConfigHttpClientManager.getInstance().getNacosRestTemplate();
private final ScheduledExecutorService executorService = new ScheduledThreadPoolExecutor(1, new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
@ -335,19 +338,20 @@ public class ServerListManager implements Closeable {
iterator = iterator();
currentServerAddr = iterator.next();
EventDispatcher.fireEvent(new ServerlistChangeEvent());
// Using unified event processor, NotifyCenter
NotifyCenter.publishEvent(new ServerlistChangeEvent());
LOGGER.info("[{}] [update-serverlist] serverlist updated to {}", name, serverUrls);
}
private List<String> getApacheServerList(String url, String name) {
try {
HttpResult httpResult = HttpSimpleClient.httpGet(url, null, null, null, 3000);
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)) {
EnvUtil.setSelfEnv(httpResult.headers);
EnvUtil.setSelfEnv(httpResult.getHeader().getOriginalResponseHeader());
}
List<String> lines = IoUtils.readLines(new StringReader(httpResult.content));
List<String> lines = IoUtils.readLines(new StringReader(httpResult.getData()));
List<String> result = new ArrayList<String>(lines.size());
for (String serverAddr : lines) {
if (StringUtils.isNotBlank(serverAddr)) {
@ -363,10 +367,10 @@ public class ServerListManager implements Closeable {
return result;
} else {
LOGGER.error("[check-serverlist] error. addressServerUrl: {}, code: {}", addressServerUrl,
httpResult.code);
httpResult.getCode());
return null;
}
} catch (IOException e) {
} catch (Exception e) {
LOGGER.error("[check-serverlist] exception. url: " + url, e);
return null;
}

View File

@ -14,13 +14,14 @@
* limitations under the License.
*/
package com.alibaba.nacos.core.notify;
package com.alibaba.nacos.client.config.impl;
import com.alibaba.nacos.common.notify.SlowEvent;
/**
* this event share one event-queue.
* Server List Change Event.
*
* @author <a href="mailto:liaochuntao@live.com">liaochuntao</a>
* @author zongtanghu
*/
public interface SlowEvent extends Event {
public class ServerlistChangeEvent extends SlowEvent {
}

View File

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

View File

@ -16,7 +16,7 @@
package com.alibaba.nacos.client.identify;
import java.nio.charset.StandardCharsets;
import java.nio.charset.Charset;
/**
* Provides Base64 encoding and decoding as defined by <a href="http://www.ietf.org/rfc/rfc2045.txt">RFC 2045</a>.
@ -179,7 +179,7 @@ public class Base64 {
if (lineSeparator != null) {
if (containsAlphabetOrPad(lineSeparator)) {
String sep = null;
sep = new String(lineSeparator, StandardCharsets.UTF_8);
sep = new String(lineSeparator, Charset.forName("UTF-8"));
throw new IllegalArgumentException("lineSeparator must not contain base64 characters: [" + sep + "]");
}
if (lineLength > 0) {

View File

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

View File

@ -25,7 +25,7 @@ import com.alibaba.nacos.common.utils.ThreadUtils;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.nio.charset.StandardCharsets;
import java.nio.charset.Charset;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadFactory;
@ -39,10 +39,12 @@ import static com.alibaba.nacos.client.utils.LogUtils.NAMING_LOGGER;
*/
public class PushReceiver implements Runnable, Closeable {
private ScheduledExecutorService executorService;
private static final Charset UTF_8 = Charset.forName("UTF-8");
private static final int UDP_MSS = 64 * 1024;
private ScheduledExecutorService executorService;
private DatagramSocket udpSocket;
private HostReactor hostReactor;
@ -80,7 +82,7 @@ public class PushReceiver implements Runnable, Closeable {
udpSocket.receive(packet);
String json = new String(IoUtils.tryDecompress(packet.getData()), StandardCharsets.UTF_8).trim();
String json = new String(IoUtils.tryDecompress(packet.getData()), UTF_8).trim();
NAMING_LOGGER.info("received push data: " + json + " from " + packet.getAddress().toString());
PushPacket pushPacket = JacksonUtils.toObj(json, PushPacket.class);
@ -102,8 +104,8 @@ public class PushReceiver implements Runnable, Closeable {
+ "\", \"data\":" + "\"\"}";
}
udpSocket.send(new DatagramPacket(ack.getBytes(StandardCharsets.UTF_8),
ack.getBytes(StandardCharsets.UTF_8).length, packet.getSocketAddress()));
udpSocket.send(new DatagramPacket(ack.getBytes(UTF_8), ack.getBytes(UTF_8).length,
packet.getSocketAddress()));
} catch (Exception e) {
NAMING_LOGGER.error("[NA] error while receiving push data", e);
}

View File

@ -16,18 +16,24 @@
package com.alibaba.nacos.client.naming.net;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.common.http.AbstractHttpClientFactory;
import com.alibaba.nacos.common.http.HttpClientBeanHolder;
import com.alibaba.nacos.common.http.HttpClientConfig;
import com.alibaba.nacos.common.http.HttpClientFactory;
import com.alibaba.nacos.common.http.client.NacosRestTemplate;
import com.alibaba.nacos.common.lifecycle.Closeable;
import com.alibaba.nacos.common.utils.ExceptionUtil;
import org.slf4j.Logger;
import static com.alibaba.nacos.client.utils.LogUtils.NAMING_LOGGER;
/**
* http Manager.
*
* @author mai.jh
*/
public class NamingHttpClientManager {
public class NamingHttpClientManager implements Closeable {
private static final int READ_TIME_OUT_MILLIS = Integer
.getInteger("com.alibaba.nacos.client.naming.rtimeout", 50000);
@ -40,17 +46,38 @@ public class NamingHttpClientManager {
private static final HttpClientFactory HTTP_CLIENT_FACTORY = new NamingHttpClientFactory();
public static String getPrefix() {
private static class NamingHttpClientManagerInstance {
private static final NamingHttpClientManager INSTANCE = new NamingHttpClientManager();
}
public static NamingHttpClientManager getInstance() {
return NamingHttpClientManagerInstance.INSTANCE;
}
public String getPrefix() {
if (ENABLE_HTTPS) {
return "https://";
}
return "http://";
}
public static NacosRestTemplate getNacosRestTemplate() {
public NacosRestTemplate getNacosRestTemplate() {
return HttpClientBeanHolder.getNacosRestTemplate(HTTP_CLIENT_FACTORY);
}
@Override
public void shutdown() throws NacosException {
NAMING_LOGGER.warn("[NamingHttpClientManager] Start destroying NacosRestTemplate");
try {
HttpClientBeanHolder.shutdownNacostSyncRest(HTTP_CLIENT_FACTORY.getClass().getName());
} catch (Exception ex) {
NAMING_LOGGER.error("[NamingHttpClientManager] An exception occurred when the HTTP client was closed : {}",
ExceptionUtil.getStackTrace(ex));
}
NAMING_LOGGER.warn("[NamingHttpClientManager] Destruction of the end");
}
private static class NamingHttpClientFactory extends AbstractHttpClientFactory {
@Override
@ -58,5 +85,10 @@ public class NamingHttpClientManager {
return HttpClientConfig.builder().setConTimeOutMillis(CON_TIME_OUT_MILLIS)
.setReadTimeOutMillis(READ_TIME_OUT_MILLIS).setMaxRedirects(MAX_REDIRECTS).build();
}
@Override
protected Logger assignLogger() {
return NAMING_LOGGER;
}
}
}

View File

@ -79,7 +79,7 @@ import static com.alibaba.nacos.client.utils.LogUtils.NAMING_LOGGER;
*/
public class NamingProxy implements Closeable {
private final NacosRestTemplate nacosRestTemplate = NamingHttpClientManager.getNacosRestTemplate();
private final NacosRestTemplate nacosRestTemplate = NamingHttpClientManager.getInstance().getNacosRestTemplate();
private static final int DEFAULT_SERVER_PORT = 8848;
@ -109,7 +109,7 @@ public class NamingProxy implements Closeable {
public NamingProxy(String namespaceId, String endpoint, String serverList, Properties properties) {
this.securityProxy = new SecurityProxy(properties);
this.securityProxy = new SecurityProxy(properties, nacosRestTemplate);
this.properties = properties;
this.setServerPort(DEFAULT_SERVER_PORT);
this.namespaceId = namespaceId;
@ -591,7 +591,7 @@ public class NamingProxy implements Closeable {
if (!curServer.contains(UtilAndComs.SERVER_ADDR_IP_SPLITER)) {
curServer = curServer + UtilAndComs.SERVER_ADDR_IP_SPLITER + serverPort;
}
url = NamingHttpClientManager.getPrefix() + curServer + api;
url = NamingHttpClientManager.getInstance().getPrefix() + curServer + api;
}
try {
@ -608,7 +608,7 @@ public class NamingProxy implements Closeable {
if (HttpStatus.SC_NOT_MODIFIED == restResult.getCode()) {
return StringUtils.EMPTY;
}
throw new NacosException(restResult.getCode(), restResult.getData());
throw new NacosException(restResult.getCode(), restResult.getMessage());
} catch (Exception e) {
NAMING_LOGGER.error("[NA] failed to request", e);
throw new NacosException(NacosException.SERVER_ERROR, e);
@ -714,6 +714,7 @@ public class NamingProxy implements Closeable {
String className = this.getClass().getName();
NAMING_LOGGER.info("{} do shutdown begin", className);
ThreadUtils.shutdownThreadPool(executorService, NAMING_LOGGER);
NamingHttpClientManager.getInstance().shutdown();
NAMING_LOGGER.info("{} do shutdown stop", className);
}
}

View File

@ -21,7 +21,6 @@ import com.alibaba.nacos.client.identify.Base64;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
/**
* Sign util.
@ -31,7 +30,7 @@ import java.nio.charset.StandardCharsets;
*/
public class SignUtil {
public static final Charset UTF8 = StandardCharsets.UTF_8;
private static final Charset UTF8 = Charset.forName("UTF-8");
public SignUtil() {
}

View File

@ -18,7 +18,6 @@ package com.alibaba.nacos.client.security;
import com.alibaba.nacos.api.PropertyKeyConst;
import com.alibaba.nacos.api.common.Constants;
import com.alibaba.nacos.client.naming.net.NamingHttpClientManager;
import com.alibaba.nacos.common.http.HttpRestResult;
import com.alibaba.nacos.common.http.client.NacosRestTemplate;
import com.alibaba.nacos.common.http.param.Header;
@ -46,7 +45,7 @@ public class SecurityProxy {
private static final String LOGIN_URL = "/v1/auth/users/login";
private final NacosRestTemplate nacosRestTemplate = NamingHttpClientManager.getNacosRestTemplate();
private final NacosRestTemplate nacosRestTemplate;
private String contextPath;
@ -85,11 +84,12 @@ public class SecurityProxy {
*
* @param properties a bunch of properties to read
*/
public SecurityProxy(Properties properties) {
public SecurityProxy(Properties properties, NacosRestTemplate nacosRestTemplate) {
username = properties.getProperty(PropertyKeyConst.USERNAME, StringUtils.EMPTY);
password = properties.getProperty(PropertyKeyConst.PASSWORD, StringUtils.EMPTY);
contextPath = properties.getProperty(PropertyKeyConst.CONTEXT_PATH, "/nacos");
contextPath = contextPath.startsWith("/") ? contextPath : "/" + contextPath;
this.nacosRestTemplate = nacosRestTemplate;
}
/**

View File

@ -19,7 +19,6 @@ package com.alibaba.nacos.client.utils;
import com.alibaba.nacos.api.PropertyKeyConst;
import com.alibaba.nacos.api.SystemPropertyKeyConst;
import com.alibaba.nacos.api.common.Constants;
import com.alibaba.nacos.client.config.impl.HttpSimpleClient;
import com.alibaba.nacos.common.utils.StringUtils;
import org.slf4j.Logger;
@ -82,7 +81,7 @@ public class ParamUtil {
LOGGER.info("[settings] [http-client] connect timeout:{}", connectTimeout);
try {
InputStream in = HttpSimpleClient.class.getClassLoader().getResourceAsStream("application.properties");
InputStream in = ValidatorUtils.class.getClassLoader().getResourceAsStream("application.properties");
Properties props = new Properties();
props.load(in);
String val = null;

View File

@ -21,7 +21,7 @@
<parent>
<artifactId>nacos-all</artifactId>
<groupId>com.alibaba.nacos</groupId>
<version>1.3.1</version>
<version>1.3.2</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -24,8 +24,8 @@ import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.cmdb.core.SwitchAndOptions;
import com.alibaba.nacos.cmdb.service.CmdbReader;
import com.alibaba.nacos.cmdb.service.CmdbWriter;
import com.alibaba.nacos.cmdb.utils.CmdbExecutor;
import com.alibaba.nacos.cmdb.utils.Loggers;
import com.alibaba.nacos.cmdb.utils.UtilsAndCommons;
import com.alibaba.nacos.common.utils.JacksonUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@ -117,11 +117,9 @@ public class CmdbProvider implements CmdbReader, CmdbWriter {
initCmdbService();
load();
UtilsAndCommons.GLOBAL_EXECUTOR.schedule(new CmdbDumpTask(), switches.getDumpTaskInterval(), TimeUnit.SECONDS);
UtilsAndCommons.GLOBAL_EXECUTOR
.schedule(new CmdbLabelTask(), switches.getLabelTaskInterval(), TimeUnit.SECONDS);
UtilsAndCommons.GLOBAL_EXECUTOR
.schedule(new CmdbEventTask(), switches.getEventTaskInterval(), TimeUnit.SECONDS);
CmdbExecutor.scheduleCmdbTask(new CmdbDumpTask(), switches.getDumpTaskInterval(), TimeUnit.SECONDS);
CmdbExecutor.scheduleCmdbTask(new CmdbLabelTask(), switches.getLabelTaskInterval(), TimeUnit.SECONDS);
CmdbExecutor.scheduleCmdbTask(new CmdbEventTask(), switches.getEventTaskInterval(), TimeUnit.SECONDS);
}
@Override
@ -205,7 +203,7 @@ public class CmdbProvider implements CmdbReader, CmdbWriter {
} catch (Exception e) {
Loggers.MAIN.error("CMDB-LABEL-TASK {}", "dump failed!", e);
} finally {
UtilsAndCommons.GLOBAL_EXECUTOR.schedule(this, switches.getLabelTaskInterval(), TimeUnit.SECONDS);
CmdbExecutor.scheduleCmdbTask(this, switches.getLabelTaskInterval(), TimeUnit.SECONDS);
}
}
}
@ -227,7 +225,7 @@ public class CmdbProvider implements CmdbReader, CmdbWriter {
} catch (Exception e) {
Loggers.MAIN.error("DUMP-TASK {}", "dump failed!", e);
} finally {
UtilsAndCommons.GLOBAL_EXECUTOR.schedule(this, switches.getDumpTaskInterval(), TimeUnit.SECONDS);
CmdbExecutor.scheduleCmdbTask(this, switches.getDumpTaskInterval(), TimeUnit.SECONDS);
}
}
}
@ -271,7 +269,7 @@ public class CmdbProvider implements CmdbReader, CmdbWriter {
} catch (Exception e) {
Loggers.MAIN.error("CMDB-EVENT {}", "event task failed!", e);
} finally {
UtilsAndCommons.GLOBAL_EXECUTOR.schedule(this, switches.getEventTaskInterval(), TimeUnit.SECONDS);
CmdbExecutor.scheduleCmdbTask(this, switches.getEventTaskInterval(), TimeUnit.SECONDS);
}
}
}

View File

@ -0,0 +1,43 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.nacos.cmdb.utils;
import com.alibaba.nacos.cmdb.CmdbApp;
import com.alibaba.nacos.common.executor.ExecutorFactory;
import com.alibaba.nacos.common.executor.NameThreadFactory;
import com.alibaba.nacos.core.utils.ClassUtils;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
/**
* Cmdb executor.
*
* @author wangweizZZ
* @date 2020/7/13 1:54 PM
*/
public class CmdbExecutor {
private static final ScheduledExecutorService GLOBAL_EXECUTOR = ExecutorFactory.Managed
.newScheduledExecutorService(ClassUtils.getCanonicalName(CmdbApp.class),
Runtime.getRuntime().availableProcessors(),
new NameThreadFactory("com.alibaba.nacos.cmdb.global.executor"));
public static void scheduleCmdbTask(Runnable runnable, long delay, TimeUnit unit) {
GLOBAL_EXECUTOR.schedule(runnable, delay, unit);
}
}

View File

@ -16,10 +16,6 @@
package com.alibaba.nacos.cmdb.utils;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadFactory;
/**
* Utils and constants.
*
@ -32,19 +28,4 @@ public class UtilsAndCommons {
public static final String NACOS_CMDB_CONTEXT = NACOS_SERVER_VERSION + "/cmdb";
public static final ScheduledExecutorService GLOBAL_EXECUTOR;
static {
GLOBAL_EXECUTOR = new ScheduledThreadPoolExecutor(Runtime.getRuntime().availableProcessors(),
new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r);
t.setName("nacos.cmdb.global.executor");
t.setDaemon(true);
return t;
}
});
}
}

View File

@ -21,7 +21,7 @@
<parent>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-all</artifactId>
<version>1.3.1</version>
<version>1.3.2</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -14,24 +14,19 @@
* limitations under the License.
*/
package com.alibaba.nacos.core.notify;
import java.io.Serializable;
package com.alibaba.nacos.common.constant;
/**
* event.
* Response Handler Type.
*
* @author <a href="mailto:liaochuntao@live.com">liaochuntao</a>
* @author mai.jh
*/
public interface Event extends Serializable {
public final class ResponseHandlerType {
/**
* Event sequence number, which can be used to handle the sequence of events.
*
* @return sequence num, It's best to make sure it's monotone
*/
default long sequence() {
return System.currentTimeMillis();
}
public static final String STRING_TYPE = "java.lang.String";
public static final String RESTRESULT_TYPE = "com.alibaba.nacos.common.model.RestResult";
public static final String DEFAULT_BEAN_TYPE = "default_bean_handler";
}

View File

@ -38,10 +38,6 @@ import java.util.concurrent.TimeUnit;
"checkstyle:missingjavadocmethod"})
public final class ExecutorFactory {
private static final String DEFAULT_NAMESPACE = "nacos";
private static final ThreadPoolManager THREAD_POOL_MANAGER = ThreadPoolManager.getInstance();
public static ExecutorService newSingleExecutorService() {
return Executors.newFixedThreadPool(1);
}
@ -73,61 +69,6 @@ public final class ExecutorFactory {
new LinkedBlockingQueue<Runnable>(), threadFactory);
}
//TODO remove Deprecated function after replace all module
@Deprecated
public static ExecutorService newSingleExecutorService(final String group) {
ExecutorService executorService = Executors.newFixedThreadPool(1);
THREAD_POOL_MANAGER.register(DEFAULT_NAMESPACE, group, executorService);
return executorService;
}
@Deprecated
public static ExecutorService newSingleExecutorService(final String group, final ThreadFactory threadFactory) {
ExecutorService executorService = Executors.newFixedThreadPool(1, threadFactory);
THREAD_POOL_MANAGER.register(DEFAULT_NAMESPACE, group, executorService);
return executorService;
}
@Deprecated
public static ExecutorService newFixedExecutorService(final String group, final int nThreads) {
ExecutorService executorService = Executors.newFixedThreadPool(nThreads);
THREAD_POOL_MANAGER.register(DEFAULT_NAMESPACE, group, executorService);
return executorService;
}
@Deprecated
public static ExecutorService newFixedExecutorService(final String group, final int nThreads,
final ThreadFactory threadFactory) {
ExecutorService executorService = Executors.newFixedThreadPool(nThreads, threadFactory);
THREAD_POOL_MANAGER.register(DEFAULT_NAMESPACE, group, executorService);
return executorService;
}
@Deprecated
public static ScheduledExecutorService newSingleScheduledExecutorService(final String group,
final ThreadFactory threadFactory) {
ScheduledExecutorService executorService = Executors.newScheduledThreadPool(1, threadFactory);
THREAD_POOL_MANAGER.register(DEFAULT_NAMESPACE, group, executorService);
return executorService;
}
@Deprecated
public static ScheduledExecutorService newScheduledExecutorService(final String group, final int nThreads,
final ThreadFactory threadFactory) {
ScheduledExecutorService executorService = Executors.newScheduledThreadPool(nThreads, threadFactory);
THREAD_POOL_MANAGER.register(DEFAULT_NAMESPACE, group, executorService);
return executorService;
}
@Deprecated
public static ThreadPoolExecutor newCustomerThreadExecutor(final String group, final int coreThreads,
final int maxThreads, final long keepAliveTimeMs, final ThreadFactory threadFactory) {
ThreadPoolExecutor executor = new ThreadPoolExecutor(coreThreads, maxThreads, keepAliveTimeMs,
TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(), threadFactory);
THREAD_POOL_MANAGER.register(DEFAULT_NAMESPACE, group, executor);
return executor;
}
public static final class Managed {
private static final String DEFAULT_NAMESPACE = "nacos";

View File

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

View File

@ -16,6 +16,7 @@
package com.alibaba.nacos.common.http;
import com.alibaba.nacos.common.constant.HttpHeaderConsts;
import com.alibaba.nacos.common.http.handler.ResponseHandler;
import com.alibaba.nacos.common.http.param.Header;
import com.alibaba.nacos.common.http.param.Query;
@ -79,7 +80,7 @@ public abstract class BaseHttpClient {
@Override
public void cancelled() {
callback.onCancel();
}
});
}
@ -97,19 +98,11 @@ public abstract class BaseHttpClient {
protected HttpRequestBase build(String url, Header header, Object body, String method) throws Exception {
BaseHttpMethod httpMethod = BaseHttpMethod.sourceOf(method);
httpMethod.init(url);
httpMethod.initHeader(header);
httpMethod.initEntity(body, header.getValue("Content-Type"));
return httpMethod.getRequestBase();
}
private Header convertHeader(org.apache.http.Header[] headers) {
final Header nHeader = Header.newInstance();
for (org.apache.http.Header header : headers) {
nHeader.addParam(header.getName(), header.getValue());
}
return nHeader;
final BaseHttpMethod httpMethod = BaseHttpMethod.sourceOf(method);
final HttpRequestBase httpRequestBase = httpMethod.init(url);
HttpUtils.initRequestHeader(httpRequestBase, header);
HttpUtils.initRequestEntity(httpRequestBase, body, header.getValue(HttpHeaderConsts.CONTENT_TYPE));
return httpRequestBase;
}
public static class HttpGetWithEntity extends HttpEntityEnclosingRequestBase {

View File

@ -16,21 +16,9 @@
package com.alibaba.nacos.common.http;
import com.alibaba.nacos.common.http.handler.RequestHandler;
import com.alibaba.nacos.common.http.param.Header;
import com.alibaba.nacos.common.utils.HttpMethod;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import com.alibaba.nacos.common.utils.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpEntityEnclosingRequest;
import org.apache.http.HttpRequest;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpHead;
@ -39,9 +27,6 @@ import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.client.methods.HttpTrace;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.message.BasicNameValuePair;
/**
* Base http method.
@ -139,78 +124,18 @@ public enum BaseHttpMethod {
private String name;
private HttpRequest requestBase;
BaseHttpMethod(String name) {
this.name = name;
}
public void init(String url) {
requestBase = createRequest(url);
public HttpRequestBase init(String url) {
return createRequest(url);
}
protected HttpRequestBase createRequest(String url) {
throw new UnsupportedOperationException();
}
/**
* Init http header.
*
* @param header header
*/
public void initHeader(Header header) {
Iterator<Map.Entry<String, String>> iterator = header.iterator();
while (iterator.hasNext()) {
Map.Entry<String, String> entry = iterator.next();
requestBase.setHeader(entry.getKey(), entry.getValue());
}
}
/**
* Init http entity.
*
* @param body body
* @param mediaType mediaType {@link ContentType}
* @throws Exception exception
*/
public void initEntity(Object body, String mediaType) throws Exception {
if (body == null) {
return;
}
if (requestBase instanceof HttpEntityEnclosingRequest) {
HttpEntityEnclosingRequest request = (HttpEntityEnclosingRequest) requestBase;
ContentType contentType = ContentType.create(mediaType);
StringEntity entity = new StringEntity(RequestHandler.parse(body), contentType);
request.setEntity(entity);
}
}
/**
* Init request from entity map.
*
* @param body body map
* @param charset charset of entity
* @throws Exception exception
*/
public void initFromEntity(Map<String, String> body, String charset) throws Exception {
if (body == null || body.isEmpty()) {
return;
}
List<NameValuePair> params = new ArrayList<NameValuePair>(body.size());
for (Map.Entry<String, String> entry : body.entrySet()) {
params.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
}
if (requestBase instanceof HttpEntityEnclosingRequest) {
HttpEntityEnclosingRequest request = (HttpEntityEnclosingRequest) requestBase;
HttpEntity entity = new UrlEncodedFormEntity(params, charset);
request.setEntity(entity);
}
}
public HttpRequestBase getRequestBase() {
return (HttpRequestBase) requestBase;
}
/**
* Value of {@link BaseHttpMethod}.
*

View File

@ -39,4 +39,9 @@ public interface Callback<T> {
*/
void onError(Throwable throwable);
/**
* Callback when the request is cancelled.
*/
void onCancel();
}

View File

@ -16,6 +16,8 @@
package com.alibaba.nacos.common.http;
import org.slf4j.Logger;
/**
* default http client factory.
*
@ -25,8 +27,19 @@ public class DefaultHttpClientFactory extends AbstractHttpClientFactory {
private static final int TIMEOUT = Integer.getInteger("nacos.http.timeout", 5000);
private final Logger logger;
public DefaultHttpClientFactory(Logger logger) {
this.logger = logger;
}
@Override
protected HttpClientConfig buildHttpClientConfig() {
return HttpClientConfig.builder().setConTimeOutMillis(TIMEOUT).setReadTimeOutMillis(TIMEOUT >> 1).build();
}
@Override
protected Logger assignLogger() {
return logger;
}
}

View File

@ -18,15 +18,10 @@ package com.alibaba.nacos.common.http;
import com.alibaba.nacos.common.http.client.NacosAsyncRestTemplate;
import com.alibaba.nacos.common.http.client.NacosRestTemplate;
import com.alibaba.nacos.common.utils.ExceptionUtil;
import com.alibaba.nacos.common.utils.ThreadUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
/**
* Create a rest template to ensure that each custom client config and rest template are in one-to-one correspondence.
@ -35,25 +30,13 @@ import java.util.concurrent.atomic.AtomicBoolean;
*/
public final class HttpClientBeanHolder {
private static final Logger LOGGER = LoggerFactory.getLogger(HttpClientManager.class);
private static final Map<String, NacosRestTemplate> SINGLETON_REST = new HashMap<String, NacosRestTemplate>(10);
private static final Map<String, NacosAsyncRestTemplate> SINGLETON_ASYNC_REST = new HashMap<String, NacosAsyncRestTemplate>(10);
private static final Map<String, NacosAsyncRestTemplate> SINGLETON_ASYNC_REST = new HashMap<String, NacosAsyncRestTemplate>(
10);
private static final AtomicBoolean ALREADY_SHUTDOWN = new AtomicBoolean(false);
static {
ThreadUtils.addShutdownHook(new Runnable() {
@Override
public void run() {
shutdown();
}
});
}
public static NacosRestTemplate getNacosRestTemplate() {
return getNacosRestTemplate(new DefaultHttpClientFactory());
public static NacosRestTemplate getNacosRestTemplate(Logger logger) {
return getNacosRestTemplate(new DefaultHttpClientFactory(logger));
}
public static NacosRestTemplate getNacosRestTemplate(HttpClientFactory httpClientFactory) {
@ -75,8 +58,8 @@ public final class HttpClientBeanHolder {
return nacosRestTemplate;
}
public static NacosAsyncRestTemplate getNacosAsyncRestTemplate() {
return getNacosAsyncRestTemplate(new DefaultHttpClientFactory());
public static NacosAsyncRestTemplate getNacosAsyncRestTemplate(Logger logger) {
return getNacosAsyncRestTemplate(new DefaultHttpClientFactory(logger));
}
public static NacosAsyncRestTemplate getNacosAsyncRestTemplate(HttpClientFactory httpClientFactory) {
@ -99,40 +82,41 @@ public final class HttpClientBeanHolder {
}
/**
* Shutdown http client holder and close all template.
* Shutdown http client holder and close remove template.
*
* @param className HttpClientFactory implement class name
* @throws Exception ex
*/
public static void shutdown() {
if (!ALREADY_SHUTDOWN.compareAndSet(false, true)) {
return;
}
LOGGER.warn("[HttpClientBeanFactory] Start destroying NacosRestTemplate");
try {
nacostRestTemplateShutdown();
nacosAsyncRestTemplateShutdown();
} catch (Exception ex) {
LOGGER.error("[HttpClientBeanFactory] An exception occurred when the HTTP client was closed : {}",
ExceptionUtil.getStackTrace(ex));
}
LOGGER.warn("[HttpClientBeanFactory] Destruction of the end");
public static void shutdown(String className) throws Exception {
shutdownNacostSyncRest(className);
shutdownNacosAsyncRest(className);
}
private static void nacostRestTemplateShutdown() throws Exception {
if (!SINGLETON_REST.isEmpty()) {
Collection<NacosRestTemplate> nacosRestTemplates = SINGLETON_REST.values();
for (NacosRestTemplate nacosRestTemplate : nacosRestTemplates) {
nacosRestTemplate.close();
}
SINGLETON_REST.clear();
/**
* Shutdown sync http client holder and remove template.
*
* @param className HttpClientFactory implement class name
* @throws Exception ex
*/
public static void shutdownNacostSyncRest(String className) throws Exception {
final NacosRestTemplate nacosRestTemplate = SINGLETON_REST.get(className);
if (nacosRestTemplate != null) {
nacosRestTemplate.close();
SINGLETON_REST.remove(className);
}
}
private static void nacosAsyncRestTemplateShutdown() throws Exception {
if (!SINGLETON_ASYNC_REST.isEmpty()) {
Collection<NacosAsyncRestTemplate> nacosAsyncRestTemplates = SINGLETON_ASYNC_REST.values();
for (NacosAsyncRestTemplate nacosAsyncRestTemplate : nacosAsyncRestTemplates) {
nacosAsyncRestTemplate.close();
}
SINGLETON_ASYNC_REST.clear();
/**
* Shutdown async http client holder and remove template.
*
* @param className HttpClientFactory implement class name
* @throws Exception ex
*/
public static void shutdownNacosAsyncRest(String className) throws Exception {
final NacosAsyncRestTemplate nacosAsyncRestTemplate = SINGLETON_ASYNC_REST.get(className);
if (nacosAsyncRestTemplate != null) {
nacosAsyncRestTemplate.close();
SINGLETON_ASYNC_REST.remove(className);
}
}
}

View File

@ -33,8 +33,8 @@ public class HttpRestResult<T> extends RestResult<T> {
public HttpRestResult() {
}
public HttpRestResult(Header header, int code, T data) {
super(code, data);
public HttpRestResult(Header header, int code, T data, String message) {
super(code, message, data);
this.header = header;
}

View File

@ -16,14 +16,25 @@
package com.alibaba.nacos.common.http;
import com.alibaba.nacos.common.http.handler.RequestHandler;
import com.alibaba.nacos.common.http.param.Header;
import com.alibaba.nacos.common.http.param.Query;
import com.alibaba.nacos.common.utils.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpEntityEnclosingRequest;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.message.BasicNameValuePair;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
@ -40,6 +51,63 @@ public final class HttpUtils {
private static final Pattern CONTEXT_PATH_MATCH = Pattern.compile("(\\/)\\1+");
/**
* Init http header.
*
* @param requestBase requestBase {@link HttpRequestBase}
* @param header header
*/
public static void initRequestHeader(HttpRequestBase requestBase, Header header) {
Iterator<Map.Entry<String, String>> iterator = header.iterator();
while (iterator.hasNext()) {
Map.Entry<String, String> entry = iterator.next();
requestBase.setHeader(entry.getKey(), entry.getValue());
}
}
/**
* Init http entity.
*
* @param requestBase requestBase {@link HttpRequestBase}
* @param body body
* @param mediaType mediaType {@link ContentType}
* @throws Exception exception
*/
public static void initRequestEntity(HttpRequestBase requestBase, Object body, String mediaType) throws Exception {
if (body == null) {
return;
}
if (requestBase instanceof HttpEntityEnclosingRequest) {
HttpEntityEnclosingRequest request = (HttpEntityEnclosingRequest) requestBase;
ContentType contentType = ContentType.create(mediaType);
StringEntity entity = new StringEntity(RequestHandler.parse(body), contentType);
request.setEntity(entity);
}
}
/**
* Init request from entity map.
*
* @param requestBase requestBase {@link HttpRequestBase}
* @param body body map
* @param charset charset of entity
* @throws Exception exception
*/
public static void initRequestFromEntity(HttpRequestBase requestBase, Map<String, String> body, String charset) throws Exception {
if (body == null || body.isEmpty()) {
return;
}
List<NameValuePair> params = new ArrayList<NameValuePair>(body.size());
for (Map.Entry<String, String> entry : body.entrySet()) {
params.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
}
if (requestBase instanceof HttpEntityEnclosingRequest) {
HttpEntityEnclosingRequest request = (HttpEntityEnclosingRequest) requestBase;
HttpEntity entity = new UrlEncodedFormEntity(params, charset);
request.setEntity(entity);
}
}
/**
* Build URL.
*

View File

@ -0,0 +1,89 @@
/*
* 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.http.client.handler.BeanResponseHandler;
import com.alibaba.nacos.common.http.client.handler.ResponseHandler;
import com.alibaba.nacos.common.http.client.handler.RestResultResponseHandler;
import com.alibaba.nacos.common.http.client.handler.StringResponseHandler;
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,49 @@
/*
* 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.client.request.HttpClientRequest;
import com.alibaba.nacos.common.http.client.response.HttpClientResponse;
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

@ -0,0 +1,60 @@
/*
* 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.client.request.HttpClientRequest;
import com.alibaba.nacos.common.http.client.response.HttpClientResponse;
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

@ -18,13 +18,15 @@ package com.alibaba.nacos.common.http.client;
import com.alibaba.nacos.common.http.Callback;
import com.alibaba.nacos.common.http.HttpUtils;
import com.alibaba.nacos.common.http.client.handler.ResponseHandler;
import com.alibaba.nacos.common.http.client.request.AsyncHttpClientRequest;
import com.alibaba.nacos.common.http.client.response.HttpClientResponse;
import com.alibaba.nacos.common.http.param.Header;
import com.alibaba.nacos.common.http.param.MediaType;
import com.alibaba.nacos.common.http.param.Query;
import com.alibaba.nacos.common.model.RequestHttpEntity;
import com.alibaba.nacos.common.utils.HttpMethod;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.reflect.Type;
import java.net.URI;
@ -37,13 +39,12 @@ import java.util.Map;
* @see AsyncHttpClientRequest
* @see HttpClientResponse
*/
public class NacosAsyncRestTemplate {
public class NacosAsyncRestTemplate extends AbstractNacosRestTemplate {
private static final Logger LOGGER = LoggerFactory.getLogger(NacosAsyncRestTemplate.class);
private final AsyncHttpClientRequest clientRequest;
private AsyncHttpClientRequest clientRequest;
public NacosAsyncRestTemplate(AsyncHttpClientRequest clientRequest) {
public NacosAsyncRestTemplate(Logger logger, AsyncHttpClientRequest clientRequest) {
super(logger);
this.clientRequest = clientRequest;
}
@ -330,13 +331,15 @@ public class NacosAsyncRestTemplate {
}
private <T> void execute(String url, String httpMethod, RequestHttpEntity requestEntity, Type responseType,
@SuppressWarnings("unchecked")
private <T> void execute(String url, String httpMethod, RequestHttpEntity requestEntity, Type type,
Callback<T> callback) throws Exception {
URI uri = HttpUtils.buildUri(url, requestEntity.getQuery());
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("HTTP " + httpMethod + " " + url);
if (logger.isDebugEnabled()) {
logger.debug("HTTP method: {}, url: {}, body: {}", httpMethod, uri, requestEntity.getBody());
}
clientRequest.execute(uri, httpMethod, requestEntity, responseType, callback);
ResponseHandler<T> responseHandler = super.selectResponseHandler(type);
clientRequest.execute(uri, httpMethod, requestEntity, responseHandler, callback);
}
/**

View File

@ -16,19 +16,24 @@
package com.alibaba.nacos.common.http.client;
import com.alibaba.nacos.common.http.HttpClientConfig;
import com.alibaba.nacos.common.http.HttpRestResult;
import com.alibaba.nacos.common.http.HttpUtils;
import com.alibaba.nacos.common.http.handler.ResponseHandler;
import com.alibaba.nacos.common.http.client.handler.ResponseHandler;
import com.alibaba.nacos.common.http.client.request.HttpClientRequest;
import com.alibaba.nacos.common.http.client.response.HttpClientResponse;
import com.alibaba.nacos.common.http.param.Header;
import com.alibaba.nacos.common.http.param.MediaType;
import com.alibaba.nacos.common.http.param.Query;
import com.alibaba.nacos.common.model.RequestHttpEntity;
import com.alibaba.nacos.common.utils.CollectionUtils;
import com.alibaba.nacos.common.utils.HttpMethod;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.reflect.Type;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
@ -38,13 +43,14 @@ import java.util.Map;
* @see HttpClientRequest
* @see HttpClientResponse
*/
public class NacosRestTemplate {
public class NacosRestTemplate extends AbstractNacosRestTemplate {
private static final Logger LOGGER = LoggerFactory.getLogger(NacosRestTemplate.class);
private final HttpClientRequest requestClient;
private HttpClientRequest requestClient;
private final List<HttpClientRequestInterceptor> interceptors = new ArrayList<HttpClientRequestInterceptor>();
public NacosRestTemplate(HttpClientRequest requestClient) {
public NacosRestTemplate(Logger logger, HttpClientRequest requestClient) {
super(logger);
this.requestClient = requestClient;
}
@ -83,6 +89,28 @@ public class NacosRestTemplate {
return execute(url, HttpMethod.GET, requestHttpEntity, responseType);
}
/**
* http get URL request params are expanded using the given query {@link Query}.
*
* <p>{@code responseType} can be an HttpRestResult or HttpRestResult data {@code T} type.
*
* <p>{@code config} Specify the request config via {@link HttpClientConfig}
*
* @param url url
* @param config http config
* @param header headers
* @param paramValues paramValues
* @param responseType return type
* @return {@link HttpRestResult}
* @throws Exception ex
*/
public <T> HttpRestResult<T> get(String url, HttpClientConfig config, Header header,
Map<String, String> paramValues, Type responseType) throws Exception {
RequestHttpEntity requestHttpEntity = new RequestHttpEntity(config, header,
Query.newInstance().initParams(paramValues));
return execute(url, HttpMethod.GET, requestHttpEntity, responseType);
}
/**
* get request, may be pulling a lot of data URL request params are expanded using the given query {@link Query},
* More request parameters can be set via body.
@ -118,6 +146,27 @@ public class NacosRestTemplate {
return execute(url, HttpMethod.DELETE, new RequestHttpEntity(header, query), responseType);
}
/**
* http delete URL request params are expanded using the given query {@link Query}.
*
* <p>{@code responseType} can be an HttpRestResult or HttpRestResult data {@code T} type.
*
* <p>{@code config} Specify the request config via {@link HttpClientConfig}
*
* @param url url
* @param config http config
* @param header http header param
* @param paramValues http query param
* @param responseType return type
* @return {@link HttpRestResult}
* @throws Exception ex
*/
public <T> HttpRestResult<T> delete(String url, HttpClientConfig config, Header header,
Map<String, String> paramValues, Type responseType) throws Exception {
return execute(url, HttpMethod.DELETE,
new RequestHttpEntity(config, header, Query.newInstance().initParams(paramValues)), responseType);
}
/**
* http put Create a new resource by PUTting the given body to http request.
*
@ -208,6 +257,33 @@ public class NacosRestTemplate {
return execute(url, HttpMethod.PUT, requestHttpEntity, responseType);
}
/**
* http put from Create a new resource by PUTting the given map {@code bodyValues} to http request, http header
* contentType default 'application/x-www-form-urlencoded;charset=utf-8'.
*
* <p>URL request params are expanded using the given map {@code paramValues}.
*
* <p>{@code responseType} can be an HttpRestResult or HttpRestResult data {@code T} type.
*
* <p>{@code config} Specify the request config via {@link HttpClientConfig}
*
* @param url url
* @param config http config
* @param header http header param
* @param paramValues http query param
* @param bodyValues http body param
* @param responseType return type
* @return {@link HttpRestResult}
* @throws Exception ex
*/
public <T> HttpRestResult<T> putForm(String url, HttpClientConfig config, Header header,
Map<String, String> paramValues, Map<String, String> bodyValues, Type responseType) throws Exception {
RequestHttpEntity requestHttpEntity = new RequestHttpEntity(config,
header.setContentType(MediaType.APPLICATION_FORM_URLENCODED),
Query.newInstance().initParams(paramValues), bodyValues);
return execute(url, HttpMethod.PUT, requestHttpEntity, responseType);
}
/**
* http post Create a new resource by POSTing the given object to the http request.
*
@ -298,6 +374,33 @@ public class NacosRestTemplate {
return execute(url, HttpMethod.POST, requestHttpEntity, responseType);
}
/**
* http post from Create a new resource by PUTting the given map {@code bodyValues} to http request, http header
* contentType default 'application/x-www-form-urlencoded;charset=utf-8'.
*
* <p>URL request params are expanded using the given map {@code paramValues}.
*
* <p>{@code responseType} can be an HttpRestResult or HttpRestResult data {@code T} type.
*
* <p>{@code config} Specify the request config via {@link HttpClientConfig}
*
* @param url url
* @param config http config
* @param header http header param
* @param paramValues http query param
* @param bodyValues http body param
* @param responseType return type
* @return {@link HttpRestResult}
* @throws Exception ex
*/
public <T> HttpRestResult<T> postForm(String url, HttpClientConfig config, Header header,
Map<String, String> paramValues, Map<String, String> bodyValues, Type responseType) throws Exception {
RequestHttpEntity requestHttpEntity = new RequestHttpEntity(config,
header.setContentType(MediaType.APPLICATION_FORM_URLENCODED),
Query.newInstance().initParams(paramValues), bodyValues);
return execute(url, HttpMethod.POST, requestHttpEntity, responseType);
}
/**
* Execute the HTTP method to the given URI template, writing the given request entity to the request, and returns
* the response as {@link HttpRestResult}.
@ -319,16 +422,40 @@ public class NacosRestTemplate {
return execute(url, httpMethod, requestHttpEntity, responseType);
}
/**
* Set the request interceptors that this accessor should use.
*
* @param interceptors {@link HttpClientRequestInterceptor}
*/
public void setInterceptors(List<HttpClientRequestInterceptor> interceptors) {
if (this.interceptors != interceptors) {
this.interceptors.clear();
this.interceptors.addAll(interceptors);
}
}
/**
* Return the request interceptors that this accessor uses.
*
* <p>The returned {@link List} is active and may get appended to.
*/
public List<HttpClientRequestInterceptor> getInterceptors() {
return interceptors;
}
@SuppressWarnings("unchecked")
private <T> HttpRestResult<T> execute(String url, String httpMethod, RequestHttpEntity requestEntity,
Type responseType) throws Exception {
URI uri = HttpUtils.buildUri(url, requestEntity.getQuery());
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("HTTP " + httpMethod + " " + url);
if (logger.isDebugEnabled()) {
logger.debug("HTTP method: {}, url: {}, body: {}", httpMethod, uri, requestEntity.getBody());
}
ResponseHandler<T> responseHandler = super.selectResponseHandler(responseType);
HttpClientResponse response = null;
try {
response = requestClient.execute(uri, httpMethod, requestEntity);
return ResponseHandler.responseEntityExtractor(response, responseType);
response = this.requestClient().execute(uri, httpMethod, requestEntity);
return responseHandler.handle(response);
} finally {
if (response != null) {
response.close();
@ -336,6 +463,16 @@ public class NacosRestTemplate {
}
}
private HttpClientRequest requestClient() {
if (CollectionUtils.isNotEmpty(interceptors)) {
if (logger.isDebugEnabled()) {
logger.debug("Execute via interceptors :{}", interceptors);
}
return new InterceptingHttpClientRequest(requestClient, interceptors.iterator());
}
return requestClient;
}
/**
* close request client.
*/

View File

@ -0,0 +1,65 @@
/*
* 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.handler;
import com.alibaba.nacos.common.http.HttpRestResult;
import com.alibaba.nacos.common.http.client.response.HttpClientResponse;
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

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

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

@ -14,13 +14,13 @@
* limitations under the License.
*/
package com.alibaba.nacos.common.http.client;
package com.alibaba.nacos.common.http.client.request;
import com.alibaba.nacos.common.http.Callback;
import com.alibaba.nacos.common.http.client.handler.ResponseHandler;
import com.alibaba.nacos.common.model.RequestHttpEntity;
import java.io.Closeable;
import java.lang.reflect.Type;
import java.net.URI;
/**
@ -37,10 +37,10 @@ public interface AsyncHttpClientRequest extends Closeable {
* @param uri http url
* @param httpMethod http request method
* @param requestHttpEntity http request entity
* @param responseType http response type
* @param responseHandler http response handler
* @param callback http response callback
* @throws Exception ex
*/
<T> void execute(URI uri, String httpMethod, RequestHttpEntity requestHttpEntity, final Type responseType,
final Callback<T> callback) throws Exception;
<T> void execute(URI uri, String httpMethod, RequestHttpEntity requestHttpEntity,
final ResponseHandler<T> responseHandler, final Callback<T> callback) throws Exception;
}

View File

@ -14,11 +14,12 @@
* limitations under the License.
*/
package com.alibaba.nacos.common.http.client;
package com.alibaba.nacos.common.http.client.request;
import com.alibaba.nacos.common.http.Callback;
import com.alibaba.nacos.common.http.HttpRestResult;
import com.alibaba.nacos.common.http.handler.ResponseHandler;
import com.alibaba.nacos.common.http.client.handler.ResponseHandler;
import com.alibaba.nacos.common.http.client.response.DefaultClientHttpResponse;
import com.alibaba.nacos.common.model.RequestHttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpRequestBase;
@ -26,7 +27,6 @@ import org.apache.http.concurrent.FutureCallback;
import org.apache.http.impl.nio.client.CloseableHttpAsyncClient;
import java.io.IOException;
import java.lang.reflect.Type;
import java.net.URI;
/**
@ -46,7 +46,7 @@ public class DefaultAsyncHttpClientRequest implements AsyncHttpClientRequest {
}
@Override
public <T> void execute(URI uri, String httpMethod, RequestHttpEntity requestHttpEntity, final Type responseType,
public <T> void execute(URI uri, String httpMethod, RequestHttpEntity requestHttpEntity, final ResponseHandler<T> responseHandler,
final Callback<T> callback) throws Exception {
HttpRequestBase httpRequestBase = DefaultHttpClientRequest.build(uri, httpMethod, requestHttpEntity);
asyncClient.execute(httpRequestBase, new FutureCallback<HttpResponse>() {
@ -54,7 +54,7 @@ public class DefaultAsyncHttpClientRequest implements AsyncHttpClientRequest {
public void completed(HttpResponse result) {
DefaultClientHttpResponse response = new DefaultClientHttpResponse(result);
try {
HttpRestResult<T> httpRestResult = ResponseHandler.responseEntityExtractor(response, responseType);
HttpRestResult<T> httpRestResult = responseHandler.handle(response);
callback.onReceive(httpRestResult);
} catch (Exception e) {
callback.onError(e);
@ -68,7 +68,7 @@ public class DefaultAsyncHttpClientRequest implements AsyncHttpClientRequest {
@Override
public void cancelled() {
callback.onCancel();
}
});

View File

@ -14,18 +14,21 @@
* limitations under the License.
*/
package com.alibaba.nacos.common.http.client;
package com.alibaba.nacos.common.http.client.request;
import com.alibaba.nacos.common.constant.HttpHeaderConsts;
import com.alibaba.nacos.common.http.BaseHttpMethod;
import com.alibaba.nacos.common.http.HttpClientConfig;
import com.alibaba.nacos.common.http.HttpUtils;
import com.alibaba.nacos.common.http.client.response.DefaultClientHttpResponse;
import com.alibaba.nacos.common.http.client.response.HttpClientResponse;
import com.alibaba.nacos.common.http.param.Header;
import com.alibaba.nacos.common.http.param.MediaType;
import com.alibaba.nacos.common.model.RequestHttpEntity;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.impl.client.CloseableHttpClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.net.URI;
@ -39,8 +42,6 @@ import java.util.Map;
@SuppressWarnings({"unchecked", "resource"})
public class DefaultHttpClientRequest implements HttpClientRequest {
private static final Logger LOGGER = LoggerFactory.getLogger(DefaultHttpClientRequest.class);
private final CloseableHttpClient client;
public DefaultHttpClientRequest(CloseableHttpClient client) {
@ -52,24 +53,37 @@ public class DefaultHttpClientRequest implements HttpClientRequest {
throws Exception {
HttpRequestBase request = build(uri, httpMethod, requestHttpEntity);
CloseableHttpResponse response = client.execute(request);
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Request from server: " + request.getURI().toString());
}
return new DefaultClientHttpResponse(response);
}
static HttpRequestBase build(URI uri, String method, RequestHttpEntity requestHttpEntity) throws Exception {
Header headers = requestHttpEntity.getHeaders();
BaseHttpMethod httpMethod = BaseHttpMethod.sourceOf(method);
httpMethod.init(uri.toString());
httpMethod.initHeader(headers);
final Header headers = requestHttpEntity.getHeaders();
final BaseHttpMethod httpMethod = BaseHttpMethod.sourceOf(method);
final HttpRequestBase httpRequestBase = httpMethod.init(uri.toString());
HttpUtils.initRequestHeader(httpRequestBase, headers);
if (MediaType.APPLICATION_FORM_URLENCODED.equals(headers.getValue(HttpHeaderConsts.CONTENT_TYPE))
&& requestHttpEntity.getBody() instanceof Map) {
httpMethod.initFromEntity((Map<String, String>) requestHttpEntity.getBody(), headers.getCharset());
HttpUtils.initRequestFromEntity(httpRequestBase, (Map<String, String>) requestHttpEntity.getBody(), headers.getCharset());
} else {
httpMethod.initEntity(requestHttpEntity.getBody(), headers.getValue(HttpHeaderConsts.CONTENT_TYPE));
HttpUtils.initRequestEntity(httpRequestBase, requestHttpEntity.getBody(), headers.getValue(HttpHeaderConsts.CONTENT_TYPE));
}
return httpMethod.getRequestBase();
replaceDefaultConfig(httpRequestBase, requestHttpEntity.getHttpClientConfig());
return httpRequestBase;
}
/**
* Replace the HTTP config created by default with the HTTP config specified in the request.
*
* @param requestBase requestBase
* @param httpClientConfig http config
*/
private static void replaceDefaultConfig(HttpRequestBase requestBase, HttpClientConfig httpClientConfig) {
if (httpClientConfig == null) {
return;
}
requestBase.setConfig(RequestConfig.custom()
.setConnectTimeout(httpClientConfig.getConTimeOutMillis())
.setSocketTimeout(httpClientConfig.getReadTimeOutMillis()).build());
}
@Override

View File

@ -14,8 +14,9 @@
* limitations under the License.
*/
package com.alibaba.nacos.common.http.client;
package com.alibaba.nacos.common.http.client.request;
import com.alibaba.nacos.common.http.client.response.HttpClientResponse;
import com.alibaba.nacos.common.model.RequestHttpEntity;
import java.io.Closeable;

View File

@ -0,0 +1,102 @@
/*
* 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.request;
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.client.response.HttpClientResponse;
import com.alibaba.nacos.common.http.client.response.JdkHttpClientResponse;
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

@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.alibaba.nacos.common.http.client;
package com.alibaba.nacos.common.http.client.response;
import com.alibaba.nacos.common.http.param.Header;
import org.apache.http.HttpResponse;

View File

@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.alibaba.nacos.common.http.client;
package com.alibaba.nacos.common.http.client.response;
import com.alibaba.nacos.common.http.param.Header;
@ -48,15 +48,17 @@ public interface HttpClientResponse extends Closeable {
* Return the HTTP status code.
*
* @return the HTTP status as an integer
* @throws IOException IOException
*/
int getStatusCode();
int getStatusCode() throws IOException;
/**
* Return the HTTP status text of the response.
*
* @return the HTTP status text
* @throws IOException IOException
*/
String getStatusText();
String getStatusText() throws IOException;
/**
* close response InputStream.

View File

@ -0,0 +1,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.response;
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

@ -16,18 +16,7 @@
package com.alibaba.nacos.common.http.handler;
import com.alibaba.nacos.api.exception.runtime.NacosDeserializationException;
import com.alibaba.nacos.common.constant.HttpHeaderConsts;
import com.alibaba.nacos.common.http.HttpRestResult;
import com.alibaba.nacos.common.http.client.HttpClientResponse;
import com.alibaba.nacos.common.http.param.Header;
import com.alibaba.nacos.common.http.param.MediaType;
import com.alibaba.nacos.common.model.RestResult;
import com.alibaba.nacos.common.utils.IoUtils;
import com.alibaba.nacos.common.utils.JacksonUtils;
import org.apache.http.HttpStatus;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.InputStream;
import java.lang.reflect.Type;
@ -39,8 +28,6 @@ import java.lang.reflect.Type;
*/
public final class ResponseHandler {
private static final Logger LOGGER = LoggerFactory.getLogger(ResponseHandler.class);
public static <T> T convert(String s, Class<T> cls) throws Exception {
return JacksonUtils.toObj(s, cls);
}
@ -52,55 +39,4 @@ public final class ResponseHandler {
public static <T> T convert(InputStream inputStream, Type type) throws Exception {
return JacksonUtils.toObj(inputStream, type);
}
private static <T> HttpRestResult<T> convert(RestResult<T> restResult) {
HttpRestResult<T> httpRestResult = new HttpRestResult<T>();
httpRestResult.setCode(restResult.getCode());
httpRestResult.setData(restResult.getData());
httpRestResult.setMessage(restResult.getMessage());
return httpRestResult;
}
/**
* Extract response entity to {@link HttpRestResult}.
*
* @param response response
* @param type type
* @param <T> general type
* @return {@link HttpRestResult}
* @throws Exception exception
*/
@SuppressWarnings({"unchecked", "rawtypes", "resource"})
public static <T> HttpRestResult<T> responseEntityExtractor(HttpClientResponse response, Type type)
throws Exception {
Header headers = response.getHeaders();
String contentType = headers.getValue(HttpHeaderConsts.CONTENT_TYPE);
InputStream body = response.getBody();
T extractBody = null;
final boolean typeToStr = String.class.toString().equals(type.toString());
if (contentType != null && contentType.startsWith(MediaType.APPLICATION_JSON) && HttpStatus.SC_OK == response
.getStatusCode()) {
// When the type is string type and the response contentType is [application/json],
// then it should be serialized as string
if (typeToStr) {
extractBody = (T) IoUtils.toString(body, headers.getCharset());
} else {
extractBody = convert(body, type);
}
}
if (extractBody == null) {
if (!typeToStr) {
LOGGER.error(
"if the response contentType is not [application/json]," + " only support to java.lang.String");
throw new NacosDeserializationException(type);
}
extractBody = (T) IoUtils.toString(body, headers.getCharset());
}
if (extractBody instanceof RestResult) {
HttpRestResult<T> httpRestResult = convert((RestResult<T>) extractBody);
httpRestResult.setHeader(headers);
return httpRestResult;
}
return new HttpRestResult<T>(response.getHeaders(), response.getStatusCode(), extractBody);
}
}

View File

@ -37,8 +37,11 @@ public class Header {
private final Map<String, String> header;
private final Map<String, List<String>> originalResponseHeader;
private Header() {
header = new LinkedHashMap<String, String>();
originalResponseHeader = new LinkedHashMap<String, List<String>>();
addParam(HttpHeaderConsts.CONTENT_TYPE, MediaType.APPLICATION_JSON);
addParam(HttpHeaderConsts.ACCEPT_CHARSET, "UTF-8");
addParam(HttpHeaderConsts.ACCEPT_ENCODING, "gzip");
@ -120,6 +123,31 @@ public class Header {
}
}
/**
* set original format response header.
*
* <p>Currently only corresponds to the response header of JDK.
*
* @param headers original response header
*/
public void setOriginalResponseHeader(Map<String, List<String>> headers) {
this.originalResponseHeader.putAll(headers);
for (Map.Entry<String, List<String>> entry : this.originalResponseHeader.entrySet()) {
addParam(entry.getKey(), entry.getValue().get(0));
}
}
/**
* get original format response header.
*
* <p>Currently only corresponds to the response header of JDK.
*
* @return Map original response header
*/
public Map<String, List<String>> getOriginalResponseHeader() {
return this.originalResponseHeader;
}
public String getCharset() {
String acceptCharset = getValue(HttpHeaderConsts.ACCEPT_CHARSET);
if (acceptCharset == null) {
@ -145,6 +173,7 @@ public class Header {
public void clear() {
header.clear();
originalResponseHeader.clear();
}
@Override

View File

@ -44,6 +44,6 @@ public final class MediaType {
public static final String TEXT_HTML = "text/html";
public static final String TEXT_PLAIN = "text/xml";
public static final String TEXT_PLAIN = "text/plain";
}

View File

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

View File

@ -16,7 +16,6 @@
package com.alibaba.nacos.common.notify;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.exception.runtime.NacosRuntimeException;
import com.alibaba.nacos.common.JustForTest;
import com.alibaba.nacos.common.notify.listener.Subscriber;
@ -291,7 +290,9 @@ public class NotifyCenter {
EventPublisher publisher = INSTANCE.publisherMap.get(topic);
return publisher.publish(event);
}
throw new NoSuchElementException("There are no [" + topic + "] publishers for this event, please register");
LOGGER.warn("There are no [{}] publishers for this event, please register", topic);
return false;
}
/**
@ -310,8 +311,7 @@ public class NotifyCenter {
* @param eventType class Instances type of the event type.
* @param queueMaxSize the publisher's queue max size.
*/
public static EventPublisher registerToPublisher(final Class<? extends Event> eventType, final int queueMaxSize)
throws NacosException {
public static EventPublisher registerToPublisher(final Class<? extends Event> eventType, final int queueMaxSize) {
if (ClassUtils.isAssignableFrom(SlowEvent.class, eventType)) {
return INSTANCE.sharePublisher;
}

View File

@ -22,6 +22,7 @@ import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.jsontype.NamedType;
@ -264,4 +265,14 @@ public final class JacksonUtils {
public static JsonNode transferToJsonNode(Object obj) {
return mapper.valueToTree(obj);
}
/**
* construct java type -> Jackson Java Type.
*
* @param type java type
* @return JavaType {@link JavaType}
*/
public static JavaType constructJavaType(Type type) {
return mapper.constructType(type);
}
}

View File

@ -35,6 +35,7 @@ import java.util.concurrent.atomic.AtomicLong;
public class NotifyCenterTest {
private static class TestSlowEvent extends SlowEvent {
}
private static class TestEvent extends Event {
@ -330,9 +331,11 @@ public class NotifyCenterTest {
}
private static class TestSlowEvent1 extends SlowEvent {
}
private static class TestSlowEvent2 extends SlowEvent {
}
@Test
@ -343,10 +346,10 @@ public class NotifyCenterTest {
final AtomicInteger count1 = new AtomicInteger(0);
final AtomicInteger count2 = new AtomicInteger(0);
final CountDownLatch latch1 = new CountDownLatch(3);
final CountDownLatch latch2 = new CountDownLatch(3);
NotifyCenter.registerSubscriber(new Subscriber<TestSlowEvent1>() {
@Override
public void onEvent(TestSlowEvent1 event) {
@ -365,7 +368,7 @@ public class NotifyCenterTest {
public void onEvent(TestSlowEvent2 event) {
count2.incrementAndGet();
latch2.countDown();
}
@Override
@ -373,26 +376,28 @@ public class NotifyCenterTest {
return TestSlowEvent2.class;
}
});
for (int i = 0; i < 3; i++) {
Assert.assertTrue(NotifyCenter.publishEvent(new TestSlowEvent1()));
Assert.assertTrue(NotifyCenter.publishEvent(new TestSlowEvent2()));
}
ThreadUtils.sleep(2000L);
latch1.await(3000L, TimeUnit.MILLISECONDS);
latch2.await(3000L, TimeUnit.MILLISECONDS);
Assert.assertEquals(3, count1.get());
Assert.assertEquals(3, count2.get());
}
private static class TestSlowEvent3 extends SlowEvent {
}
private static class TestSlowEvent4 extends SlowEvent {
}
@Test
@ -408,7 +413,7 @@ public class NotifyCenterTest {
final CountDownLatch latch2 = new CountDownLatch(3);
NotifyCenter.registerSubscriber(new SmartSubscriber() {
@Override
public void onEvent(Event event) {
if (event instanceof TestSlowEvent3) {
@ -421,7 +426,7 @@ public class NotifyCenterTest {
latch2.countDown();
}
}
@Override
public List<Class<? extends Event>> subscribeTypes() {
List<Class<? extends Event>> subTypes = new ArrayList<Class<? extends Event>>();
@ -447,9 +452,11 @@ public class NotifyCenterTest {
}
private static class TestSlowEvent5 extends SlowEvent {
}
private static class TestEvent6 extends Event {
}
@Test
@ -502,4 +509,16 @@ public class NotifyCenterTest {
Assert.assertEquals(3, count2.get());
}
private static class TestEvent7 extends Event {
}
@Test
public void testPublishEventByNoSubscriber() {
for (int i = 0; i < 3; i++) {
Assert.assertFalse(NotifyCenter.publishEvent(new TestEvent7()));
}
}
}

View File

@ -20,7 +20,7 @@
<parent>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-all</artifactId>
<version>1.3.1</version>
<version>1.3.2</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -19,6 +19,7 @@ package com.alibaba.nacos.config.server.controller;
import com.alibaba.nacos.common.model.RestResult;
import com.alibaba.nacos.common.model.RestResultUtils;
import com.alibaba.nacos.common.utils.Objects;
import com.alibaba.nacos.common.notify.NotifyCenter;
import com.alibaba.nacos.config.server.constant.Constants;
import com.alibaba.nacos.config.server.model.event.DerbyImportEvent;
import com.alibaba.nacos.config.server.service.datasource.DynamicDataSource;
@ -30,7 +31,6 @@ import com.alibaba.nacos.config.server.utils.LogUtil;
import com.alibaba.nacos.config.server.utils.PropertyUtil;
import com.alibaba.nacos.core.auth.ActionTypes;
import com.alibaba.nacos.core.auth.Secured;
import com.alibaba.nacos.core.notify.NotifyCenter;
import com.alibaba.nacos.core.utils.ApplicationUtils;
import com.alibaba.nacos.core.utils.WebUtils;
import org.apache.commons.lang3.StringUtils;

View File

@ -16,7 +16,9 @@
package com.alibaba.nacos.config.server.controller;
import com.alibaba.nacos.common.constant.HttpHeaderConsts;
import com.alibaba.nacos.config.server.constant.Constants;
import com.alibaba.nacos.config.server.enums.FileTypeEnum;
import com.alibaba.nacos.config.server.model.CacheItem;
import com.alibaba.nacos.config.server.model.ConfigInfoBase;
import com.alibaba.nacos.config.server.service.ConfigCacheService;
@ -136,8 +138,18 @@ public class ConfigServletInner {
isBeta = true;
}
}
String configType = cacheItem.getType();
response.setHeader("Config-Type", (null != configType) ? configType : "text");
final String configType =
(null != cacheItem.getType()) ? cacheItem.getType() : FileTypeEnum.TEXT.getFileType();
response.setHeader("Config-Type", configType);
String contentTypeHeader;
try {
contentTypeHeader = FileTypeEnum.valueOf(configType.toUpperCase()).getContentType();
} catch (IllegalArgumentException ex) {
contentTypeHeader = FileTypeEnum.TEXT.getContentType();
}
response.setHeader(HttpHeaderConsts.CONTENT_TYPE, contentTypeHeader);
}
File file = null;
ConfigInfoBase configInfoBase = null;

View File

@ -16,6 +16,8 @@
package com.alibaba.nacos.config.server.enums;
import com.alibaba.nacos.common.http.param.MediaType;
/**
* Config file type enum.
*
@ -27,58 +29,73 @@ public enum FileTypeEnum {
/**
* Yaml file.
*/
YML("yaml"),
YML("yaml", MediaType.TEXT_PLAIN),
/**
* Yaml file.
*/
YAML("yaml"),
YAML("yaml", MediaType.TEXT_PLAIN),
/**
* Text file.
*/
TXT("text"),
TXT("text", MediaType.TEXT_PLAIN),
/**
* Text file.
*/
TEXT("text"),
TEXT("text", MediaType.TEXT_PLAIN),
/**
* Json file.
*/
JSON("json"),
JSON("json", MediaType.APPLICATION_JSON),
/**
* Xml file.
*/
XML("xml"),
XML("xml", MediaType.APPLICATION_XML),
/**
* Html file.
*/
HTM("html"),
HTM("html", MediaType.TEXT_HTML),
/**
* Html file.
*/
HTML("html"),
HTML("html", MediaType.TEXT_HTML),
/**
* Properties file.
*/
PROPERTIES("properties");
PROPERTIES("properties", MediaType.TEXT_PLAIN);
/**
* File type corresponding to file extension.
*/
private String fileType;
/**
* Http Content type corresponding to file extension.
*/
private String contentType;
FileTypeEnum(String fileType) {
this.fileType = fileType;
this.contentType = MediaType.TEXT_PLAIN;
}
FileTypeEnum(String fileType, String contentType) {
this.fileType = fileType;
this.contentType = contentType;
}
public String getFileType() {
return this.fileType;
}
public String getContentType() {
return contentType;
}
}

View File

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

View File

@ -16,7 +16,7 @@
package com.alibaba.nacos.config.server.model.event;
import com.alibaba.nacos.config.server.utils.event.EventDispatcher.Event;
import com.alibaba.nacos.common.notify.Event;
import org.apache.commons.lang3.StringUtils;
/**
@ -24,7 +24,7 @@ import org.apache.commons.lang3.StringUtils;
*
* @author Nacos
*/
public class ConfigDataChangeEvent implements Event {
public class ConfigDataChangeEvent extends Event {
public final boolean isBeta;

View File

@ -16,14 +16,14 @@
package com.alibaba.nacos.config.server.model.event;
import com.alibaba.nacos.core.notify.Event;
import com.alibaba.nacos.common.notify.Event;
/**
* ConfigDumpEvent.
*
* @author <a href="mailto:liaochuntao@live.com">liaochuntao</a>
*/
public class ConfigDumpEvent implements Event {
public class ConfigDumpEvent extends Event {
private static final long serialVersionUID = -8776888606458370294L;
@ -222,7 +222,7 @@ public class ConfigDumpEvent implements Event {
this.lastModifiedTs = lastModifiedTs;
return this;
}
/**
* Build a configDumpEvent.
*

View File

@ -16,14 +16,14 @@
package com.alibaba.nacos.config.server.model.event;
import com.alibaba.nacos.core.notify.SlowEvent;
import com.alibaba.nacos.common.notify.SlowEvent;
/**
* Data import event.
*
* @author <a href="mailto:liaochuntao@live.com">liaochuntao</a>
*/
public class DerbyImportEvent implements SlowEvent {
public class DerbyImportEvent extends SlowEvent {
private static final long serialVersionUID = 3299565864352399053L;

View File

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

View File

@ -16,7 +16,7 @@
package com.alibaba.nacos.config.server.model.event;
import com.alibaba.nacos.config.server.utils.event.EventDispatcher.Event;
import com.alibaba.nacos.common.notify.Event;
import java.util.List;
@ -25,7 +25,7 @@ import java.util.List;
*
* @author Nacos
*/
public class LocalDataChangeEvent implements Event {
public class LocalDataChangeEvent extends Event {
public final String groupKey;

View File

@ -16,14 +16,14 @@
package com.alibaba.nacos.config.server.model.event;
import com.alibaba.nacos.core.notify.SlowEvent;
import com.alibaba.nacos.common.notify.SlowEvent;
/**
* RaftDBErrorEvent.
*
* @author <a href="mailto:liaochunyhm@live.com">liaochuntao</a>
*/
public class RaftDbErrorEvent implements SlowEvent {
public class RaftDbErrorEvent extends SlowEvent {
private static final long serialVersionUID = 101591819161802336L;

View File

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

View File

@ -35,13 +35,14 @@ public class MemoryMonitor {
@Autowired
public MemoryMonitor(AsyncNotifyService notifySingleService) {
ConfigExecutor.scheduleWithFixedDelay(new PrintMemoryTask(), DELAY_SECONDS, DELAY_SECONDS, TimeUnit.SECONDS);
ConfigExecutor.scheduleConfigTask(new PrintMemoryTask(), DELAY_SECONDS, DELAY_SECONDS, TimeUnit.SECONDS);
ConfigExecutor.scheduleWithFixedDelay(new PrintGetConfigResponeTask(), DELAY_SECONDS, DELAY_SECONDS,
TimeUnit.SECONDS);
ConfigExecutor
.scheduleConfigTask(new PrintGetConfigResponeTask(), DELAY_SECONDS, DELAY_SECONDS, TimeUnit.SECONDS);
ConfigExecutor.scheduleWithFixedDelay(new NotifyTaskQueueMonitorTask(notifySingleService), DELAY_SECONDS,
DELAY_SECONDS, TimeUnit.SECONDS);
ConfigExecutor
.scheduleConfigTask(new NotifyTaskQueueMonitorTask(notifySingleService), DELAY_SECONDS, DELAY_SECONDS,
TimeUnit.SECONDS);
}

View File

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

View File

@ -16,6 +16,7 @@
package com.alibaba.nacos.config.server.service;
import com.alibaba.nacos.common.notify.NotifyCenter;
import com.alibaba.nacos.common.utils.MD5Utils;
import com.alibaba.nacos.config.server.constant.Constants;
import com.alibaba.nacos.config.server.model.CacheItem;
@ -26,7 +27,6 @@ import com.alibaba.nacos.config.server.utils.DiskUtil;
import com.alibaba.nacos.config.server.utils.GroupKey;
import com.alibaba.nacos.config.server.utils.GroupKey2;
import com.alibaba.nacos.config.server.utils.PropertyUtil;
import com.alibaba.nacos.config.server.utils.event.EventDispatcher;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -67,12 +67,12 @@ public class ConfigCacheService {
/**
* Save config file and update md5 value in cache.
*
* @param dataId dataId string value.
* @param group group string value.
* @param tenant tenant string value.
* @param content content string value.
* @param dataId dataId string value.
* @param group group string value.
* @param tenant tenant string value.
* @param content content string value.
* @param lastModifiedTs lastModifiedTs.
* @param type file type.
* @param type file type.
* @return dumpChange success or not.
*/
public static boolean dump(String dataId, String group, String tenant, String content, long lastModifiedTs,
@ -120,12 +120,12 @@ public class ConfigCacheService {
/**
* Save config file and update md5 value in cache.
*
* @param dataId dataId string value.
* @param group group string value.
* @param tenant tenant string value.
* @param content content string value.
* @param dataId dataId string value.
* @param group group string value.
* @param tenant tenant string value.
* @param content content string value.
* @param lastModifiedTs lastModifiedTs.
* @param betaIps betaIps string value.
* @param betaIps betaIps string value.
* @return dumpChange success or not.
*/
public static boolean dumpBeta(String dataId, String group, String tenant, String content, long lastModifiedTs,
@ -165,12 +165,12 @@ public class ConfigCacheService {
/**
* Save config file and update md5 value in cache.
*
* @param dataId dataId string value.
* @param group group string value.
* @param tenant tenant string value.
* @param content content string value.
* @param dataId dataId string value.
* @param group group string value.
* @param tenant tenant string value.
* @param content content string value.
* @param lastModifiedTs lastModifiedTs.
* @param tag tag string value.
* @param tag tag string value.
* @return dumpChange success or not.
*/
public static boolean dumpTag(String dataId, String group, String tenant, String tag, String content,
@ -209,10 +209,10 @@ public class ConfigCacheService {
/**
* Save config file and update md5 value in cache.
*
* @param dataId dataId string value.
* @param group group string value.
* @param tenant tenant string value.
* @param content content string value.
* @param dataId dataId string value.
* @param group group string value.
* @param tenant tenant string value.
* @param content content string value.
* @param lastModifiedTs lastModifiedTs.
* @return dumpChange success or not.
*/
@ -313,6 +313,7 @@ public class ConfigCacheService {
/**
* Check md5.
*
* @return return diff result list.
*/
public static List<String> checkMd5() {
@ -343,20 +344,20 @@ public class ConfigCacheService {
* Delete config file, and delete cache.
*
* @param dataId dataId string value.
* @param group group string value.
* @param group group string value.
* @param tenant tenant string value.
* @return remove success or not.
*/
public static boolean remove(String dataId, String group, String tenant) {
final String groupKey = GroupKey2.getKey(dataId, group, tenant);
final int lockResult = tryWriteLock(groupKey);
// If data is non-existent.
if (0 == lockResult) {
DUMP_LOG.info("[remove-ok] {} not exist.", groupKey);
return true;
}
// try to lock failed
if (lockResult < 0) {
DUMP_LOG.warn("[remove-error] write lock failed. {}", groupKey);
@ -368,7 +369,7 @@ public class ConfigCacheService {
DiskUtil.removeConfigInfo(dataId, group, tenant);
}
CACHE.remove(groupKey);
EventDispatcher.fireEvent(new LocalDataChangeEvent(groupKey));
NotifyCenter.publishEvent(new LocalDataChangeEvent(groupKey));
return true;
} finally {
@ -380,7 +381,7 @@ public class ConfigCacheService {
* Delete beta config file, and delete cache.
*
* @param dataId dataId string value.
* @param group group string value.
* @param group group string value.
* @param tenant tenant string value.
* @return remove success or not.
*/
@ -393,7 +394,7 @@ public class ConfigCacheService {
DUMP_LOG.info("[remove-ok] {} not exist.", groupKey);
return true;
}
// try to lock failed
if (lockResult < 0) {
DUMP_LOG.warn("[remove-error] write lock failed. {}", groupKey);
@ -404,7 +405,7 @@ public class ConfigCacheService {
if (!PropertyUtil.isDirectRead()) {
DiskUtil.removeConfigInfo4Beta(dataId, group, tenant);
}
EventDispatcher.fireEvent(new LocalDataChangeEvent(groupKey, true, CACHE.get(groupKey).getIps4Beta()));
NotifyCenter.publishEvent(new LocalDataChangeEvent(groupKey, true, CACHE.get(groupKey).getIps4Beta()));
CACHE.get(groupKey).setBeta(false);
CACHE.get(groupKey).setIps4Beta(null);
CACHE.get(groupKey).setMd54Beta(Constants.NULL);
@ -418,21 +419,21 @@ public class ConfigCacheService {
* Delete tag config file, and delete cache.
*
* @param dataId dataId string value.
* @param group group string value.
* @param group group string value.
* @param tenant tenant string value.
* @param tag tag string value.
* @param tag tag string value.
* @return remove success or not.
*/
public static boolean removeTag(String dataId, String group, String tenant, String tag) {
final String groupKey = GroupKey2.getKey(dataId, group, tenant);
final int lockResult = tryWriteLock(groupKey);
// If data is non-existent.
if (0 == lockResult) {
DUMP_LOG.info("[remove-ok] {} not exist.", groupKey);
return true;
}
// try to lock failed
if (lockResult < 0) {
DUMP_LOG.warn("[remove-error] write lock failed. {}", groupKey);
@ -447,7 +448,7 @@ public class ConfigCacheService {
CacheItem ci = CACHE.get(groupKey);
ci.tagMd5.remove(tag);
ci.tagLastModifiedTs.remove(tag);
EventDispatcher.fireEvent(new LocalDataChangeEvent(groupKey, false, null, tag));
NotifyCenter.publishEvent(new LocalDataChangeEvent(groupKey, false, null, tag));
return true;
} finally {
releaseWriteLock(groupKey);
@ -457,8 +458,8 @@ public class ConfigCacheService {
/**
* Update md5 value.
*
* @param groupKey groupKey string value.
* @param md5 md5 string value.
* @param groupKey groupKey string value.
* @param md5 md5 string value.
* @param lastModifiedTs lastModifiedTs long value.
*/
public static void updateMd5(String groupKey, String md5, long lastModifiedTs) {
@ -466,16 +467,16 @@ public class ConfigCacheService {
if (cache.md5 == null || !cache.md5.equals(md5)) {
cache.md5 = md5;
cache.lastModifiedTs = lastModifiedTs;
EventDispatcher.fireEvent(new LocalDataChangeEvent(groupKey));
NotifyCenter.publishEvent(new LocalDataChangeEvent(groupKey));
}
}
/**
* Update Beta md5 value.
*
* @param groupKey groupKey string value.
* @param md5 md5 string value.
* @param ips4Beta ips4Beta List.
* @param groupKey groupKey string value.
* @param md5 md5 string value.
* @param ips4Beta ips4Beta List.
* @param lastModifiedTs lastModifiedTs long value.
*/
public static void updateBetaMd5(String groupKey, String md5, List<String> ips4Beta, long lastModifiedTs) {
@ -485,16 +486,16 @@ public class ConfigCacheService {
cache.md54Beta = md5;
cache.lastModifiedTs4Beta = lastModifiedTs;
cache.ips4Beta = ips4Beta;
EventDispatcher.fireEvent(new LocalDataChangeEvent(groupKey, true, ips4Beta));
NotifyCenter.publishEvent(new LocalDataChangeEvent(groupKey, true, ips4Beta));
}
}
/**
* Update tag md5 value.
*
* @param groupKey groupKey string value.
* @param tag tag string value.
* @param md5 md5 string value.
* @param groupKey groupKey string value.
* @param tag tag string value.
* @param md5 md5 string value.
* @param lastModifiedTs lastModifiedTs long value.
*/
public static void updateTagMd5(String groupKey, String tag, String md5, long lastModifiedTs) {
@ -510,13 +511,13 @@ public class ConfigCacheService {
} else {
cache.tagLastModifiedTs.put(tag, lastModifiedTs);
}
EventDispatcher.fireEvent(new LocalDataChangeEvent(groupKey, false, null, tag));
NotifyCenter.publishEvent(new LocalDataChangeEvent(groupKey, false, null, tag));
return;
}
if (cache.tagMd5.get(tag) == null || !cache.tagMd5.get(tag).equals(md5)) {
cache.tagMd5.put(tag, md5);
cache.tagLastModifiedTs.put(tag, lastModifiedTs);
EventDispatcher.fireEvent(new LocalDataChangeEvent(groupKey, false, null, tag));
NotifyCenter.publishEvent(new LocalDataChangeEvent(groupKey, false, null, tag));
}
}

View File

@ -16,9 +16,9 @@
package com.alibaba.nacos.config.server.service;
import com.alibaba.nacos.common.notify.NotifyCenter;
import com.alibaba.nacos.config.server.model.event.ConfigDataChangeEvent;
import com.alibaba.nacos.config.server.utils.PropertyUtil;
import com.alibaba.nacos.config.server.utils.event.EventDispatcher;
import com.alibaba.nacos.core.utils.ApplicationUtils;
/**
@ -30,13 +30,14 @@ public class ConfigChangePublisher {
/**
* Notify ConfigChange.
*
* @param event ConfigDataChangeEvent instance.
*/
public static void notifyConfigChange(ConfigDataChangeEvent event) {
if (PropertyUtil.isEmbeddedStorage() && !ApplicationUtils.getStandaloneMode()) {
return;
}
EventDispatcher.fireEvent(event);
NotifyCenter.publishEvent(event);
}
}

View File

@ -16,17 +16,17 @@
package com.alibaba.nacos.config.server.service;
import com.alibaba.nacos.common.utils.ThreadUtils;
import com.alibaba.nacos.config.server.constant.Constants;
import com.alibaba.nacos.config.server.model.SampleResult;
import com.alibaba.nacos.config.server.service.notify.NotifyService;
import com.alibaba.nacos.config.server.utils.ConfigExecutor;
import com.alibaba.nacos.config.server.utils.JSONUtils;
import com.alibaba.nacos.config.server.utils.LogUtil;
import com.alibaba.nacos.core.cluster.Member;
import com.alibaba.nacos.core.cluster.ServerMemberManager;
import com.alibaba.nacos.core.utils.ApplicationUtils;
import org.apache.commons.lang3.StringUtils;
import com.fasterxml.jackson.core.type.TypeReference;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@ -37,18 +37,15 @@ import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletionService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.Future;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.Callable;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.Future;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
/**
* Config sub service.
@ -58,24 +55,12 @@ import java.util.concurrent.ExecutorCompletionService;
@Service
public class ConfigSubService {
private ScheduledExecutorService scheduler;
private ServerMemberManager memberManager;
@Autowired
@SuppressWarnings("PMD.ThreadPoolCreationRule")
public ConfigSubService(ServerMemberManager memberManager) {
this.memberManager = memberManager;
scheduler = Executors.newScheduledThreadPool(ThreadUtils.getSuitableThreadCount(), new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r);
t.setDaemon(true);
t.setName("com.alibaba.nacos.ConfigSubService");
return t;
}
});
}
protected ConfigSubService() {
@ -140,7 +125,7 @@ public class ConfigSubService {
* Merge SampleResult.
*
* @param sampleCollectResult sampleCollectResult.
* @param sampleResults sampleResults.
* @param sampleResults sampleResults.
* @return SampleResult.
*/
public SampleResult mergeSampleResult(SampleResult sampleCollectResult, List<SampleResult> sampleResults) {
@ -195,7 +180,7 @@ public class ConfigSubService {
String urlAll = getUrl(ip, url) + "?" + paramUrl;
com.alibaba.nacos.config.server.service.notify.NotifyService.HttpResult result = NotifyService
.invokeURL(urlAll, null, Constants.ENCODE);
// Http code 200
if (result.code == HttpURLConnection.HTTP_OK) {
String json = result.content;
@ -227,8 +212,8 @@ public class ConfigSubService {
}
BlockingQueue<Future<SampleResult>> queue = new LinkedBlockingDeque<Future<SampleResult>>(
memberManager.getServerList().size());
CompletionService<SampleResult> completionService = new ExecutorCompletionService<SampleResult>(scheduler,
queue);
CompletionService<SampleResult> completionService = new ExecutorCompletionService<SampleResult>(
ConfigExecutor.getConfigSubServiceExecutor(), queue);
SampleResult sampleCollectResult = new SampleResult();
for (int i = 0; i < sampleTime; i++) {
@ -247,8 +232,8 @@ public class ConfigSubService {
params.put("ip", ip);
BlockingQueue<Future<SampleResult>> queue = new LinkedBlockingDeque<Future<SampleResult>>(
memberManager.getServerList().size());
CompletionService<SampleResult> completionService = new ExecutorCompletionService<SampleResult>(scheduler,
queue);
CompletionService<SampleResult> completionService = new ExecutorCompletionService<SampleResult>(
ConfigExecutor.getConfigSubServiceExecutor(), queue);
SampleResult sampleCollectResult = new SampleResult();
for (int i = 0; i < sampleTime; i++) {

View File

@ -16,41 +16,40 @@
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.common.utils.CollectionUtils;
import com.alibaba.nacos.common.utils.ExceptionUtil;
import com.alibaba.nacos.config.server.model.SampleResult;
import com.alibaba.nacos.config.server.model.event.LocalDataChangeEvent;
import com.alibaba.nacos.config.server.monitor.MetricsMonitor;
import com.alibaba.nacos.config.server.utils.ConfigExecutor;
import com.alibaba.nacos.config.server.utils.GroupKey;
import com.alibaba.nacos.config.server.utils.LogUtil;
import com.alibaba.nacos.config.server.utils.MD5Util;
import com.alibaba.nacos.config.server.utils.RequestUtil;
import com.alibaba.nacos.config.server.utils.event.EventDispatcher.AbstractEventListener;
import com.alibaba.nacos.config.server.utils.event.EventDispatcher.Event;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import javax.servlet.AsyncContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Iterator;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.Future;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.Arrays;
import static com.alibaba.nacos.config.server.utils.LogUtil.MEMORY_LOG;
import static com.alibaba.nacos.config.server.utils.LogUtil.PULL_LOG;
@ -61,7 +60,7 @@ import static com.alibaba.nacos.config.server.utils.LogUtil.PULL_LOG;
* @author Nacos
*/
@Service
public class LongPollingService extends AbstractEventListener {
public class LongPollingService {
private static final int FIXED_POLLING_INTERVAL_MS = 10000;
@ -126,8 +125,8 @@ public class LongPollingService extends AbstractEventListener {
}
/**
* Aggregate the sampling IP and monitoring configuration information in the sampling results.
* There is no problem for the merging strategy to cover the previous one with the latter.
* Aggregate the sampling IP and monitoring configuration information in the sampling results. There is no problem
* for the merging strategy to cover the previous one with the latter.
*
* @param sampleResults sample Results.
* @return Results.
@ -147,6 +146,7 @@ public class LongPollingService extends AbstractEventListener {
/**
* Collect application subscribe configinfos.
*
* @return configinfos results.
*/
public Map<String, Set<String>> collectApplicationSubscribeConfigInfos() {
@ -232,9 +232,9 @@ public class LongPollingService extends AbstractEventListener {
/**
* Add LongPollingClient.
*
* @param req HttpServletRequest.
* @param rsp HttpServletResponse.
* @param clientMd5Map clientMd5Map.
* @param req HttpServletRequest.
* @param rsp HttpServletResponse.
* @param clientMd5Map clientMd5Map.
* @param probeRequestSize probeRequestSize.
*/
public void addLongPollingClient(HttpServletRequest req, HttpServletResponse rsp, Map<String, String> clientMd5Map,
@ -245,7 +245,7 @@ public class LongPollingService extends AbstractEventListener {
String appName = req.getHeader(RequestUtil.CLIENT_APPNAME_HEADER);
String tag = req.getHeader("Vipserver-Tag");
int delayTime = SwitchService.getSwitchInteger(SwitchService.FIXED_DELAY_TIME, 500);
// Add delay time for LoadBalance, and one response is returned 500 ms in advance to avoid client timeout.
long timeout = Math.max(10000, Long.parseLong(str) - delayTime);
if (isFixedPolling()) {
@ -275,29 +275,10 @@ public class LongPollingService extends AbstractEventListener {
// AsyncContext.setTimeout() is incorrect, Control by oneself
asyncContext.setTimeout(0L);
scheduler.execute(
ConfigExecutor.executeLongPolling(
new ClientLongPolling(asyncContext, clientMd5Map, ip, probeRequestSize, timeout, appName, tag));
}
@Override
public List<Class<? extends Event>> interest() {
List<Class<? extends Event>> eventTypes = new ArrayList<Class<? extends Event>>();
eventTypes.add(LocalDataChangeEvent.class);
return eventTypes;
}
@Override
public void onEvent(Event event) {
if (isFixedPolling()) {
// Ignore.
} else {
if (event instanceof LocalDataChangeEvent) {
LocalDataChangeEvent evt = (LocalDataChangeEvent) event;
scheduler.execute(new DataChangeTask(evt.groupKey, evt.isBeta, evt.betaIps));
}
}
}
public static boolean isSupportLongPolling(HttpServletRequest req) {
return null != req.getHeader(LONG_POLLING_HEADER);
}
@ -306,24 +287,38 @@ public class LongPollingService extends AbstractEventListener {
public LongPollingService() {
allSubs = new ConcurrentLinkedQueue<ClientLongPolling>();
scheduler = Executors.newScheduledThreadPool(1, new ThreadFactory() {
ConfigExecutor.scheduleLongPolling(new StatTask(), 0L, 10L, TimeUnit.SECONDS);
// Register LocalDataChangeEvent to NotifyCenter.
NotifyCenter.registerToPublisher(LocalDataChangeEvent.class, NotifyCenter.ringBufferSize);
// Register A Subscriber to subscribe LocalDataChangeEvent.
NotifyCenter.registerSubscriber(new Subscriber() {
@Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r);
t.setDaemon(true);
t.setName("com.alibaba.nacos.LongPolling");
return t;
public void onEvent(Event event) {
if (isFixedPolling()) {
// Ignore.
} else {
if (event instanceof LocalDataChangeEvent) {
LocalDataChangeEvent evt = (LocalDataChangeEvent) event;
ConfigExecutor.executeLongPolling(new DataChangeTask(evt.groupKey, evt.isBeta, evt.betaIps));
}
}
}
@Override
public Class<? extends Event> subscribeType() {
return LocalDataChangeEvent.class;
}
});
scheduler.scheduleWithFixedDelay(new StatTask(), 0L, 10L, TimeUnit.SECONDS);
}
public static final String LONG_POLLING_HEADER = "Long-Pulling-Timeout";
public static final String LONG_POLLING_NO_HANG_UP_HEADER = "Long-Pulling-Timeout-No-Hangup";
final ScheduledExecutorService scheduler;
/**
* ClientLongPolling subscibers.
*/
@ -398,12 +393,12 @@ public class LongPollingService extends AbstractEventListener {
@Override
public void run() {
asyncTimeoutFuture = scheduler.schedule(new Runnable() {
asyncTimeoutFuture = ConfigExecutor.scheduleLongPolling(new Runnable() {
@Override
public void run() {
try {
getRetainIps().put(ClientLongPolling.this.ip, System.currentTimeMillis());
// Delete subsciber's relations.
allSubs.remove(ClientLongPolling.this);
@ -439,7 +434,7 @@ public class LongPollingService extends AbstractEventListener {
}
void sendResponse(List<String> changedGroups) {
// Cancel time out task.
if (null != asyncTimeoutFuture) {
asyncTimeoutFuture.cancel(false);
@ -449,7 +444,7 @@ public class LongPollingService extends AbstractEventListener {
void generateResponse(List<String> changedGroups) {
if (null == changedGroups) {
// Tell web container to send http response.
asyncContext.complete();
return;

View File

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

View File

@ -45,7 +45,7 @@ public class ExternalDataSourceProperties {
public static final int DEFAULT_MAX_POOL_SIZE = 20;
public static final int DEFAULT_MINIMUM_IDLE = 50;
public static final int DEFAULT_MINIMUM_IDLE = 20;
private Integer num;

View File

@ -101,13 +101,13 @@ public class ExternalDataSourceServiceImpl implements DataSourceService {
testMasterWritableJT.setQueryTimeout(1);
// Database health check
testJtList = new ArrayList<JdbcTemplate>();
isHealthList = new ArrayList<Boolean>();
tm = new DataSourceTransactionManager();
tjt = new TransactionTemplate(tm);
// Transaction timeout needs to be distinguished from ordinary operations.
tjt.setTimeout(TRANSACTION_QUERY_TIMEOUT);
if (PropertyUtil.isUseExternalDB()) {
@ -118,8 +118,8 @@ public class ExternalDataSourceServiceImpl implements DataSourceService {
throw new RuntimeException(DB_LOAD_ERROR_MSG);
}
ConfigExecutor.scheduleWithFixedDelay(new SelectMasterTask(), 10, 10, TimeUnit.SECONDS);
ConfigExecutor.scheduleWithFixedDelay(new CheckDbHealthTask(), 10, 10, TimeUnit.SECONDS);
ConfigExecutor.scheduleConfigTask(new SelectMasterTask(), 10, 10, TimeUnit.SECONDS);
ConfigExecutor.scheduleConfigTask(new CheckDbHealthTask(), 10, 10, TimeUnit.SECONDS);
}
}

View File

@ -17,28 +17,27 @@
package com.alibaba.nacos.config.server.service.dump;
import com.alibaba.nacos.common.utils.StringUtils;
import com.alibaba.nacos.common.notify.Event;
import com.alibaba.nacos.common.notify.listener.Subscriber;
import com.alibaba.nacos.config.server.model.event.ConfigDumpEvent;
import com.alibaba.nacos.config.server.service.AggrWhitelist;
import com.alibaba.nacos.config.server.service.ClientIpWhiteList;
import com.alibaba.nacos.config.server.service.ConfigCacheService;
import com.alibaba.nacos.config.server.service.SwitchService;
import com.alibaba.nacos.config.server.service.trace.ConfigTraceService;
import com.alibaba.nacos.core.notify.Event;
import com.alibaba.nacos.core.notify.listener.Subscribe;
/**
* Dump config subscriber.
*
* @author <a href="mailto:liaochuntao@live.com">liaochuntao</a>
*/
public class DumpConfigHandler implements Subscribe<ConfigDumpEvent> {
public class DumpConfigHandler extends Subscriber<ConfigDumpEvent> {
/**
* trigger config dump event.
*
* @param event {@link ConfigDumpEvent}
* @return {@code true} if the config dump task success , else
* {@code false}
* @return {@code true} if the config dump task success , else {@code false}
*/
public static boolean configDump(ConfigDumpEvent event) {
final String dataId = event.getDataId();

View File

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

View File

@ -16,6 +16,7 @@
package com.alibaba.nacos.config.server.service.merge;
import com.alibaba.nacos.common.notify.NotifyCenter;
import com.alibaba.nacos.config.server.constant.Constants;
import com.alibaba.nacos.config.server.manager.AbstractTask;
import com.alibaba.nacos.config.server.manager.TaskProcessor;
@ -27,7 +28,6 @@ import com.alibaba.nacos.config.server.service.repository.PersistService;
import com.alibaba.nacos.config.server.service.trace.ConfigTraceService;
import com.alibaba.nacos.config.server.utils.ContentUtils;
import com.alibaba.nacos.config.server.utils.TimeUtils;
import com.alibaba.nacos.config.server.utils.event.EventDispatcher;
import com.alibaba.nacos.core.utils.InetUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
@ -79,8 +79,9 @@ public class MergeTaskProcessor implements TaskProcessor {
persistService.insertOrUpdate(null, null, cf, time, null);
LOGGER.info("[merge-ok] {}, {}, size={}, length={}, md5={}, content={}", dataId, group, datumList.size(),
cf.getContent().length(), cf.getMd5(), ContentUtils.truncateContent(cf.getContent()));
LOGGER.info("[merge-ok] {}, {}, size={}, length={}, md5={}, content={}", dataId, group,
datumList.size(), cf.getContent().length(), cf.getMd5(),
ContentUtils.truncateContent(cf.getContent()));
ConfigTraceService
.logPersistenceEvent(dataId, group, tenant, null, time.getTime(), InetUtils.getSelfIp(),
@ -93,14 +94,14 @@ public class MergeTaskProcessor implements TaskProcessor {
persistService.removeConfigInfoTag(dataId, group, tenant, tag, clientIp, null);
}
LOGGER.warn("[merge-delete] delete config info because no datum. dataId=" + dataId + ", groupId=" + group);
LOGGER.warn(
"[merge-delete] delete config info because no datum. dataId=" + dataId + ", groupId=" + group);
ConfigTraceService
.logPersistenceEvent(dataId, group, tenant, null, time.getTime(), InetUtils.getSelfIp(),
ConfigTraceService.PERSISTENCE_EVENT_REMOVE, null);
}
EventDispatcher.fireEvent(new ConfigDataChangeEvent(false, dataId, group, tenant, tag, time.getTime()));
NotifyCenter.publishEvent(new ConfigDataChangeEvent(false, dataId, group, tenant, tag, time.getTime()));
} catch (Exception e) {
mergeService.addMergeTask(dataId, group, tenant, mergeTask.getClientIp());
@ -113,9 +114,9 @@ public class MergeTaskProcessor implements TaskProcessor {
/**
* merge datumList {@link ConfigInfoAggr}.
*
* @param dataId data id
* @param group group
* @param tenant tenant
* @param dataId data id
* @param group group
* @param tenant tenant
* @param datumList datumList
* @return {@link ConfigInfo}
*/

View File

@ -16,14 +16,16 @@
package com.alibaba.nacos.config.server.service.notify;
import com.alibaba.nacos.common.notify.Event;
import com.alibaba.nacos.common.notify.NotifyCenter;
import com.alibaba.nacos.common.notify.listener.Subscriber;
import com.alibaba.nacos.config.server.constant.Constants;
import com.alibaba.nacos.config.server.monitor.MetricsMonitor;
import com.alibaba.nacos.config.server.model.event.ConfigDataChangeEvent;
import com.alibaba.nacos.config.server.monitor.MetricsMonitor;
import com.alibaba.nacos.config.server.service.trace.ConfigTraceService;
import com.alibaba.nacos.config.server.utils.ConfigExecutor;
import com.alibaba.nacos.config.server.utils.LogUtil;
import com.alibaba.nacos.config.server.utils.PropertyUtil;
import com.alibaba.nacos.config.server.utils.event.EventDispatcher.AbstractEventListener;
import com.alibaba.nacos.config.server.utils.event.EventDispatcher.Event;
import com.alibaba.nacos.core.cluster.Member;
import com.alibaba.nacos.core.cluster.ServerMemberManager;
import com.alibaba.nacos.core.utils.ApplicationUtils;
@ -45,15 +47,9 @@ import org.springframework.stereotype.Service;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
/**
@ -62,51 +58,48 @@ import java.util.concurrent.TimeUnit;
* @author Nacos
*/
@Service
public class AsyncNotifyService extends AbstractEventListener {
@Override
public List<Class<? extends Event>> interest() {
List<Class<? extends Event>> types = new ArrayList<Class<? extends Event>>();
// Trigger configuration change synchronization notification
types.add(ConfigDataChangeEvent.class);
return types;
}
@Override
public void onEvent(Event event) {
// Generate ConfigDataChangeEvent concurrently
if (event instanceof ConfigDataChangeEvent) {
ConfigDataChangeEvent evt = (ConfigDataChangeEvent) event;
long dumpTs = evt.lastModifiedTs;
String dataId = evt.dataId;
String group = evt.group;
String tenant = evt.tenant;
String tag = evt.tag;
Collection<Member> ipList = memberManager.allMembers();
// In fact, any type of queue here can be
Queue<NotifySingleTask> queue = new LinkedList<NotifySingleTask>();
for (Member member : ipList) {
queue.add(new NotifySingleTask(dataId, group, tenant, tag, dumpTs, member.getAddress(), evt.isBeta));
}
EXECUTOR.execute(new AsyncTask(httpclient, queue));
}
}
public class AsyncNotifyService {
@Autowired
public AsyncNotifyService(ServerMemberManager memberManager) {
this.memberManager = memberManager;
httpclient.start();
// Register ConfigDataChangeEvent to NotifyCenter.
NotifyCenter.registerToPublisher(ConfigDataChangeEvent.class, NotifyCenter.ringBufferSize);
// Register A Subscriber to subscribe ConfigDataChangeEvent.
NotifyCenter.registerSubscriber(new Subscriber() {
@Override
public void onEvent(Event event) {
// Generate ConfigDataChangeEvent concurrently
if (event instanceof ConfigDataChangeEvent) {
ConfigDataChangeEvent evt = (ConfigDataChangeEvent) event;
long dumpTs = evt.lastModifiedTs;
String dataId = evt.dataId;
String group = evt.group;
String tenant = evt.tenant;
String tag = evt.tag;
Collection<Member> ipList = memberManager.allMembers();
// In fact, any type of queue here can be
Queue<NotifySingleTask> queue = new LinkedList<NotifySingleTask>();
for (Member member : ipList) {
queue.add(new NotifySingleTask(dataId, group, tenant, tag, dumpTs, member.getAddress(),
evt.isBeta));
}
ConfigExecutor.executeAsyncNotify(new AsyncTask(httpclient, queue));
}
}
@Override
public Class<? extends Event> subscribeType() {
return ConfigDataChangeEvent.class;
}
});
}
public Executor getExecutor() {
return EXECUTOR;
}
@SuppressWarnings("PMD.ThreadPoolCreationRule")
private static final Executor EXECUTOR = Executors.newScheduledThreadPool(100, new NotifyThreadFactory());
private RequestConfig requestConfig = RequestConfig.custom()
.setConnectTimeout(PropertyUtil.getNotifyConnectTimeout())
.setSocketTimeout(PropertyUtil.getNotifySocketTimeout()).build();
@ -169,7 +162,7 @@ public class AsyncNotifyService extends AbstractEventListener {
Queue<NotifySingleTask> queue = new LinkedList<NotifySingleTask>();
queue.add(task);
AsyncTask asyncTask = new AsyncTask(httpclient, queue);
((ScheduledThreadPoolExecutor) EXECUTOR).schedule(asyncTask, delay, TimeUnit.MILLISECONDS);
ConfigExecutor.scheduleAsyncNotify(asyncTask, delay, TimeUnit.MILLISECONDS);
}
class AsyncNotifyCallBack implements FutureCallback<HttpResponse> {
@ -310,16 +303,6 @@ public class AsyncNotifyService extends AbstractEventListener {
}
static class NotifyThreadFactory implements ThreadFactory {
@Override
public Thread newThread(Runnable r) {
Thread thread = new Thread(r, "com.alibaba.nacos.AsyncNotifyServiceThread");
thread.setDaemon(true);
return thread;
}
}
/**
* get delayTime and also set failCount to task; The failure time index increases, so as not to retry invalid tasks
* in the offline scene, which affects the normal synchronization.

View File

@ -16,6 +16,8 @@
package com.alibaba.nacos.config.server.service.notify;
import com.alibaba.nacos.common.executor.ExecutorFactory;
import com.alibaba.nacos.common.executor.NameThreadFactory;
import com.alibaba.nacos.config.server.manager.AbstractTask;
import com.alibaba.nacos.config.server.utils.GroupKey2;
import com.alibaba.nacos.config.server.utils.LogUtil;
@ -28,9 +30,7 @@ import java.util.Collection;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
@ -102,22 +102,6 @@ public class NotifySingleService {
}
}
static class NotifyThreadFactory implements ThreadFactory {
private final String notifyTarget;
NotifyThreadFactory(String notifyTarget) {
this.notifyTarget = notifyTarget;
}
@Override
public Thread newThread(Runnable r) {
Thread thread = new Thread(r, "com.alibaba.nacos.NotifySingleServiceThread-" + notifyTarget);
thread.setDaemon(true);
return thread;
}
}
@Autowired
public NotifySingleService(ServerMemberManager memberManager) {
this.memberManager = memberManager;
@ -141,8 +125,8 @@ public class NotifySingleService {
* there will be no continuous task accumulation,
* there is occasional instantaneous pressure)
*/
@SuppressWarnings("PMD.ThreadPoolCreationRule") Executor executor = Executors
.newScheduledThreadPool(1, new NotifyThreadFactory(address));
Executor executor = ExecutorFactory.newSingleScheduledExecutorService(
new NameThreadFactory("com.alibaba.nacos.config.NotifySingleServiceThread-" + address));
if (null == executors.putIfAbsent(address, executor)) {
LOGGER.warn("[notify-thread-pool] setup thread target ip {} ok.", address);

View File

@ -16,6 +16,7 @@
package com.alibaba.nacos.config.server.service.repository.embedded;
import com.alibaba.nacos.common.notify.NotifyCenter;
import com.alibaba.nacos.config.server.model.event.DerbyLoadEvent;
import com.alibaba.nacos.config.server.service.datasource.DataSourceService;
import com.alibaba.nacos.config.server.service.datasource.DynamicDataSource;
@ -27,7 +28,6 @@ import com.alibaba.nacos.consistency.snapshot.SnapshotOperation;
import com.alibaba.nacos.consistency.snapshot.Writer;
import com.alibaba.nacos.core.distributed.raft.utils.RaftExecutor;
import com.alibaba.nacos.core.utils.DiskUtils;
import com.alibaba.nacos.core.notify.NotifyCenter;
import com.alibaba.nacos.core.utils.ApplicationUtils;
import com.alibaba.nacos.core.utils.TimerContext;
import com.alipay.sofa.jraft.util.CRC64;

View File

@ -21,6 +21,9 @@ import com.alibaba.nacos.api.exception.runtime.NacosRuntimeException;
import com.alibaba.nacos.common.JustForTest;
import com.alibaba.nacos.common.model.RestResult;
import com.alibaba.nacos.common.model.RestResultUtils;
import com.alibaba.nacos.common.notify.Event;
import com.alibaba.nacos.common.notify.NotifyCenter;
import com.alibaba.nacos.common.notify.listener.Subscriber;
import com.alibaba.nacos.common.utils.ExceptionUtil;
import com.alibaba.nacos.common.utils.JacksonUtils;
import com.alibaba.nacos.common.utils.LoggerUtils;
@ -53,9 +56,6 @@ import com.alibaba.nacos.consistency.exception.ConsistencyException;
import com.alibaba.nacos.consistency.snapshot.SnapshotOperation;
import com.alibaba.nacos.core.cluster.ServerMemberManager;
import com.alibaba.nacos.core.distributed.ProtocolManager;
import com.alibaba.nacos.core.notify.Event;
import com.alibaba.nacos.core.notify.NotifyCenter;
import com.alibaba.nacos.core.notify.listener.Subscribe;
import com.alibaba.nacos.core.utils.ClassUtils;
import com.alibaba.nacos.core.utils.DiskUtils;
import com.alibaba.nacos.core.utils.GenericType;
@ -190,7 +190,7 @@ public class DistributedDatabaseOperateImpl extends LogProcessor4CP implements B
// Register the snapshot load event
NotifyCenter.registerToSharePublisher(DerbyLoadEvent.class);
NotifyCenter.registerSubscribe(new Subscribe<RaftDbErrorEvent>() {
NotifyCenter.registerSubscriber(new Subscriber<RaftDbErrorEvent>() {
@Override
public void onEvent(RaftDbErrorEvent event) {
dataSourceService.setHealthStatus("DOWN");
@ -202,8 +202,8 @@ public class DistributedDatabaseOperateImpl extends LogProcessor4CP implements B
}
});
NotifyCenter.registerToPublisher(ConfigDumpEvent.class, NotifyCenter.RING_BUFFER_SIZE);
NotifyCenter.registerSubscribe(new DumpConfigHandler());
NotifyCenter.registerToPublisher(ConfigDumpEvent.class, NotifyCenter.ringBufferSize);
NotifyCenter.registerSubscriber(new DumpConfigHandler());
this.protocol.addLogProcessors(Collections.singletonList(this));
LogUtil.DEFAULT_LOG.info("use DistributedTransactionServicesImpl");

View File

@ -18,6 +18,7 @@ package com.alibaba.nacos.config.server.service.repository.embedded;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.common.utils.MD5Utils;
import com.alibaba.nacos.common.notify.NotifyCenter;
import com.alibaba.nacos.config.server.configuration.ConditionOnEmbeddedStorage;
import com.alibaba.nacos.config.server.constant.Constants;
import com.alibaba.nacos.config.server.enums.FileTypeEnum;
@ -48,7 +49,6 @@ import com.alibaba.nacos.config.server.service.sql.EmbeddedStorageContextUtils;
import com.alibaba.nacos.config.server.utils.LogUtil;
import com.alibaba.nacos.config.server.utils.ParamUtils;
import com.alibaba.nacos.core.distributed.id.IdGeneratorManager;
import com.alibaba.nacos.core.notify.NotifyCenter;
import com.google.common.base.Joiner;
import com.google.common.collect.Lists;
import org.apache.commons.collections.CollectionUtils;
@ -1078,8 +1078,8 @@ public class EmbeddedStoragePersistServiceImpl implements PersistService {
@Override
public int configInfoCount(String tenant) {
String sql = " SELECT COUNT(ID) FROM config_info where tenant_id like '" + tenant + "'";
Integer result = databaseOperate.queryOne(sql, Integer.class);
String sql = " SELECT COUNT(ID) FROM config_info where tenant_id like ?";
Integer result = databaseOperate.queryOne(sql, new Object[] {tenant}, Integer.class);
if (result == null) {
throw new IllegalArgumentException("configInfoCount error");
}
@ -2194,7 +2194,7 @@ public class EmbeddedStoragePersistServiceImpl implements PersistService {
@Override
public boolean isExistTable(String tableName) {
String sql = String.format("select 1 from %s limit 1", tableName);
String sql = String.format("SELECT 1 FROM %s FETCH FIRST ROW ONLY", tableName);
try {
databaseOperate.queryOne(sql, Integer.class);
return true;

View File

@ -1130,8 +1130,8 @@ public class ExternalStoragePersistServiceImpl implements PersistService {
@Override
public int configInfoCount(String tenant) {
String sql = " SELECT COUNT(ID) FROM config_info where tenant_id like '" + tenant + "'";
Integer result = jt.queryForObject(sql, Integer.class);
String sql = " SELECT COUNT(ID) FROM config_info where tenant_id like ?";
Integer result = jt.queryForObject(sql, new Object[] {tenant}, Integer.class);
if (result == null) {
throw new IllegalArgumentException("configInfoCount error");
}

View File

@ -18,10 +18,14 @@ package com.alibaba.nacos.config.server.utils;
import com.alibaba.nacos.common.executor.ExecutorFactory;
import com.alibaba.nacos.common.executor.NameThreadFactory;
import com.alibaba.nacos.common.utils.ThreadUtils;
import com.alibaba.nacos.config.server.Config;
import com.alibaba.nacos.core.utils.ClassUtils;
import java.util.concurrent.Executor;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
@ -31,15 +35,32 @@ import java.util.concurrent.TimeUnit;
*/
public final class ConfigExecutor {
private static final Executor DUMP_EXECUTOR = ExecutorFactory
.newFixedExecutorService(Config.class.getCanonicalName(), 1,
new NameThreadFactory("nacos.config.embedded.dump"));
private static final Executor DUMP_EXECUTOR = ExecutorFactory.Managed
.newSingleExecutorService(ClassUtils.getCanonicalName(Config.class),
new NameThreadFactory("com.alibaba.nacos.config.embedded.dump"));
private static final ScheduledExecutorService TIMER_EXECUTOR = ExecutorFactory
.newScheduledExecutorService(Config.class.getCanonicalName(), 10,
new NameThreadFactory("com.alibaba.nacos.server.Timer"));
private static final ScheduledExecutorService TIMER_EXECUTOR = ExecutorFactory.Managed
.newScheduledExecutorService(ClassUtils.getCanonicalName(Config.class), 10,
new NameThreadFactory("com.alibaba.nacos.config.server.timer"));
public static void scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit) {
private static final ScheduledExecutorService CAPACITY_MANAGEMENT_EXECUTOR = ExecutorFactory.Managed
.newSingleScheduledExecutorService(ClassUtils.getCanonicalName(Config.class),
new NameThreadFactory("com.alibaba.nacos.config.CapacityManagement"));
private static final ScheduledExecutorService ASYNC_NOTIFY_EXECUTOR = ExecutorFactory.Managed
.newScheduledExecutorService(ClassUtils.getCanonicalName(Config.class), 100,
new NameThreadFactory("com.alibaba.nacos.config.AsyncNotifyService"));
private static final ScheduledExecutorService CONFIG_SUB_SERVICE_EXECUTOR = ExecutorFactory.Managed
.newScheduledExecutorService(ClassUtils.getCanonicalName(Config.class),
ThreadUtils.getSuitableThreadCount(),
new NameThreadFactory("com.alibaba.nacos.config.ConfigSubService"));
private static final ScheduledExecutorService LONG_POLLING_EXECUTOR = ExecutorFactory.Managed
.newSingleScheduledExecutorService(ClassUtils.getCanonicalName(Config.class),
new NameThreadFactory("com.alibaba.nacos.config.LongPolling"));
public static void scheduleConfigTask(Runnable command, long initialDelay, long delay, TimeUnit unit) {
TIMER_EXECUTOR.scheduleWithFixedDelay(command, initialDelay, delay, unit);
}
@ -47,4 +68,35 @@ public final class ConfigExecutor {
DUMP_EXECUTOR.execute(runnable);
}
public static void scheduleCorrectUsageTask(Runnable runnable, long initialDelay, long delay, TimeUnit unit) {
CAPACITY_MANAGEMENT_EXECUTOR.scheduleWithFixedDelay(runnable, initialDelay, delay, unit);
}
public static void executeAsyncNotify(Runnable runnable) {
ASYNC_NOTIFY_EXECUTOR.execute(runnable);
}
public static void scheduleAsyncNotify(Runnable command, long delay, TimeUnit unit) {
ASYNC_NOTIFY_EXECUTOR.schedule(command, delay, unit);
}
public static int asyncNotifyQueueSize() {
return ((ScheduledThreadPoolExecutor) ASYNC_NOTIFY_EXECUTOR).getQueue().size();
}
public static ScheduledExecutorService getConfigSubServiceExecutor() {
return CONFIG_SUB_SERVICE_EXECUTOR;
}
public static void scheduleLongPolling(Runnable runnable, long initialDelay, long period, TimeUnit unit) {
LONG_POLLING_EXECUTOR.scheduleWithFixedDelay(runnable, initialDelay, period, unit);
}
public static ScheduledFuture<?> scheduleLongPolling(Runnable runnable, long period, TimeUnit unit) {
return LONG_POLLING_EXECUTOR.schedule(runnable, period, unit);
}
public static void executeLongPolling(Runnable runnable) {
LONG_POLLING_EXECUTOR.execute(runnable);
}
}

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