From 164ed33ada04d713219e9c1af1f6505333341997 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E6=9D=A8=E7=BF=8A=20SionYang?= <263976490@qq.com>
Date: Wed, 11 Nov 2020 19:50:14 +0800
Subject: [PATCH] Feature support grpc core (#4204)
* NacosNamingMetadataManager --> NamingMetadataManager
* Try to add ServiceMetadata consistency
* add catalog api support new data
* Change version to 2.0.0-SNAPSHOT
---
address/pom.xml | 2 +-
api/pom.xml | 2 +-
auth/pom.xml | 2 +-
client/pom.xml | 2 +-
cmdb/pom.xml | 2 +-
common/pom.xml | 2 +-
config/pom.xml | 2 +-
consistency/pom.xml | 2 +-
console/pom.xml | 2 +-
core/pom.xml | 2 +-
distribution/pom.xml | 2 +-
example/pom.xml | 2 +-
istio/pom.xml | 2 +-
naming/pom.xml | 2 +-
.../naming/controllers/CatalogController.java | 161 ++-----------
.../nacos/naming/core/CatalogService.java | 84 +++++++
.../naming/core/CatalogServiceV1Impl.java | 194 ++++++++++++++++
.../naming/core/CatalogServiceV2Impl.java | 211 ++++++++++++++++++
.../naming/core/v2/index/ServiceStorage.java | 21 +-
.../core/v2/metadata/MetadataOperation.java | 65 ++++++
...anager.java => NamingMetadataManager.java} | 4 +-
.../NamingMetadataOperateService.java | 93 ++++++++
.../core/v2/metadata/ServiceMetadata.java | 32 ++-
.../v2/metadata/ServiceMetadataProcessor.java | 102 +++++++++
.../EphemeralClientOperationServiceImpl.java | 1 +
.../heartbeat/ClientBeatCheckTaskV2.java | 6 +-
.../heartbeat/ExpiredInstanceChecker.java | 4 +-
.../InstanceEnableBeatCheckInterceptor.java | 4 +-
.../ServiceEnableBeatCheckInterceptor.java | 4 +-
.../heartbeat/UnhealthyInstanceChecker.java | 4 +-
.../alibaba/nacos/naming/utils/Constants.java | 2 +-
.../controllers/CatalogControllerTest.java | 2 +-
.../heartbeat/ClientBeatCheckTaskV2Test.java | 8 +-
.../HealthCheckTaskInterceptWrapperTest.java | 8 +-
pom.xml | 4 +-
sys/pom.xml | 2 +-
test/pom.xml | 2 +-
37 files changed, 856 insertions(+), 190 deletions(-)
create mode 100644 naming/src/main/java/com/alibaba/nacos/naming/core/CatalogService.java
create mode 100644 naming/src/main/java/com/alibaba/nacos/naming/core/CatalogServiceV1Impl.java
create mode 100644 naming/src/main/java/com/alibaba/nacos/naming/core/CatalogServiceV2Impl.java
create mode 100644 naming/src/main/java/com/alibaba/nacos/naming/core/v2/metadata/MetadataOperation.java
rename naming/src/main/java/com/alibaba/nacos/naming/core/v2/metadata/{NacosNamingMetadataManager.java => NamingMetadataManager.java} (98%)
create mode 100644 naming/src/main/java/com/alibaba/nacos/naming/core/v2/metadata/NamingMetadataOperateService.java
create mode 100644 naming/src/main/java/com/alibaba/nacos/naming/core/v2/metadata/ServiceMetadataProcessor.java
diff --git a/address/pom.xml b/address/pom.xml
index 5db51447c..475582f82 100644
--- a/address/pom.xml
+++ b/address/pom.xml
@@ -19,7 +19,7 @@
nacos-all
com.alibaba.nacos
- 2.0.0-ALPHA
+ 2.0.0-SNAPSHOT
4.0.0
diff --git a/api/pom.xml b/api/pom.xml
index 4e1143c8b..c2cc72f73 100644
--- a/api/pom.xml
+++ b/api/pom.xml
@@ -19,7 +19,7 @@
com.alibaba.nacos
nacos-all
- 2.0.0-ALPHA
+ 2.0.0-SNAPSHOT
4.0.0
diff --git a/auth/pom.xml b/auth/pom.xml
index d350fe492..572600f50 100644
--- a/auth/pom.xml
+++ b/auth/pom.xml
@@ -21,7 +21,7 @@
com.alibaba.nacos
nacos-all
- 2.0.0-ALPHA
+ 2.0.0-SNAPSHOT
../pom.xml
4.0.0
diff --git a/client/pom.xml b/client/pom.xml
index 3340b3ab4..af7216f89 100644
--- a/client/pom.xml
+++ b/client/pom.xml
@@ -19,7 +19,7 @@
com.alibaba.nacos
nacos-all
- 2.0.0-ALPHA
+ 2.0.0-SNAPSHOT
../pom.xml
diff --git a/cmdb/pom.xml b/cmdb/pom.xml
index d223a2e15..5ad21d8cb 100644
--- a/cmdb/pom.xml
+++ b/cmdb/pom.xml
@@ -21,7 +21,7 @@
nacos-all
com.alibaba.nacos
- 2.0.0-ALPHA
+ 2.0.0-SNAPSHOT
../pom.xml
4.0.0
diff --git a/common/pom.xml b/common/pom.xml
index af54a0dd9..9ae93f830 100644
--- a/common/pom.xml
+++ b/common/pom.xml
@@ -21,7 +21,7 @@
com.alibaba.nacos
nacos-all
- 2.0.0-ALPHA
+ 2.0.0-SNAPSHOT
../pom.xml
4.0.0
diff --git a/config/pom.xml b/config/pom.xml
index 990aace4e..4a614671f 100644
--- a/config/pom.xml
+++ b/config/pom.xml
@@ -20,7 +20,7 @@
com.alibaba.nacos
nacos-all
- 2.0.0-ALPHA
+ 2.0.0-SNAPSHOT
4.0.0
diff --git a/consistency/pom.xml b/consistency/pom.xml
index c713df2b6..eb4d2bb99 100644
--- a/consistency/pom.xml
+++ b/consistency/pom.xml
@@ -85,7 +85,7 @@
com.alibaba.nacos
nacos-all
../pom.xml
- 2.0.0-ALPHA
+ 2.0.0-SNAPSHOT
diff --git a/console/pom.xml b/console/pom.xml
index 11d98a6a2..f472b4232 100644
--- a/console/pom.xml
+++ b/console/pom.xml
@@ -21,7 +21,7 @@
com.alibaba.nacos
nacos-all
- 2.0.0-ALPHA
+ 2.0.0-SNAPSHOT
nacos-console
jar
diff --git a/core/pom.xml b/core/pom.xml
index 49c468b03..3c63a371f 100644
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -21,7 +21,7 @@
com.alibaba.nacos
nacos-all
- 2.0.0-ALPHA
+ 2.0.0-SNAPSHOT
../pom.xml
diff --git a/distribution/pom.xml b/distribution/pom.xml
index a7fa42583..ea876cc4a 100644
--- a/distribution/pom.xml
+++ b/distribution/pom.xml
@@ -21,7 +21,7 @@
com.alibaba.nacos
nacos-all
- 2.0.0-ALPHA
+ 2.0.0-SNAPSHOT
../pom.xml
diff --git a/example/pom.xml b/example/pom.xml
index be732f90c..8a4b2337d 100644
--- a/example/pom.xml
+++ b/example/pom.xml
@@ -21,7 +21,7 @@
com.alibaba.nacos
nacos-all
- 2.0.0-ALPHA
+ 2.0.0-SNAPSHOT
../pom.xml
diff --git a/istio/pom.xml b/istio/pom.xml
index bbd3c7d12..c8937f4c8 100644
--- a/istio/pom.xml
+++ b/istio/pom.xml
@@ -19,7 +19,7 @@
nacos-all
com.alibaba.nacos
- 2.0.0-ALPHA
+ 2.0.0-SNAPSHOT
4.0.0
diff --git a/naming/pom.xml b/naming/pom.xml
index 426f83205..d3312dd0b 100644
--- a/naming/pom.xml
+++ b/naming/pom.xml
@@ -21,7 +21,7 @@
com.alibaba.nacos
nacos-all
- 2.0.0-ALPHA
+ 2.0.0-SNAPSHOT
../pom.xml
diff --git a/naming/src/main/java/com/alibaba/nacos/naming/controllers/CatalogController.java b/naming/src/main/java/com/alibaba/nacos/naming/controllers/CatalogController.java
index ce0992e8f..c9ce30fff 100644
--- a/naming/src/main/java/com/alibaba/nacos/naming/controllers/CatalogController.java
+++ b/naming/src/main/java/com/alibaba/nacos/naming/controllers/CatalogController.java
@@ -19,26 +19,21 @@ package com.alibaba.nacos.naming.controllers;
import com.alibaba.nacos.api.common.Constants;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.naming.CommonParams;
-import com.alibaba.nacos.api.naming.pojo.Cluster;
+import com.alibaba.nacos.api.naming.pojo.Instance;
import com.alibaba.nacos.api.naming.utils.NamingUtils;
import com.alibaba.nacos.auth.annotation.Secured;
import com.alibaba.nacos.auth.common.ActionTypes;
import com.alibaba.nacos.common.utils.JacksonUtils;
import com.alibaba.nacos.core.utils.WebUtils;
-import com.alibaba.nacos.naming.core.Instance;
+import com.alibaba.nacos.naming.core.CatalogServiceV1Impl;
+import com.alibaba.nacos.naming.core.CatalogServiceV2Impl;
import com.alibaba.nacos.naming.core.Service;
import com.alibaba.nacos.naming.core.ServiceManager;
import com.alibaba.nacos.naming.healthcheck.HealthCheckTask;
import com.alibaba.nacos.naming.misc.UtilsAndCommons;
-import com.alibaba.nacos.naming.pojo.ClusterInfo;
-import com.alibaba.nacos.naming.pojo.IpAddressInfo;
-import com.alibaba.nacos.naming.pojo.ServiceDetailInfo;
-import com.alibaba.nacos.naming.pojo.ServiceView;
import com.alibaba.nacos.naming.web.NamingResourceParser;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
-
-import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
@@ -47,10 +42,6 @@ import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.LinkedList;
import java.util.List;
import java.util.Map;
@@ -66,6 +57,12 @@ public class CatalogController {
@Autowired
protected ServiceManager serviceManager;
+ @Autowired
+ private CatalogServiceV1Impl catalogServiceV1;
+
+ @Autowired
+ private CatalogServiceV2Impl catalogServiceV2;
+
/**
* Get service detail.
*
@@ -76,41 +73,11 @@ public class CatalogController {
*/
@Secured(parser = NamingResourceParser.class, action = ActionTypes.READ)
@GetMapping("/service")
- public ObjectNode serviceDetail(@RequestParam(defaultValue = Constants.DEFAULT_NAMESPACE_ID) String namespaceId,
+ public Object serviceDetail(@RequestParam(defaultValue = Constants.DEFAULT_NAMESPACE_ID) String namespaceId,
String serviceName) throws NacosException {
-
- Service detailedService = serviceManager.getService(namespaceId, serviceName);
-
- if (detailedService == null) {
- throw new NacosException(NacosException.NOT_FOUND, "service " + serviceName + " is not found!");
- }
- ObjectNode serviceObject = JacksonUtils.createEmptyJsonNode();
- serviceObject.put("name", NamingUtils.getServiceName(serviceName));
- serviceObject.put("protectThreshold", detailedService.getProtectThreshold());
- serviceObject.put("groupName", NamingUtils.getGroupName(serviceName));
- serviceObject.replace("selector", JacksonUtils.transferToJsonNode(detailedService.getSelector()));
- serviceObject.replace("metadata", JacksonUtils.transferToJsonNode(detailedService.getMetadata()));
-
- ObjectNode detailView = JacksonUtils.createEmptyJsonNode();
- detailView.replace("service", serviceObject);
-
- List clusters = new ArrayList<>();
-
- for (com.alibaba.nacos.naming.core.Cluster cluster : detailedService.getClusterMap().values()) {
- Cluster clusterView = new Cluster();
- clusterView.setName(cluster.getName());
- clusterView.setHealthChecker(cluster.getHealthChecker());
- clusterView.setMetadata(cluster.getMetadata());
- clusterView.setUseIPPort4Check(cluster.isUseIPPort4Check());
- clusterView.setDefaultPort(cluster.getDefaultPort());
- clusterView.setDefaultCheckPort(cluster.getDefaultCheckPort());
- clusterView.setServiceName(cluster.getService().getName());
- clusters.add(clusterView);
- }
-
- detailView.replace("clusters", JacksonUtils.transferToJsonNode(clusters));
-
- return detailView;
+ String serviceNameWithoutGroup = NamingUtils.getServiceName(serviceName);
+ String groupName = NamingUtils.getGroupName(serviceName);
+ return catalogServiceV2.getServiceDetail(namespaceId, groupName, serviceNameWithoutGroup);
}
/**
@@ -129,18 +96,10 @@ public class CatalogController {
public ObjectNode instanceList(@RequestParam(defaultValue = Constants.DEFAULT_NAMESPACE_ID) String namespaceId,
@RequestParam String serviceName, @RequestParam String clusterName, @RequestParam(name = "pageNo") int page,
@RequestParam int pageSize) throws NacosException {
-
- Service service = serviceManager.getService(namespaceId, serviceName);
- if (service == null) {
- throw new NacosException(NacosException.NOT_FOUND, "serivce " + serviceName + " is not found!");
- }
-
- if (!service.getClusterMap().containsKey(clusterName)) {
- throw new NacosException(NacosException.NOT_FOUND, "cluster " + clusterName + " is not found!");
- }
-
- List instances = service.getClusterMap().get(clusterName).allIPs();
-
+ String serviceNameWithoutGroup = NamingUtils.getServiceName(serviceName);
+ String groupName = NamingUtils.getGroupName(serviceName);
+ List extends Instance> instances = catalogServiceV2
+ .listInstances(namespaceId, groupName, serviceNameWithoutGroup, clusterName);
int start = (page - 1) * pageSize;
int end = page * pageSize;
@@ -184,58 +143,13 @@ public class CatalogController {
@RequestParam(name = "serviceNameParam", defaultValue = StringUtils.EMPTY) String serviceName,
@RequestParam(name = "groupNameParam", defaultValue = StringUtils.EMPTY) String groupName,
@RequestParam(name = "instance", defaultValue = StringUtils.EMPTY) String containedInstance,
- @RequestParam(required = false) boolean hasIpCount) {
-
- String param = StringUtils.isBlank(serviceName) && StringUtils.isBlank(groupName) ? StringUtils.EMPTY
- : NamingUtils.getGroupedName(serviceName, groupName);
+ @RequestParam(required = false) boolean hasIpCount) throws NacosException {
if (withInstances) {
- List serviceDetailInfoList = new ArrayList<>();
-
- List services = new ArrayList<>(8);
- serviceManager.getPagedService(namespaceId, pageNo, pageSize, param, StringUtils.EMPTY, services, false);
-
- for (Service service : services) {
- ServiceDetailInfo serviceDetailInfo = new ServiceDetailInfo();
- serviceDetailInfo.setServiceName(NamingUtils.getServiceName(service.getName()));
- serviceDetailInfo.setGroupName(NamingUtils.getGroupName(service.getName()));
- serviceDetailInfo.setMetadata(service.getMetadata());
-
- Map clusterInfoMap = getStringClusterInfoMap(service);
- serviceDetailInfo.setClusterMap(clusterInfoMap);
-
- serviceDetailInfoList.add(serviceDetailInfo);
- }
-
- return serviceDetailInfoList;
+ return catalogServiceV2.pageListServiceDetail(namespaceId, groupName, serviceName, pageNo, pageSize);
}
-
- ObjectNode result = JacksonUtils.createEmptyJsonNode();
-
- List services = new ArrayList<>();
- final int total = serviceManager.getPagedService(namespaceId, pageNo - 1, pageSize, param, containedInstance, services, hasIpCount);
- if (CollectionUtils.isEmpty(services)) {
- result.replace("serviceList", JacksonUtils.transferToJsonNode(Collections.emptyList()));
- result.put("count", 0);
- return result;
- }
-
- List serviceViews = new LinkedList<>();
- for (Service service : services) {
- ServiceView serviceView = new ServiceView();
- serviceView.setName(NamingUtils.getServiceName(service.getName()));
- serviceView.setGroupName(NamingUtils.getGroupName(service.getName()));
- serviceView.setClusterCount(service.getClusterMap().size());
- serviceView.setIpCount(service.allIPs().size());
- serviceView.setHealthyInstanceCount(service.healthyInstanceCount());
- serviceView.setTriggerFlag(service.triggerFlag() ? "true" : "false");
- serviceViews.add(serviceView);
- }
-
- result.replace("serviceList", JacksonUtils.transferToJsonNode(serviceViews));
- result.put("count", total);
-
- return result;
+ return catalogServiceV2
+ .pageListService(namespaceId, groupName, serviceName, pageNo, pageSize, containedInstance, hasIpCount);
}
/**
@@ -273,37 +187,4 @@ public class CatalogController {
result.replace("clusters", clusters);
return result;
}
-
- private Map getStringClusterInfoMap(Service service) {
- Map clusterInfoMap = new HashMap<>(8);
-
- service.getClusterMap().forEach((clusterName, cluster) -> {
-
- ClusterInfo clusterInfo = new ClusterInfo();
- List ipAddressInfos = getIpAddressInfos(cluster.allIPs());
- clusterInfo.setHosts(ipAddressInfos);
- clusterInfoMap.put(clusterName, clusterInfo);
-
- });
- return clusterInfoMap;
- }
-
- private List getIpAddressInfos(List instances) {
- List ipAddressInfos = new ArrayList<>();
-
- instances.forEach((ipAddress) -> {
-
- IpAddressInfo ipAddressInfo = new IpAddressInfo();
- ipAddressInfo.setIp(ipAddress.getIp());
- ipAddressInfo.setPort(ipAddress.getPort());
- ipAddressInfo.setMetadata(ipAddress.getMetadata());
- ipAddressInfo.setValid(ipAddress.isHealthy());
- ipAddressInfo.setWeight(ipAddress.getWeight());
- ipAddressInfo.setEnabled(ipAddress.isEnabled());
- ipAddressInfos.add(ipAddressInfo);
-
- });
- return ipAddressInfos;
- }
-
}
diff --git a/naming/src/main/java/com/alibaba/nacos/naming/core/CatalogService.java b/naming/src/main/java/com/alibaba/nacos/naming/core/CatalogService.java
new file mode 100644
index 000000000..35d332423
--- /dev/null
+++ b/naming/src/main/java/com/alibaba/nacos/naming/core/CatalogService.java
@@ -0,0 +1,84 @@
+/*
+ * 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.naming.core;
+
+import com.alibaba.nacos.api.exception.NacosException;
+import com.alibaba.nacos.api.naming.pojo.Instance;
+
+import java.util.List;
+
+/**
+ * Catalog service.
+ *
+ * @author xiweng.yy
+ */
+public interface CatalogService {
+
+ /**
+ * Get service detail information.
+ *
+ * @param namespaceId namespace id of service
+ * @param groupName group name of service
+ * @param serviceName service name
+ * @return detail information of service
+ * @throws NacosException exception in query
+ */
+ Object getServiceDetail(String namespaceId, String groupName, String serviceName) throws NacosException;
+
+ /**
+ * List all instances of specified services.
+ *
+ * @param namespaceId namespace id of service
+ * @param groupName group name of service
+ * @param serviceName service name
+ * @param clusterName cluster name of instances
+ * @return instances list
+ * @throws NacosException exception in query
+ */
+ List extends Instance> listInstances(String namespaceId, String groupName, String serviceName, String clusterName)
+ throws NacosException;
+
+ /**
+ * List service by page.
+ *
+ * @param namespaceId namespace id of service
+ * @param groupName group name of service
+ * @param serviceName service name
+ * @param pageNo page number
+ * @param pageSize page size
+ * @param instancePattern contained instances pattern
+ * @param ignoreEmptyService whether ignore empty service
+ * @return service list
+ * @throws NacosException exception in query
+ */
+ Object pageListService(String namespaceId, String groupName, String serviceName, int pageNo, int pageSize,
+ String instancePattern, boolean ignoreEmptyService) throws NacosException;
+
+ /**
+ * List service with cluster and instances by page.
+ *
+ * @param namespaceId namespace id of service
+ * @param groupName group name of service
+ * @param serviceName service name
+ * @param pageNo page number
+ * @param pageSize page size
+ * @return service list
+ * @throws NacosException exception in query
+ */
+ Object pageListServiceDetail(String namespaceId, String groupName, String serviceName, int pageNo, int pageSize)
+ throws NacosException;
+}
diff --git a/naming/src/main/java/com/alibaba/nacos/naming/core/CatalogServiceV1Impl.java b/naming/src/main/java/com/alibaba/nacos/naming/core/CatalogServiceV1Impl.java
new file mode 100644
index 000000000..23539f98d
--- /dev/null
+++ b/naming/src/main/java/com/alibaba/nacos/naming/core/CatalogServiceV1Impl.java
@@ -0,0 +1,194 @@
+/*
+ * 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.naming.core;
+
+import com.alibaba.nacos.api.exception.NacosException;
+import com.alibaba.nacos.api.naming.pojo.Instance;
+import com.alibaba.nacos.api.naming.utils.NamingUtils;
+import com.alibaba.nacos.common.utils.JacksonUtils;
+import com.alibaba.nacos.naming.pojo.ClusterInfo;
+import com.alibaba.nacos.naming.pojo.IpAddressInfo;
+import com.alibaba.nacos.naming.pojo.ServiceDetailInfo;
+import com.alibaba.nacos.naming.pojo.ServiceView;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.stereotype.Component;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Catalog service for v1.x .
+ *
+ * @author xiweng.yy
+ */
+@Component()
+public class CatalogServiceV1Impl implements CatalogService {
+
+ private final ServiceManager serviceManager;
+
+ public CatalogServiceV1Impl(ServiceManager serviceManager) {
+ this.serviceManager = serviceManager;
+ }
+
+ @Override
+ public Object getServiceDetail(String namespaceId, String groupName, String serviceName) throws NacosException {
+ Service detailedService = serviceManager.getService(namespaceId, NamingUtils.getGroupedName(serviceName, groupName));
+
+ if (detailedService == null) {
+ throw new NacosException(NacosException.NOT_FOUND,
+ String.format("service %s@@%s is not found!", groupName, serviceName));
+ }
+ ObjectNode serviceObject = JacksonUtils.createEmptyJsonNode();
+ serviceObject.put("name", serviceName);
+ serviceObject.put("protectThreshold", detailedService.getProtectThreshold());
+ serviceObject.put("groupName", groupName);
+ serviceObject.replace("selector", JacksonUtils.transferToJsonNode(detailedService.getSelector()));
+ serviceObject.replace("metadata", JacksonUtils.transferToJsonNode(detailedService.getMetadata()));
+
+ ObjectNode detailView = JacksonUtils.createEmptyJsonNode();
+ detailView.replace("service", serviceObject);
+
+ List clusters = new ArrayList<>();
+
+ for (com.alibaba.nacos.naming.core.Cluster cluster : detailedService.getClusterMap().values()) {
+ com.alibaba.nacos.api.naming.pojo.Cluster clusterView = new com.alibaba.nacos.api.naming.pojo.Cluster();
+ clusterView.setName(cluster.getName());
+ clusterView.setHealthChecker(cluster.getHealthChecker());
+ clusterView.setMetadata(cluster.getMetadata());
+ clusterView.setUseIPPort4Check(cluster.isUseIPPort4Check());
+ clusterView.setDefaultPort(cluster.getDefaultPort());
+ clusterView.setDefaultCheckPort(cluster.getDefaultCheckPort());
+ clusterView.setServiceName(cluster.getService().getName());
+ clusters.add(clusterView);
+ }
+
+ detailView.replace("clusters", JacksonUtils.transferToJsonNode(clusters));
+
+ return detailView;
+ }
+
+ @Override
+ public List extends Instance> listInstances(String namespaceId, String groupName, String serviceName,
+ String clusterName) throws NacosException {
+ Service service = serviceManager.getService(namespaceId, serviceName);
+ if (service == null) {
+ throw new NacosException(NacosException.NOT_FOUND,
+ String.format("service %s@@%s is not found!", groupName, serviceName));
+ }
+ if (!service.getClusterMap().containsKey(clusterName)) {
+ throw new NacosException(NacosException.NOT_FOUND, "cluster " + clusterName + " is not found!");
+ }
+ return service.getClusterMap().get(clusterName).allIPs();
+ }
+
+ @Override
+ public Object pageListService(String namespaceId, String groupName, String serviceName, int pageNo, int pageSize,
+ String instancePattern, boolean ignoreEmptyService) throws NacosException {
+ String param = StringUtils.isBlank(serviceName) && StringUtils.isBlank(groupName) ? StringUtils.EMPTY
+ : NamingUtils.getGroupedName(serviceName, groupName);
+ ObjectNode result = JacksonUtils.createEmptyJsonNode();
+
+ List services = new ArrayList<>();
+ final int total = serviceManager
+ .getPagedService(namespaceId, pageNo - 1, pageSize, param, instancePattern, services,
+ ignoreEmptyService);
+ if (CollectionUtils.isEmpty(services)) {
+ result.replace("serviceList", JacksonUtils.transferToJsonNode(Collections.emptyList()));
+ result.put("count", 0);
+ return result;
+ }
+
+ List serviceViews = new LinkedList<>();
+ for (Service each : services) {
+ ServiceView serviceView = new ServiceView();
+ serviceView.setName(NamingUtils.getServiceName(each.getName()));
+ serviceView.setGroupName(NamingUtils.getGroupName(each.getName()));
+ serviceView.setClusterCount(each.getClusterMap().size());
+ serviceView.setIpCount(each.allIPs().size());
+ serviceView.setHealthyInstanceCount(each.healthyInstanceCount());
+ serviceView.setTriggerFlag(each.triggerFlag() ? "true" : "false");
+ serviceViews.add(serviceView);
+ }
+
+ result.set("serviceList", JacksonUtils.transferToJsonNode(serviceViews));
+ result.put("count", total);
+
+ return result;
+ }
+
+ @Override
+ public Object pageListServiceDetail(String namespaceId, String groupName, String serviceName, int pageNo,
+ int pageSize) throws NacosException {
+ String param = StringUtils.isBlank(serviceName) && StringUtils.isBlank(groupName) ? StringUtils.EMPTY
+ : NamingUtils.getGroupedName(serviceName, groupName);
+ List serviceDetailInfoList = new ArrayList<>();
+ List services = new ArrayList<>(8);
+ serviceManager.getPagedService(namespaceId, pageNo, pageSize, param, StringUtils.EMPTY, services, false);
+
+ for (Service each : services) {
+ ServiceDetailInfo serviceDetailInfo = new ServiceDetailInfo();
+ serviceDetailInfo.setServiceName(NamingUtils.getServiceName(each.getName()));
+ serviceDetailInfo.setGroupName(NamingUtils.getGroupName(each.getName()));
+ serviceDetailInfo.setMetadata(each.getMetadata());
+
+ Map clusterInfoMap = getStringClusterInfoMap(each);
+ serviceDetailInfo.setClusterMap(clusterInfoMap);
+
+ serviceDetailInfoList.add(serviceDetailInfo);
+ }
+
+ return serviceDetailInfoList;
+ }
+
+ private Map getStringClusterInfoMap(Service service) {
+ Map clusterInfoMap = new HashMap<>(8);
+
+ service.getClusterMap().forEach((clusterName, cluster) -> {
+
+ ClusterInfo clusterInfo = new ClusterInfo();
+ List ipAddressInfos = getIpAddressInfos(cluster.allIPs());
+ clusterInfo.setHosts(ipAddressInfos);
+ clusterInfoMap.put(clusterName, clusterInfo);
+
+ });
+ return clusterInfoMap;
+ }
+
+ private List getIpAddressInfos(List instances) {
+ List ipAddressInfos = new ArrayList<>();
+
+ instances.forEach((ipAddress) -> {
+
+ IpAddressInfo ipAddressInfo = new IpAddressInfo();
+ ipAddressInfo.setIp(ipAddress.getIp());
+ ipAddressInfo.setPort(ipAddress.getPort());
+ ipAddressInfo.setMetadata(ipAddress.getMetadata());
+ ipAddressInfo.setValid(ipAddress.isHealthy());
+ ipAddressInfo.setWeight(ipAddress.getWeight());
+ ipAddressInfo.setEnabled(ipAddress.isEnabled());
+ ipAddressInfos.add(ipAddressInfo);
+
+ });
+ return ipAddressInfos;
+ }
+}
diff --git a/naming/src/main/java/com/alibaba/nacos/naming/core/CatalogServiceV2Impl.java b/naming/src/main/java/com/alibaba/nacos/naming/core/CatalogServiceV2Impl.java
new file mode 100644
index 000000000..21d3eb8d5
--- /dev/null
+++ b/naming/src/main/java/com/alibaba/nacos/naming/core/CatalogServiceV2Impl.java
@@ -0,0 +1,211 @@
+/*
+ * 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.naming.core;
+
+import com.alibaba.nacos.api.common.Constants;
+import com.alibaba.nacos.api.exception.NacosException;
+import com.alibaba.nacos.api.naming.pojo.Cluster;
+import com.alibaba.nacos.api.naming.pojo.Instance;
+import com.alibaba.nacos.api.naming.pojo.ServiceInfo;
+import com.alibaba.nacos.api.naming.utils.NamingUtils;
+import com.alibaba.nacos.common.utils.JacksonUtils;
+import com.alibaba.nacos.naming.core.v2.ServiceManager;
+import com.alibaba.nacos.naming.core.v2.index.ServiceStorage;
+import com.alibaba.nacos.naming.core.v2.metadata.ClusterMetadata;
+import com.alibaba.nacos.naming.core.v2.metadata.NamingMetadataManager;
+import com.alibaba.nacos.naming.core.v2.metadata.ServiceMetadata;
+import com.alibaba.nacos.naming.core.v2.pojo.Service;
+import com.alibaba.nacos.naming.pojo.ServiceView;
+import com.alibaba.nacos.naming.utils.ServiceUtil;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.stereotype.Component;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Optional;
+import java.util.StringJoiner;
+import java.util.stream.Collectors;
+
+/**
+ * Catalog service for v1.x .
+ *
+ * @author xiweng.yy
+ */
+@Component()
+public class CatalogServiceV2Impl implements CatalogService {
+
+ private final ServiceStorage serviceStorage;
+
+ private final NamingMetadataManager metadataManager;
+
+ public CatalogServiceV2Impl(ServiceStorage serviceStorage, NamingMetadataManager metadataManager) {
+ this.serviceStorage = serviceStorage;
+ this.metadataManager = metadataManager;
+ }
+
+ @Override
+ public Object getServiceDetail(String namespaceId, String groupName, String serviceName) throws NacosException {
+ Service service = Service.newService(namespaceId, NamingUtils.getGroupName(serviceName),
+ NamingUtils.getServiceName(serviceName));
+ if (!ServiceManager.getInstance().containSingleton(service)) {
+ throw new NacosException(NacosException.NOT_FOUND,
+ String.format("service %s@@%s is not found!", groupName, serviceName));
+ }
+
+ Optional metadata = metadataManager.getServiceMetadata(service);
+ ServiceMetadata detailedService = metadata.orElseGet(ServiceMetadata::new);
+
+ ObjectNode serviceObject = JacksonUtils.createEmptyJsonNode();
+ serviceObject.put("name", NamingUtils.getServiceName(serviceName));
+ serviceObject.put("groupName", NamingUtils.getGroupName(serviceName));
+ serviceObject.put("protectThreshold", detailedService.getProtectThreshold());
+ serviceObject.replace("selector", JacksonUtils.transferToJsonNode(detailedService.getSelector()));
+ serviceObject.replace("metadata", JacksonUtils.transferToJsonNode(detailedService.getExtendData()));
+
+ ObjectNode detailView = JacksonUtils.createEmptyJsonNode();
+ detailView.replace("service", serviceObject);
+
+ List clusters = new ArrayList<>();
+
+ for (String each : serviceStorage.getClusters(service)) {
+ ClusterMetadata clusterMetadata =
+ detailedService.getClusters().containsKey(each) ? detailedService.getClusters().get(each)
+ : new ClusterMetadata();
+ com.alibaba.nacos.api.naming.pojo.Cluster clusterView = new Cluster();
+ clusterView.setName(each);
+ clusterView.setHealthChecker(clusterMetadata.getHealthChecker());
+ clusterView.setMetadata(clusterMetadata.getExtendData());
+ clusterView.setUseIPPort4Check(clusterMetadata.isUseInstancePortForCheck());
+ clusterView.setDefaultPort(80);
+ clusterView.setDefaultCheckPort(clusterMetadata.getHealthyCheckPort());
+ clusterView.setServiceName(service.getGroupedServiceName());
+ clusters.add(clusterView);
+ }
+
+ detailView.replace("clusters", JacksonUtils.transferToJsonNode(clusters));
+
+ return detailView;
+ }
+
+ @Override
+ public List extends Instance> listInstances(String namespaceId, String groupName, String serviceName,
+ String clusterName) throws NacosException {
+ Service service = Service.newService(namespaceId, groupName, serviceName);
+ if (!ServiceManager.getInstance().containSingleton(service)) {
+ throw new NacosException(NacosException.NOT_FOUND,
+ String.format("service %s@@%s is not found!", groupName, serviceName));
+ }
+ if (!serviceStorage.getClusters(service).contains(clusterName)) {
+ throw new NacosException(NacosException.NOT_FOUND, "cluster " + clusterName + " is not found!");
+ }
+ ServiceInfo serviceInfo = serviceStorage.getData(service);
+ ServiceInfo result = ServiceUtil.filterInstances(serviceInfo, clusterName, false);
+ return result.getHosts();
+ }
+
+ @Override
+ public Object pageListService(String namespaceId, String groupName, String serviceName, int pageNo, int pageSize,
+ String instancePattern, boolean ignoreEmptyService) throws NacosException {
+ ObjectNode result = JacksonUtils.createEmptyJsonNode();
+ List serviceViews = new LinkedList<>();
+ Collection services = patternServices(namespaceId, groupName, serviceName);
+ if (ignoreEmptyService) {
+ services = services.stream().filter(each -> 0 != serviceStorage.getData(each).ipCount())
+ .collect(Collectors.toList());
+ }
+ result.put("count", services.size());
+ services = doPage(services, pageNo - 1, pageSize);
+ for (Service each : services) {
+ ServiceMetadata serviceMetadata = metadataManager.getServiceMetadata(each).orElseGet(ServiceMetadata::new);
+ ServiceView serviceView = new ServiceView();
+ serviceView.setName(each.getName());
+ serviceView.setGroupName(each.getGroup());
+ serviceView.setClusterCount(serviceStorage.getClusters(each).size());
+ serviceView.setIpCount(serviceStorage.getData(each).ipCount());
+ serviceView.setHealthyInstanceCount(countHealthyInstance(serviceStorage.getData(each)));
+ serviceView.setTriggerFlag(isProtectThreshold(serviceView, serviceMetadata) ? "true" : "false");
+ serviceViews.add(serviceView);
+ }
+ result.set("serviceList", JacksonUtils.transferToJsonNode(serviceViews));
+ return result;
+ }
+
+ private int countHealthyInstance(ServiceInfo data) {
+ int result = 0;
+ for (Instance each : data.getHosts()) {
+ if (each.isHealthy()) {
+ result++;
+ }
+ }
+ return result;
+ }
+
+ private boolean isProtectThreshold(ServiceView serviceView, ServiceMetadata metadata) {
+ return (serviceView.getHealthyInstanceCount() * 1.0 / serviceView.getIpCount()) <= metadata
+ .getProtectThreshold();
+ }
+
+ @Override
+ public Object pageListServiceDetail(String namespaceId, String groupName, String serviceName, int pageNo,
+ int pageSize) throws NacosException {
+ return null;
+ }
+
+ private Collection patternServices(String namespaceId, String group, String serviceName) {
+ boolean noFilter = StringUtils.isBlank(serviceName) && StringUtils.isBlank(group);
+ if (noFilter) {
+ return serviceStorage.getAllServicesOfNamespace(namespaceId);
+ }
+ Collection result = new LinkedList<>();
+ StringJoiner regex = new StringJoiner(Constants.SERVICE_INFO_SPLITER);
+ regex.add(getRegexString(group));
+ regex.add(getRegexString(serviceName));
+ String regexString = regex.toString();
+ for (Service each : serviceStorage.getAllServicesOfNamespace(namespaceId)) {
+ if (each.getGroupedServiceName().matches(regexString)) {
+ result.add(each);
+ }
+ }
+ return result;
+ }
+
+ private String getRegexString(String target) {
+ return StringUtils.isBlank(target) ? Constants.ANY_PATTERN
+ : Constants.ANY_PATTERN + target + Constants.ANY_PATTERN;
+ }
+
+ private Collection doPage(Collection services, int pageNo, int pageSize) {
+ if (services.size() < pageSize) {
+ return services;
+ }
+ Collection result = new LinkedList<>();
+ int i = 0;
+ for (Service each : services) {
+ if (i++ < pageNo * pageSize) {
+ continue;
+ }
+ result.add(each);
+ if (result.size() >= pageSize) {
+ break;
+ }
+ }
+ return result;
+ }
+}
diff --git a/naming/src/main/java/com/alibaba/nacos/naming/core/v2/index/ServiceStorage.java b/naming/src/main/java/com/alibaba/nacos/naming/core/v2/index/ServiceStorage.java
index 8e6be096a..28a089adc 100644
--- a/naming/src/main/java/com/alibaba/nacos/naming/core/v2/index/ServiceStorage.java
+++ b/naming/src/main/java/com/alibaba/nacos/naming/core/v2/index/ServiceStorage.java
@@ -31,6 +31,7 @@ import org.springframework.stereotype.Component;
import java.util.Collection;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
@@ -55,6 +56,8 @@ public class ServiceStorage {
private final ConcurrentMap serviceDataIndexes;
+ private final ConcurrentMap> serviceClusterIndex;
+
private final ConcurrentMap> namespaceServiceIndex;
public ServiceStorage(ClientServiceIndexesManager serviceIndexesManager, ClientManagerDelegate clientManager,
@@ -62,8 +65,9 @@ public class ServiceStorage {
this.serviceIndexesManager = serviceIndexesManager;
this.clientManager = clientManager;
this.switchDomain = switchDomain;
- serviceDataIndexes = new ConcurrentHashMap<>();
- namespaceServiceIndex = new ConcurrentHashMap<>();
+ this.serviceDataIndexes = new ConcurrentHashMap<>();
+ this.serviceClusterIndex = new ConcurrentHashMap<>();
+ this.namespaceServiceIndex = new ConcurrentHashMap<>();
}
public ServiceInfo getData(Service service) {
@@ -77,16 +81,26 @@ public class ServiceStorage {
result.setLastRefTime(System.currentTimeMillis());
result.setCacheMillis(switchDomain.getDefaultPushCacheMillis());
List instances = new LinkedList<>();
+ Set clusters = new HashSet<>();
for (String each : serviceIndexesManager.getAllClientsRegisteredService(service)) {
Optional instancePublishInfo = getInstanceInfo(each, service);
- instancePublishInfo.ifPresent(publishInfo -> instances.add(parseInstance(service, publishInfo)));
+ if (instancePublishInfo.isPresent()) {
+ Instance instance = parseInstance(service, instancePublishInfo.get());
+ instances.add(instance);
+ clusters.add(instance.getClusterName());
+ }
}
result.setHosts(instances);
serviceDataIndexes.put(service, result);
+ serviceClusterIndex.put(service, clusters);
updateNamespaceIndex(service);
return result;
}
+ public Set getClusters(Service service) {
+ return serviceClusterIndex.getOrDefault(service, new HashSet<>());
+ }
+
public Collection getAllServicesOfNamespace(String namespace) {
return namespaceServiceIndex.getOrDefault(namespace, new ConcurrentHashSet<>());
}
@@ -114,6 +128,7 @@ public class ServiceStorage {
}
result.setMetadata(instanceMetadata);
result.setEphemeral(service.isEphemeral());
+ result.setHealthy(instancePublishInfo.isHealthy());
return result;
}
diff --git a/naming/src/main/java/com/alibaba/nacos/naming/core/v2/metadata/MetadataOperation.java b/naming/src/main/java/com/alibaba/nacos/naming/core/v2/metadata/MetadataOperation.java
new file mode 100644
index 000000000..729490d41
--- /dev/null
+++ b/naming/src/main/java/com/alibaba/nacos/naming/core/v2/metadata/MetadataOperation.java
@@ -0,0 +1,65 @@
+/*
+ * 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.naming.core.v2.metadata;
+
+/**
+ * Metadata operation.
+ *
+ * @author xiweng.yy
+ */
+public class MetadataOperation {
+
+ private String namespace;
+
+ private String group;
+
+ private String serviceName;
+
+ private T metadata;
+
+ public String getNamespace() {
+ return namespace;
+ }
+
+ public void setNamespace(String namespace) {
+ this.namespace = namespace;
+ }
+
+ public String getGroup() {
+ return group;
+ }
+
+ public void setGroup(String group) {
+ this.group = group;
+ }
+
+ public String getServiceName() {
+ return serviceName;
+ }
+
+ public void setServiceName(String serviceName) {
+ this.serviceName = serviceName;
+ }
+
+ public T getMetadata() {
+ return metadata;
+ }
+
+ public void setMetadata(T metadata) {
+ this.metadata = metadata;
+ }
+}
diff --git a/naming/src/main/java/com/alibaba/nacos/naming/core/v2/metadata/NacosNamingMetadataManager.java b/naming/src/main/java/com/alibaba/nacos/naming/core/v2/metadata/NamingMetadataManager.java
similarity index 98%
rename from naming/src/main/java/com/alibaba/nacos/naming/core/v2/metadata/NacosNamingMetadataManager.java
rename to naming/src/main/java/com/alibaba/nacos/naming/core/v2/metadata/NamingMetadataManager.java
index 03b7eb2f7..15979e72f 100644
--- a/naming/src/main/java/com/alibaba/nacos/naming/core/v2/metadata/NacosNamingMetadataManager.java
+++ b/naming/src/main/java/com/alibaba/nacos/naming/core/v2/metadata/NamingMetadataManager.java
@@ -29,13 +29,13 @@ import java.util.concurrent.ConcurrentMap;
* @author xiweng.yy
*/
@Component
-public class NacosNamingMetadataManager {
+public class NamingMetadataManager {
private final ConcurrentMap serviceMetadataMap;
private final ConcurrentMap> instanceMetadataMap;
- public NacosNamingMetadataManager() {
+ public NamingMetadataManager() {
serviceMetadataMap = new ConcurrentHashMap<>(1 << 10);
instanceMetadataMap = new ConcurrentHashMap<>(1 << 10);
}
diff --git a/naming/src/main/java/com/alibaba/nacos/naming/core/v2/metadata/NamingMetadataOperateService.java b/naming/src/main/java/com/alibaba/nacos/naming/core/v2/metadata/NamingMetadataOperateService.java
new file mode 100644
index 000000000..d8c9e3a93
--- /dev/null
+++ b/naming/src/main/java/com/alibaba/nacos/naming/core/v2/metadata/NamingMetadataOperateService.java
@@ -0,0 +1,93 @@
+/*
+ * 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.naming.core.v2.metadata;
+
+import com.alibaba.nacos.api.exception.NacosException;
+import com.alibaba.nacos.api.exception.runtime.NacosRuntimeException;
+import com.alibaba.nacos.consistency.DataOperation;
+import com.alibaba.nacos.consistency.SerializeFactory;
+import com.alibaba.nacos.consistency.Serializer;
+import com.alibaba.nacos.consistency.cp.CPProtocol;
+import com.alibaba.nacos.consistency.entity.Log;
+import com.alibaba.nacos.consistency.entity.Response;
+import com.alibaba.nacos.core.distributed.ProtocolManager;
+import com.alibaba.nacos.naming.core.v2.pojo.Service;
+import com.alibaba.nacos.naming.utils.Constants;
+import com.google.protobuf.ByteString;
+import org.springframework.stereotype.Component;
+
+/**
+ * Nacos naming metadata operate service.
+ *
+ * @author xiweng.yy
+ */
+@Component
+public class NamingMetadataOperateService {
+
+ private final CPProtocol cpProtocol;
+
+ private final Serializer serializer;
+
+ public NamingMetadataOperateService(ProtocolManager protocolManager) {
+ this.cpProtocol = protocolManager.getCpProtocol();
+ this.serializer = SerializeFactory.getSerializer("JSON");
+ }
+
+ /**
+ * Update service metadata.
+ *
+ * @param service service of metadata
+ * @param serviceMetadata metadata
+ */
+ public void updateServiceMetadata(Service service, ServiceMetadata serviceMetadata) {
+ MetadataOperation operation = new MetadataOperation<>();
+ operation.setNamespace(service.getNamespace());
+ operation.setGroup(service.getGroup());
+ operation.setServiceName(service.getGroupedServiceName());
+ operation.setMetadata(serviceMetadata);
+ Log operationLog = Log.newBuilder().setGroup(Constants.SERVICE_METADATA).setType(DataOperation.CHANGE.name())
+ .setData(ByteString.copyFrom(serializer.serialize(operation))).build();
+ submitMetadataOperation(operationLog);
+ }
+
+ /**
+ * Delete service metadata.
+ *
+ * @param service service of metadata
+ */
+ public void deleteServiceMetadata(Service service) {
+ MetadataOperation operation = new MetadataOperation<>();
+ operation.setNamespace(service.getNamespace());
+ operation.setGroup(service.getGroup());
+ operation.setServiceName(service.getGroupedServiceName());
+ Log operationLog = Log.newBuilder().setGroup(Constants.SERVICE_METADATA).setType(DataOperation.DELETE.name())
+ .setData(ByteString.copyFrom(serializer.serialize(operation))).build();
+ submitMetadataOperation(operationLog);
+ }
+
+ private void submitMetadataOperation(Log operationLog) {
+ try {
+ Response response = cpProtocol.submit(operationLog);
+ if (!response.getSuccess()) {
+ throw new NacosRuntimeException(NacosException.SERVER_ERROR,
+ "do metadata operation failed " + response.getErrMsg());
+ }
+ } catch (Exception e) {
+ throw new NacosRuntimeException(NacosException.SERVER_ERROR, "do metadata operation failed", e);
+ }
+ }
+}
diff --git a/naming/src/main/java/com/alibaba/nacos/naming/core/v2/metadata/ServiceMetadata.java b/naming/src/main/java/com/alibaba/nacos/naming/core/v2/metadata/ServiceMetadata.java
index 0b879738a..dd45edb4c 100644
--- a/naming/src/main/java/com/alibaba/nacos/naming/core/v2/metadata/ServiceMetadata.java
+++ b/naming/src/main/java/com/alibaba/nacos/naming/core/v2/metadata/ServiceMetadata.java
@@ -16,9 +16,11 @@
package com.alibaba.nacos.naming.core.v2.metadata;
-import com.alibaba.nacos.api.selector.SelectorType;
+import com.alibaba.nacos.naming.selector.NoneSelector;
+import com.alibaba.nacos.naming.selector.Selector;
import java.util.Map;
+import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
/**
@@ -36,7 +38,7 @@ public class ServiceMetadata {
/**
* Type of {@link com.alibaba.nacos.naming.selector.Selector}.
*/
- private SelectorType selectorType = SelectorType.none;
+ private Selector selector = new NoneSelector();
private Map extendData = new ConcurrentHashMap<>(1);
@@ -50,12 +52,12 @@ public class ServiceMetadata {
this.protectThreshold = protectThreshold;
}
- public SelectorType getSelectorType() {
- return selectorType;
+ public Selector getSelector() {
+ return selector;
}
- public void setSelectorType(SelectorType selectorType) {
- this.selectorType = selectorType;
+ public void setSelector(Selector selector) {
+ this.selector = selector;
}
public Map getExtendData() {
@@ -73,4 +75,22 @@ public class ServiceMetadata {
public void setClusters(Map clusters) {
this.clusters = clusters;
}
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (!(o instanceof ServiceMetadata)) {
+ return false;
+ }
+ ServiceMetadata metadata = (ServiceMetadata) o;
+ return Float.compare(metadata.protectThreshold, protectThreshold) == 0 && selector == metadata.selector
+ && Objects.equals(extendData, metadata.extendData) && Objects.equals(clusters, metadata.clusters);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(protectThreshold, selector, extendData, clusters);
+ }
}
diff --git a/naming/src/main/java/com/alibaba/nacos/naming/core/v2/metadata/ServiceMetadataProcessor.java b/naming/src/main/java/com/alibaba/nacos/naming/core/v2/metadata/ServiceMetadataProcessor.java
new file mode 100644
index 000000000..2d77de58c
--- /dev/null
+++ b/naming/src/main/java/com/alibaba/nacos/naming/core/v2/metadata/ServiceMetadataProcessor.java
@@ -0,0 +1,102 @@
+/*
+ * 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.naming.core.v2.metadata;
+
+import com.alibaba.nacos.consistency.DataOperation;
+import com.alibaba.nacos.consistency.SerializeFactory;
+import com.alibaba.nacos.consistency.Serializer;
+import com.alibaba.nacos.consistency.cp.LogProcessor4CP;
+import com.alibaba.nacos.consistency.entity.GetRequest;
+import com.alibaba.nacos.consistency.entity.Log;
+import com.alibaba.nacos.consistency.entity.Response;
+import com.alibaba.nacos.core.distributed.ProtocolManager;
+import com.alibaba.nacos.naming.core.v2.pojo.Service;
+import com.alibaba.nacos.naming.utils.Constants;
+import com.google.protobuf.ByteString;
+import org.apache.commons.lang3.reflect.TypeUtils;
+import org.springframework.stereotype.Component;
+
+import java.lang.reflect.Type;
+import java.util.Collections;
+import java.util.Optional;
+
+/**
+ * Service metadata processor.
+ *
+ * @author xiweng.yy
+ */
+@Component
+public class ServiceMetadataProcessor extends LogProcessor4CP {
+
+ private final NamingMetadataManager namingMetadataManager;
+
+ private final Serializer serializer;
+
+ private final Type processType;
+
+ @SuppressWarnings("unchecked")
+ public ServiceMetadataProcessor(NamingMetadataManager namingMetadataManager, ProtocolManager protocolManager) {
+ this.namingMetadataManager = namingMetadataManager;
+ this.serializer = SerializeFactory.getSerializer("JSON");
+ this.processType = TypeUtils.parameterize(MetadataOperation.class, ServiceMetadata.class);
+ protocolManager.getCpProtocol().addLogProcessors(Collections.singletonList(this));
+ }
+
+ @Override
+ public Response onRequest(GetRequest request) {
+ return null;
+ }
+
+ @Override
+ public Response onApply(Log log) {
+ switch (DataOperation.valueOf(log.getOperation())) {
+ case ADD:
+ case CHANGE:
+ updateServiceMetadata(log.getData());
+ break;
+ case DELETE:
+ deleteServiceMetadata(log.getData());
+ break;
+ default:
+ return Response.newBuilder().setSuccess(false).setErrMsg("Unsupported operation " + log.getOperation())
+ .build();
+ }
+ return Response.newBuilder().setSuccess(true).build();
+ }
+
+ private void updateServiceMetadata(ByteString data) {
+ MetadataOperation op = serializer.deserialize(data.toByteArray(), processType);
+ Service service = Service.newService(op.getNamespace(), op.getGroup(), op.getServiceName());
+ Optional serviceMetadata = namingMetadataManager.getServiceMetadata(service);
+ if (serviceMetadata.isPresent()) {
+ namingMetadataManager.updateServiceMetadata(service, serviceMetadata.get());
+ } else {
+ namingMetadataManager.updateServiceMetadata(service, op.getMetadata());
+ }
+ }
+
+ private void deleteServiceMetadata(ByteString data) {
+ MetadataOperation op = serializer.deserialize(data.toByteArray(), processType);
+ Service service = Service.newService(op.getNamespace(), op.getGroup(), op.getServiceName());
+ namingMetadataManager.removeServiceMetadata(service);
+ }
+
+ @Override
+ public String group() {
+ return Constants.SERVICE_METADATA;
+ }
+}
diff --git a/naming/src/main/java/com/alibaba/nacos/naming/core/v2/service/impl/EphemeralClientOperationServiceImpl.java b/naming/src/main/java/com/alibaba/nacos/naming/core/v2/service/impl/EphemeralClientOperationServiceImpl.java
index f4e403772..e69388854 100644
--- a/naming/src/main/java/com/alibaba/nacos/naming/core/v2/service/impl/EphemeralClientOperationServiceImpl.java
+++ b/naming/src/main/java/com/alibaba/nacos/naming/core/v2/service/impl/EphemeralClientOperationServiceImpl.java
@@ -75,6 +75,7 @@ public class EphemeralClientOperationServiceImpl implements ClientOperationServi
result.getExtendDatum().putAll(instance.getMetadata());
String clusterName = StringUtils.isBlank(instance.getClusterName()) ? UtilsAndCommons.DEFAULT_CLUSTER_NAME
: instance.getClusterName();
+ result.setHealthy(instance.isHealthy());
result.getExtendDatum().put(CommonParams.CLUSTER_NAME, clusterName);
return result;
}
diff --git a/naming/src/main/java/com/alibaba/nacos/naming/healthcheck/heartbeat/ClientBeatCheckTaskV2.java b/naming/src/main/java/com/alibaba/nacos/naming/healthcheck/heartbeat/ClientBeatCheckTaskV2.java
index 76228683a..6d3413f9b 100644
--- a/naming/src/main/java/com/alibaba/nacos/naming/healthcheck/heartbeat/ClientBeatCheckTaskV2.java
+++ b/naming/src/main/java/com/alibaba/nacos/naming/healthcheck/heartbeat/ClientBeatCheckTaskV2.java
@@ -19,7 +19,7 @@ package com.alibaba.nacos.naming.healthcheck.heartbeat;
import com.alibaba.nacos.common.task.AbstractExecuteTask;
import com.alibaba.nacos.naming.consistency.KeyBuilder;
import com.alibaba.nacos.naming.core.v2.client.impl.IpPortBasedClient;
-import com.alibaba.nacos.naming.core.v2.metadata.NacosNamingMetadataManager;
+import com.alibaba.nacos.naming.core.v2.metadata.NamingMetadataManager;
import com.alibaba.nacos.naming.core.v2.pojo.HeartBeatInstancePublishInfo;
import com.alibaba.nacos.naming.core.v2.pojo.Service;
import com.alibaba.nacos.naming.healthcheck.NacosHealthCheckTask;
@@ -52,8 +52,8 @@ public class ClientBeatCheckTaskV2 extends AbstractExecuteTask implements BeatCh
return ApplicationUtils.getBean(GlobalConfig.class);
}
- public NacosNamingMetadataManager getMetadataManager() {
- return ApplicationUtils.getBean(NacosNamingMetadataManager.class);
+ public NamingMetadataManager getMetadataManager() {
+ return ApplicationUtils.getBean(NamingMetadataManager.class);
}
@Override
diff --git a/naming/src/main/java/com/alibaba/nacos/naming/healthcheck/heartbeat/ExpiredInstanceChecker.java b/naming/src/main/java/com/alibaba/nacos/naming/healthcheck/heartbeat/ExpiredInstanceChecker.java
index 2ad6ebd39..327b18f3e 100644
--- a/naming/src/main/java/com/alibaba/nacos/naming/healthcheck/heartbeat/ExpiredInstanceChecker.java
+++ b/naming/src/main/java/com/alibaba/nacos/naming/healthcheck/heartbeat/ExpiredInstanceChecker.java
@@ -24,7 +24,7 @@ import com.alibaba.nacos.common.utils.JacksonUtils;
import com.alibaba.nacos.naming.core.v2.client.Client;
import com.alibaba.nacos.naming.core.v2.event.client.ClientOperationEvent;
import com.alibaba.nacos.naming.core.v2.metadata.InstanceMetadata;
-import com.alibaba.nacos.naming.core.v2.metadata.NacosNamingMetadataManager;
+import com.alibaba.nacos.naming.core.v2.metadata.NamingMetadataManager;
import com.alibaba.nacos.naming.core.v2.pojo.HeartBeatInstancePublishInfo;
import com.alibaba.nacos.naming.core.v2.pojo.InstancePublishInfo;
import com.alibaba.nacos.naming.core.v2.pojo.Service;
@@ -65,7 +65,7 @@ public class ExpiredInstanceChecker implements InstanceBeatChecker {
}
private Optional