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]