diff --git a/api/src/main/java/com/alibaba/nacos/api/common/Constants.java b/api/src/main/java/com/alibaba/nacos/api/common/Constants.java index f6d330a92..11d3ed303 100644 --- a/api/src/main/java/com/alibaba/nacos/api/common/Constants.java +++ b/api/src/main/java/com/alibaba/nacos/api/common/Constants.java @@ -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"; } diff --git a/api/src/main/java/com/alibaba/nacos/api/config/remote/request/ConfigChangeNotifyRequest.java b/api/src/main/java/com/alibaba/nacos/api/config/remote/request/ConfigChangeNotifyRequest.java index 0377ce2c9..e4c67742f 100644 --- a/api/src/main/java/com/alibaba/nacos/api/config/remote/request/ConfigChangeNotifyRequest.java +++ b/api/src/main/java/com/alibaba/nacos/api/config/remote/request/ConfigChangeNotifyRequest.java @@ -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"; } } diff --git a/api/src/main/java/com/alibaba/nacos/api/config/remote/request/ConfigReSyncRequest.java b/api/src/main/java/com/alibaba/nacos/api/config/remote/request/ConfigReSyncRequest.java deleted file mode 100644 index d0d3b9322..000000000 --- a/api/src/main/java/com/alibaba/nacos/api/config/remote/request/ConfigReSyncRequest.java +++ /dev/null @@ -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 dataId. - * - * @return property value of dataId - */ - public String getDataId() { - return dataId; - } - - /** - * Setter method for property dataId. - * - * @param dataId value to be assigned to property dataId - */ - public void setDataId(String dataId) { - this.dataId = dataId; - } - - /** - * Getter method for property group. - * - * @return property value of group - */ - public String getGroup() { - return group; - } - - /** - * Setter method for property group. - * - * @param group value to be assigned to property group - */ - public void setGroup(String group) { - this.group = group; - } - - /** - * Getter method for property tenant. - * - * @return property value of tenant - */ - public String getTenant() { - return tenant; - } - - /** - * Setter method for property tenant. - * - * @param tenant value to be assigned to property tenant - */ - public void setTenant(String tenant) { - this.tenant = tenant; - } -} diff --git a/api/src/main/java/com/alibaba/nacos/api/config/remote/response/ConfigQueryResponse.java b/api/src/main/java/com/alibaba/nacos/api/config/remote/response/ConfigQueryResponse.java index 3b67269c5..48ca4936c 100644 --- a/api/src/main/java/com/alibaba/nacos/api/config/remote/response/ConfigQueryResponse.java +++ b/api/src/main/java/com/alibaba/nacos/api/config/remote/response/ConfigQueryResponse.java @@ -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 labels = new HashMap(); + 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 labels. - * - * @return property value of labels - */ - public Map getLabels() { - return labels; + public String getTag() { + return tag; } - /** - * Setter method for property labels. - * - * @param labels value to be assigned to property labels - */ - public void setLabels(Map 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; } /** diff --git a/api/src/main/java/com/alibaba/nacos/api/config/remote/response/ConfigReSyncResponse.java b/api/src/main/java/com/alibaba/nacos/api/config/remote/response/ConfigReSyncResponse.java deleted file mode 100644 index 9989ec482..000000000 --- a/api/src/main/java/com/alibaba/nacos/api/config/remote/response/ConfigReSyncResponse.java +++ /dev/null @@ -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 { - -} diff --git a/client/src/main/java/com/alibaba/nacos/client/config/impl/ClientWorker.java b/client/src/main/java/com/alibaba/nacos/client/config/impl/ClientWorker.java index ad166dd6b..aae4b5f6c 100644 --- a/client/src/main/java/com/alibaba/nacos/client/config/impl/ClientWorker.java +++ b/client/src/main/java/com/alibaba/nacos/client/config/impl/ClientWorker.java @@ -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); } diff --git a/client/src/main/java/com/alibaba/nacos/client/config/impl/ConfigTransportClient.java b/client/src/main/java/com/alibaba/nacos/client/config/impl/ConfigTransportClient.java index 0ac40cf37..692efdb8d 100644 --- a/client/src/main/java/com/alibaba/nacos/client/config/impl/ConfigTransportClient.java +++ b/client/src/main/java/com/alibaba/nacos/client/config/impl/ConfigTransportClient.java @@ -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; } diff --git a/client/src/main/java/com/alibaba/nacos/client/utils/EnvUtil.java b/client/src/main/java/com/alibaba/nacos/client/utils/EnvUtil.java index 35eb554bc..dae81fa49 100644 --- a/client/src/main/java/com/alibaba/nacos/client/utils/EnvUtil.java +++ b/client/src/main/java/com/alibaba/nacos/client/utils/EnvUtil.java @@ -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> headers) { if (headers != null) { - List amorayTagTmp = headers.get(AMORY_TAG); + List amorayTagTmp = headers.get(Constants.AMORY_TAG); if (amorayTagTmp == null) { if (selfAmorayTag != null) { selfAmorayTag = null; @@ -46,7 +47,7 @@ public class EnvUtil { } } - List vipserverTagTmp = headers.get(VIPSERVER_TAG); + List 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 locationTagTmp = headers.get(LOCATION_TAG); + List 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"; -} +} \ No newline at end of file diff --git a/config/src/main/java/com/alibaba/nacos/config/server/constant/Constants.java b/config/src/main/java/com/alibaba/nacos/config/server/constant/Constants.java index b5c5ffbc7..3a6fef66c 100644 --- a/config/src/main/java/com/alibaba/nacos/config/server/constant/Constants.java +++ b/config/src/main/java/com/alibaba/nacos/config/server/constant/Constants.java @@ -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"; diff --git a/config/src/main/java/com/alibaba/nacos/config/server/controller/ClientMetricsController.java b/config/src/main/java/com/alibaba/nacos/config/server/controller/ClientMetricsController.java new file mode 100644 index 000000000..6c9f11ed8 --- /dev/null +++ b/config/src/main/java/com/alibaba/nacos/config/server/controller/ClientMetricsController.java @@ -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 responseMap = new HashMap<>(3); + Collection 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() { + }.getType(), new Callback() { + + @Override + public void onReceive(RestResult 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 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 metrics = new HashMap<>(16); + List 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; + + } + +} diff --git a/config/src/main/java/com/alibaba/nacos/config/server/controller/CommunicationController.java b/config/src/main/java/com/alibaba/nacos/config/server/controller/CommunicationController.java index 2ce32e389..0cbc39181 100755 --- a/config/src/main/java/com/alibaba/nacos/config/server/controller/CommunicationController.java +++ b/config/src/main/java/com/alibaba/nacos/config/server/controller/CommunicationController.java @@ -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 listenersClients = configChangeListenContext.getListeners(groupKey); - List 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 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 metrics = new HashMap<>(16); - List 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; - - } + } diff --git a/config/src/main/java/com/alibaba/nacos/config/server/controller/ConfigController.java b/config/src/main/java/com/alibaba/nacos/config/server/controller/ConfigController.java index 6e2349feb..c1890d335 100644 --- a/config/src/main/java/com/alibaba/nacos/config/server/controller/ConfigController.java +++ b/config/src/main/java/com/alibaba/nacos/config/server/controller/ConfigController.java @@ -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 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 clientMd5Map; @@ -413,7 +462,7 @@ public class ConfigController { RestResult rr = new RestResult(); 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"); diff --git a/config/src/main/java/com/alibaba/nacos/config/server/controller/ConfigServletInner.java b/config/src/main/java/com/alibaba/nacos/config/server/controller/ConfigServletInner.java index a3a2dd36b..bf325e93c 100755 --- a/config/src/main/java/com/alibaba/nacos/config/server/controller/ConfigServletInner.java +++ b/config/src/main/java/com/alibaba/nacos/config/server/controller/ConfigServletInner.java @@ -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。 */ diff --git a/config/src/main/java/com/alibaba/nacos/config/server/controller/HealthController.java b/config/src/main/java/com/alibaba/nacos/config/server/controller/HealthController.java index 1fa35f643..896306dc7 100644 --- a/config/src/main/java/com/alibaba/nacos/config/server/controller/HealthController.java +++ b/config/src/main/java/com/alibaba/nacos/config/server/controller/HealthController.java @@ -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 info = memberManager.getLookup().info(); + return info != null && info.get("addressServerHealth") != null && Boolean + .valueOf(info.get("addressServerHealth").toString()); + } + } diff --git a/config/src/main/java/com/alibaba/nacos/config/server/remote/ConfigQueryRequestHandler.java b/config/src/main/java/com/alibaba/nacos/config/server/remote/ConfigQueryRequestHandler.java index 13d08642b..7537c818a 100644 --- a/config/src/main/java/com/alibaba/nacos/config/server/remote/ConfigQueryRequestHandler.java +++ b/config/src/main/java/com/alibaba/nacos/config/server/remote/ConfigQueryRequestHandler.java @@ -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 0) { //FileInputStream fis = null; try { @@ -134,7 +134,7 @@ public class ConfigQueryRequestHandler extends RequestHandler rpcQueue = new LinkedList(); 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 { diff --git a/console/src/main/java/com/alibaba/nacos/console/controller/ClientMetricsController.java b/console/src/main/java/com/alibaba/nacos/console/controller/ClientMetricsController.java deleted file mode 100644 index 25df5fb0b..000000000 --- a/console/src/main/java/com/alibaba/nacos/console/controller/ClientMetricsController.java +++ /dev/null @@ -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 responseMap = new HashMap<>(3); - - return ResponseEntity.ok().body(responseMap); - } - - private Map geMetrics(String clientIp) { - return null; - } - -} diff --git a/core/src/main/java/com/alibaba/nacos/core/cluster/MemberLookup.java b/core/src/main/java/com/alibaba/nacos/core/cluster/MemberLookup.java index 4d6f40785..9dee565bb 100644 --- a/core/src/main/java/com/alibaba/nacos/core/cluster/MemberLookup.java +++ b/core/src/main/java/com/alibaba/nacos/core/cluster/MemberLookup.java @@ -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. * diff --git a/core/src/main/java/com/alibaba/nacos/core/cluster/ServerMemberManager.java b/core/src/main/java/com/alibaba/nacos/core/cluster/ServerMemberManager.java index 67fb314ba..75c74a65b 100644 --- a/core/src/main/java/com/alibaba/nacos/core/cluster/ServerMemberManager.java +++ b/core/src/main/java/com/alibaba/nacos/core/cluster/ServerMemberManager.java @@ -82,6 +82,8 @@ public class ServerMemberManager implements ApplicationListener getServerListUnhealth() { + List 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 labels) { this.connectionId = connectionId;