remove config resync request and add getting cluster metrics (#4846)

* from diamond over nacos  2.0

* config notify task type bugfix

* keep consistent  with diamond over nacos 2.0

* remove config resync  request and add getting cluster metrics

* add using address server to look up interface

* add using address server to look up interface
This commit is contained in:
nov.lzf 2021-02-01 13:33:56 +08:00 committed by GitHub
parent 5626b2be1f
commit d5af830d52
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 433 additions and 370 deletions

View File

@ -196,4 +196,11 @@ public class Constants {
public static final String POUND = "#";
public static final String VIPSERVER_TAG = "Vipserver-Tag";
public static final String AMORY_TAG = "Amory-Tag";
public static final String LOCATION_TAG = "Location-Tag";
public static final String CHARSET_KEY = "charset";
}

View File

@ -16,13 +16,45 @@
package com.alibaba.nacos.api.config.remote.request;
import com.alibaba.nacos.api.remote.request.ServerRequest;
/**
* ConfigChangeNotifyRequest.
*
* @author liuzunfei
* @version $Id: ConfigChangeNotifyRequest.java, v 0.1 2020年07月14日 3:20 PM liuzunfei Exp $
*/
public class ConfigChangeNotifyRequest extends ConfigReSyncRequest {
public class ConfigChangeNotifyRequest extends ServerRequest {
String dataId;
String group;
String tenant;
public String getDataId() {
return dataId;
}
public void setDataId(String dataId) {
this.dataId = dataId;
}
public String getGroup() {
return group;
}
public void setGroup(String group) {
this.group = group;
}
public String getTenant() {
return tenant;
}
public void setTenant(String tenant) {
this.tenant = tenant;
}
/**
* build success response.
@ -33,10 +65,15 @@ public class ConfigChangeNotifyRequest extends ConfigReSyncRequest {
* @return ConfigChangeNotifyResponse
*/
public static ConfigChangeNotifyRequest build(String dataId, String group, String tenant) {
ConfigChangeNotifyRequest response = new ConfigChangeNotifyRequest();
response.setDataId(dataId);
response.setGroup(group);
response.setTenant(tenant);
return response;
ConfigChangeNotifyRequest request = new ConfigChangeNotifyRequest();
request.setDataId(dataId);
request.setGroup(group);
request.setTenant(tenant);
return request;
}
@Override
public String getModule() {
return "config";
}
}

View File

@ -1,109 +0,0 @@
/*
* Copyright 1999-2020 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.api.config.remote.request;
import com.alibaba.nacos.api.remote.request.ServerRequest;
/**
* ConfigReSyncRequest.
*
* @author liuzunfei
* @version $Id: ConfigReSyncRequest.java, v 0.1 2020年07月14日 3:20 PM liuzunfei Exp $
*/
public class ConfigReSyncRequest extends ServerRequest {
private String dataId;
private String group;
private String tenant;
@Override
public String getModule() {
return "config";
}
/**
* build success response.
*
* @param dataId dataId
* @param group group
* @param tenant tenant
* @return ConfigReSyncRequest
*/
public static ConfigReSyncRequest build(String dataId, String group, String tenant) {
ConfigReSyncRequest response = new ConfigReSyncRequest();
response.setDataId(dataId);
response.setGroup(group);
response.setTenant(tenant);
return response;
}
/**
* Getter method for property <tt>dataId</tt>.
*
* @return property value of dataId
*/
public String getDataId() {
return dataId;
}
/**
* Setter method for property <tt>dataId</tt>.
*
* @param dataId value to be assigned to property dataId
*/
public void setDataId(String dataId) {
this.dataId = dataId;
}
/**
* Getter method for property <tt>group</tt>.
*
* @return property value of group
*/
public String getGroup() {
return group;
}
/**
* Setter method for property <tt>group</tt>.
*
* @param group value to be assigned to property group
*/
public void setGroup(String group) {
this.group = group;
}
/**
* Getter method for property <tt>tenant</tt>.
*
* @return property value of tenant
*/
public String getTenant() {
return tenant;
}
/**
* Setter method for property <tt>tenant</tt>.
*
* @param tenant value to be assigned to property tenant
*/
public void setTenant(String tenant) {
this.tenant = tenant;
}
}

View File

@ -18,9 +18,6 @@ package com.alibaba.nacos.api.config.remote.response;
import com.alibaba.nacos.api.remote.response.Response;
import java.util.HashMap;
import java.util.Map;
/**
* ConfigQueryResponse.
*
@ -37,23 +34,19 @@ public class ConfigQueryResponse extends Response {
String contentType;
Map<String, String> labels = new HashMap<String, String>();
String md5;
long lastModified;
boolean isBeta;
String tag;
public ConfigQueryResponse() {
}
/**
* add label to this response.
*
* @param key key.
* @param value value.
*/
public void addLabel(String key, String value) {
this.labels.put(key, value);
}
/**
* Buid fail response.
* Build fail response.
*
* @param errorCode errorCode.
* @param message message.
@ -77,22 +70,36 @@ public class ConfigQueryResponse extends Response {
return response;
}
/**
* Getter method for property <tt>labels</tt>.
*
* @return property value of labels
*/
public Map<String, String> getLabels() {
return labels;
public String getTag() {
return tag;
}
/**
* Setter method for property <tt>labels</tt>.
*
* @param labels value to be assigned to property labels
*/
public void setLabels(Map<String, String> labels) {
this.labels = labels;
public void setTag(String tag) {
this.tag = tag;
}
public String getMd5() {
return md5;
}
public void setMd5(String md5) {
this.md5 = md5;
}
public long getLastModified() {
return lastModified;
}
public void setLastModified(long lastModified) {
this.lastModified = lastModified;
}
public boolean isBeta() {
return isBeta;
}
public void setBeta(boolean beta) {
isBeta = beta;
}
/**

View File

@ -1,28 +0,0 @@
/*
* Copyright 1999-2020 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.api.config.remote.response;
import com.alibaba.nacos.api.remote.response.Response;
/**
* config change notify response from client.
* @author liuzunfei
* @version $Id: ConfigChangeNotifyResponse.java, v 0.1 2020年09月01日 2:59 PM liuzunfei Exp $
*/
public class ConfigReSyncResponse extends Response {
}

View File

@ -26,14 +26,12 @@ import com.alibaba.nacos.api.config.remote.request.ConfigBatchListenRequest;
import com.alibaba.nacos.api.config.remote.request.ConfigChangeNotifyRequest;
import com.alibaba.nacos.api.config.remote.request.ConfigPublishRequest;
import com.alibaba.nacos.api.config.remote.request.ConfigQueryRequest;
import com.alibaba.nacos.api.config.remote.request.ConfigReSyncRequest;
import com.alibaba.nacos.api.config.remote.request.ConfigRemoveRequest;
import com.alibaba.nacos.api.config.remote.response.ClientConfigMetricResponse;
import com.alibaba.nacos.api.config.remote.response.ConfigChangeBatchListenResponse;
import com.alibaba.nacos.api.config.remote.response.ConfigChangeNotifyResponse;
import com.alibaba.nacos.api.config.remote.response.ConfigPublishResponse;
import com.alibaba.nacos.api.config.remote.response.ConfigQueryResponse;
import com.alibaba.nacos.api.config.remote.response.ConfigReSyncResponse;
import com.alibaba.nacos.api.config.remote.response.ConfigRemoveResponse;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.remote.RemoteConstants;
@ -45,6 +43,7 @@ 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.AppNameUtils;
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.TenantUtil;
@ -581,6 +580,9 @@ public class ClientWorker implements Closeable {
labels.put(RemoteConstants.LABEL_SOURCE, RemoteConstants.LABEL_SOURCE_SDK);
labels.put(RemoteConstants.LABEL_MODULE, RemoteConstants.LABEL_MODULE_CONFIG);
labels.put(Constants.APPNAME, AppNameUtils.getAppName());
labels.put(Constants.VIPSERVER_TAG, EnvUtil.getSelfVipserverTag());
labels.put(Constants.AMORY_TAG, EnvUtil.getSelfAmorayTag());
labels.put(Constants.LOCATION_TAG, EnvUtil.getSelfLocationTag());
return labels;
}
@ -590,22 +592,21 @@ public class ClientWorker implements Closeable {
* Register Config Change /Config ReSync Handler
*/
rpcClientInner.registerServerRequestHandler((request) -> {
if (request instanceof ConfigChangeNotifyRequest || request instanceof ConfigReSyncRequest) {
ConfigReSyncRequest configReSyncRequest = (ConfigReSyncRequest) request;
LOGGER.info("[{}] [server-push] config {}. dataId={}, group={}", rpcClientInner.getName(),
(request instanceof ConfigChangeNotifyRequest) ? "changed" : "re sync",
configReSyncRequest.getDataId(), configReSyncRequest.getGroup());
if (request instanceof ConfigChangeNotifyRequest) {
ConfigChangeNotifyRequest configChangeNotifyRequest = (ConfigChangeNotifyRequest) request;
LOGGER.info("[{}] [server-push] config changed. dataId={}, group={},tenant={}",
rpcClientInner.getName(), configChangeNotifyRequest.getDataId(),
configChangeNotifyRequest.getGroup(), configChangeNotifyRequest.getTenant());
String groupKey = GroupKey
.getKeyTenant(configReSyncRequest.getDataId(), configReSyncRequest.getGroup(),
configReSyncRequest.getTenant());
.getKeyTenant(configChangeNotifyRequest.getDataId(), configChangeNotifyRequest.getGroup(),
configChangeNotifyRequest.getTenant());
CacheData cacheData = cacheMap.get().get(groupKey);
if (cacheData != null) {
cacheData.setSyncWithServer(false);
notifyListenConfig();
}
return (request instanceof ConfigChangeNotifyRequest) ? new ConfigChangeNotifyResponse()
: new ConfigReSyncResponse();
return new ConfigChangeNotifyResponse();
}
return null;
});
@ -947,6 +948,7 @@ public class ClientWorker implements Closeable {
try {
request.putAllHeader(super.getSecurityHeaders());
request.putAllHeader(super.getSpasHeaders());
request.putAllHeader(super.getCommonHeader());
} catch (Exception e) {
throw new NacosException(NacosException.CLIENT_INVALID_PARAM, e);
}

View File

@ -23,7 +23,6 @@ import com.alibaba.nacos.client.identify.StsConfig;
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.common.constant.HttpHeaderConsts;
import com.alibaba.nacos.common.http.HttpRestResult;
import com.alibaba.nacos.common.http.param.Header;
import com.alibaba.nacos.common.http.param.Query;
@ -31,8 +30,6 @@ import com.alibaba.nacos.common.utils.ConvertUtils;
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.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;
@ -142,10 +139,8 @@ public abstract class ConfigTransportClient {
headers.put(Constants.CLIENT_APPNAME_HEADER, ParamUtil.getAppName());
headers.put(Constants.CLIENT_REQUEST_TS_HEADER, ts);
headers.put(Constants.CLIENT_REQUEST_TOKEN_HEADER, token);
headers.put(HttpHeaderConsts.CLIENT_VERSION_HEADER, VersionUtils.version);
headers.put("exConfigInfo", "true");
headers.put(HttpHeaderConsts.REQUEST_ID, UuidUtils.generateUuid());
headers.put(HttpHeaderConsts.ACCEPT_CHARSET, encode);
headers.put(Constants.CHARSET_KEY, encode);
return headers;
}

View File

@ -16,6 +16,7 @@
package com.alibaba.nacos.client.utils;
import com.alibaba.nacos.api.common.Constants;
import org.slf4j.Logger;
import java.util.List;
@ -32,7 +33,7 @@ public class EnvUtil {
public static void setSelfEnv(Map<String, List<String>> headers) {
if (headers != null) {
List<String> amorayTagTmp = headers.get(AMORY_TAG);
List<String> amorayTagTmp = headers.get(Constants.AMORY_TAG);
if (amorayTagTmp == null) {
if (selfAmorayTag != null) {
selfAmorayTag = null;
@ -46,7 +47,7 @@ public class EnvUtil {
}
}
List<String> vipserverTagTmp = headers.get(VIPSERVER_TAG);
List<String> vipserverTagTmp = headers.get(Constants.VIPSERVER_TAG);
if (vipserverTagTmp == null) {
if (selfVipserverTag != null) {
selfVipserverTag = null;
@ -59,7 +60,7 @@ public class EnvUtil {
LOGGER.warn("selfVipserverTag:{}", selfVipserverTag);
}
}
List<String> locationTagTmp = headers.get(LOCATION_TAG);
List<String> locationTagTmp = headers.get(Constants.LOCATION_TAG);
if (locationTagTmp == null) {
if (selfLocationTag != null) {
selfLocationTag = null;
@ -105,9 +106,4 @@ public class EnvUtil {
private static String selfLocationTag;
private static final String AMORY_TAG = "Amory-Tag";
private static final String VIPSERVER_TAG = "Vipserver-Tag";
private static final String LOCATION_TAG = "Location-Tag";
}
}

View File

@ -127,6 +127,8 @@ public class Constants {
public static final String NAMESPACE_CONTROLLER_PATH = BASE_PATH + "/namespaces";
public static final String METRICS_CONTROLLER_PATH = BASE_PATH + "/metrics";
public static final String ENCODE = "UTF-8";
public static final String MAP_FILE = "map-file.js";

View File

@ -0,0 +1,161 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.nacos.config.server.controller;
import com.alibaba.nacos.api.config.remote.request.ClientConfigMetricRequest;
import com.alibaba.nacos.api.config.remote.response.ClientConfigMetricResponse;
import com.alibaba.nacos.common.http.Callback;
import com.alibaba.nacos.common.http.HttpClientBeanHolder;
import com.alibaba.nacos.common.http.HttpUtils;
import com.alibaba.nacos.common.http.client.NacosAsyncRestTemplate;
import com.alibaba.nacos.common.http.param.Header;
import com.alibaba.nacos.common.http.param.Query;
import com.alibaba.nacos.common.model.RestResult;
import com.alibaba.nacos.config.server.constant.Constants;
import com.alibaba.nacos.config.server.utils.GroupKey2;
import com.alibaba.nacos.core.cluster.Member;
import com.alibaba.nacos.core.cluster.ServerMemberManager;
import com.alibaba.nacos.core.remote.Connection;
import com.alibaba.nacos.core.remote.ConnectionManager;
import com.alibaba.nacos.core.utils.GenericType;
import com.alibaba.nacos.core.utils.Loggers;
import com.alibaba.nacos.sys.env.EnvUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import static com.alibaba.nacos.api.config.remote.request.ClientConfigMetricRequest.MetricsKey.CACHE_DATA;
import static com.alibaba.nacos.api.config.remote.request.ClientConfigMetricRequest.MetricsKey.SNAPSHOT_DATA;
/**
* ClientMetricsController.
*
* @author zunfei.lzf
*/
@RestController
@RequestMapping(Constants.METRICS_CONTROLLER_PATH)
public class ClientMetricsController {
@Autowired
private ServerMemberManager serverMemberManager;
@Autowired
private ConnectionManager connectionManager;
/**
* get client metric.
*
* @param ip client ip .
* @return
*/
@GetMapping("/cluster")
public ResponseEntity metric(@RequestParam("ip") String ip,
@RequestParam(value = "dataId", required = false) String dataId,
@RequestParam(value = "group", required = false) String group,
@RequestParam(value = "tenant", required = false) String tenant) {
Loggers.CORE.info("Get cluster config metrics received, ip={},dataId={},group={},tenant={}", ip, dataId, group,
tenant);
Map<String, Object> responseMap = new HashMap<>(3);
Collection<Member> members = serverMemberManager.allMembers();
final NacosAsyncRestTemplate nacosAsyncRestTemplate = HttpClientBeanHolder
.getNacosAsyncRestTemplate(Loggers.CLUSTER);
CountDownLatch latch = new CountDownLatch(members.size());
for (Member member : members) {
String url = HttpUtils
.buildUrl(false, member.getAddress(), EnvUtil.getContextPath(), Constants.METRICS_CONTROLLER_PATH,
"current");
Query query = Query.newInstance().addParam("ip", ip).addParam("dataId", dataId).addParam("group", group)
.addParam("tenant", tenant);
nacosAsyncRestTemplate.get(url, Header.EMPTY, query, new GenericType<Map>() {
}.getType(), new Callback<Map>() {
@Override
public void onReceive(RestResult<Map> result) {
if (result.ok()) {
responseMap.putAll(result.getData());
}
latch.countDown();
}
@Override
public void onError(Throwable throwable) {
Loggers.CORE
.error("Get config metrics error from member address={}, ip={},dataId={},group={},tenant={},error={}",
member.getAddress(), ip, dataId, group, tenant, throwable);
latch.countDown();
}
@Override
public void onCancel() {
latch.countDown();
}
});
}
try {
latch.await(3L, TimeUnit.SECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
}
return ResponseEntity.ok().body(responseMap);
}
/**
* Get client config listener lists of subscriber in local machine.
*/
@GetMapping("/current")
public Map<String, Object> getClientMetrics(@RequestParam("ip") String ip,
@RequestParam(value = "dataId", required = false) String dataId,
@RequestParam(value = "group", required = false) String group,
@RequestParam(value = "tenant", required = false) String tenant) {
Map<String, Object> metrics = new HashMap<>(16);
List<Connection> connectionsByIp = connectionManager.getConnectionByIp(ip);
for (Connection connectionByIp : connectionsByIp) {
try {
ClientConfigMetricRequest clientMetrics = new ClientConfigMetricRequest();
if (StringUtils.isNotBlank(dataId)) {
clientMetrics.getMetricsKeys().add(ClientConfigMetricRequest.MetricsKey
.build(CACHE_DATA, GroupKey2.getKey(dataId, group, tenant)));
clientMetrics.getMetricsKeys().add(ClientConfigMetricRequest.MetricsKey
.build(SNAPSHOT_DATA, GroupKey2.getKey(dataId, group, tenant)));
}
ClientConfigMetricResponse request1 = (ClientConfigMetricResponse) connectionByIp
.request(clientMetrics, 1000L);
metrics.putAll(request1.getMetrics());
} catch (Exception e) {
Loggers.CORE.error("Get config metrics error from client ip={},dataId={},group={},tenant={},error={}", ip, dataId,
group, tenant, e);
}
}
return metrics;
}
}

View File

@ -16,10 +16,6 @@
package com.alibaba.nacos.config.server.controller;
import com.alibaba.nacos.api.config.remote.request.ClientConfigMetricRequest;
import com.alibaba.nacos.api.config.remote.request.ConfigChangeNotifyRequest;
import com.alibaba.nacos.api.config.remote.response.ClientConfigMetricResponse;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.config.server.constant.Constants;
import com.alibaba.nacos.config.server.model.SampleResult;
import com.alibaba.nacos.config.server.remote.ConfigChangeListenContext;
@ -31,7 +27,6 @@ import com.alibaba.nacos.core.remote.Connection;
import com.alibaba.nacos.core.remote.ConnectionManager;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
@ -40,15 +35,11 @@ import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import static com.alibaba.nacos.api.config.remote.request.ClientConfigMetricRequest.MetricsKey.CACHE_DATA;
import static com.alibaba.nacos.api.config.remote.request.ClientConfigMetricRequest.MetricsKey.SNAPSHOT_DATA;
/**
* Controller for other node notification.
*
@ -145,73 +136,5 @@ public class CommunicationController {
return result;
}
/**
* Notify client to check config from server.
*/
@GetMapping("/watcherSyncConfig")
public ResponseEntity watcherSyncConfig(@RequestParam("dataId") String dataId, @RequestParam("group") String group,
@RequestParam(value = "tenant", required = false) String tenant,
@RequestParam(value = "clientIp", required = false) String clientIp, ModelMap modelMap) {
String groupKey = GroupKey2.getKey(dataId, group, tenant);
Set<String> listenersClients = configChangeListenContext.getListeners(groupKey);
List<Connection> listeners = new ArrayList<>();
for (String connectionId : listenersClients) {
Connection connection = connectionManager.getConnection(connectionId);
if (connection != null) {
if (StringUtils.isNotBlank(clientIp) && !connection.getMetaInfo().getClientIp().equals(clientIp)) {
continue;
}
listeners.add(connection);
}
}
if (!listeners.isEmpty()) {
ConfigChangeNotifyRequest notifyRequest = new ConfigChangeNotifyRequest();
notifyRequest.setDataId(dataId);
notifyRequest.setGroup(group);
notifyRequest.setTenant(tenant);
for (Connection connectionByIp : listeners) {
try {
connectionByIp.request(notifyRequest, 3000L);
} catch (NacosException e) {
e.printStackTrace();
}
}
}
return ResponseEntity.ok().body(trueStr);
}
/**
* Get client config listener lists of subscriber in local machine.
*/
@GetMapping("/clientMetrics")
public Map<String, Object> getClientMetrics(@RequestParam("ip") String ip,
@RequestParam(value = "dataId", required = false) String dataId,
@RequestParam(value = "group", required = false) String group,
@RequestParam(value = "tenant", required = false) String tenant) {
Map<String, Object> metrics = new HashMap<>(16);
List<Connection> connectionsByIp = connectionManager.getConnectionByIp(ip);
for (Connection connectionByIp : connectionsByIp) {
try {
ClientConfigMetricRequest clientMetrics = new ClientConfigMetricRequest();
if (StringUtils.isNotBlank(dataId)) {
clientMetrics.getMetricsKeys().add(ClientConfigMetricRequest.MetricsKey
.build(CACHE_DATA, GroupKey2.getKey(dataId, group, tenant)));
clientMetrics.getMetricsKeys().add(ClientConfigMetricRequest.MetricsKey
.build(SNAPSHOT_DATA, GroupKey2.getKey(dataId, group, tenant)));
}
ClientConfigMetricResponse request1 = (ClientConfigMetricResponse) connectionByIp
.request(clientMetrics, 3000L);
metrics.putAll(request1.getMetrics());
} catch (NacosException e) {
e.printStackTrace();
}
}
return metrics;
}
}

View File

@ -48,8 +48,11 @@ import com.alibaba.nacos.config.server.utils.RequestUtil;
import com.alibaba.nacos.config.server.utils.TimeUtils;
import com.alibaba.nacos.config.server.utils.ZipUtils;
import com.alibaba.nacos.sys.utils.InetUtils;
import org.apache.catalina.connector.Request;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.tomcat.util.buf.ByteChunk;
import org.apache.tomcat.util.http.Parameters;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
@ -70,12 +73,14 @@ import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.Field;
import java.net.URLDecoder;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
@ -164,17 +169,17 @@ public class ConfigController {
configInfo.setType(type);
if (StringUtils.isBlank(betaIps)) {
if (StringUtils.isBlank(tag)) {
persistService.insertOrUpdate(srcIp, srcUser, configInfo, time, configAdvanceInfo, true);
persistService.insertOrUpdate(srcIp, srcUser, configInfo, time, configAdvanceInfo, false);
ConfigChangePublisher
.notifyConfigChange(new ConfigDataChangeEvent(false, dataId, group, tenant, time.getTime()));
} else {
persistService.insertOrUpdateTag(configInfo, tag, srcIp, srcUser, time, true);
persistService.insertOrUpdateTag(configInfo, tag, srcIp, srcUser, time, false);
ConfigChangePublisher.notifyConfigChange(
new ConfigDataChangeEvent(false, dataId, group, tenant, tag, time.getTime()));
}
} else {
// beta publish
persistService.insertOrUpdateBeta(configInfo, betaIps, srcIp, srcUser, time, true);
persistService.insertOrUpdateBeta(configInfo, betaIps, srcIp, srcUser, time, false);
ConfigChangePublisher
.notifyConfigChange(new ConfigDataChangeEvent(true, dataId, group, tenant, time.getTime()));
}
@ -204,9 +209,10 @@ public class ConfigController {
// check params
ParamUtils.checkParam(dataId, group, "datumId", "content");
ParamUtils.checkParam(tag);
final String clientIp = RequestUtil.getRemoteIp(request);
inner.doGetConfig(request, response, dataId, group, tenant, tag, clientIp);
String isNotify = request.getHeader("notify");
inner.doGetConfig(request, response, dataId, group, tenant, tag, isNotify, clientIp);
}
/**
@ -299,6 +305,46 @@ public class ConfigController {
return rr;
}
private void removeRequestContext(HttpServletRequest request) {
try {
request.removeAttribute("body");
Map<String, String[]> parameterMap = request.getParameterMap();
Field locked = parameterMap.getClass().getDeclaredField("locked");
locked.setAccessible(true);
locked.set(parameterMap, false);
parameterMap.remove(Constants.PROBE_MODIFY_REQUEST);
Field inneRequestFiled = request.getClass().getDeclaredField("request");
inneRequestFiled.setAccessible(true);
Request innerRequest = (Request) inneRequestFiled.get(request);
Field coyoteRequest = innerRequest.getClass().getDeclaredField("coyoteRequest");
coyoteRequest.setAccessible(true);
org.apache.coyote.Request coyotoRequest = (org.apache.coyote.Request) coyoteRequest.get(innerRequest);
Parameters parameters = coyotoRequest.getParameters();
Field hashMapField = parameters.getClass().getDeclaredField("paramHashValues");
hashMapField.setAccessible(true);
LinkedHashMap hashMaps = (LinkedHashMap) hashMapField.get(parameters);
hashMaps.remove(Constants.PROBE_MODIFY_REQUEST);
Field tmpNameField = parameters.getClass().getDeclaredField("tmpName");
tmpNameField.setAccessible(true);
ByteChunk tmpName = (ByteChunk) tmpNameField.get(parameters);
byte[] bytemp = new byte[0];
tmpName.setBytes(bytemp, 0, 0);
Field tmpValueField = parameters.getClass().getDeclaredField("tmpValue");
tmpValueField.setAccessible(true);
ByteChunk tmpValue = (ByteChunk) tmpValueField.get(parameters);
tmpValue.setBytes(bytemp, 0, 0);
} catch (Exception e) {
LOGGER.warn("remove listen request param error", e);
}
}
/**
* The client listens for configuration changes.
*/
@ -306,13 +352,16 @@ public class ConfigController {
@Secured(action = ActionTypes.READ, parser = ConfigResourceParser.class)
public void listener(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setAttribute("org.apache.catalina.ASYNC_SUPPORTED", true);
//remove large listen context , reduce request content to optimize cms gc.
removeRequestContext(request);
String probeModify = request.getParameter("Listening-Configs");
if (StringUtils.isBlank(probeModify)) {
LOGGER.warn("invalid probeModify is blank");
throw new IllegalArgumentException("invalid probeModify");
}
request.removeAttribute("body");
probeModify = URLDecoder.decode(probeModify, Constants.ENCODE);
Map<String, String> clientMd5Map;
@ -413,7 +462,7 @@ public class ConfigController {
RestResult<Boolean> rr = new RestResult<Boolean>();
try {
persistService.removeConfigInfo4Beta(dataId, group, tenant);
} catch (Exception e) {
} catch (Throwable e) {
LOGGER.error("remove beta data error", e);
rr.setCode(500);
rr.setData(false);
@ -448,7 +497,7 @@ public class ConfigController {
rr.setData(ci);
rr.setMessage("stop beta ok");
return rr;
} catch (Exception e) {
} catch (Throwable e) {
LOGGER.error("remove beta data error", e);
rr.setCode(500);
rr.setMessage("remove beta data error");

View File

@ -119,10 +119,15 @@ public class ConfigServletInner {
* Execute to get config API.
*/
public String doGetConfig(HttpServletRequest request, HttpServletResponse response, String dataId, String group,
String tenant, String tag, String clientIp) throws IOException, ServletException {
String tenant, String tag, String isNotify, String clientIp) throws IOException, ServletException {
boolean notify = false;
if (StringUtils.isNotBlank(isNotify)) {
notify = Boolean.valueOf(isNotify);
}
final String groupKey = GroupKey2.getKey(dataId, group, tenant);
String autoTag = request.getHeader("Vipserver-Tag");
boolean notify = Boolean.valueOf(request.getHeader("notify"));
String requestIpApp = RequestUtil.getAppName(request);
int lockResult = tryConfigReadLock(groupKey);
@ -139,14 +144,14 @@ public class ConfigServletInner {
if (cacheItem.isBeta() && cacheItem.getIps4Beta().contains(clientIp)) {
isBeta = true;
}
final String configType =
(null != cacheItem.getType()) ? cacheItem.getType() : FileTypeEnum.TEXT.getFileType();
response.setHeader("Config-Type", configType);
FileTypeEnum fileTypeEnum = FileTypeEnum.getFileTypeEnumByFileExtensionOrFileType(configType);
String contentTypeHeader = fileTypeEnum.getContentType();
response.setHeader(HttpHeaderConsts.CONTENT_TYPE, contentTypeHeader);
File file = null;
ConfigInfoBase configInfoBase = null;
PrintWriter out = null;
@ -194,9 +199,7 @@ public class ConfigServletInner {
// no data",
// new Object[]{clientIp, groupKey});
response.setStatus(HttpServletResponse.SC_NOT_FOUND);
response.getWriter().println("config data not exist");
return HttpServletResponse.SC_NOT_FOUND + "";
return get404Result(response);
}
}
} else {
@ -277,9 +280,7 @@ public class ConfigServletInner {
.logPullEvent(dataId, group, tenant, requestIpApp, -1, ConfigTraceService.PULL_EVENT_NOTFOUND, -1,
requestIp, notify);
response.setStatus(HttpServletResponse.SC_NOT_FOUND);
response.getWriter().println("config data not exist");
return HttpServletResponse.SC_NOT_FOUND + "";
return get404Result(response);
} else {
@ -297,9 +298,16 @@ public class ConfigServletInner {
private static void releaseConfigReadLock(String groupKey) {
ConfigCacheService.releaseReadLock(groupKey);
}
private String get404Result(HttpServletResponse response) throws IOException {
response.setStatus(HttpServletResponse.SC_NOT_FOUND);
response.getWriter().println("config data not exist");
return HttpServletResponse.SC_NOT_FOUND + "";
}
/**
* Try to add read lock.
*
* @param groupKey groupKey string value.
* @return 0 - No data and failed. Positive number - lock succeeded. Negative number - lock failed
*/

View File

@ -27,6 +27,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.PostConstruct;
import java.util.Map;
/**
* Health service.
@ -58,9 +59,10 @@ public class HealthController {
// TODO UP DOWN WARN
StringBuilder sb = new StringBuilder();
String dbStatus = dataSourceService.getHealth();
if (dbStatus.contains(heathUpStr) && memberManager.isInIpList()) {
boolean addressServerHealthy = isAddressServerHealthy();
if (dbStatus.contains(heathUpStr) && addressServerHealthy && memberManager.isInIpList()) {
sb.append(heathUpStr);
} else if (dbStatus.contains(heathWarnStr) && memberManager.isInIpList()) {
} else if (dbStatus.contains(heathWarnStr) && addressServerHealthy && memberManager.isInIpList()) {
sb.append("WARN:");
sb.append("slave db (").append(dbStatus.split(":")[1]).append(") down. ");
} else {
@ -68,13 +70,23 @@ public class HealthController {
if (dbStatus.contains(heathDownStr)) {
sb.append("master db (").append(dbStatus.split(":")[1]).append(") down. ");
}
if (!addressServerHealthy) {
sb.append("address server down. ");
}
if (!memberManager.isInIpList()) {
sb.append("server ip ").append(InetUtils.getSelfIP())
.append(" is not in the serverList of address server. ");
}
}
return sb.toString();
}
private boolean isAddressServerHealthy() {
Map<String, Object> info = memberManager.getLookup().info();
return info != null && info.get("addressServerHealth") != null && Boolean
.valueOf(info.get("addressServerHealth").toString());
}
}

View File

@ -49,7 +49,6 @@ import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import static com.alibaba.nacos.api.common.Constants.LINE_BREAK;
import static com.alibaba.nacos.config.server.utils.LogUtil.PULL_LOG;
@ -75,11 +74,11 @@ public class ConfigQueryRequestHandler extends RequestHandler<ConfigQueryRequest
@Override
@TpsControl(pointName = "ConfigQuery", parsers = {ConfigQueryGroupKeyParser.class, ConfigQueryGroupParser.class})
@Secured(action = ActionTypes.READ, parser = ConfigResourceParser.class)
public ConfigQueryResponse handle(ConfigQueryRequest configQueryRequest, RequestMeta requestMeta)
public ConfigQueryResponse handle(ConfigQueryRequest request, RequestMeta meta)
throws NacosException {
try {
ConfigQueryResponse context = getContext(configQueryRequest, requestMeta, configQueryRequest.isNotify());
ConfigQueryResponse context = getContext(request, meta, request.isNotify());
return context;
} catch (Exception e) {
ConfigQueryResponse contextFail = ConfigQueryResponse
@ -100,14 +99,15 @@ public class ConfigQueryRequestHandler extends RequestHandler<ConfigQueryRequest
final String groupKey = GroupKey2
.getKey(configQueryRequest.getDataId(), configQueryRequest.getGroup(), configQueryRequest.getTenant());
String autoTag = configQueryRequest.getHeader("Vipserver-Tag");
String autoTag = configQueryRequest.getHeader(com.alibaba.nacos.api.common.Constants.VIPSERVER_TAG);
String requestIpApp = meta.getLabels().get(CLIENT_APPNAME_HEADER);
int lockResult = tryConfigReadLock(groupKey);
boolean isBeta = false;
boolean isSli = false;
if (lockResult > 0) {
//FileInputStream fis = null;
try {
@ -134,7 +134,7 @@ public class ConfigQueryRequestHandler extends RequestHandler<ConfigQueryRequest
} else {
file = DiskUtil.targetBetaFile(dataId, group, tenant);
}
response.addLabel("isBeta", "Y");
response.setBeta(true);
} else {
if (StringUtils.isBlank(tag)) {
if (isUseTag(cacheItem, autoTag)) {
@ -151,9 +151,8 @@ public class ConfigQueryRequestHandler extends RequestHandler<ConfigQueryRequest
} else {
file = DiskUtil.targetTagFile(dataId, group, tenant, autoTag);
}
response.setTag(URLEncoder.encode(autoTag, Constants.ENCODE));
response.addLabel("Vipserver-Tag",
URLEncoder.encode(autoTag, StandardCharsets.UTF_8.displayName()));
} else {
md5 = cacheItem.getMd5();
lastModified = cacheItem.getLastModifiedTs();
@ -209,11 +208,11 @@ public class ConfigQueryRequestHandler extends RequestHandler<ConfigQueryRequest
}
}
}
response.addLabel(Constants.CONTENT_MD5, md5);
response.setMd5(md5);
if (PropertyUtil.isDirectRead()) {
response.addLabel("Last-Modified", String.valueOf(lastModified));
response.setLastModified(lastModified);
response.setContent(configInfoBase.getContent());
response.setResultCode(ResponseCode.SUCCESS.getCode());
@ -221,7 +220,7 @@ public class ConfigQueryRequestHandler extends RequestHandler<ConfigQueryRequest
//read from file
String content = readFileContent(file);
response.setContent(content);
response.addLabel("Last-Modified", String.valueOf(lastModified));
response.setLastModified(lastModified);
response.setResultCode(ResponseCode.SUCCESS.getCode());
}

View File

@ -95,7 +95,7 @@ public class AsyncNotifyService {
Queue<NotifySingleRpcTask> rpcQueue = new LinkedList<NotifySingleRpcTask>();
for (Member member : ipList) {
if (MemberUtil.isSupportedLongCon(member)) {
if (!MemberUtil.isSupportedLongCon(member)) {
httpQueue.add(new NotifySingleTask(dataId, group, tenant, tag, dumpTs, member.getAddress(),
evt.isBeta));
} else {

View File

@ -1,56 +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.console.controller;
import com.alibaba.nacos.core.cluster.ServerMemberManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import java.util.HashMap;
import java.util.Map;
/**
* ClientMetricsController.
*
* @author zunfei.lzf
*/
@RequestMapping("/v1/console/client")
public class ClientMetricsController {
@Autowired
private ServerMemberManager serverMemberManager;
/**
* get client metric.
* @param clientIp client ip .
* @return
*/
@GetMapping("/metrics")
public ResponseEntity metric(@RequestParam String clientIp) {
Map<String, String> responseMap = new HashMap<>(3);
return ResponseEntity.ok().body(responseMap);
}
private Map<String, String> geMetrics(String clientIp) {
return null;
}
}

View File

@ -36,6 +36,13 @@ public interface MemberLookup {
*/
void start() throws NacosException;
/**
* is using address server.
*
* @return using address server or not.
*/
boolean useAddressServer();
/**
* Inject the ServerMemberManager property.
*

View File

@ -82,6 +82,8 @@ public class ServerMemberManager implements ApplicationListener<WebServerInitial
private final NacosAsyncRestTemplate asyncRestTemplate = HttpClientBeanHolder
.getNacosAsyncRestTemplate(Loggers.CORE);
private static boolean isUseAddressServer = false;
/**
* Cluster node list.
*/
@ -90,7 +92,7 @@ public class ServerMemberManager implements ApplicationListener<WebServerInitial
/**
* Is this node in the cluster list.
*/
private volatile boolean isInIpList = true;
private static volatile boolean isInIpList = true;
/**
* port.
@ -162,11 +164,19 @@ public class ServerMemberManager implements ApplicationListener<WebServerInitial
private void initAndStartLookup() throws NacosException {
this.lookup = LookupFactory.createLookUp(this);
isUseAddressServer = this.lookup.useAddressServer();
this.lookup.start();
}
/**
* switch look up.
*
* @param name look up name.
* @throws NacosException exception.
*/
public void switchLookup(String name) throws NacosException {
this.lookup = LookupFactory.switchLookup(name, this);
isUseAddressServer = this.lookup.useAddressServer();
this.lookup.start();
}
@ -202,6 +212,10 @@ public class ServerMemberManager implements ApplicationListener<WebServerInitial
});
}
public static boolean isUseAddressServer() {
return isUseAddressServer;
}
/**
* member information update.
*
@ -257,6 +271,22 @@ public class ServerMemberManager implements ApplicationListener<WebServerInitial
return result;
}
public List<String> getServerListUnhealth() {
List<String> unhealthyMembers = new ArrayList<>();
for (Member member : this.allMembers()) {
NodeState state = member.getState();
if (state.equals(NodeState.DOWN)) {
unhealthyMembers.add(member.getAddress());
}
}
return unhealthyMembers;
}
public MemberLookup getLookup() {
return lookup;
}
public Member getSelf() {
return this.self;
}
@ -438,7 +468,7 @@ public class ServerMemberManager implements ApplicationListener<WebServerInitial
return Collections.unmodifiableMap(serverList);
}
public boolean isInIpList() {
public static boolean isInIpList() {
return isInIpList;
}

View File

@ -75,6 +75,11 @@ public class AddressServerMemberLookup extends AbstractMemberLookup {
}
}
@Override
public boolean useAddressServer() {
return true;
}
private void initAddressSys() {
String envDomainName = System.getenv("address_server_domain");
if (StringUtils.isBlank(envDomainName)) {

View File

@ -65,6 +65,11 @@ public class FileConfigMemberLookup extends AbstractMemberLookup {
}
}
@Override
public boolean useAddressServer() {
return false;
}
@Override
public void destroy() throws NacosException {
WatchFileCenter.deregisterWatcher(EnvUtil.getConfPath(), watcher);

View File

@ -37,4 +37,9 @@ public class StandaloneMemberLookup extends AbstractMemberLookup {
afterLookup(MemberUtil.readServerConf(Collections.singletonList(url)));
}
}
@Override
public boolean useAddressServer() {
return false;
}
}

View File

@ -23,6 +23,8 @@ import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import static com.alibaba.nacos.api.common.Constants.VIPSERVER_TAG;
/**
* ConnectionMetaInfo.
*
@ -87,6 +89,10 @@ public class ConnectionMeta {
return labels.get(labelKey);
}
public String getTag() {
return labels.get(VIPSERVER_TAG);
}
public ConnectionMeta(String connectionId, String clientIp, int clientPort, int localPort, String connectType,
String version, String appName, Map<String, String> labels) {
this.connectionId = connectionId;