This is an automated email from the ASF dual-hosted git repository.

xingfudeshi pushed a commit to branch 2.x
in repository https://gitbox.apache.org/repos/asf/incubator-seata.git


The following commit(s) were added to refs/heads/2.x by this push:
     new e8ea2cce35 bugfix: thread safety issue when adding and removing 
instances (#6668)
e8ea2cce35 is described below

commit e8ea2cce35b298a36902074dd1cf0bcf142b1561
Author: funkye <[email protected]>
AuthorDate: Sat Jul 13 14:07:42 2024 +0800

    bugfix: thread safety issue when adding and removing instances (#6668)
---
 changes/en-us/2.x.md                               |  1 +
 changes/zh-cn/2.x.md                               |  2 +
 .../seata/common/metadata/namingserver/Unit.java   |  8 ++-
 .../namingserver}/controller/HealthController.java | 30 ++++-------
 .../namingserver/controller/NamingController.java  | 23 ++++----
 .../{ => entity}/pojo/ClusterData.java             | 62 ++++++++++++---------
 .../{ => entity}/vo/monitor/ClusterVO.java         |  4 +-
 .../{ => entity}/vo/monitor/WatcherVO.java         |  2 +-
 .../seata/namingserver/manager/NamingManager.java  | 63 +++++++++++-----------
 .../namingserver/pojo/AbstractClusterData.java     | 55 -------------------
 .../seata/namingserver/NamingControllerTest.java   |  4 ++
 .../seata/server/controller/HealthController.java  |  8 ++-
 12 files changed, 104 insertions(+), 158 deletions(-)

diff --git a/changes/en-us/2.x.md b/changes/en-us/2.x.md
index e8a244ab0f..ab1e0e4dd2 100644
--- a/changes/en-us/2.x.md
+++ b/changes/en-us/2.x.md
@@ -13,6 +13,7 @@ Add changes here for all PR submitted to the 2.x branch.
 - [[#6626](https://github.com/apache/incubator-seata/pull/6626)] fix hsf 
ConsumerModel convert error
 - [[#6642](https://github.com/apache/incubator-seata/pull/6642)] codecov token 
not found
 - [[#6661](https://github.com/apache/incubator-seata/pull/6661)] fix 
`tableMeta` cache scheduled refresh issue
+- [[#6668](https://github.com/apache/incubator-seata/pull/6668)] thread safety 
issue when adding and removing instances
 
 ### optimize:
 - [[#6499](https://github.com/apache/incubator-seata/pull/6499)] split the 
task thread pool for committing and rollbacking statuses
diff --git a/changes/zh-cn/2.x.md b/changes/zh-cn/2.x.md
index de858465c9..a5b951ce84 100644
--- a/changes/zh-cn/2.x.md
+++ b/changes/zh-cn/2.x.md
@@ -14,6 +14,8 @@
 - [[#6640](https://github.com/apache/incubator-seata/pull/6640)] 优化codecov相关配置
 - [[#6642](https://github.com/apache/incubator-seata/pull/6642)] 修复codecov 
token找不到导致无法提交单测覆盖度报告
 - [[#6661](https://github.com/apache/incubator-seata/pull/6661)] 
修复`tableMeta`缓存定时刷新失效问题
+- [[#6668](https://github.com/apache/incubator-seata/pull/6668)] 
解决namingserver同一个集群下instance添加和删除时的线程安全问题
+
 
 ### optimize:
 - [[#6499](https://github.com/apache/incubator-seata/pull/6499)] 拆分 committing 
和 rollbacking 状态的任务线程池
diff --git 
a/common/src/main/java/org/apache/seata/common/metadata/namingserver/Unit.java 
b/common/src/main/java/org/apache/seata/common/metadata/namingserver/Unit.java
index 9b0efea365..f85dad24bd 100644
--- 
a/common/src/main/java/org/apache/seata/common/metadata/namingserver/Unit.java
+++ 
b/common/src/main/java/org/apache/seata/common/metadata/namingserver/Unit.java
@@ -49,20 +49,18 @@ public class Unit {
     }
 
     /**
-     * @param node
-     * @return true if the node has changed, false if there is no change.
+     * @param node node
      */
-    public boolean addInstance(NamingServerNode node) {
+    public void addInstance(NamingServerNode node) {
         if (nodeList.contains(node)) {
             Node node1 = nodeList.get(nodeList.indexOf(node));
             if (node.isTotalEqual(node1)) {
-                return false;
+                return;
             } else {
                 nodeList.remove(node1);
             }
         }
         nodeList.add(node);
-        return true;
 
     }
 
diff --git 
a/server/src/main/java/org/apache/seata/server/controller/HealthController.java 
b/namingserver/src/main/java/org/apache/seata/namingserver/controller/HealthController.java
similarity index 56%
copy from 
server/src/main/java/org/apache/seata/server/controller/HealthController.java
copy to 
namingserver/src/main/java/org/apache/seata/namingserver/controller/HealthController.java
index aff112feb9..a50ce1f08d 100644
--- 
a/server/src/main/java/org/apache/seata/server/controller/HealthController.java
+++ 
b/namingserver/src/main/java/org/apache/seata/namingserver/controller/HealthController.java
@@ -14,30 +14,18 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.seata.server.controller;
+package org.apache.seata.namingserver.controller;
 
-import org.apache.seata.server.ServerRunner;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Controller;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.ResponseBody;
+import org.apache.seata.common.result.Result;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RestController;
 
-/**
- */
-@Controller
-@RequestMapping
+@RestController
 public class HealthController {
 
-    private static final String OK = "ok";
-    private static final String NOT_OK = "not_ok";
-
-    @Autowired
-    private ServerRunner serverRunner;
-
-
-    @RequestMapping("/health")
-    @ResponseBody
-    String healthCheck() {
-        return serverRunner.started() ? OK : NOT_OK;
+    @GetMapping("/health")
+    public Result<?> healthCheck() {
+        return new Result<>();
     }
+
 }
diff --git 
a/namingserver/src/main/java/org/apache/seata/namingserver/controller/NamingController.java
 
b/namingserver/src/main/java/org/apache/seata/namingserver/controller/NamingController.java
index c7aa4e624f..1d13a6cc7c 100644
--- 
a/namingserver/src/main/java/org/apache/seata/namingserver/controller/NamingController.java
+++ 
b/namingserver/src/main/java/org/apache/seata/namingserver/controller/NamingController.java
@@ -24,8 +24,8 @@ import org.apache.seata.common.result.Result;
 import org.apache.seata.namingserver.listener.Watcher;
 import org.apache.seata.namingserver.manager.ClusterWatcherManager;
 import org.apache.seata.namingserver.manager.NamingManager;
-import org.apache.seata.namingserver.vo.monitor.ClusterVO;
-import org.apache.seata.namingserver.vo.monitor.WatcherVO;
+import org.apache.seata.namingserver.entity.vo.monitor.ClusterVO;
+import org.apache.seata.namingserver.entity.vo.monitor.WatcherVO;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.web.bind.annotation.PostMapping;
@@ -56,11 +56,11 @@ public class NamingController {
     private ClusterWatcherManager clusterWatcherManager;
 
     @PostMapping("/register")
-    public Result<?> registerInstance(@RequestParam String namespace,
+    public Result<String> registerInstance(@RequestParam String namespace,
                                       @RequestParam String clusterName,
                                       @RequestParam String unit,
                                       @RequestBody NamingServerNode 
registerBody) {
-        Result result = new Result();
+        Result<String> result = new Result<>();
         boolean isSuccess = namingManager.registerInstance(registerBody, 
namespace, clusterName, unit);
         if (isSuccess) {
             result.setMessage("node has registered successfully!");
@@ -72,9 +72,9 @@ public class NamingController {
     }
 
     @PostMapping("/unregister")
-    public Result<?> unregisterInstance(@RequestParam String unit,
+    public Result<String> unregisterInstance(@RequestParam String unit,
                                         @RequestBody Node registerBody) {
-        Result result = new Result();
+        Result<String> result = new Result<>();
         boolean isSuccess = namingManager.unregisterInstance(unit, 
registerBody);
         if (isSuccess) {
             result.setMessage("node has unregistered successfully!");
@@ -90,11 +90,6 @@ public class NamingController {
         return namingManager.monitorCluster(namespace);
     }
 
-    @GetMapping("/health")
-    public Result<?> healthCheck() {
-        return new Result<>();
-    }
-
     @GetMapping("/discovery")
     public MetaResponse discovery(@RequestParam String vGroup, @RequestParam 
String namespace) {
         return new MetaResponse(namingManager.getClusterListByVgroup(vGroup, 
namespace),
@@ -102,17 +97,17 @@ public class NamingController {
     }
 
     @PostMapping("/changeGroup")
-    public Result<?> changeGroup(@RequestParam String namespace,
+    public Result<String> changeGroup(@RequestParam String namespace,
                                  @RequestParam String clusterName,
                                  @RequestParam String unitName,
                                  @RequestParam String vGroup) {
 
-        Result<?> addGroupResult = namingManager.addGroup(namespace, vGroup, 
clusterName, unitName);
+        Result<String> addGroupResult = namingManager.addGroup(namespace, 
vGroup, clusterName, unitName);
         if (!addGroupResult.isSuccess()) {
             return addGroupResult;
         }
         // remove vGroup in old cluster
-        Result<?> removeGroupResult = namingManager.removeGroup(namespace, 
vGroup, unitName);
+        Result<String> removeGroupResult = 
namingManager.removeGroup(namespace, vGroup, unitName);
         if (!removeGroupResult.isSuccess()) {
             return removeGroupResult;
         }
diff --git 
a/namingserver/src/main/java/org/apache/seata/namingserver/pojo/ClusterData.java
 
b/namingserver/src/main/java/org/apache/seata/namingserver/entity/pojo/ClusterData.java
similarity index 77%
rename from 
namingserver/src/main/java/org/apache/seata/namingserver/pojo/ClusterData.java
rename to 
namingserver/src/main/java/org/apache/seata/namingserver/entity/pojo/ClusterData.java
index 3b217d7bec..c862e1477f 100644
--- 
a/namingserver/src/main/java/org/apache/seata/namingserver/pojo/ClusterData.java
+++ 
b/namingserver/src/main/java/org/apache/seata/namingserver/entity/pojo/ClusterData.java
@@ -14,16 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.seata.namingserver.pojo;
-
-
-import org.apache.seata.common.metadata.Cluster;
-import org.apache.seata.common.metadata.Node;
-import org.apache.seata.common.metadata.namingserver.NamingServerNode;
-import org.apache.seata.common.metadata.namingserver.Unit;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.stereotype.Component;
+package org.apache.seata.namingserver.entity.pojo;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -31,14 +22,27 @@ import java.util.Map;
 import java.util.Objects;
 import java.util.Optional;
 import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
 import java.util.stream.Collectors;
 
-@Component
-public class ClusterData extends AbstractClusterData {
+import org.apache.seata.common.metadata.Cluster;
+import org.apache.seata.common.metadata.Node;
+import org.apache.seata.common.metadata.namingserver.NamingServerNode;
+import org.apache.seata.common.metadata.namingserver.Unit;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.util.CollectionUtils;
+import org.springframework.util.StringUtils;
+
+public class ClusterData {
     private static final Logger LOGGER = 
LoggerFactory.getLogger(ClusterData.class);
     private String clusterName;
     private String clusterType;
     private final Map<String, Unit> unitData;
+    
+    private Lock lock = new ReentrantLock();
 
 
     public ClusterData() {
@@ -84,8 +88,14 @@ public class ClusterData extends AbstractClusterData {
             return;
         }
         unit.removeInstance(node);
-        if (unit.getNamingInstanceList() == null || 
unit.getNamingInstanceList().size() == 0) {
-            unitData.remove(unitName);
+        // remove unit if unit has no instance
+        lock.lock();
+        try {
+            if (CollectionUtils.isEmpty(unit.getNamingInstanceList())) {
+                unitData.remove(unitName);
+            }
+        } finally {
+            lock.unlock();
         }
     }
 
@@ -101,7 +111,7 @@ public class ClusterData extends AbstractClusterData {
         Cluster clusterResponse = new Cluster();
         clusterResponse.setClusterName(clusterName);
         clusterResponse.setClusterType(clusterType);
-        if (unitName == null || unitName.equals("")) {
+        if (!StringUtils.hasLength(unitName)) {
             clusterResponse.setUnitData(new ArrayList<>(unitData.values()));
         } else {
             List<Unit> unitList = new ArrayList<>();
@@ -112,7 +122,6 @@ public class ClusterData extends AbstractClusterData {
         return clusterResponse;
     }
 
-    @Override
     public boolean registerInstance(NamingServerNode instance, String 
unitName) {
         // refresh node weight
         Object weightValue = instance.getMetadata().get("weight");
@@ -120,18 +129,21 @@ public class ClusterData extends AbstractClusterData {
             
instance.setWeight(Double.parseDouble(String.valueOf(weightValue)));
             instance.getMetadata().remove("weight");
         }
-
-        Unit unit = unitData.get(unitName);
-        if (unit == null) {
-            unit = new Unit();
-            List<Node> instances = new ArrayList<>();
-            instances.add(instance);
+        Unit currentUnit = unitData.computeIfAbsent(unitName, value -> {
+            Unit unit = new Unit();
+            List<Node> instances = new CopyOnWriteArrayList<>();
             unit.setUnitName(unitName);
             unit.setNamingInstanceList(instances);
-            unitData.put(unitName, unit);
-            return true;
+            return unit;
+        });
+        // ensure that when adding an instance, the remove side will not 
delete the unit.
+        lock.lock();
+        try {
+            currentUnit.addInstance(instance);
+        } finally {
+            lock.unlock();
         }
-        return unit.addInstance(instance);
+        return true;
     }
 
 
diff --git 
a/namingserver/src/main/java/org/apache/seata/namingserver/vo/monitor/ClusterVO.java
 
b/namingserver/src/main/java/org/apache/seata/namingserver/entity/vo/monitor/ClusterVO.java
similarity index 95%
rename from 
namingserver/src/main/java/org/apache/seata/namingserver/vo/monitor/ClusterVO.java
rename to 
namingserver/src/main/java/org/apache/seata/namingserver/entity/vo/monitor/ClusterVO.java
index a1d253f031..e4a49ef162 100644
--- 
a/namingserver/src/main/java/org/apache/seata/namingserver/vo/monitor/ClusterVO.java
+++ 
b/namingserver/src/main/java/org/apache/seata/namingserver/entity/vo/monitor/ClusterVO.java
@@ -14,10 +14,10 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.seata.namingserver.vo.monitor;
+package org.apache.seata.namingserver.entity.vo.monitor;
 
 import org.apache.seata.common.metadata.namingserver.Unit;
-import org.apache.seata.namingserver.pojo.ClusterData;
+import org.apache.seata.namingserver.entity.pojo.ClusterData;
 
 import java.util.ArrayList;
 import java.util.List;
diff --git 
a/namingserver/src/main/java/org/apache/seata/namingserver/vo/monitor/WatcherVO.java
 
b/namingserver/src/main/java/org/apache/seata/namingserver/entity/vo/monitor/WatcherVO.java
similarity index 96%
rename from 
namingserver/src/main/java/org/apache/seata/namingserver/vo/monitor/WatcherVO.java
rename to 
namingserver/src/main/java/org/apache/seata/namingserver/entity/vo/monitor/WatcherVO.java
index d7a3fec738..e5930bdd9d 100644
--- 
a/namingserver/src/main/java/org/apache/seata/namingserver/vo/monitor/WatcherVO.java
+++ 
b/namingserver/src/main/java/org/apache/seata/namingserver/entity/vo/monitor/WatcherVO.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.seata.namingserver.vo.monitor;
+package org.apache.seata.namingserver.entity.vo.monitor;
 
 import java.util.List;
 
diff --git 
a/namingserver/src/main/java/org/apache/seata/namingserver/manager/NamingManager.java
 
b/namingserver/src/main/java/org/apache/seata/namingserver/manager/NamingManager.java
index be48c887fc..9d0cb9b832 100644
--- 
a/namingserver/src/main/java/org/apache/seata/namingserver/manager/NamingManager.java
+++ 
b/namingserver/src/main/java/org/apache/seata/namingserver/manager/NamingManager.java
@@ -28,9 +28,8 @@ import org.apache.seata.common.result.Result;
 import org.apache.seata.common.util.HttpClientUtil;
 import org.apache.seata.namingserver.constants.NamingServerConstants;
 import org.apache.seata.namingserver.listener.ClusterChangeEvent;
-import org.apache.seata.namingserver.pojo.AbstractClusterData;
-import org.apache.seata.namingserver.pojo.ClusterData;
-import org.apache.seata.namingserver.vo.monitor.ClusterVO;
+import org.apache.seata.namingserver.entity.pojo.ClusterData;
+import org.apache.seata.namingserver.entity.vo.monitor.ClusterVO;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -38,11 +37,11 @@ import org.springframework.beans.factory.annotation.Value;
 import org.springframework.context.ApplicationContext;
 import org.springframework.scheduling.concurrent.CustomizableThreadFactory;
 import org.springframework.stereotype.Component;
+import org.springframework.util.CollectionUtils;
 
 import java.io.IOException;
 import java.net.InetSocketAddress;
 import java.util.HashMap;
-import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.ArrayList;
@@ -123,8 +122,7 @@ public class NamingManager {
         return new ArrayList<>(clusterVOHashMap.values());
     }
 
-    public Result<?> addGroup(String namespace, String vGroup, String 
clusterName, String unitName) {
-        changeGroup(namespace,clusterName,unitName,vGroup);
+    public Result<String> addGroup(String namespace, String vGroup, String 
clusterName, String unitName) {
         // add vGroup in new cluster
         List<Node> nodeList = getInstances(namespace, clusterName);
         if (nodeList == null || nodeList.size() == 0) {
@@ -152,10 +150,11 @@ public class NamingManager {
                 return new Result<>("500", "add vGroup in new cluster failed");
             }
         }
+        changeGroup(namespace,clusterName,unitName,vGroup);
         return new Result<>("200", "add vGroup successfully!");
     }
 
-    public Result<?> removeGroup(String namespace, String vGroup, String 
unitName) {
+    public Result<String> removeGroup(String namespace, String vGroup, String 
unitName) {
         List<Cluster> clusterList = getClusterListByVgroup(vGroup, namespace);
         for (Cluster cluster : clusterList) {
             if (cluster.getUnitData() != null && cluster.getUnitData().size() 
> 0) {
@@ -281,56 +280,60 @@ public class NamingManager {
 
     public List<Cluster> getClusterListByVgroup(String vGroup, String 
namespace) {
         // find the cluster where the transaction group is located
-        List<Cluster> clusterList = new ArrayList<>();
-        try {
-            Pair<String, String> clusterUnitPair = 
vGroupMap.get(vGroup).get(namespace);
-            String clusterName = clusterUnitPair.getKey();
-            String unitName = clusterUnitPair.getValue();
-            ClusterData clusterData = 
namespaceClusterDataMap.get(namespace).get(clusterName);
-            clusterList.add(clusterData.getClusterByUnit(unitName));
-        } catch (NullPointerException e) {
-            LOGGER.error("no cluster mapping for vGroup: " + vGroup);
+        ConcurrentMap<String/* namespace */, Pair<String/* clusterName */, 
String/* unitName */>> map =
+            vGroupMap.get(vGroup);
+        if (!CollectionUtils.isEmpty(map)) {
+            Pair<String, String> clusterUnitPair = map.get(namespace);
+            if (clusterUnitPair != null) {
+                String clusterName = clusterUnitPair.getKey();
+                String unitName = clusterUnitPair.getValue();
+                List<Cluster> clusterList = new ArrayList<>();
+                Optional.ofNullable(namespaceClusterDataMap.get(namespace))
+                    .flatMap(clusterDataMap -> 
Optional.ofNullable(clusterDataMap.get(clusterName))).ifPresent(data -> {
+                        clusterList.add(data.getClusterByUnit(unitName));
+                    });
+                return clusterList;
+            }
         }
-        return clusterList;
+        return Collections.emptyList();
     }
 
     public List<Node> getInstances(String namespace, String clusterName) {
         Map<String, ClusterData> clusterDataHashMap = 
namespaceClusterDataMap.get(namespace);
-        AbstractClusterData abstractClusterData = 
clusterDataHashMap.get(clusterName);
-        if (abstractClusterData == null) {
+        ClusterData clusterData = clusterDataHashMap.get(clusterName);
+        if (clusterData == null) {
             LOGGER.warn("no instances in {} : {}", namespace, clusterName);
             return Collections.emptyList();
         }
-        return abstractClusterData.getInstanceList();
+        return clusterData.getInstanceList();
     }
 
     public void instanceHeartBeatCheck() {
         for (String namespace : namespaceClusterDataMap.keySet()) {
             for (ClusterData clusterData : 
namespaceClusterDataMap.get(namespace).values()) {
                 for (Unit unit : clusterData.getUnitData().values()) {
-                    Iterator<Node> instanceIterator = 
unit.getNamingInstanceList().iterator();
-
-                    while (instanceIterator.hasNext()) {
-                        Node instance = instanceIterator.next();
+                    List<Node> removeList = new ArrayList<>();
+                    for (Node instance : unit.getNamingInstanceList()) {
                         InetSocketAddress inetSocketAddress = new 
InetSocketAddress(instance.getTransaction().getHost(),
                             instance.getTransaction().getPort());
                         long lastHeatBeatTimeStamp = 
instanceLiveTable.getOrDefault(inetSocketAddress, (long)0);
-
                         if (Math.abs(lastHeatBeatTimeStamp - 
System.currentTimeMillis()) > heartbeatTimeThreshold) {
                             instanceLiveTable.remove(inetSocketAddress);
-
-                            instanceIterator.remove(); // Safe removal using 
iterator's remove method
+                            removeList.add(instance);
+                        }
+                    }
+                    if (!CollectionUtils.isEmpty(removeList)) {
+                        unit.getNamingInstanceList().removeAll(removeList);
+                        for (Node instance : removeList) {
                             clusterData.removeInstance(instance, 
unit.getUnitName());
-
-                            notifyClusterChange(namespace, 
clusterData.getClusterName(), unit.getUnitName());
                             LOGGER.warn("{} instance has gone offline",
                                 instance.getTransaction().getHost() + ":" + 
instance.getTransaction().getPort());
                         }
+                        notifyClusterChange(namespace, 
clusterData.getClusterName(), unit.getUnitName());
                     }
                 }
             }
         }
-
     }
 
 }
diff --git 
a/namingserver/src/main/java/org/apache/seata/namingserver/pojo/AbstractClusterData.java
 
b/namingserver/src/main/java/org/apache/seata/namingserver/pojo/AbstractClusterData.java
deleted file mode 100644
index b17c58375d..0000000000
--- 
a/namingserver/src/main/java/org/apache/seata/namingserver/pojo/AbstractClusterData.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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 org.apache.seata.namingserver.pojo;
-
-
-import org.apache.seata.common.metadata.Node;
-import org.apache.seata.common.metadata.namingserver.NamingServerNode;
-
-import java.util.Collections;
-import java.util.List;
-
-public abstract class AbstractClusterData {
-    /**
-     * register instance in cluster
-     *
-     * @param node     node msg
-     * @param unitName unit Name
-     * @return true if the node has changed, false if there is no change.
-     */
-    public boolean registerInstance(NamingServerNode node, String unitName) {
-        return false;
-    }
-
-    /**
-     * get all nodes in cluster
-     *
-     * @return all nodes in cluster
-     */
-    public List<Node> getInstanceList() {
-        return Collections.EMPTY_LIST;
-    }
-
-    /**
-     * remove instacne in cluster
-     *
-     * @param node     node msg
-     * @param unitName unit Name
-     */
-    public void removeInstance(Node node, String unitName) {
-    }
-}
diff --git 
a/namingserver/src/test/java/org/apache/seata/namingserver/NamingControllerTest.java
 
b/namingserver/src/test/java/org/apache/seata/namingserver/NamingControllerTest.java
index 2974e06477..c9bf44edbf 100644
--- 
a/namingserver/src/test/java/org/apache/seata/namingserver/NamingControllerTest.java
+++ 
b/namingserver/src/test/java/org/apache/seata/namingserver/NamingControllerTest.java
@@ -60,6 +60,10 @@ class NamingControllerTest {
         NamingServerNode node = new NamingServerNode();
         node.setTransaction(new Node.Endpoint("127.0.0.1", 8091, "netty"));
         node.setControl(new Node.Endpoint("127.0.0.1", 7091, "http"));
+        Map<String, Object> meatadata = node.getMetadata();
+        List<String> vGroups = new ArrayList<>();
+        vGroups.add("vgroup1");
+        meatadata.put(CONSTANT_GROUP, vGroups);
         namingController.registerInstance(namespace, clusterName, unitName, 
node);
         String vGroup = "vgroup1";
         namingController.changeGroup(namespace, clusterName, unitName, vGroup);
diff --git 
a/server/src/main/java/org/apache/seata/server/controller/HealthController.java 
b/server/src/main/java/org/apache/seata/server/controller/HealthController.java
index aff112feb9..a519340277 100644
--- 
a/server/src/main/java/org/apache/seata/server/controller/HealthController.java
+++ 
b/server/src/main/java/org/apache/seata/server/controller/HealthController.java
@@ -18,14 +18,12 @@ package org.apache.seata.server.controller;
 
 import org.apache.seata.server.ServerRunner;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Controller;
 import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.ResponseBody;
+import org.springframework.web.bind.annotation.RestController;
 
 /**
  */
-@Controller
-@RequestMapping
+@RestController
 public class HealthController {
 
     private static final String OK = "ok";
@@ -36,8 +34,8 @@ public class HealthController {
 
 
     @RequestMapping("/health")
-    @ResponseBody
     String healthCheck() {
         return serverRunner.started() ? OK : NOT_OK;
     }
+
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to