Remove ServiceManager usage part3 and remove ServiceManager.java

This commit is contained in:
KomachiSion 2022-08-29 14:31:49 +08:00
parent 2f5ebe0af9
commit e648586064
8 changed files with 209 additions and 1200 deletions

View File

@ -99,7 +99,7 @@ public class AddressServerGeneratorManager {
* @param instanceList a instance set will generate string response to client.
* @return the result of response to client
*/
public String generateResponseIps(List<Instance> instanceList) {
public String generateResponseIps(List<com.alibaba.nacos.api.naming.pojo.Instance> instanceList) {
StringBuilder ips = new StringBuilder();
instanceList.forEach(instance -> {

View File

@ -21,13 +21,19 @@ import com.alibaba.nacos.address.component.AddressServerManager;
import com.alibaba.nacos.address.constant.AddressServerConstants;
import com.alibaba.nacos.address.misc.Loggers;
import com.alibaba.nacos.api.common.Constants;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.naming.pojo.healthcheck.AbstractHealthChecker;
import com.alibaba.nacos.api.naming.utils.NamingUtils;
import com.alibaba.nacos.common.utils.InternetAddressUtil;
import com.alibaba.nacos.naming.core.Cluster;
import com.alibaba.nacos.naming.core.Instance;
import com.alibaba.nacos.naming.core.Service;
import com.alibaba.nacos.naming.core.ServiceManager;
import com.alibaba.nacos.common.utils.StringUtils;
import com.alibaba.nacos.naming.core.ClusterOperator;
import com.alibaba.nacos.naming.core.Instance;
import com.alibaba.nacos.naming.core.InstanceOperator;
import com.alibaba.nacos.naming.core.v2.ServiceManager;
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 org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
@ -36,6 +42,7 @@ import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import java.util.Optional;
/**
* Address server cluster controller.
@ -47,15 +54,22 @@ import java.util.List;
@RequestMapping({AddressServerConstants.ADDRESS_SERVER_REQUEST_URL + "/nodes"})
public class AddressServerClusterController {
private final ServiceManager serviceManager;
private final InstanceOperator instanceOperator;
private final NamingMetadataManager metadataManager;
private final ClusterOperator clusterOperator;
private final AddressServerManager addressServerManager;
private final AddressServerGeneratorManager addressServerGeneratorManager;
public AddressServerClusterController(ServiceManager serviceManager, AddressServerManager addressServerManager,
public AddressServerClusterController(InstanceOperator instanceOperator, NamingMetadataManager metadataManager,
ClusterOperator clusterOperator, AddressServerManager addressServerManager,
AddressServerGeneratorManager addressServerGeneratorManager) {
this.serviceManager = serviceManager;
this.instanceOperator = instanceOperator;
this.metadataManager = metadataManager;
this.clusterOperator = clusterOperator;
this.addressServerManager = addressServerManager;
this.addressServerGeneratorManager = addressServerGeneratorManager;
}
@ -86,23 +100,13 @@ public class AddressServerClusterController {
try {
String serviceName = addressServerGeneratorManager.generateNacosServiceName(productName);
Cluster clusterObj = new Cluster();
clusterObj.setName(clusterName);
clusterObj.setHealthChecker(new AbstractHealthChecker.None());
serviceManager.createServiceIfAbsent(Constants.DEFAULT_NAMESPACE_ID, serviceName, false, clusterObj);
String[] ipArray = addressServerManager.splitIps(ips);
String checkResult = InternetAddressUtil.checkIPs(ipArray);
if (InternetAddressUtil.checkOK(checkResult)) {
List<Instance> instanceList = addressServerGeneratorManager
.generateInstancesByIps(serviceName, rawProductName, clusterName, ipArray);
for (Instance instance : instanceList) {
serviceManager.registerInstance(Constants.DEFAULT_NAMESPACE_ID, serviceName, instance);
}
Result result = registerCluster(serviceName, rawProductName, clusterName, ips);
if (InternetAddressUtil.checkOK(result.getCheckResult())) {
responseEntity = ResponseEntity
.ok("product=" + rawProductName + ",cluster=" + rawClusterName + "; put success with size="
+ instanceList.size());
+ result.getSize());
} else {
responseEntity = ResponseEntity.status(HttpStatus.BAD_REQUEST).body(checkResult);
responseEntity = ResponseEntity.status(HttpStatus.BAD_REQUEST).body(result.getCheckResult());
}
} catch (Exception e) {
responseEntity = ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(e.getMessage());
@ -111,6 +115,35 @@ public class AddressServerClusterController {
return responseEntity;
}
private Result registerCluster(String serviceName, String productName, String clusterName, String ips)
throws NacosException {
String serviceWithoutGroup = NamingUtils.getServiceName(serviceName);
String groupName = NamingUtils.getGroupName(serviceName);
Service service = Service.newService(Constants.DEFAULT_NAMESPACE_ID, groupName, serviceWithoutGroup, false);
service = ServiceManager.getInstance().getSingleton(service);
if (service.isEphemeral()) {
return new Result(
String.format("Service %s is ephemeral service, can't use as address server", serviceName), 0);
}
ServiceMetadata serviceMetadata = metadataManager.getServiceMetadata(service).orElse(new ServiceMetadata());
if (!serviceMetadata.getClusters().containsKey(clusterName)) {
ClusterMetadata metadata = new ClusterMetadata();
metadata.setHealthyCheckType(AbstractHealthChecker.None.TYPE);
metadata.setHealthChecker(new AbstractHealthChecker.None());
clusterOperator.updateClusterMetadata(Constants.DEFAULT_NAMESPACE_ID, serviceName, clusterName, metadata);
}
String[] ipArray = addressServerManager.splitIps(ips);
String checkResult = InternetAddressUtil.checkIPs(ipArray);
if (InternetAddressUtil.checkOK(checkResult)) {
List<Instance> instanceList = addressServerGeneratorManager
.generateInstancesByIps(serviceName, productName, clusterName, ipArray);
for (Instance instance : instanceList) {
instanceOperator.registerInstance(Constants.DEFAULT_NAMESPACE_ID, serviceName, instance);
}
}
return new Result(checkResult, ipArray.length);
}
/**
* Delete cluster.
*
@ -134,9 +167,12 @@ public class AddressServerClusterController {
try {
String serviceName = addressServerGeneratorManager.generateNacosServiceName(productName);
Service service = serviceManager.getService(Constants.DEFAULT_NAMESPACE_ID, serviceName);
String serviceWithoutGroup = NamingUtils.getServiceName(serviceName);
String groupName = NamingUtils.getGroupName(serviceName);
Optional<com.alibaba.nacos.naming.core.v2.pojo.Service> service = com.alibaba.nacos.naming.core.v2.ServiceManager
.getInstance().getSingletonIfExist(Constants.DEFAULT_NAMESPACE_ID, groupName, serviceWithoutGroup);
if (service == null) {
if (!service.isPresent()) {
return ResponseEntity.status(HttpStatus.NOT_FOUND).body("product=" + rawProductName + " not found.");
}
if (StringUtils.isBlank(ips)) {
@ -149,8 +185,9 @@ public class AddressServerClusterController {
if (InternetAddressUtil.checkOK(checkResult)) {
List<Instance> instanceList = addressServerGeneratorManager
.generateInstancesByIps(serviceName, rawProductName, clusterName, ipArray);
serviceManager.removeInstance(Constants.DEFAULT_NAMESPACE_ID, serviceName, false,
instanceList.toArray(new Instance[0]));
for (Instance each : instanceList) {
instanceOperator.removeInstance(Constants.DEFAULT_NAMESPACE_ID, serviceName, each);
}
} else {
responseEntity = ResponseEntity.status(HttpStatus.BAD_REQUEST).body(checkResult);
}
@ -162,4 +199,23 @@ public class AddressServerClusterController {
return responseEntity;
}
private class Result {
private final String checkResult;
private final int size;
public Result(String checkResult, int size) {
this.checkResult = checkResult;
this.size = size;
}
public String getCheckResult() {
return checkResult;
}
public int getSize() {
return size;
}
}
}

View File

@ -18,9 +18,15 @@ package com.alibaba.nacos.address.controller;
import com.alibaba.nacos.address.component.AddressServerGeneratorManager;
import com.alibaba.nacos.api.common.Constants;
import com.alibaba.nacos.naming.core.Cluster;
import com.alibaba.nacos.naming.core.Service;
import com.alibaba.nacos.naming.core.ServiceManager;
import com.alibaba.nacos.api.naming.pojo.ServiceInfo;
import com.alibaba.nacos.api.naming.utils.NamingUtils;
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.utils.ServiceUtil;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PathVariable;
@ -28,6 +34,8 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import java.util.Optional;
/**
* Server list controller.
*
@ -37,14 +45,17 @@ import org.springframework.web.bind.annotation.RestController;
@RestController
public class ServerListController {
private final ServiceManager serviceManager;
private final AddressServerGeneratorManager addressServerBuilderManager;
public ServerListController(ServiceManager serviceManager,
AddressServerGeneratorManager addressServerBuilderManager) {
this.serviceManager = serviceManager;
private final NamingMetadataManager metadataManager;
private final ServiceStorage serviceStorage;
public ServerListController(AddressServerGeneratorManager addressServerBuilderManager,
NamingMetadataManager metadataManager, ServiceStorage serviceStorage) {
this.addressServerBuilderManager = addressServerBuilderManager;
this.metadataManager = metadataManager;
this.serviceStorage = serviceStorage;
}
/**
@ -59,20 +70,22 @@ public class ServerListController {
String productName = addressServerBuilderManager.generateProductName(product);
String serviceName = addressServerBuilderManager.generateNacosServiceName(productName);
Service service = serviceManager.getService(Constants.DEFAULT_NAMESPACE_ID, serviceName);
if (service == null) {
String serviceWithoutGroup = NamingUtils.getServiceName(serviceName);
String groupName = NamingUtils.getGroupName(serviceName);
Optional<Service> service = ServiceManager.getInstance()
.getSingletonIfExist(Constants.DEFAULT_NAMESPACE_ID, groupName, serviceWithoutGroup);
if (!service.isPresent()) {
return ResponseEntity.status(HttpStatus.NOT_FOUND).body("product=" + product + " not found.");
}
if (!service.getClusterMap().containsKey(cluster)) {
ClusterMetadata metadata = metadataManager.getServiceMetadata(service.get()).orElse(new ServiceMetadata())
.getClusters().get(cluster);
if (null == metadata) {
return ResponseEntity.status(HttpStatus.NOT_FOUND)
.body("product=" + product + ",cluster=" + cluster + " not found.");
}
Cluster clusterObj = service.getClusterMap().get(cluster);
ServiceInfo serviceInfo = serviceStorage.getData(service.get());
serviceInfo = ServiceUtil.selectInstances(serviceInfo, cluster, false);
return ResponseEntity.status(HttpStatus.OK)
.body(addressServerBuilderManager.generateResponseIps(clusterObj.allIPs(false)));
.body(addressServerBuilderManager.generateResponseIps(serviceInfo.getHosts()));
}
}

View File

@ -67,7 +67,7 @@ public class AddressServerGeneratorManagerTest {
@Test
public void testGenerateResponseIps() {
final List<Instance> instanceList = new ArrayList<>();
final List<com.alibaba.nacos.api.naming.pojo.Instance> instanceList = new ArrayList<>();
Instance instance1 = new Instance();
instance1.setIp("192.168.3.1");
instance1.setPort(8848);

View File

@ -21,8 +21,12 @@ import com.alibaba.nacos.address.component.AddressServerManager;
import com.alibaba.nacos.address.constant.AddressServerConstants;
import com.alibaba.nacos.api.common.Constants;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.naming.core.Service;
import com.alibaba.nacos.naming.core.ServiceManager;
import com.alibaba.nacos.naming.core.ClusterOperator;
import com.alibaba.nacos.naming.core.InstanceOperator;
import com.alibaba.nacos.naming.core.v2.ServiceManager;
import com.alibaba.nacos.naming.core.v2.metadata.NamingMetadataManager;
import com.alibaba.nacos.naming.core.v2.pojo.Service;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@ -40,124 +44,94 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
public class AddressServerClusterControllerTest {
@Mock
private ServiceManager serviceManager;
private InstanceOperator instanceOperator;
@Mock
private NamingMetadataManager metadataManager;
@Mock
private ClusterOperator clusterOperator;
private MockMvc mockMvc;
@Before
public void before() {
mockMvc = MockMvcBuilders.standaloneSetup(new AddressServerClusterController(serviceManager, new AddressServerManager(),
new AddressServerGeneratorManager())).build();
mockMvc = MockMvcBuilders.standaloneSetup(
new AddressServerClusterController(instanceOperator, metadataManager, clusterOperator,
new AddressServerManager(), new AddressServerGeneratorManager())).build();
Service service = Service
.newService(Constants.DEFAULT_NAMESPACE_ID, Constants.DEFAULT_GROUP, "nacos.as.default", false);
ServiceManager.getInstance().getSingleton(service);
}
@After
public void tearDown() {
Service service = Service
.newService(Constants.DEFAULT_NAMESPACE_ID, Constants.DEFAULT_GROUP, "nacos.as.default", false);
ServiceManager.getInstance().removeSingleton(service);
}
@Test
public void testPostCluster() throws Exception {
mockMvc.perform(post("/nacos/v1/as/nodes")
.param("product", "default")
.param("cluster", "serverList")
.param("ips", "192.168.3.1,192.168.3.2"))
.andExpect(status().isOk());
mockMvc.perform(post("/nacos/v1/as/nodes").param("product", "default").param("cluster", "serverList")
.param("ips", "192.168.3.1,192.168.3.2")).andExpect(status().isOk());
}
@Test
public void testPostClusterWithErrorIps() throws Exception {
mockMvc.perform(post("/nacos/v1/as/nodes")
.param("product", "default")
.param("cluster", "serverList")
.param("ips", "192.168.1"))
.andExpect(status().isBadRequest());
mockMvc.perform(post("/nacos/v1/as/nodes").param("product", "default").param("cluster", "serverList")
.param("ips", "192.168.1")).andExpect(status().isBadRequest());
}
@Test
public void testPostClusterThrowException() throws Exception {
Mockito.doThrow(new NacosException(500, "create service error")).when(serviceManager)
.createServiceIfAbsent(Mockito.eq(Constants.DEFAULT_NAMESPACE_ID), Mockito.eq(
Constants.DEFAULT_GROUP + AddressServerConstants.GROUP_SERVICE_NAME_SEP + "nacos.as.default"),
Mockito.eq(false), Mockito.any());
mockMvc.perform(post("/nacos/v1/as/nodes")
.param("product", "default")
.param("cluster", "serverList")
.param("ips", "192.168.1"))
.andExpect(status().isInternalServerError());
Mockito.doThrow(new NacosException(500, "create service error")).when(clusterOperator)
.updateClusterMetadata(Mockito.eq(Constants.DEFAULT_NAMESPACE_ID), Mockito.eq(
Constants.DEFAULT_GROUP + AddressServerConstants.GROUP_SERVICE_NAME_SEP + "nacos.as.default"),
Mockito.eq("serverList"), Mockito.any());
mockMvc.perform(post("/nacos/v1/as/nodes").param("product", "default").param("cluster", "serverList")
.param("ips", "192.168.1")).andExpect(status().isInternalServerError());
}
@Test
public void testDeleteCluster() throws Exception {
Mockito.when(serviceManager.getService(Mockito.eq(Constants.DEFAULT_NAMESPACE_ID),
Mockito.eq(Constants.DEFAULT_GROUP + AddressServerConstants.GROUP_SERVICE_NAME_SEP + "nacos.as.default")))
.thenReturn(new Service(Constants.DEFAULT_GROUP + AddressServerConstants.GROUP_SERVICE_NAME_SEP + "nacos.as.default"));
mockMvc.perform(delete("/nacos/v1/as/nodes")
.param("product", "default")
.param("cluster", "serverList")
.param("ips", "192.168.3.1,192.168.3.2")
).andExpect(status().isOk());
mockMvc.perform(delete("/nacos/v1/as/nodes").param("product", "default").param("cluster", "serverList")
.param("ips", "192.168.3.1,192.168.3.2")).andExpect(status().isOk());
}
@Test
public void testDeleteClusterCannotFindService() throws Exception {
mockMvc.perform(delete("/nacos/v1/as/nodes")
.param("product", "default")
.param("cluster", "serverList")
.param("ips", "192.168.3.1,192.168.3.2")
).andExpect(status().isNotFound());
tearDown();
mockMvc.perform(delete("/nacos/v1/as/nodes").param("product", "default").param("cluster", "serverList")
.param("ips", "192.168.3.1,192.168.3.2")).andExpect(status().isNotFound());
}
@Test
public void testDeleteClusterEmptyIps() throws Exception {
Mockito.when(serviceManager.getService(Mockito.eq(Constants.DEFAULT_NAMESPACE_ID),
Mockito.eq(Constants.DEFAULT_GROUP + AddressServerConstants.GROUP_SERVICE_NAME_SEP + "nacos.as.default")))
.thenReturn(new Service(Constants.DEFAULT_GROUP + AddressServerConstants.GROUP_SERVICE_NAME_SEP + "nacos.as.default"));
mockMvc.perform(delete("/nacos/v1/as/nodes")
.param("product", "default")
.param("cluster", "serverList")
.param("ips", "")
).andExpect(status().isBadRequest());
mockMvc.perform(delete("/nacos/v1/as/nodes").param("product", "default").param("cluster", "serverList")
.param("ips", "")).andExpect(status().isBadRequest());
}
@Test
public void testDeleteClusterErrorIps() throws Exception {
Mockito.when(serviceManager.getService(Mockito.eq(Constants.DEFAULT_NAMESPACE_ID),
Mockito.eq(Constants.DEFAULT_GROUP + AddressServerConstants.GROUP_SERVICE_NAME_SEP + "nacos.as.default")))
.thenReturn(new Service(Constants.DEFAULT_GROUP + AddressServerConstants.GROUP_SERVICE_NAME_SEP + "nacos.as.default"));
mockMvc.perform(delete("/nacos/v1/as/nodes")
.param("product", "default")
.param("cluster", "serverList")
.param("ips", "192.168.1")
).andExpect(status().isBadRequest());
mockMvc.perform(delete("/nacos/v1/as/nodes").param("product", "default").param("cluster", "serverList")
.param("ips", "192.168.1")).andExpect(status().isBadRequest());
}
@Test
public void testDeleteClusterThrowException() throws Exception {
Mockito.when(serviceManager.getService(Mockito.eq(Constants.DEFAULT_NAMESPACE_ID),
Mockito.eq(Constants.DEFAULT_GROUP + AddressServerConstants.GROUP_SERVICE_NAME_SEP + "nacos.as.default")))
.thenReturn(new Service(Constants.DEFAULT_GROUP + AddressServerConstants.GROUP_SERVICE_NAME_SEP + "nacos.as.default"));
Mockito.doThrow(new NacosException(500, "remove service error"))
.when(serviceManager)
.removeInstance(Mockito.eq(Constants.DEFAULT_NAMESPACE_ID),
Mockito.eq(Constants.DEFAULT_GROUP + AddressServerConstants.GROUP_SERVICE_NAME_SEP + "nacos.as.default"),
Mockito.eq(false),
Mockito.doThrow(new NacosException(500, "remove service error")).when(instanceOperator)
.removeInstance(Mockito.eq(Constants.DEFAULT_NAMESPACE_ID), Mockito.eq(
Constants.DEFAULT_GROUP + AddressServerConstants.GROUP_SERVICE_NAME_SEP + "nacos.as.default"),
Mockito.any());
mockMvc.perform(delete("/nacos/v1/as/nodes")
.param("product", "default")
.param("cluster", "serverList")
.param("ips", "192.168.3.1,192.168.3.2")
).andExpect(status().isInternalServerError());
mockMvc.perform(delete("/nacos/v1/as/nodes").param("product", "default").param("cluster", "serverList")
.param("ips", "192.168.3.1,192.168.3.2")).andExpect(status().isInternalServerError());
}
}

View File

@ -17,25 +17,29 @@
package com.alibaba.nacos.address.controller;
import com.alibaba.nacos.address.component.AddressServerGeneratorManager;
import com.alibaba.nacos.address.constant.AddressServerConstants;
import com.alibaba.nacos.api.common.Constants;
import com.alibaba.nacos.naming.core.Cluster;
import com.alibaba.nacos.naming.core.Instance;
import com.alibaba.nacos.naming.core.Service;
import com.alibaba.nacos.naming.core.ServiceManager;
import com.alibaba.nacos.api.naming.pojo.Instance;
import com.alibaba.nacos.api.naming.pojo.ServiceInfo;
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 org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Optional;
import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@ -43,68 +47,56 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
public class ServerListControllerTest {
@Mock
private ServiceManager serviceManager;
private NamingMetadataManager metadataManager;
@Mock
private ServiceStorage serviceStorage;
private Service service;
private MockMvc mockMvc;
@Before
public void before() {
this.mockMvc = MockMvcBuilders
.standaloneSetup(new ServerListController(serviceManager, new AddressServerGeneratorManager()))
.build();
this.mockMvc = MockMvcBuilders.standaloneSetup(
new ServerListController(new AddressServerGeneratorManager(), metadataManager, serviceStorage)).build();
service = Service
.newService(Constants.DEFAULT_NAMESPACE_ID, Constants.DEFAULT_GROUP, "nacos.as.default", false);
ServiceManager.getInstance().getSingleton(service);
}
@After
public void tearDown() {
ServiceManager.getInstance().removeSingleton(service);
}
@Test
public void testGetCluster() throws Exception {
final Service service = new Service(
Constants.DEFAULT_GROUP + AddressServerConstants.GROUP_SERVICE_NAME_SEP + "nacos.as.default");
Cluster cluster = new Cluster();
cluster.setName("serverList");
cluster.setService(service);
final HashMap<String, Cluster> clusterMap = new HashMap<>(1);
clusterMap.put("serverList", cluster);
service.setClusterMap(clusterMap);
final Service service = Service
.newService(Constants.DEFAULT_NAMESPACE_ID, Constants.DEFAULT_GROUP, "nacos.as.default", false);
ServiceMetadata serviceMetadata = new ServiceMetadata();
serviceMetadata.getClusters().put("serverList", new ClusterMetadata());
when(metadataManager.getServiceMetadata(service)).thenReturn(Optional.of(serviceMetadata));
List<Instance> list = new ArrayList<>(2);
list.add(new Instance("192.168.3.1", 8848));
list.add(new Instance("192.168.3.2", 8848));
cluster.updateIps(list, false);
Mockito.when(serviceManager.getService(Mockito.eq(Constants.DEFAULT_NAMESPACE_ID),
Mockito.eq(Constants.DEFAULT_GROUP + AddressServerConstants.GROUP_SERVICE_NAME_SEP + "nacos.as.default")))
.thenReturn(service);
mockMvc.perform(get("/nacos/serverList"))
.andExpect(status().isOk());
list.add(new Instance());
list.add(new Instance());
ServiceInfo serviceInfo = new ServiceInfo();
serviceInfo.setHosts(list);
when(serviceStorage.getData(service)).thenReturn(serviceInfo);
mockMvc.perform(get("/nacos/serverList")).andExpect(status().isOk());
}
@Test
public void testGetClusterCannotFindService() throws Exception {
mockMvc.perform(get("/default/serverList"))
.andExpect(status().isNotFound());
tearDown();
mockMvc.perform(get("/default/serverList")).andExpect(status().isNotFound());
}
@Test
public void testGetClusterCannotFindCluster() throws Exception {
final Service service = new Service(
Constants.DEFAULT_GROUP + AddressServerConstants.GROUP_SERVICE_NAME_SEP + "nacos.as.default");
final HashMap<String, Cluster> clusterMap = new HashMap<>(1);
service.setClusterMap(clusterMap);
Mockito.when(serviceManager.getService(Mockito.eq(Constants.DEFAULT_NAMESPACE_ID),
Mockito.eq(Constants.DEFAULT_GROUP + AddressServerConstants.GROUP_SERVICE_NAME_SEP + "nacos.as.default")))
.thenReturn(service);
mockMvc.perform(get("/nacos/serverList"))
.andExpect(status().isNotFound());
mockMvc.perform(get("/nacos/serverList")).andExpect(status().isNotFound());
}
}

View File

@ -1,843 +0,0 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.nacos.naming.core;
import com.alibaba.nacos.api.common.Constants;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.naming.utils.NamingUtils;
import com.alibaba.nacos.common.utils.CollectionUtils;
import com.alibaba.nacos.common.utils.InternetAddressUtil;
import com.alibaba.nacos.common.utils.JacksonUtils;
import com.alibaba.nacos.common.utils.StringUtils;
import com.alibaba.nacos.core.cluster.ServerMemberManager;
import com.alibaba.nacos.naming.consistency.ConsistencyService;
import com.alibaba.nacos.naming.consistency.Datum;
import com.alibaba.nacos.naming.consistency.KeyBuilder;
import com.alibaba.nacos.naming.consistency.RecordListener;
import com.alibaba.nacos.naming.misc.Loggers;
import com.alibaba.nacos.naming.misc.SwitchDomain;
import com.alibaba.nacos.naming.misc.UtilsAndCommons;
import com.alibaba.nacos.naming.push.UdpPushService;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.StringJoiner;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentSkipListMap;
import java.util.stream.Collectors;
import static com.alibaba.nacos.naming.misc.UtilsAndCommons.UPDATE_INSTANCE_METADATA_ACTION_REMOVE;
import static com.alibaba.nacos.naming.misc.UtilsAndCommons.UPDATE_INSTANCE_METADATA_ACTION_UPDATE;
/**
* Core manager storing all services in Nacos.
*
* @author nkorange
*/
@Component
public class ServiceManager implements RecordListener<Service> {
/**
* Map(namespace, Map(group::serviceName, Service)).
*/
private final Map<String, Map<String, Service>> serviceMap = new ConcurrentHashMap<>();
@Resource(name = "consistencyDelegate")
private ConsistencyService consistencyService;
private final SwitchDomain switchDomain;
private final DistroMapper distroMapper;
private final ServerMemberManager memberManager;
private final UdpPushService pushService;
public ServiceManager(SwitchDomain switchDomain, DistroMapper distroMapper, ServerMemberManager memberManager,
UdpPushService pushService) {
this.switchDomain = switchDomain;
this.distroMapper = distroMapper;
this.memberManager = memberManager;
this.pushService = pushService;
}
/**
* Init service maneger.
*/
@PostConstruct
public void init() {
try {
Loggers.SRV_LOG.info("listen for service meta change");
consistencyService.listen(KeyBuilder.SERVICE_META_KEY_PREFIX, this);
} catch (NacosException e) {
Loggers.SRV_LOG.error("listen for service meta change failed!");
}
}
public Map<String, Service> chooseServiceMap(String namespaceId) {
return serviceMap.get(namespaceId);
}
@Override
public boolean interests(String key) {
return KeyBuilder.matchServiceMetaKey(key) && !KeyBuilder.matchSwitchKey(key);
}
@Override
public boolean matchUnlistenKey(String key) {
return KeyBuilder.matchServiceMetaKey(key) && !KeyBuilder.matchSwitchKey(key);
}
@Override
public void onChange(String key, Service service) throws Exception {
try {
if (service == null) {
Loggers.SRV_LOG.warn("received empty push from raft, key: {}", key);
return;
}
if (StringUtils.isBlank(service.getNamespaceId())) {
service.setNamespaceId(Constants.DEFAULT_NAMESPACE_ID);
}
Loggers.RAFT.info("[RAFT-NOTIFIER] datum is changed, key: {}, value: {}", key, service);
Service oldDom = getService(service.getNamespaceId(), service.getName());
if (oldDom != null) {
oldDom.update(service);
// re-listen to handle the situation when the underlying listener is removed:
consistencyService
.listen(KeyBuilder.buildInstanceListKey(service.getNamespaceId(), service.getName(), true),
oldDom);
consistencyService
.listen(KeyBuilder.buildInstanceListKey(service.getNamespaceId(), service.getName(), false),
oldDom);
} else {
putServiceAndInit(service);
}
} catch (Throwable e) {
Loggers.SRV_LOG.error("[NACOS-SERVICE] error while processing service update", e);
}
}
@Override
public void onDelete(String key) throws Exception {
String namespace = KeyBuilder.getNamespace(key);
String name = KeyBuilder.getServiceName(key);
Service service = chooseServiceMap(namespace).get(name);
Loggers.RAFT.info("[RAFT-NOTIFIER] datum is deleted, key: {}", key);
if (service != null) {
cleanupService(namespace, name, service);
}
chooseServiceMap(namespace).remove(name);
}
public Set<String> getAllServiceNames(String namespaceId) {
return serviceMap.get(namespaceId).keySet();
}
public Map<String, Set<String>> getAllServiceNames() {
Map<String, Set<String>> namesMap = new HashMap<>(16);
for (String namespaceId : serviceMap.keySet()) {
namesMap.put(namespaceId, serviceMap.get(namespaceId).keySet());
}
return namesMap;
}
public Set<String> getAllNamespaces() {
return serviceMap.keySet();
}
public List<String> getAllServiceNameList(String namespaceId) {
if (chooseServiceMap(namespaceId) == null) {
return new ArrayList<>();
}
return new ArrayList<>(chooseServiceMap(namespaceId).keySet());
}
public Map<String, Set<Service>> getResponsibleServices() {
Map<String, Set<Service>> result = new HashMap<>(16);
for (String namespaceId : serviceMap.keySet()) {
result.put(namespaceId, new HashSet<>());
for (Map.Entry<String, Service> entry : serviceMap.get(namespaceId).entrySet()) {
Service service = entry.getValue();
if (distroMapper.responsible(entry.getKey())) {
result.get(namespaceId).add(service);
}
}
}
return result;
}
public int getResponsibleServiceCount() {
int serviceCount = 0;
for (String namespaceId : serviceMap.keySet()) {
for (Map.Entry<String, Service> entry : serviceMap.get(namespaceId).entrySet()) {
if (distroMapper.responsible(entry.getKey())) {
serviceCount++;
}
}
}
return serviceCount;
}
public int getResponsibleInstanceCount() {
Map<String, Set<Service>> responsibleServices = getResponsibleServices();
int count = 0;
for (String namespaceId : responsibleServices.keySet()) {
for (Service service : responsibleServices.get(namespaceId)) {
count += service.allIPs().size();
}
}
return count;
}
/**
* Fast remove service.
*
* <p>Remove service bu async.
*
* @param namespaceId namespace
* @param serviceName service name
* @throws NacosException exception
*/
public void easyRemoveService(String namespaceId, String serviceName) throws NacosException {
Service service = getService(namespaceId, serviceName);
if (service == null) {
throw new NacosException(NacosException.INVALID_PARAM,
"specified service not exist, serviceName : " + serviceName);
}
consistencyService.remove(KeyBuilder.buildServiceMetaKey(namespaceId, serviceName));
}
public void addOrReplaceService(Service service) throws NacosException {
consistencyService.put(KeyBuilder.buildServiceMetaKey(service.getNamespaceId(), service.getName()), service);
}
public void createEmptyService(String namespaceId, String serviceName, boolean local) throws NacosException {
createServiceIfAbsent(namespaceId, serviceName, local, null);
}
/**
* Create service if not exist.
*
* @param namespaceId namespace
* @param serviceName service name
* @param local whether create service by local
* @param cluster cluster
* @throws NacosException nacos exception
*/
public void createServiceIfAbsent(String namespaceId, String serviceName, boolean local, Cluster cluster)
throws NacosException {
Service service = getService(namespaceId, serviceName);
//return if service already exists
if (service != null) {
return;
}
Loggers.SRV_LOG.info("creating empty service {}:{}", namespaceId, serviceName);
service = new Service();
service.setName(serviceName);
service.setNamespaceId(namespaceId);
service.setGroupName(NamingUtils.getGroupName(serviceName));
// now validate the service. if failed, exception will be thrown
service.setLastModifiedMillis(System.currentTimeMillis());
service.recalculateChecksum();
if (cluster != null) {
cluster.setService(service);
service.getClusterMap().put(cluster.getName(), cluster);
}
service.validate();
putServiceAndInit(service);
if (!local) {
addOrReplaceService(service);
}
}
/**
* Register an instance to a service in AP mode.
*
* <p>This method creates service or cluster silently if they don't exist.
*
* @param namespaceId id of namespace
* @param serviceName service name
* @param instance instance to register
* @throws Exception any error occurred in the process
*/
public void registerInstance(String namespaceId, String serviceName, Instance instance) throws NacosException {
NamingUtils.checkInstanceIsLegal(instance);
createEmptyService(namespaceId, serviceName, instance.isEphemeral());
Service service = getService(namespaceId, serviceName);
checkServiceIsNull(service, namespaceId, serviceName);
addInstance(namespaceId, serviceName, instance.isEphemeral(), instance);
}
/**
* Update instance to service.
*
* @param namespaceId namespace
* @param serviceName service name
* @param instance instance
* @throws NacosException nacos exception
*/
public void updateInstance(String namespaceId, String serviceName, Instance instance) throws NacosException {
Service service = getService(namespaceId, serviceName);
checkServiceIsNull(service, namespaceId, serviceName);
if (!service.allIPs().contains(instance)) {
throw new NacosException(NacosException.INVALID_PARAM, "instance not exist: " + instance);
}
addInstance(namespaceId, serviceName, instance.isEphemeral(), instance);
}
/**
* Update instance's metadata.
*
* @param namespaceId namespace
* @param serviceName service name
* @param action update or remove
* @param ips need update instances
* @param metadata target metadata
* @return update succeed instances
* @throws NacosException nacos exception
*/
public List<Instance> updateMetadata(String namespaceId, String serviceName, boolean isEphemeral, String action,
boolean all, List<Instance> ips, Map<String, String> metadata) throws NacosException {
Service service = getService(namespaceId, serviceName);
checkServiceIsNull(service, namespaceId, serviceName);
List<Instance> locatedInstance = getLocatedInstance(namespaceId, serviceName, isEphemeral, all, ips);
if (CollectionUtils.isEmpty(locatedInstance)) {
throw new NacosException(NacosException.INVALID_PARAM, "not locate instances, input instances: " + ips);
}
if (UPDATE_INSTANCE_METADATA_ACTION_UPDATE.equals(action)) {
locatedInstance.forEach(ele -> ele.getMetadata().putAll(metadata));
} else if (UPDATE_INSTANCE_METADATA_ACTION_REMOVE.equals(action)) {
Set<String> removeKeys = metadata.keySet();
for (String removeKey : removeKeys) {
locatedInstance.forEach(ele -> ele.getMetadata().remove(removeKey));
}
}
Instance[] instances = new Instance[locatedInstance.size()];
locatedInstance.toArray(instances);
addInstance(namespaceId, serviceName, isEphemeral, instances);
return locatedInstance;
}
/**
* Check if the service is null.
*
* @param service service
* @param namespaceId namespace
* @param serviceName service name
* @throws NacosException nacos exception
*/
public void checkServiceIsNull(Service service, String namespaceId, String serviceName) throws NacosException {
if (service == null) {
throw new NacosException(NacosException.INVALID_PARAM,
"service not found, namespace: " + namespaceId + ", serviceName: " + serviceName);
}
}
/**
* Locate consistency's datum by all or instances provided.
*
* @param namespaceId namespace
* @param serviceName serviceName
* @param isEphemeral isEphemeral
* @param all get from consistencyService directly
* @param waitLocateInstance instances provided
* @return located instances
* @throws NacosException nacos exception
*/
public List<Instance> getLocatedInstance(String namespaceId, String serviceName, boolean isEphemeral, boolean all,
List<Instance> waitLocateInstance) throws NacosException {
List<Instance> locatedInstance;
//need the newest data from consistencyService
Datum datum = consistencyService.get(KeyBuilder.buildInstanceListKey(namespaceId, serviceName, isEphemeral));
if (datum == null) {
throw new NacosException(NacosException.NOT_FOUND,
"instances from consistencyService not exist, namespace: " + namespaceId + ", service: "
+ serviceName + ", ephemeral: " + isEphemeral);
}
if (all) {
locatedInstance = ((Instances) datum.value).getInstanceList();
} else {
locatedInstance = new ArrayList<>();
for (Instance instance : waitLocateInstance) {
Instance located = locateInstance(((Instances) datum.value).getInstanceList(), instance);
if (located == null) {
continue;
}
locatedInstance.add(located);
}
}
return locatedInstance;
}
private Instance locateInstance(List<Instance> sources, Instance target) {
if (CollectionUtils.isEmpty(sources)) {
return null;
}
for (Instance element : sources) {
//also need clusterName equals, the same instance maybe exist in two cluster.
if (Objects.equals(element, target) && Objects.equals(element.getClusterName(), target.getClusterName())) {
return element;
}
}
return null;
}
/**
* Add instance to service.
*
* @param namespaceId namespace
* @param serviceName service name
* @param ephemeral whether instance is ephemeral
* @param ips instances
* @throws NacosException nacos exception
*/
public void addInstance(String namespaceId, String serviceName, boolean ephemeral, Instance... ips)
throws NacosException {
String key = KeyBuilder.buildInstanceListKey(namespaceId, serviceName, ephemeral);
Service service = getService(namespaceId, serviceName);
synchronized (service) {
List<Instance> instanceList = addIpAddresses(service, ephemeral, ips);
Instances instances = new Instances();
instances.setInstanceList(instanceList);
consistencyService.put(key, instances);
}
}
/**
* Remove instance from service.
*
* @param namespaceId namespace
* @param serviceName service name
* @param ephemeral whether instance is ephemeral
* @param ips instances
* @throws NacosException nacos exception
*/
public void removeInstance(String namespaceId, String serviceName, boolean ephemeral, Instance... ips)
throws NacosException {
Service service = getService(namespaceId, serviceName);
synchronized (service) {
removeInstance(namespaceId, serviceName, ephemeral, service, ips);
}
}
private void removeInstance(String namespaceId, String serviceName, boolean ephemeral, Service service,
Instance... ips) throws NacosException {
String key = KeyBuilder.buildInstanceListKey(namespaceId, serviceName, ephemeral);
List<Instance> instanceList = substractIpAddresses(service, ephemeral, ips);
Instances instances = new Instances();
instances.setInstanceList(instanceList);
consistencyService.put(key, instances);
}
public Instance getInstance(String namespaceId, String serviceName, String cluster, String ip, int port) {
Service service = getService(namespaceId, serviceName);
if (service == null) {
return null;
}
List<String> clusters = new ArrayList<>();
clusters.add(cluster);
List<Instance> ips = service.allIPs(clusters);
if (ips == null || ips.isEmpty()) {
return null;
}
for (Instance instance : ips) {
if (instance.getIp().equals(ip) && instance.getPort() == port) {
return instance;
}
}
return null;
}
/**
* Compare and get new instance list.
*
* @param service service
* @param action {@link UtilsAndCommons#UPDATE_INSTANCE_ACTION_REMOVE} or {@link UtilsAndCommons#UPDATE_INSTANCE_ACTION_ADD}
* @param ephemeral whether instance is ephemeral
* @param ips instances
* @return instance list after operation
* @throws NacosException nacos exception
*/
public List<Instance> updateIpAddresses(Service service, String action, boolean ephemeral, Instance... ips)
throws NacosException {
Datum datum = consistencyService
.get(KeyBuilder.buildInstanceListKey(service.getNamespaceId(), service.getName(), ephemeral));
List<Instance> currentIPs = service.allIPs(ephemeral);
Map<String, Instance> currentInstances = new HashMap<>(currentIPs.size());
Set<String> currentInstanceIds = CollectionUtils.set();
for (Instance instance : currentIPs) {
currentInstances.put(instance.toIpAddr(), instance);
currentInstanceIds.add(instance.getInstanceId());
}
Map<String, Instance> instanceMap;
if (datum != null && null != datum.value) {
instanceMap = setValid(((Instances) datum.value).getInstanceList(), currentInstances);
} else {
instanceMap = new HashMap<>(ips.length);
}
for (Instance instance : ips) {
if (!service.getClusterMap().containsKey(instance.getClusterName())) {
Cluster cluster = new Cluster(instance.getClusterName(), service);
cluster.init();
service.getClusterMap().put(instance.getClusterName(), cluster);
Loggers.SRV_LOG
.warn("cluster: {} not found, ip: {}, will create new cluster with default configuration.",
instance.getClusterName(), instance.toJson());
}
if (UtilsAndCommons.UPDATE_INSTANCE_ACTION_REMOVE.equals(action)) {
instanceMap.remove(instance.getDatumKey());
} else {
Instance oldInstance = instanceMap.get(instance.getDatumKey());
if (oldInstance != null) {
instance.setInstanceId(oldInstance.getInstanceId());
} else {
instance.setInstanceId(instance.generateInstanceId(currentInstanceIds));
}
instanceMap.put(instance.getDatumKey(), instance);
}
}
if (instanceMap.size() <= 0 && UtilsAndCommons.UPDATE_INSTANCE_ACTION_ADD.equals(action)) {
throw new IllegalArgumentException(
"ip list can not be empty, service: " + service.getName() + ", ip list: " + JacksonUtils
.toJson(instanceMap.values()));
}
return new ArrayList<>(instanceMap.values());
}
private List<Instance> substractIpAddresses(Service service, boolean ephemeral, Instance... ips)
throws NacosException {
return updateIpAddresses(service, UtilsAndCommons.UPDATE_INSTANCE_ACTION_REMOVE, ephemeral, ips);
}
private List<Instance> addIpAddresses(Service service, boolean ephemeral, Instance... ips) throws NacosException {
return updateIpAddresses(service, UtilsAndCommons.UPDATE_INSTANCE_ACTION_ADD, ephemeral, ips);
}
private Map<String, Instance> setValid(List<Instance> oldInstances, Map<String, Instance> map) {
Map<String, Instance> instanceMap = new HashMap<>(oldInstances.size());
for (Instance instance : oldInstances) {
Instance instance1 = map.get(instance.toIpAddr());
if (instance1 != null) {
instance.setHealthy(instance1.isHealthy());
instance.setLastBeat(instance1.getLastBeat());
}
instanceMap.put(instance.getDatumKey(), instance);
}
return instanceMap;
}
public Service getService(String namespaceId, String serviceName) {
Map<String, Service> service = this.serviceMap.get(namespaceId);
if (service == null) {
return null;
}
return service.get(serviceName);
}
public boolean containService(String namespaceId, String serviceName) {
return getService(namespaceId, serviceName) != null;
}
/**
* Put service into manager.
*
* @param service service
*/
public void putService(Service service) {
if (!serviceMap.containsKey(service.getNamespaceId())) {
serviceMap.putIfAbsent(service.getNamespaceId(), new ConcurrentSkipListMap<>());
}
serviceMap.get(service.getNamespaceId()).putIfAbsent(service.getName(), service);
}
private void putServiceAndInit(Service service) throws NacosException {
putService(service);
service = getService(service.getNamespaceId(), service.getName());
service.init();
consistencyService
.listen(KeyBuilder.buildInstanceListKey(service.getNamespaceId(), service.getName(), true), service);
consistencyService
.listen(KeyBuilder.buildInstanceListKey(service.getNamespaceId(), service.getName(), false), service);
Loggers.SRV_LOG.info("[NEW-SERVICE] {}", service.toJson());
}
/**
* Search services.
*
* @param namespaceId namespace
* @param regex search regex
* @return list of service which searched
*/
public List<Service> searchServices(String namespaceId, String regex) {
List<Service> result = new ArrayList<>();
for (Map.Entry<String, Service> entry : chooseServiceMap(namespaceId).entrySet()) {
Service service = entry.getValue();
String key = service.getName() + ":" + service.getOwners().toString();
if (key.matches(regex)) {
result.add(service);
}
}
return result;
}
public int getServiceCount() {
int serviceCount = 0;
for (String namespaceId : serviceMap.keySet()) {
serviceCount += serviceMap.get(namespaceId).size();
}
return serviceCount;
}
public int getInstanceCount() {
int total = 0;
for (String namespaceId : serviceMap.keySet()) {
for (Service service : serviceMap.get(namespaceId).values()) {
total += service.allIPs().size();
}
}
return total;
}
public int getPagedService(String namespaceId, int startPage, int pageSize, String param, String containedInstance,
List<Service> serviceList, boolean hasIpCount) {
List<Service> matchList;
if (chooseServiceMap(namespaceId) == null) {
return 0;
}
if (StringUtils.isNotBlank(param)) {
StringJoiner regex = new StringJoiner(Constants.SERVICE_INFO_SPLITER);
for (String s : param.split(Constants.SERVICE_INFO_SPLITER, Constants.SERVICE_INFO_SPLIT_COUNT)) {
regex.add(StringUtils.isBlank(s) ? Constants.ANY_PATTERN
: Constants.ANY_PATTERN + s + Constants.ANY_PATTERN);
}
matchList = searchServices(namespaceId, regex.toString());
} else {
matchList = new ArrayList<>(chooseServiceMap(namespaceId).values());
}
if (!CollectionUtils.isEmpty(matchList) && hasIpCount) {
matchList = matchList.stream().filter(s -> !CollectionUtils.isEmpty(s.allIPs()))
.collect(Collectors.toList());
}
if (StringUtils.isNotBlank(containedInstance)) {
boolean contained;
for (int i = 0; i < matchList.size(); i++) {
Service service = matchList.get(i);
contained = false;
List<Instance> instances = service.allIPs();
for (Instance instance : instances) {
if (InternetAddressUtil.containsPort(containedInstance)) {
if (StringUtils
.equals(instance.getIp() + InternetAddressUtil.IP_PORT_SPLITER + instance.getPort(),
containedInstance)) {
contained = true;
break;
}
} else {
if (StringUtils.equals(instance.getIp(), containedInstance)) {
contained = true;
break;
}
}
}
if (!contained) {
matchList.remove(i);
i--;
}
}
}
if (pageSize >= matchList.size()) {
serviceList.addAll(matchList);
return matchList.size();
}
for (int i = 0; i < matchList.size(); i++) {
if (i < startPage * pageSize) {
continue;
}
serviceList.add(matchList.get(i));
if (serviceList.size() >= pageSize) {
break;
}
}
return matchList.size();
}
/**
* Shut down service manager v1.x.
*
* @throws NacosException nacos exception during shutdown
*/
public void shutdown() throws NacosException {
try {
long start = System.nanoTime();
Loggers.SRV_LOG
.info("Start to destroy ALL services. namespaces: {}, services: {}", serviceMap.keySet().size(),
getServiceCount());
for (Iterator<Map.Entry<String, Map<String, Service>>> iterator = serviceMap.entrySet().iterator();
iterator.hasNext(); ) {
Map.Entry<String, Map<String, Service>> entry = iterator.next();
destroyAllService(entry.getKey(), entry.getValue());
iterator.remove();
}
Loggers.SRV_LOG.info(String.format("Successfully destroy ALL services. costs %.2fms",
((float) (System.nanoTime() - start)) * 1e-6));
} catch (Exception e) {
throw new NacosException(NacosException.SERVER_ERROR, "shutdown serviceManager failed", e);
}
}
private void destroyAllService(String namespace, Map<String, Service> serviceMap) throws Exception {
for (Iterator<Map.Entry<String, Service>> iterator = serviceMap.entrySet().iterator(); iterator.hasNext(); ) {
Map.Entry<String, Service> entry = iterator.next();
Service service = entry.getValue();
String name = service.getName();
cleanupService(namespace, name, service);
iterator.remove();
}
}
private void cleanupService(String namespace, String name, Service service) throws Exception {
service.destroy();
String ephemeralInstanceListKey = KeyBuilder.buildInstanceListKey(namespace, name, true);
String persistInstanceListKey = KeyBuilder.buildInstanceListKey(namespace, name, false);
String serviceMetaKey = KeyBuilder.buildServiceMetaKey(namespace, name);
consistencyService.remove(ephemeralInstanceListKey);
consistencyService.remove(persistInstanceListKey);
consistencyService.remove(serviceMetaKey);
// remove listeners of key to avoid mem leak
consistencyService.unListen(ephemeralInstanceListKey, service);
consistencyService.unListen(persistInstanceListKey, service);
consistencyService.unListen(serviceMetaKey, service);
Loggers.SRV_LOG.info("[DEAD-SERVICE] {}", service.toJson());
}
private static class ServiceKey {
private String namespaceId;
private String serviceName;
private String serverIP;
private String checksum;
public String getChecksum() {
return checksum;
}
public String getServerIP() {
return serverIP;
}
public String getServiceName() {
return serviceName;
}
public String getNamespaceId() {
return namespaceId;
}
public ServiceKey(String namespaceId, String serviceName, String serverIP, String checksum) {
this.namespaceId = namespaceId;
this.serviceName = serviceName;
this.serverIP = serverIP;
this.checksum = checksum;
}
@Override
public String toString() {
return JacksonUtils.toJson(this);
}
}
}

View File

@ -1,183 +0,0 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.nacos.naming.core;
import com.alibaba.nacos.api.naming.pojo.healthcheck.impl.Http;
import com.alibaba.nacos.common.utils.JacksonUtils;
import com.alibaba.nacos.sys.env.EnvUtil;
import com.alibaba.nacos.sys.utils.ApplicationUtils;
import com.alibaba.nacos.naming.misc.SwitchDomain;
import com.alibaba.nacos.naming.misc.SwitchDomain.TcpHealthParams;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.mock.env.MockEnvironment;
import java.util.ArrayList;
import java.util.List;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.when;
@RunWith(MockitoJUnitRunner.class)
public class ClusterTest {
private Cluster cluster;
@Mock
private ConfigurableApplicationContext context;
@Mock
private SwitchDomain switchDomain;
@Before
public void before() {
EnvUtil.setEnvironment(new MockEnvironment());
ApplicationUtils.injectContext(context);
when(context.getBean(SwitchDomain.class)).thenReturn(switchDomain);
when(switchDomain.getTcpHealthParams()).thenReturn(new TcpHealthParams());
Service service = new Service();
service.setName("nacos.service.1");
cluster = new Cluster("nacos-cluster-1", service);
cluster.setDefCkport(80);
cluster.setDefIPPort(8080);
cluster.init();
}
@After
public void tearDown() {
cluster.destroy();
}
@Test
public void updateCluster() {
Service service = new Service();
service.setName("nacos.service.2");
Cluster newCluster = new Cluster("nacos-cluster-1", service);
newCluster.setDefCkport(8888);
newCluster.setDefIPPort(9999);
Http healthCheckConfig = new Http();
healthCheckConfig.setPath("/nacos-path-1");
healthCheckConfig.setExpectedResponseCode(500);
healthCheckConfig.setHeaders("Client-Version:nacos-test-1");
newCluster.setHealthChecker(healthCheckConfig);
cluster.update(newCluster);
assertEquals(8888, cluster.getDefCkport());
assertEquals(9999, cluster.getDefIPPort());
assertTrue(cluster.getHealthChecker() instanceof Http);
Http httpHealthCheck = (Http) (cluster.getHealthChecker());
assertEquals("/nacos-path-1", httpHealthCheck.getPath());
assertEquals(500, httpHealthCheck.getExpectedResponseCode());
assertEquals("Client-Version:nacos-test-1", httpHealthCheck.getHeaders());
}
@Test
public void updateIps() {
Instance instance1 = new Instance();
instance1.setIp("1.1.1.1");
instance1.setPort(1234);
Instance instance2 = new Instance();
instance2.setIp("1.1.1.1");
instance2.setPort(2345);
List<Instance> list = new ArrayList<>();
list.add(instance1);
list.add(instance2);
cluster.updateIps(list, false);
List<Instance> ips = cluster.allIPs();
assertNotNull(ips);
assertEquals(2, ips.size());
assertEquals("1.1.1.1", ips.get(0).getIp());
assertEquals(1234, ips.get(0).getPort());
assertEquals("1.1.1.1", ips.get(1).getIp());
assertEquals(2345, ips.get(1).getPort());
}
@Test
public void testValidate() {
Service service = new Service("nacos.service.2");
cluster = new Cluster("nacos-cluster-1", service);
cluster.validate();
}
@Test(expected = IllegalArgumentException.class)
public void testValidateClusterNameNull() {
Service service = new Service("nacos.service.2");
cluster = new Cluster(null, service);
cluster.validate();
}
@Test(expected = IllegalArgumentException.class)
public void testValidateServiceNull() {
cluster = new Cluster("nacos-cluster-1", null);
cluster.validate();
}
@Test
public void testSerialize() throws Exception {
String actual = JacksonUtils.toJson(cluster);
System.out.println(actual);
assertTrue(actual.contains("\"defaultPort\":80"));
assertTrue(actual.contains("\"defIPPort\":8080"));
assertTrue(actual.contains("\"healthChecker\":{\"type\":\"TCP\"}"));
assertTrue(actual.contains("\"metadata\":{}"));
assertTrue(actual.contains("\"defCkport\":80"));
assertTrue(actual.contains("\"name\":\"nacos-cluster-1\""));
assertTrue(actual.contains("\"defaultCheckPort\":80"));
assertTrue(actual.contains("\"serviceName\":\"nacos.service.1\""));
assertTrue(actual.contains("\"useIPPort4Check\":true"));
assertTrue(actual.contains("\"sitegroup\":\"\""));
assertTrue(actual.contains("\"empty\":true"));
assertFalse(actual.contains("\"service\""));
}
@Test
@SuppressWarnings("checkstyle:linelength")
public void testDeserialize() throws Exception {
String example = "{\"defCkport\":80,\"defIPPort\":8080,\"defaultCheckPort\":80,\"defaultPort\":80,\"empty\":true,\"healthChecker\":{\"type\":\"TCP\"},\"metadata\":{},\"name\":\"nacos-cluster-1\",\"serviceName\":\"nacos.service.1\",\"sitegroup\":\"\",\"useIPPort4Check\":true}";
Cluster actual = JacksonUtils.toObj(example, Cluster.class);
assertEquals(80, actual.getDefCkport());
assertEquals(8080, actual.getDefIPPort());
assertEquals(80, actual.getDefaultCheckPort());
assertEquals(80, actual.getDefaultPort());
assertTrue(actual.isEmpty());
assertTrue(actual.getMetadata().isEmpty());
assertTrue(actual.isUseIPPort4Check());
assertEquals("nacos-cluster-1", actual.getName());
assertEquals("nacos.service.1", actual.getServiceName());
assertEquals("", actual.getSitegroup());
assertNull(actual.getHealthCheckTask());
}
}