Merge remote-tracking branch 'upstream/2.2.0' into asoc2022_issue#8461
# Conflicts: # config/src/main/java/com/alibaba/nacos/config/server/controller/ConfigController.java
This commit is contained in:
commit
8410fbccf3
3
.github/workflows/ci.yml
vendored
3
.github/workflows/ci.yml
vendored
@ -9,6 +9,9 @@ on:
|
||||
pull_request:
|
||||
branches: [ develop, v1.x-develop ]
|
||||
|
||||
permissions:
|
||||
contents: read # to fetch code (actions/checkout)
|
||||
|
||||
jobs:
|
||||
unix:
|
||||
runs-on: ${{ matrix.os }}
|
||||
|
3
.github/workflows/it.yml
vendored
3
.github/workflows/it.yml
vendored
@ -9,6 +9,9 @@ on:
|
||||
pull_request:
|
||||
branches: [ develop, v1.x-develop ]
|
||||
|
||||
permissions:
|
||||
contents: read # to fetch code (actions/checkout)
|
||||
|
||||
jobs:
|
||||
unix:
|
||||
runs-on: ${{ matrix.os }}
|
||||
|
@ -172,7 +172,7 @@
|
||||
|
||||
## 0.2.1-release(Sept 28, 2018)
|
||||
|
||||
* FIx deregister last instance failed error.
|
||||
* Fix deregister last instance failed error.
|
||||
* Fix url pattern error.
|
||||
* Fully integrate with and seamlessly support Spring framework, Spring Boot and Spring Cloud
|
||||
* Separate nacos-api from nacos client implementation
|
||||
|
@ -83,6 +83,8 @@ For more details, see [quick-start.](https://nacos.io/en-us/docs/quick-start.htm
|
||||
|
||||
You can view the full documentation from the [Nacos website](https://nacos.io/en-us/docs/what-is-nacos.html).
|
||||
|
||||
You can also read this online eBook from the [NACOS ARCHITECTURE & PRINCIPLES](https://www.yuque.com/nacos/ebook/kbyo6n).
|
||||
|
||||
All the latest and long-term notice can also be found here from [Github notice issue](https://github.com/alibaba/nacos/labels/notice).
|
||||
|
||||
## Contributing
|
||||
|
@ -18,8 +18,8 @@ package com.alibaba.nacos.address.component;
|
||||
|
||||
import com.alibaba.nacos.address.constant.AddressServerConstants;
|
||||
import com.alibaba.nacos.api.common.Constants;
|
||||
import com.alibaba.nacos.api.naming.pojo.Instance;
|
||||
import com.alibaba.nacos.common.utils.InternetAddressUtil;
|
||||
import com.alibaba.nacos.naming.core.Instance;
|
||||
import com.alibaba.nacos.common.utils.StringUtils;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@ -76,9 +76,9 @@ public class AddressServerGeneratorManager {
|
||||
instance.setPort(Integer.parseInt(ipAndPort[1]));
|
||||
instance.setClusterName(clusterName);
|
||||
instance.setServiceName(serviceName);
|
||||
instance.setTenant(Constants.DEFAULT_NAMESPACE_ID);
|
||||
instance.setApp(rawProductName);
|
||||
instance.setEphemeral(false);
|
||||
instance.getMetadata().put("app", rawProductName);
|
||||
instance.getMetadata().put("tenant", Constants.DEFAULT_NAMESPACE_ID);
|
||||
instanceList.add(instance);
|
||||
}
|
||||
|
||||
@ -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 -> {
|
||||
|
@ -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.Instance;
|
||||
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.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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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()));
|
||||
}
|
||||
}
|
||||
|
@ -17,7 +17,7 @@
|
||||
package com.alibaba.nacos.address.component;
|
||||
|
||||
import com.alibaba.nacos.address.constant.AddressServerConstants;
|
||||
import com.alibaba.nacos.naming.core.Instance;
|
||||
import com.alibaba.nacos.api.naming.pojo.Instance;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
@ -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);
|
||||
|
@ -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());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -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());
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -75,6 +75,8 @@ public class PropertyKeyConst {
|
||||
|
||||
public static final String NAMING_PUSH_EMPTY_PROTECTION = "namingPushEmptyProtection";
|
||||
|
||||
public static final String NAMING_ASYNC_QUERY_SUBSCRIBE_SERVICE = "namingAsyncQuerySubscribeService";
|
||||
|
||||
public static final String PUSH_RECEIVER_UDP_PORT = "push.receiver.udp.port";
|
||||
|
||||
/**
|
||||
|
@ -27,8 +27,6 @@ public interface SystemPropertyKeyConst {
|
||||
|
||||
String NAMING_SERVER_PORT = "nacos.naming.exposed.port";
|
||||
|
||||
String NAMING_WEB_CONTEXT = "nacos.naming.web.context";
|
||||
|
||||
/**
|
||||
* In the cloud (Alibaba Cloud or other cloud vendors) environment, whether to enable namespace resolution in the
|
||||
* cloud environment.
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 1999-2018 Alibaba Group Holding Ltd.
|
||||
* Copyright 1999-2022 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.
|
||||
@ -14,29 +14,23 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.api.config.filter;
|
||||
package com.alibaba.nacos.api.annotation;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Filter Config Interface.
|
||||
*
|
||||
* @author Nacos
|
||||
* An annotation for Nacos API v2 Controller.
|
||||
* @author dongyafei
|
||||
* @date 2022/7/22
|
||||
*/
|
||||
@Deprecated
|
||||
public interface IFilterConfig {
|
||||
|
||||
/**
|
||||
* get filter name.
|
||||
*
|
||||
* @return filter name
|
||||
*/
|
||||
String getFilterName();
|
||||
|
||||
/**
|
||||
* Get init param.
|
||||
*
|
||||
* @param name parameter name
|
||||
* @return param
|
||||
*/
|
||||
Object getInitParameter(String name);
|
||||
|
||||
|
||||
@Target({ElementType.TYPE})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
public @interface NacosApi {
|
||||
|
||||
}
|
@ -62,13 +62,6 @@ public @interface NacosConfigurationProperties {
|
||||
*/
|
||||
String dataId();
|
||||
|
||||
/**
|
||||
* set config type is yaml this method is deprecated, we support you use {@link #type()} to set config type.
|
||||
*
|
||||
* @return default value <code>false</code>
|
||||
*/
|
||||
@Deprecated boolean yaml() default false;
|
||||
|
||||
/**
|
||||
* config style.
|
||||
*
|
||||
|
@ -22,13 +22,5 @@ package com.alibaba.nacos.api.config.filter;
|
||||
* @author luyanbo(RobberPhex)
|
||||
*/
|
||||
public abstract class AbstractConfigFilter implements IConfigFilter {
|
||||
|
||||
/**
|
||||
* init.
|
||||
*
|
||||
* @param filterConfig Filter Config
|
||||
*/
|
||||
@Override
|
||||
public void init(IFilterConfig filterConfig) {
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -30,14 +30,6 @@ import java.util.Properties;
|
||||
*/
|
||||
public interface IConfigFilter {
|
||||
|
||||
/**
|
||||
* Init.
|
||||
*
|
||||
* @param filterConfig Filter Config
|
||||
*/
|
||||
@Deprecated
|
||||
void init(IFilterConfig filterConfig);
|
||||
|
||||
/**
|
||||
* Init.
|
||||
*
|
||||
|
@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright 1999-2022 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.api.exception.api;
|
||||
|
||||
import com.alibaba.nacos.api.common.Constants;
|
||||
import com.alibaba.nacos.api.exception.NacosException;
|
||||
import com.alibaba.nacos.api.model.v2.ErrorCode;
|
||||
import com.alibaba.nacos.api.utils.StringUtils;
|
||||
|
||||
/** Exception for open API. <BR/>
|
||||
* errCode -> HTTP status code inherited from {@link NacosException} <BR/>
|
||||
* errMsg -> detail error message inherited from {@link NacosException} <BR/>
|
||||
* detailErrCode -> error code for api v2.0 <BR/>
|
||||
* errAbstract -> abstract error message for api v2.0
|
||||
* @author dongyafei
|
||||
* @date 2022/7/22
|
||||
*/
|
||||
public class NacosApiException extends NacosException {
|
||||
|
||||
/**
|
||||
* serialVersionUID.
|
||||
*/
|
||||
private static final long serialVersionUID = 2245627968556056573L;
|
||||
|
||||
/**
|
||||
* error code for api v2.0.
|
||||
*/
|
||||
private int detailErrCode;
|
||||
|
||||
/**
|
||||
* abstract error description for api v2.0.
|
||||
*/
|
||||
private String errAbstract;
|
||||
|
||||
public NacosApiException() {
|
||||
}
|
||||
|
||||
public NacosApiException(int statusCode, ErrorCode errorCode, Throwable throwable, String message) {
|
||||
super(statusCode, message, throwable);
|
||||
this.detailErrCode = errorCode.getCode();
|
||||
this.errAbstract = errorCode.getMsg();
|
||||
}
|
||||
|
||||
public NacosApiException(int statusCode, ErrorCode errorCode, String message) {
|
||||
super(statusCode, message);
|
||||
this.detailErrCode = errorCode.getCode();
|
||||
this.errAbstract = errorCode.getMsg();
|
||||
}
|
||||
|
||||
public int getDetailErrCode() {
|
||||
return detailErrCode;
|
||||
}
|
||||
|
||||
public String getErrAbstract() {
|
||||
if (!StringUtils.isBlank(this.errAbstract)) {
|
||||
return this.errAbstract;
|
||||
}
|
||||
return Constants.NULL;
|
||||
}
|
||||
|
||||
public void setErrAbstract(String errAbstract) {
|
||||
this.errAbstract = errAbstract;
|
||||
}
|
||||
}
|
204
api/src/main/java/com/alibaba/nacos/api/model/v2/ErrorCode.java
Normal file
204
api/src/main/java/com/alibaba/nacos/api/model/v2/ErrorCode.java
Normal file
@ -0,0 +1,204 @@
|
||||
/*
|
||||
* Copyright 1999-2022 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.api.model.v2;
|
||||
|
||||
/**
|
||||
* Response Error Code.
|
||||
*
|
||||
* @author dongyafei
|
||||
* @date 2022/7/22
|
||||
*/
|
||||
|
||||
public enum ErrorCode {
|
||||
|
||||
/**
|
||||
* success.
|
||||
*/
|
||||
SUCCESS(0, "success"),
|
||||
|
||||
/**
|
||||
* parameter missing.
|
||||
*/
|
||||
PARAMETER_MISSING(10000, "parameter missing"),
|
||||
|
||||
/**
|
||||
* access denied.
|
||||
*/
|
||||
ACCESS_DENIED(10001, "access denied"),
|
||||
|
||||
/**
|
||||
* data access error.
|
||||
*/
|
||||
DATA_ACCESS_ERROR(10002, "data access error"),
|
||||
|
||||
/**
|
||||
* 'tenant' parameter error.
|
||||
*/
|
||||
TENANT_PARAM_ERROR(20001, "'tenant' parameter error"),
|
||||
|
||||
/**
|
||||
* parameter validate error.
|
||||
*/
|
||||
PARAMETER_VALIDATE_ERROR(20002, "parameter validate error"),
|
||||
|
||||
/**
|
||||
* MediaType Error.
|
||||
*/
|
||||
MEDIA_TYPE_ERROR(20003, "MediaType Error"),
|
||||
|
||||
/**
|
||||
* resource not found.
|
||||
*/
|
||||
RESOURCE_NOT_FOUND(20004, "resource not found"),
|
||||
|
||||
/**
|
||||
* resource conflict.
|
||||
*/
|
||||
RESOURCE_CONFLICT(20005, "resource conflict"),
|
||||
|
||||
/**
|
||||
* config listener is null.
|
||||
*/
|
||||
CONFIG_LISTENER_IS_NULL(20006, "config listener is null"),
|
||||
|
||||
/**
|
||||
* config listener error.
|
||||
*/
|
||||
CONFIG_LISTENER_ERROR(20007, "config listener error"),
|
||||
|
||||
/**
|
||||
* invalid dataId.
|
||||
*/
|
||||
INVALID_DATA_ID(20008, "invalid dataId"),
|
||||
|
||||
/**
|
||||
* parameter mismatch.
|
||||
*/
|
||||
PARAMETER_MISMATCH(20009, "parameter mismatch"),
|
||||
|
||||
/**
|
||||
* service name error.
|
||||
*/
|
||||
SERVICE_NAME_ERROR(21000, "service name error"),
|
||||
|
||||
/**
|
||||
* weight error.
|
||||
*/
|
||||
WEIGHT_ERROR(21001, "weight error"),
|
||||
|
||||
/**
|
||||
* instance metadata error.
|
||||
*/
|
||||
INSTANCE_METADATA_ERROR(21002, "instance metadata error"),
|
||||
|
||||
/**
|
||||
* instance not found.
|
||||
*/
|
||||
INSTANCE_NOT_FOUND(21003, "instance not found"),
|
||||
|
||||
/**
|
||||
* instance error.
|
||||
*/
|
||||
INSTANCE_ERROR(21004, "instance error"),
|
||||
|
||||
/**
|
||||
* service metadata error.
|
||||
*/
|
||||
SERVICE_METADATA_ERROR(21005, "service metadata error"),
|
||||
|
||||
/**
|
||||
* selector error.
|
||||
*/
|
||||
SELECTOR_ERROR(21006, "selector error"),
|
||||
|
||||
/**
|
||||
* service already exist.
|
||||
*/
|
||||
SERVICE_ALREADY_EXIST(21007, "service already exist"),
|
||||
|
||||
/**
|
||||
* service not exist.
|
||||
*/
|
||||
SERVICE_NOT_EXIST(21008, "service not exist"),
|
||||
|
||||
/**
|
||||
* service delete failure.
|
||||
*/
|
||||
SERVICE_DELETE_FAILURE(21009, "service delete failure"),
|
||||
|
||||
/**
|
||||
* healthy param miss.
|
||||
*/
|
||||
HEALTHY_PARAM_MISS(21010, "healthy param miss"),
|
||||
|
||||
/**
|
||||
* health check still running.
|
||||
*/
|
||||
HEALTH_CHECK_STILL_RUNNING(21011, "health check still running"),
|
||||
|
||||
/**
|
||||
* illegal namespace.
|
||||
*/
|
||||
ILLEGAL_NAMESPACE(22000, "illegal namespace"),
|
||||
|
||||
/**
|
||||
* namespace not exist.
|
||||
*/
|
||||
NAMESPACE_NOT_EXIST(22001, "namespace not exist"),
|
||||
|
||||
/**
|
||||
* namespace already exist.
|
||||
*/
|
||||
NAMESPACE_ALREADY_EXIST(22002, "namespace already exist"),
|
||||
|
||||
/**
|
||||
* illegal state.
|
||||
*/
|
||||
ILLEGAL_STATE(23000, "illegal state"),
|
||||
|
||||
/**
|
||||
* node info error.
|
||||
*/
|
||||
NODE_INFO_ERROR(23001, "node info error"),
|
||||
|
||||
/**
|
||||
* node down failure.
|
||||
*/
|
||||
NODE_DOWN_FAILURE(23001, "node down failure"),
|
||||
|
||||
/**
|
||||
* server error.
|
||||
*/
|
||||
SERVER_ERROR(30000, "server error");
|
||||
|
||||
private final Integer code;
|
||||
|
||||
private final String msg;
|
||||
|
||||
public Integer getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public String getMsg() {
|
||||
return msg;
|
||||
}
|
||||
|
||||
ErrorCode(Integer code, String msg) {
|
||||
this.code = code;
|
||||
this.msg = msg;
|
||||
}
|
||||
}
|
115
api/src/main/java/com/alibaba/nacos/api/model/v2/Result.java
Normal file
115
api/src/main/java/com/alibaba/nacos/api/model/v2/Result.java
Normal file
@ -0,0 +1,115 @@
|
||||
/*
|
||||
* Copyright 1999-2022 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.api.model.v2;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* Response Result.
|
||||
*
|
||||
* @author dongyafei
|
||||
* @date 2022/7/12
|
||||
*/
|
||||
public class Result<T> implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 6258345442767540526L;
|
||||
|
||||
private final Integer code;
|
||||
|
||||
private final String message;
|
||||
|
||||
private final T data;
|
||||
|
||||
public Result(Integer code, String message, T data) {
|
||||
this.code = code;
|
||||
this.message = message;
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public Result() {
|
||||
this(null);
|
||||
}
|
||||
|
||||
public Result(T data) {
|
||||
this(ErrorCode.SUCCESS.getCode(), ErrorCode.SUCCESS.getMsg(), data);
|
||||
}
|
||||
|
||||
public Result(Integer code, String message) {
|
||||
this(code, message, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Success return with nothing.
|
||||
* @param <T> data type
|
||||
* @return Result
|
||||
*/
|
||||
public static <T> Result<T> success() {
|
||||
return new Result<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Success return with data.
|
||||
* @param <T> data type
|
||||
* @return Result
|
||||
*/
|
||||
public static <T> Result<T> success(T data) {
|
||||
return new Result<>(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Failed return with message and detail error information.
|
||||
* @return Result
|
||||
*/
|
||||
public static Result<String> failure(String message) {
|
||||
return Result.failure(ErrorCode.SERVER_ERROR, message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Failed return with errorCode and message.
|
||||
* @param <T> data type
|
||||
* @return Result
|
||||
*/
|
||||
public static <T> Result<T> failure(ErrorCode errorCode) {
|
||||
return new Result<>(errorCode.getCode(), errorCode.getMsg());
|
||||
}
|
||||
|
||||
/**
|
||||
* Failed return with errorCode, message and data.
|
||||
* @param <T> data type
|
||||
* @return Result
|
||||
*/
|
||||
public static <T> Result<T> failure(ErrorCode errorCode, T data) {
|
||||
return new Result<>(errorCode.getCode(), errorCode.getMsg(), data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Result{" + "errorCode=" + code + ", message='" + message + '\'' + ", data=" + data + '}';
|
||||
}
|
||||
|
||||
public Integer getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public T getData() {
|
||||
return data;
|
||||
}
|
||||
}
|
@ -107,6 +107,17 @@ public interface NamingService {
|
||||
*/
|
||||
void batchRegisterInstance(String serviceName, String groupName, List<Instance> instances) throws NacosException;
|
||||
|
||||
/**
|
||||
* batch deRegister instance to service with specified instance properties.
|
||||
*
|
||||
* @param serviceName name of service
|
||||
* @param groupName group of service
|
||||
* @param instances instances to deRegister
|
||||
* @throws NacosException nacos exception
|
||||
* @since 2.2.0
|
||||
*/
|
||||
void batchDeregisterInstance(String serviceName, String groupName, List<Instance> instances) throws NacosException;
|
||||
|
||||
/**
|
||||
* deregister instance from a service.
|
||||
*
|
||||
|
@ -16,25 +16,18 @@
|
||||
|
||||
package com.alibaba.nacos.api.naming.remote.response;
|
||||
|
||||
import com.alibaba.nacos.api.remote.response.Response;
|
||||
|
||||
/**
|
||||
* batch instance response.
|
||||
*
|
||||
* @author <a href="mailto:chenhao26@xiaomi.com">chenhao26</a>
|
||||
*/
|
||||
public class BatchInstanceResponse extends Response {
|
||||
|
||||
private String type;
|
||||
public class BatchInstanceResponse extends InstanceResponse {
|
||||
|
||||
public BatchInstanceResponse() {
|
||||
super();
|
||||
}
|
||||
|
||||
public BatchInstanceResponse(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
super(type);
|
||||
}
|
||||
}
|
||||
|
@ -38,4 +38,7 @@ public class InstanceResponse extends Response {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
|
@ -18,6 +18,8 @@ package com.alibaba.nacos.api.naming.utils;
|
||||
|
||||
import com.alibaba.nacos.api.common.Constants;
|
||||
import com.alibaba.nacos.api.exception.NacosException;
|
||||
import com.alibaba.nacos.api.exception.api.NacosApiException;
|
||||
import com.alibaba.nacos.api.model.v2.ErrorCode;
|
||||
import com.alibaba.nacos.api.naming.pojo.Instance;
|
||||
import com.alibaba.nacos.api.utils.StringUtils;
|
||||
|
||||
@ -138,11 +140,11 @@ public class NamingUtils {
|
||||
public static void checkInstanceIsLegal(Instance instance) throws NacosException {
|
||||
if (instance.getInstanceHeartBeatTimeOut() < instance.getInstanceHeartBeatInterval()
|
||||
|| instance.getIpDeleteTimeout() < instance.getInstanceHeartBeatInterval()) {
|
||||
throw new NacosException(NacosException.INVALID_PARAM,
|
||||
throw new NacosApiException(NacosException.INVALID_PARAM, ErrorCode.INSTANCE_ERROR,
|
||||
"Instance 'heart beat interval' must less than 'heart beat timeout' and 'ip delete timeout'.");
|
||||
}
|
||||
if (!StringUtils.isEmpty(instance.getClusterName()) && !CLUSTER_NAME_PATTERN.matcher(instance.getClusterName()).matches()) {
|
||||
throw new NacosException(NacosException.INVALID_PARAM,
|
||||
throw new NacosApiException(NacosException.INVALID_PARAM, ErrorCode.INSTANCE_ERROR,
|
||||
String.format("Instance 'clusterName' should be characters with only 0-9a-zA-Z-. (current: %s)",
|
||||
instance.getClusterName()));
|
||||
}
|
||||
@ -155,7 +157,7 @@ public class NamingUtils {
|
||||
*/
|
||||
public static void checkInstanceIsEphemeral(Instance instance) throws NacosException {
|
||||
if (!instance.isEphemeral()) {
|
||||
throw new NacosException(NacosException.INVALID_PARAM,
|
||||
throw new NacosApiException(NacosException.INVALID_PARAM, ErrorCode.INSTANCE_ERROR,
|
||||
String.format("Batch registration does not allow persistent instance registration , Instance:%s", instance));
|
||||
}
|
||||
}
|
||||
|
@ -30,14 +30,11 @@ import java.util.Enumeration;
|
||||
* @author xuanyin.zy
|
||||
*/
|
||||
public class NetUtils {
|
||||
|
||||
@Deprecated
|
||||
private static final String CLIENT_NAMING_LOCAL_IP_PROPERTY = "com.alibaba.nacos.client.naming.local.ip";
|
||||
|
||||
|
||||
private static final String CLIENT_LOCAL_IP_PROPERTY = "com.alibaba.nacos.client.local.ip";
|
||||
|
||||
|
||||
private static final String CLIENT_LOCAL_PREFER_HOSTNAME_PROPERTY = "com.alibaba.nacos.client.local.preferHostname";
|
||||
|
||||
|
||||
private static final String LEGAL_LOCAL_IP_PROPERTY = "java.net.preferIPv6Addresses";
|
||||
|
||||
private static final String DEFAULT_SOLVE_FAILED_RETURN = "resolve_failed";
|
||||
@ -53,23 +50,19 @@ public class NetUtils {
|
||||
if (!StringUtils.isEmpty(localIp)) {
|
||||
return localIp;
|
||||
}
|
||||
|
||||
if (System.getProperties().containsKey(CLIENT_LOCAL_IP_PROPERTY)) {
|
||||
return localIp = System.getProperty(CLIENT_LOCAL_IP_PROPERTY, getAddress());
|
||||
}
|
||||
|
||||
String ip = System.getProperty(CLIENT_NAMING_LOCAL_IP_PROPERTY, getAddress());
|
||||
|
||||
return localIp = ip;
|
||||
|
||||
localIp = getAddress();
|
||||
return localIp;
|
||||
}
|
||||
|
||||
|
||||
private static String getAddress() {
|
||||
InetAddress inetAddress = findFirstNonLoopbackAddress();
|
||||
if (inetAddress == null) {
|
||||
return DEFAULT_SOLVE_FAILED_RETURN;
|
||||
}
|
||||
|
||||
|
||||
boolean preferHost = Boolean.parseBoolean(System.getProperty(CLIENT_LOCAL_PREFER_HOSTNAME_PROPERTY));
|
||||
return preferHost ? inetAddress.getHostName() : inetAddress.getHostAddress();
|
||||
}
|
||||
@ -91,9 +84,8 @@ public class NetUtils {
|
||||
|
||||
for (Enumeration<InetAddress> addrs = ifc.getInetAddresses(); addrs.hasMoreElements(); ) {
|
||||
InetAddress address = addrs.nextElement();
|
||||
boolean isLegalIpVersion =
|
||||
Boolean.parseBoolean(System.getProperty(LEGAL_LOCAL_IP_PROPERTY))
|
||||
? address instanceof Inet6Address : address instanceof Inet4Address;
|
||||
boolean isLegalIpVersion = Boolean.parseBoolean(System.getProperty(LEGAL_LOCAL_IP_PROPERTY))
|
||||
? address instanceof Inet6Address : address instanceof Inet4Address;
|
||||
if (isLegalIpVersion && !address.isLoopbackAddress()) {
|
||||
result = address;
|
||||
}
|
||||
|
@ -54,7 +54,7 @@ public class NamingUtilsTest {
|
||||
NamingUtils.checkInstanceIsLegal(instance);
|
||||
assertTrue(false);
|
||||
} catch (Exception e) {
|
||||
assertTrue(NacosException.class.equals(e.getClass()));
|
||||
assertTrue(e instanceof NacosException);
|
||||
assertEquals(
|
||||
"Instance 'clusterName' should be characters with only 0-9a-zA-Z-. (current: cluster1,cluster2)",
|
||||
e.getMessage());
|
||||
@ -75,7 +75,7 @@ public class NamingUtilsTest {
|
||||
NamingUtils.checkInstanceIsLegal(instance);
|
||||
assertTrue(false);
|
||||
} catch (Exception e) {
|
||||
assertTrue(NacosException.class.equals(e.getClass()));
|
||||
assertTrue(e instanceof NacosException);
|
||||
assertEquals(
|
||||
"Instance 'heart beat interval' must less than 'heart beat timeout' and 'ip delete timeout'.",
|
||||
e.getMessage());
|
||||
@ -98,7 +98,7 @@ public class NamingUtilsTest {
|
||||
NamingUtils.batchCheckInstanceIsLegal(instanceList);
|
||||
assertTrue(false);
|
||||
} catch (Exception e) {
|
||||
assertTrue(NacosException.class.equals(e.getClass()));
|
||||
assertTrue(e instanceof NacosException);
|
||||
assertEquals(
|
||||
"Instance 'clusterName' should be characters with only 0-9a-zA-Z-. (current: cluster1,cluster2)",
|
||||
e.getMessage());
|
||||
@ -124,7 +124,7 @@ public class NamingUtilsTest {
|
||||
NamingUtils.batchCheckInstanceIsLegal(instanceList);
|
||||
assertTrue(false);
|
||||
} catch (Exception e) {
|
||||
assertTrue(NacosException.class.equals(e.getClass()));
|
||||
assertTrue(e instanceof NacosException);
|
||||
assertEquals(
|
||||
"Instance 'heart beat interval' must less than 'heart beat timeout' and 'ip delete timeout'.",
|
||||
e.getMessage());
|
||||
@ -166,4 +166,4 @@ public class NamingUtilsTest {
|
||||
String str2 = "123456";
|
||||
assertTrue(NamingUtils.isNumber(str2));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -34,7 +34,6 @@ public class NetUtilsTest {
|
||||
field.setAccessible(true);
|
||||
field.set(null, "");
|
||||
System.clearProperty("com.alibaba.nacos.client.local.ip");
|
||||
System.clearProperty("com.alibaba.nacos.client.naming.local.ip");
|
||||
System.clearProperty("com.alibaba.nacos.client.local.preferHostname");
|
||||
}
|
||||
|
||||
@ -45,12 +44,6 @@ public class NetUtilsTest {
|
||||
assertEquals("10.2.8.8", NetUtils.localIP());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCompatibleLocalIP() {
|
||||
System.setProperty("com.alibaba.nacos.client.naming.local.ip", "10.2.7.8");
|
||||
assertEquals("10.2.7.8", NetUtils.localIP());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPreferHostname() throws Exception {
|
||||
Class<?> clazz = Class.forName("com.alibaba.nacos.api.utils.NetUtils");
|
||||
@ -63,4 +56,4 @@ public class NetUtilsTest {
|
||||
assertEquals(hostname, NetUtils.localIP());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
166
client/pom.xml
166
client/pom.xml
@ -145,7 +145,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>3.2.1</version>
|
||||
<version>3.2.4</version>
|
||||
<configuration>
|
||||
<createDependencyReducedPom>false</createDependencyReducedPom>
|
||||
</configuration>
|
||||
@ -159,25 +159,56 @@
|
||||
<keepDependenciesWithProvidedScope>false</keepDependenciesWithProvidedScope>
|
||||
<promoteTransitiveDependencies>true</promoteTransitiveDependencies>
|
||||
<createDependencyReducedPom>false</createDependencyReducedPom>
|
||||
<minimizeJar>false</minimizeJar>
|
||||
<minimizeJar>true</minimizeJar>
|
||||
<filters>
|
||||
<filter>
|
||||
<artifact>*:*</artifact>
|
||||
<excludes>
|
||||
<exclude>META-INF/*.SF</exclude>
|
||||
<exclude>META-INF/*.DSA</exclude>
|
||||
<exclude>META-INF/*.RSA</exclude>
|
||||
</excludes>
|
||||
</filter>
|
||||
<filter>
|
||||
<artifact>io.grpc:grpc-netty-shaded</artifact>
|
||||
<excludes>
|
||||
<exclude>
|
||||
META-INF/native/*.*
|
||||
</exclude>
|
||||
</excludes>
|
||||
</filter>
|
||||
<filter>
|
||||
<artifact>com.alibaba.nacos:nacos-api</artifact>
|
||||
<includes>
|
||||
<include>
|
||||
com/alibaba/nacos/api/**/**
|
||||
</include>
|
||||
</includes>
|
||||
</filter>
|
||||
|
||||
</filters>
|
||||
<createSourcesJar>true</createSourcesJar>
|
||||
<shadeSourcesContent>true</shadeSourcesContent>
|
||||
|
||||
<artifactSet>
|
||||
<includes>
|
||||
<include>io.grpc:*</include>
|
||||
<include>io.opencensus:*</include>
|
||||
<include>io.perfmark:*</include>
|
||||
<include>com.google.guava:guava</include>
|
||||
<include>com.google.guava:failureaccess</include>
|
||||
<include>com.google.errorprone:error_prone_annotations</include>
|
||||
<include>com.google.j2objc:j2objc-annotations</include>
|
||||
<include>com.google.code.gson:gson</include>
|
||||
<include>com.google.protobuf:protobuf-java</include>
|
||||
<include>com.alibaba.nacos:nacos-api</include>
|
||||
<include>com.alibaba.nacos:nacos-common</include>
|
||||
<include>org.checkerframework:checker-qual</include>
|
||||
<include>org.conscrypt:conscrypt-openjdk</include>
|
||||
<include>org.mortbay.jetty.alpn:alpn-boot</include>
|
||||
<include>org.eclipse.jetty.npn:npn-api</include>
|
||||
<include>org.reflections:reflections</include>
|
||||
<include>com.google.guava:guava</include>
|
||||
<include>io.grpc:*</include>
|
||||
<include>io.opencensus:*</include>
|
||||
<include>org.javassist:*</include>
|
||||
<include>io.perfmark:perfmark-api</include>
|
||||
<include>com.google.*:*</include>
|
||||
<include>javax.annotation:javax.annotation-api</include>
|
||||
<include>org.checkerframework:*</include>
|
||||
<include>org.codehaus.mojo:*</include>
|
||||
</includes>
|
||||
|
||||
</artifactSet>
|
||||
|
||||
<relocations>
|
||||
@ -202,6 +233,12 @@
|
||||
<pattern>com.google</pattern>
|
||||
<shadedPattern>com.alibaba.nacos.shaded.com.google</shadedPattern>
|
||||
</relocation>
|
||||
|
||||
<relocation>
|
||||
<pattern>javax.annotation</pattern>
|
||||
<shadedPattern>com.alibaba.nacos.shaded.javax.annotation</shadedPattern>
|
||||
</relocation>
|
||||
|
||||
<relocation>
|
||||
<pattern>io.perfmark</pattern>
|
||||
<shadedPattern>com.alibaba.nacos.shaded.io.perfmark</shadedPattern>
|
||||
@ -227,7 +264,6 @@
|
||||
<shadedPattern>com.alibaba.nacos.shaded.org.example</shadedPattern>
|
||||
</relocation>
|
||||
|
||||
|
||||
</relocations>
|
||||
<transformers>
|
||||
<transformer
|
||||
@ -240,6 +276,21 @@
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>pure-jar</id>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>jar</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<classifier>pure</classifier>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
@ -250,7 +301,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>3.2.1</version>
|
||||
<version>3.2.4</version>
|
||||
<configuration>
|
||||
<createDependencyReducedPom>false</createDependencyReducedPom>
|
||||
</configuration>
|
||||
@ -264,29 +315,60 @@
|
||||
<keepDependenciesWithProvidedScope>false</keepDependenciesWithProvidedScope>
|
||||
<promoteTransitiveDependencies>true</promoteTransitiveDependencies>
|
||||
<createDependencyReducedPom>false</createDependencyReducedPom>
|
||||
<minimizeJar>false</minimizeJar>
|
||||
<minimizeJar>true</minimizeJar>
|
||||
<filters>
|
||||
<filter>
|
||||
<artifact>*:*</artifact>
|
||||
<excludes>
|
||||
<exclude>META-INF/*.SF</exclude>
|
||||
<exclude>META-INF/*.DSA</exclude>
|
||||
<exclude>META-INF/*.RSA</exclude>
|
||||
</excludes>
|
||||
</filter>
|
||||
<filter>
|
||||
<artifact>io.grpc:grpc-netty-shaded</artifact>
|
||||
<excludes>
|
||||
<exclude>
|
||||
META-INF/native/*.*
|
||||
</exclude>
|
||||
</excludes>
|
||||
</filter>
|
||||
<filter>
|
||||
<artifact>com.alibaba.nacos:nacos-api</artifact>
|
||||
<includes>
|
||||
<include>
|
||||
com/alibaba/nacos/api/**/**
|
||||
</include>
|
||||
</includes>
|
||||
</filter>
|
||||
|
||||
</filters>
|
||||
<createSourcesJar>true</createSourcesJar>
|
||||
<shadeSourcesContent>true</shadeSourcesContent>
|
||||
|
||||
|
||||
<artifactSet>
|
||||
<includes>
|
||||
<include>io.grpc:*</include>
|
||||
<include>io.opencensus:*</include>
|
||||
<include>io.perfmark:*</include>
|
||||
<include>com.google.guava:guava</include>
|
||||
<include>com.google.guava:failureaccess</include>
|
||||
<include>com.google.errorprone:error_prone_annotations</include>
|
||||
<include>com.google.j2objc:j2objc-annotations</include>
|
||||
<include>com.google.code.gson:gson</include>
|
||||
<include>com.google.protobuf:protobuf-java</include>
|
||||
<include>com.alibaba.nacos:nacos-api</include>
|
||||
<include>com.alibaba.nacos:nacos-common</include>
|
||||
<include>org.checkerframework:checker-qual</include>
|
||||
<include>org.conscrypt:conscrypt-openjdk</include>
|
||||
<include>org.mortbay.jetty.alpn:alpn-boot</include>
|
||||
<include>org.eclipse.jetty.npn:npn-api</include>
|
||||
<include>org.reflections:reflections</include>
|
||||
<include>com.google.guava:guava</include>
|
||||
<include>io.grpc:*</include>
|
||||
<include>io.opencensus:*</include>
|
||||
<include>org.javassist:*</include>
|
||||
<include>io.perfmark:perfmark-api</include>
|
||||
<include>com.google.*:*</include>
|
||||
<include>javax.annotation:javax.annotation-api</include>
|
||||
<include>org.checkerframework:*</include>
|
||||
<include>org.codehaus.mojo:*</include>
|
||||
</includes>
|
||||
|
||||
</artifactSet>
|
||||
|
||||
|
||||
<relocations>
|
||||
|
||||
|
||||
<relocation>
|
||||
<pattern>io.grpc</pattern>
|
||||
<shadedPattern>com.alibaba.nacos.shaded.io.grpc</shadedPattern>
|
||||
@ -302,11 +384,17 @@
|
||||
<include>io.grpc.netty.shaded.io.grpc.netty.*</include>
|
||||
</includes>
|
||||
</relocation>
|
||||
|
||||
|
||||
<relocation>
|
||||
<pattern>com.google</pattern>
|
||||
<shadedPattern>com.alibaba.nacos.shaded.com.google</shadedPattern>
|
||||
</relocation>
|
||||
|
||||
<relocation>
|
||||
<pattern>javax.annotation</pattern>
|
||||
<shadedPattern>com.alibaba.nacos.shaded.javax.annotation</shadedPattern>
|
||||
</relocation>
|
||||
|
||||
<relocation>
|
||||
<pattern>io.perfmark</pattern>
|
||||
<shadedPattern>com.alibaba.nacos.shaded.io.perfmark</shadedPattern>
|
||||
@ -331,20 +419,34 @@
|
||||
<pattern>org.example</pattern>
|
||||
<shadedPattern>com.alibaba.nacos.shaded.org.example</shadedPattern>
|
||||
</relocation>
|
||||
|
||||
|
||||
|
||||
</relocations>
|
||||
<transformers>
|
||||
<transformer
|
||||
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"/>
|
||||
<transformer
|
||||
implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
|
||||
|
||||
|
||||
</transformers>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>pure-jar</id>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>jar</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<classifier>pure</classifier>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
|
@ -126,25 +126,4 @@ public final class CredentialService implements SpasCredentialLoader {
|
||||
public void registerCredentialListener(CredentialListener listener) {
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public void setAccessKey(String accessKey) {
|
||||
credentials.setAccessKey(accessKey);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public void setSecretKey(String secretKey) {
|
||||
credentials.setSecretKey(secretKey);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public String getAccessKey() {
|
||||
return credentials.getAccessKey();
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public String getSecretKey() {
|
||||
return credentials.getSecretKey();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -275,6 +275,7 @@ public class ServerHttpAgent implements HttpAgent {
|
||||
String className = this.getClass().getName();
|
||||
LOGGER.info("{} do shutdown begin", className);
|
||||
ConfigHttpClientManager.getInstance().shutdown();
|
||||
serverListMgr.shutdown();
|
||||
LOGGER.info("{} do shutdown stop", className);
|
||||
}
|
||||
}
|
||||
|
@ -111,6 +111,11 @@ public class CacheData {
|
||||
*/
|
||||
private volatile boolean isSyncWithServer = false;
|
||||
|
||||
/**
|
||||
* if is cache data is discard,need to remove.
|
||||
*/
|
||||
private volatile boolean isDiscard = false;
|
||||
|
||||
private String type;
|
||||
|
||||
public boolean isInitializing() {
|
||||
@ -402,6 +407,14 @@ public class CacheData {
|
||||
isSyncWithServer = syncWithServer;
|
||||
}
|
||||
|
||||
public boolean isDiscard() {
|
||||
return isDiscard;
|
||||
}
|
||||
|
||||
public void setDiscard(boolean discard) {
|
||||
isDiscard = discard;
|
||||
}
|
||||
|
||||
public CacheData(ConfigFilterChainManager configFilterChainManager, String name, String dataId, String group) {
|
||||
this(configFilterChainManager, name, dataId, group, TenantUtil.getUserTenantForAcm());
|
||||
}
|
||||
|
@ -126,11 +126,11 @@ public class ClientWorker implements Closeable {
|
||||
private int taskPenaltyTime;
|
||||
|
||||
private boolean enableRemoteSyncConfig = false;
|
||||
|
||||
|
||||
private static final int MIN_THREAD_NUM = 2;
|
||||
|
||||
|
||||
private static final int THREAD_MULTIPLE = 1;
|
||||
|
||||
|
||||
/**
|
||||
* Add listeners for data.
|
||||
*
|
||||
@ -146,6 +146,7 @@ public class ClientWorker implements Closeable {
|
||||
for (Listener listener : listeners) {
|
||||
cache.addListener(listener);
|
||||
}
|
||||
cache.setDiscard(false);
|
||||
cache.setSyncWithServer(false);
|
||||
agent.notifyListenConfig();
|
||||
|
||||
@ -169,6 +170,7 @@ public class ClientWorker implements Closeable {
|
||||
for (Listener listener : listeners) {
|
||||
cache.addListener(listener);
|
||||
}
|
||||
cache.setDiscard(false);
|
||||
cache.setSyncWithServer(false);
|
||||
agent.notifyListenConfig();
|
||||
}
|
||||
@ -196,6 +198,7 @@ public class ClientWorker implements Closeable {
|
||||
for (Listener listener : listeners) {
|
||||
cache.addListener(listener);
|
||||
}
|
||||
cache.setDiscard(false);
|
||||
cache.setSyncWithServer(false);
|
||||
agent.notifyListenConfig();
|
||||
}
|
||||
@ -217,6 +220,7 @@ public class ClientWorker implements Closeable {
|
||||
cache.removeListener(listener);
|
||||
if (cache.getListeners().isEmpty()) {
|
||||
cache.setSyncWithServer(false);
|
||||
cache.setDiscard(true);
|
||||
agent.removeCache(dataId, group);
|
||||
}
|
||||
}
|
||||
@ -240,6 +244,7 @@ public class ClientWorker implements Closeable {
|
||||
cache.removeListener(listener);
|
||||
if (cache.getListeners().isEmpty()) {
|
||||
cache.setSyncWithServer(false);
|
||||
cache.setDiscard(true);
|
||||
agent.removeCache(dataId, group);
|
||||
}
|
||||
}
|
||||
@ -425,8 +430,8 @@ public class ClientWorker implements Closeable {
|
||||
}
|
||||
|
||||
private void refreshContentAndCheck(String groupKey, boolean notify) {
|
||||
if (cacheMap.get() != null && cacheMap.get().containsKey(groupKey)) {
|
||||
CacheData cache = cacheMap.get().get(groupKey);
|
||||
CacheData cache = cacheMap.get().get(groupKey);
|
||||
if (cache != null) {
|
||||
refreshContentAndCheck(cache, notify);
|
||||
}
|
||||
}
|
||||
@ -696,7 +701,7 @@ public class ClientWorker implements Closeable {
|
||||
continue;
|
||||
}
|
||||
executeConfigListen();
|
||||
} catch (Exception e) {
|
||||
} catch (Throwable e) {
|
||||
LOGGER.error("[ rpc listen execute ] [rpc listen] exception", e);
|
||||
}
|
||||
}
|
||||
@ -733,7 +738,7 @@ public class ClientWorker implements Closeable {
|
||||
}
|
||||
}
|
||||
|
||||
if (!CollectionUtils.isEmpty(cache.getListeners())) {
|
||||
if (!cache.isDiscard()) {
|
||||
//get listen config
|
||||
if (!cache.isUseLocalConfigInfo()) {
|
||||
List<CacheData> cacheDatas = listenCachesMap.get(String.valueOf(cache.getTaskId()));
|
||||
@ -744,7 +749,7 @@ public class ClientWorker implements Closeable {
|
||||
cacheDatas.add(cache);
|
||||
|
||||
}
|
||||
} else if (CollectionUtils.isEmpty(cache.getListeners())) {
|
||||
} else if (cache.isDiscard()) {
|
||||
|
||||
if (!cache.isUseLocalConfigInfo()) {
|
||||
List<CacheData> cacheDatas = removeListenCachesMap.get(String.valueOf(cache.getTaskId()));
|
||||
@ -779,7 +784,7 @@ public class ClientWorker implements Closeable {
|
||||
RpcClient rpcClient = ensureRpcClient(taskId);
|
||||
ConfigChangeBatchListenResponse configChangeBatchListenResponse = (ConfigChangeBatchListenResponse) requestProxy(
|
||||
rpcClient, configChangeListenRequest);
|
||||
if (configChangeBatchListenResponse != null && configChangeBatchListenResponse.isSuccess()) {
|
||||
if (configChangeBatchListenResponse.isSuccess()) {
|
||||
|
||||
Set<String> changeKeys = new HashSet<>();
|
||||
//handle changed keys,notify listener
|
||||
@ -807,8 +812,8 @@ public class ClientWorker implements Closeable {
|
||||
if (!cacheData.getListeners().isEmpty()) {
|
||||
|
||||
Long previousTimesStamp = timestampMap.get(groupKey);
|
||||
if (previousTimesStamp != null && !cacheData.getLastModifiedTs().compareAndSet(previousTimesStamp,
|
||||
System.currentTimeMillis())) {
|
||||
if (previousTimesStamp != null && !cacheData.getLastModifiedTs()
|
||||
.compareAndSet(previousTimesStamp, System.currentTimeMillis())) {
|
||||
continue;
|
||||
}
|
||||
cacheData.setSyncWithServer(true);
|
||||
@ -844,7 +849,7 @@ public class ClientWorker implements Closeable {
|
||||
if (removeSuccess) {
|
||||
for (CacheData cacheData : removeListenCaches) {
|
||||
synchronized (cacheData) {
|
||||
if (cacheData.getListeners().isEmpty()) {
|
||||
if (cacheData.isDiscard()) {
|
||||
ClientWorker.this
|
||||
.removeCache(cacheData.dataId, cacheData.group, cacheData.tenant);
|
||||
}
|
||||
@ -979,8 +984,8 @@ public class ClientWorker implements Closeable {
|
||||
LOGGER.error("[{}] [sub-server-error] dataId={}, group={}, tenant={}, code={}", this.getName(), dataId,
|
||||
group, tenant, response);
|
||||
throw new NacosException(response.getErrorCode(),
|
||||
"http error, code=" + response.getErrorCode() + ",msg=" + response.getMessage() + ",dataId=" + dataId + ",group=" + group
|
||||
+ ",tenant=" + tenant);
|
||||
"http error, code=" + response.getErrorCode() + ",msg=" + response.getMessage() + ",dataId="
|
||||
+ dataId + ",group=" + group + ",tenant=" + tenant);
|
||||
|
||||
}
|
||||
}
|
||||
@ -1012,20 +1017,20 @@ public class ClientWorker implements Closeable {
|
||||
if (request instanceof ConfigQueryRequest) {
|
||||
String tenant = ((ConfigQueryRequest) request).getTenant();
|
||||
String group = ((ConfigQueryRequest) request).getGroup();
|
||||
String dataId = ((ConfigQueryRequest) request).getGroup();
|
||||
String dataId = ((ConfigQueryRequest) request).getDataId();
|
||||
return buildResource(tenant, group, dataId);
|
||||
}
|
||||
if (request instanceof ConfigPublishRequest) {
|
||||
String tenant = ((ConfigPublishRequest) request).getTenant();
|
||||
String group = ((ConfigPublishRequest) request).getGroup();
|
||||
String dataId = ((ConfigPublishRequest) request).getGroup();
|
||||
String dataId = ((ConfigPublishRequest) request).getDataId();
|
||||
return buildResource(tenant, group, dataId);
|
||||
}
|
||||
|
||||
if (request instanceof ConfigRemoveRequest) {
|
||||
String tenant = ((ConfigRemoveRequest) request).getTenant();
|
||||
String group = ((ConfigRemoveRequest) request).getGroup();
|
||||
String dataId = ((ConfigRemoveRequest) request).getGroup();
|
||||
String dataId = ((ConfigRemoveRequest) request).getDataId();
|
||||
return buildResource(tenant, group, dataId);
|
||||
}
|
||||
return RequestResource.configBuilder().build();
|
||||
@ -1059,7 +1064,7 @@ public class ClientWorker implements Closeable {
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LOGGER.warn("[{}] [publish-single] error, dataId={}, group={}, tenant={}, code={}, msg={}",
|
||||
this.getName(), dataId, group, tenant, "unkonw", e.getMessage());
|
||||
this.getName(), dataId, group, tenant, "unknown", e.getMessage());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -35,7 +35,7 @@ public class Constants {
|
||||
|
||||
public static final String JM_SNAPSHOT_PATH = "JM.SNAPSHOT.PATH";
|
||||
|
||||
public static final String NACOS_ENVS_SEARCH = "nacos.envs.search";
|
||||
public static final String NACOS_ENV_FIRST = "nacos.env.first";
|
||||
|
||||
}
|
||||
|
||||
|
@ -16,6 +16,8 @@
|
||||
|
||||
package com.alibaba.nacos.client.env;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
abstract class AbstractPropertySource {
|
||||
|
||||
/**
|
||||
@ -31,4 +33,17 @@ abstract class AbstractPropertySource {
|
||||
*/
|
||||
abstract String getProperty(String key);
|
||||
|
||||
/**
|
||||
* Tests if the specified object is a key in this propertySource.
|
||||
* @param key key – possible key
|
||||
* @return true if and only if the specified object is a key in this propertySource, false otherwise.
|
||||
*/
|
||||
abstract boolean containsKey(String key);
|
||||
|
||||
/**
|
||||
* to properties.
|
||||
* @return properties
|
||||
*/
|
||||
abstract Properties asProperties();
|
||||
|
||||
}
|
||||
|
@ -21,7 +21,6 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
import java.util.Properties;
|
||||
|
||||
class DefaultSettingPropertySource extends AbstractPropertySource {
|
||||
@ -33,12 +32,10 @@ class DefaultSettingPropertySource extends AbstractPropertySource {
|
||||
private final Properties defaultSetting = new Properties();
|
||||
|
||||
DefaultSettingPropertySource() {
|
||||
try {
|
||||
final URL resourceUrl = ResourceUtils.getResourceUrl(DEFAULT_SETTING_PATH);
|
||||
final InputStream inputStream = resourceUrl.openStream();
|
||||
try (final InputStream inputStream = ResourceUtils.getResourceUrl(DEFAULT_SETTING_PATH).openStream()) {
|
||||
defaultSetting.load(inputStream);
|
||||
} catch (Exception e) {
|
||||
LOGGER.warn("load default setting failed");
|
||||
LOGGER.error("load default setting failed", e);
|
||||
}
|
||||
}
|
||||
|
||||
@ -51,4 +48,16 @@ class DefaultSettingPropertySource extends AbstractPropertySource {
|
||||
String getProperty(String key) {
|
||||
return defaultSetting.getProperty(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean containsKey(String key) {
|
||||
return defaultSetting.containsKey(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
Properties asProperties() {
|
||||
Properties properties = new Properties();
|
||||
properties.putAll(defaultSetting);
|
||||
return properties;
|
||||
}
|
||||
}
|
||||
|
@ -35,4 +35,16 @@ class JvmArgsPropertySource extends AbstractPropertySource {
|
||||
String getProperty(String key) {
|
||||
return properties.getProperty(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean containsKey(String key) {
|
||||
return properties.containsKey(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
Properties asProperties() {
|
||||
Properties properties = new Properties();
|
||||
properties.putAll(this.properties);
|
||||
return properties;
|
||||
}
|
||||
}
|
||||
|
@ -16,12 +16,27 @@
|
||||
|
||||
package com.alibaba.nacos.client.env;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* nacos env interface.
|
||||
*
|
||||
* NacosClientProperties interface.
|
||||
* include all the properties from jvm args, system environment, default setting.
|
||||
* more details you can see https://github.com/alibaba/nacos/issues/8622
|
||||
* @author onewe
|
||||
*/
|
||||
public interface NacosEnvironment {
|
||||
public interface NacosClientProperties {
|
||||
|
||||
/**
|
||||
* all the NacosClientProperties object must be created by PROTOTYPE,
|
||||
* so child NacosClientProperties can read properties from the PROTOTYPE.
|
||||
* it looks like this:
|
||||
* |-PROTOTYPE----------------> ip=127.0.0.1
|
||||
* |---|-child1---------------> port=6379
|
||||
* if you search key called "port" from child1, certainly you will get 6379
|
||||
* if you search key called "ip" from child1, you will get 127.0.0.1.
|
||||
* because the child can read properties from parent NacosClientProperties
|
||||
*/
|
||||
NacosClientProperties PROTOTYPE = SearchableProperties.INSTANCE;
|
||||
|
||||
/**
|
||||
* get property, if the value can not be got by the special key, the null will be returned.
|
||||
@ -87,4 +102,42 @@ public interface NacosEnvironment {
|
||||
*/
|
||||
Long getLong(String key, Long defaultValue);
|
||||
|
||||
/**
|
||||
* set property.
|
||||
* @param key key
|
||||
* @param value value
|
||||
*/
|
||||
void setProperty(String key, String value);
|
||||
|
||||
/**
|
||||
* add properties.
|
||||
* @param properties properties
|
||||
*/
|
||||
void addProperties(Properties properties);
|
||||
|
||||
/**
|
||||
* Tests if the specified object is a key in this NacosClientProperties.
|
||||
* @param key key – possible key
|
||||
* @return true if and only if the specified object is a key in this NacosClientProperties, false otherwise.
|
||||
*/
|
||||
boolean containsKey(String key);
|
||||
|
||||
/**
|
||||
* get properties from NacosClientProperties.
|
||||
* @return properties
|
||||
*/
|
||||
Properties asProperties();
|
||||
|
||||
/**
|
||||
* create a new NacosClientProperties which scope is itself.
|
||||
* @return NacosClientProperties
|
||||
*/
|
||||
NacosClientProperties derive();
|
||||
|
||||
/**
|
||||
* create a new NacosClientProperties from NacosClientProperties#PROTOTYPE and init.
|
||||
* @param properties properties
|
||||
* @return NacosClientProperties
|
||||
*/
|
||||
NacosClientProperties derive(Properties properties);
|
||||
}
|
@ -1,68 +0,0 @@
|
||||
/*
|
||||
* Copyright 1999-2022 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.client.env;
|
||||
|
||||
import java.lang.reflect.InvocationHandler;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.util.Properties;
|
||||
|
||||
class NacosEnvironmentFactory {
|
||||
|
||||
/**
|
||||
* create nacos environment.
|
||||
* @return NacosEnvironment's proxy object, it contains a SearchableEnvironment object.
|
||||
* @see SearchableEnvironment
|
||||
*/
|
||||
static NacosEnvironment createEnvironment() {
|
||||
|
||||
return (NacosEnvironment) Proxy.newProxyInstance(NacosEnvironmentFactory.class.getClassLoader(), new Class[] {NacosEnvironment.class},
|
||||
new NacosEnvironmentDelegate() {
|
||||
volatile NacosEnvironment environment;
|
||||
|
||||
@Override
|
||||
public void init(Properties properties) {
|
||||
if (environment == null) {
|
||||
synchronized (NacosEnvironmentFactory.class) {
|
||||
if (environment == null) {
|
||||
environment = new SearchableEnvironment(properties);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
|
||||
if (environment == null) {
|
||||
throw new IllegalStateException(
|
||||
"Nacos environment doesn't init, please call NacosEnvs#init method then try it again.");
|
||||
}
|
||||
return method.invoke(environment, args);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
interface NacosEnvironmentDelegate extends InvocationHandler {
|
||||
|
||||
/**
|
||||
* init environment.
|
||||
* @param properties user customize properties
|
||||
*/
|
||||
void init(Properties properties);
|
||||
}
|
||||
|
||||
}
|
@ -1,116 +0,0 @@
|
||||
/*
|
||||
* Copyright 1999-2022 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.client.env;
|
||||
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* environment utils.
|
||||
* @author onewe
|
||||
*/
|
||||
public class NacosEnvs {
|
||||
|
||||
private static final NacosEnvironment ENVIRONMENT = NacosEnvironmentFactory.createEnvironment();
|
||||
|
||||
/**
|
||||
* init environment.
|
||||
* @param properties properties
|
||||
*/
|
||||
public static void init(Properties properties) {
|
||||
NacosEnvironmentFactory.NacosEnvironmentDelegate warrper = (NacosEnvironmentFactory.NacosEnvironmentDelegate) Proxy.getInvocationHandler(
|
||||
ENVIRONMENT);
|
||||
warrper.init(properties);
|
||||
}
|
||||
|
||||
public static String getProperty(String key, String defaultValue) {
|
||||
return ENVIRONMENT.getProperty(key, defaultValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* get property, if the value can not be got by the special key, the null will be returned.
|
||||
*
|
||||
* @param key special key
|
||||
* @return string value or null.
|
||||
*/
|
||||
public static String getProperty(String key) {
|
||||
return ENVIRONMENT.getProperty(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* get boolean, if the value can not be got by the special key, the null will be returned.
|
||||
*
|
||||
* @param key special key
|
||||
* @return boolean value or null.
|
||||
*/
|
||||
public static Boolean getBoolean(String key) {
|
||||
return ENVIRONMENT.getBoolean(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* get boolean, if the value can not be got by the special key, the default value will be returned.
|
||||
*
|
||||
* @param key special key
|
||||
* @param defaultValue default value
|
||||
* @return boolean value or defaultValue.
|
||||
*/
|
||||
public static Boolean getBoolean(String key, Boolean defaultValue) {
|
||||
return ENVIRONMENT.getBoolean(key, defaultValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* get integer, if the value can not be got by the special key, the null will be returned.
|
||||
*
|
||||
* @param key special key
|
||||
* @return integer value or null
|
||||
*/
|
||||
public static Integer getInteger(String key) {
|
||||
return ENVIRONMENT.getInteger(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* get integer, if the value can not be got by the special key, the default value will be returned.
|
||||
*
|
||||
* @param key special key
|
||||
* @param defaultValue default value
|
||||
* @return integer value or default value
|
||||
*/
|
||||
public static Integer getInteger(String key, Integer defaultValue) {
|
||||
return ENVIRONMENT.getInteger(key, defaultValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* get long, if the value can not be got by the special key, the null will be returned.
|
||||
*
|
||||
* @param key special key
|
||||
* @return long value or null
|
||||
*/
|
||||
public static Long getLong(String key) {
|
||||
return ENVIRONMENT.getLong(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* get long, if the value can not be got by the special key, the default value will be returned.
|
||||
*
|
||||
* @param key special key
|
||||
* @param defaultValue default value
|
||||
* @return long value or default value
|
||||
*/
|
||||
public static Long getLong(String key, Long defaultValue) {
|
||||
return ENVIRONMENT.getLong(key, defaultValue);
|
||||
}
|
||||
}
|
@ -16,14 +16,23 @@
|
||||
|
||||
package com.alibaba.nacos.client.env;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
import java.util.Properties;
|
||||
|
||||
class PropertiesPropertySource extends AbstractPropertySource {
|
||||
|
||||
private final Properties properties;
|
||||
private final Properties properties = new Properties();
|
||||
|
||||
PropertiesPropertySource(Properties properties) {
|
||||
this.properties = properties;
|
||||
private final PropertiesPropertySource parent;
|
||||
|
||||
PropertiesPropertySource() {
|
||||
this.parent = null;
|
||||
}
|
||||
|
||||
PropertiesPropertySource(PropertiesPropertySource parent) {
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -33,6 +42,67 @@ class PropertiesPropertySource extends AbstractPropertySource {
|
||||
|
||||
@Override
|
||||
String getProperty(String key) {
|
||||
return properties.getProperty(key);
|
||||
return getProperty(this, key);
|
||||
}
|
||||
|
||||
private String getProperty(PropertiesPropertySource propertiesPropertySource, String key) {
|
||||
final String value = propertiesPropertySource.properties.getProperty(key);
|
||||
if (value != null) {
|
||||
return value;
|
||||
}
|
||||
final PropertiesPropertySource parent = propertiesPropertySource.parent;
|
||||
if (parent == null) {
|
||||
return null;
|
||||
}
|
||||
return getProperty(parent, key);
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean containsKey(String key) {
|
||||
return containsKey(this, key);
|
||||
}
|
||||
|
||||
boolean containsKey(PropertiesPropertySource propertiesPropertySource, String key) {
|
||||
final boolean exist = propertiesPropertySource.properties.containsKey(key);
|
||||
if (exist) {
|
||||
return true;
|
||||
}
|
||||
final PropertiesPropertySource parent = propertiesPropertySource.parent;
|
||||
if (parent == null) {
|
||||
return false;
|
||||
}
|
||||
return containsKey(parent, key);
|
||||
}
|
||||
|
||||
@Override
|
||||
Properties asProperties() {
|
||||
List<Properties> propertiesList = new ArrayList<>(8);
|
||||
|
||||
propertiesList = lookForProperties(this, propertiesList);
|
||||
|
||||
Properties ret = new Properties();
|
||||
final ListIterator<Properties> iterator = propertiesList.listIterator(propertiesList.size());
|
||||
while (iterator.hasPrevious()) {
|
||||
final Properties properties = iterator.previous();
|
||||
ret.putAll(properties);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
List<Properties> lookForProperties(PropertiesPropertySource propertiesPropertySource, List<Properties> propertiesList) {
|
||||
propertiesList.add(propertiesPropertySource.properties);
|
||||
final PropertiesPropertySource parent = propertiesPropertySource.parent;
|
||||
if (parent == null) {
|
||||
return propertiesList;
|
||||
}
|
||||
return lookForProperties(parent, propertiesList);
|
||||
}
|
||||
|
||||
synchronized void setProperty(String key, String value) {
|
||||
properties.setProperty(key, value);
|
||||
}
|
||||
|
||||
synchronized void addProperties(Properties source) {
|
||||
properties.putAll(source);
|
||||
}
|
||||
}
|
||||
|
@ -1,119 +0,0 @@
|
||||
/*
|
||||
* Copyright 1999-2022 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.client.env;
|
||||
|
||||
import com.alibaba.nacos.client.constant.Constants;
|
||||
import com.alibaba.nacos.client.env.convert.CompositeConverter;
|
||||
import com.alibaba.nacos.common.utils.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Properties;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
class PropertySourceSearch {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(PropertySourceSearch.class);
|
||||
|
||||
private static final List<SourceType> DEFAULT_ORDER = Arrays.asList(SourceType.PROPERTIES, SourceType.JVM,
|
||||
SourceType.SYS);
|
||||
|
||||
private final List<AbstractPropertySource> propertySources;
|
||||
|
||||
private final CompositeConverter converter;
|
||||
|
||||
private PropertySourceSearch(List<AbstractPropertySource> propertySources) {
|
||||
this.propertySources = propertySources;
|
||||
this.propertySources.add(new DefaultSettingPropertySource());
|
||||
this.converter = new CompositeConverter();
|
||||
}
|
||||
|
||||
static PropertySourceSearch build(Properties properties) {
|
||||
if (properties == null) {
|
||||
properties = new Properties();
|
||||
}
|
||||
PropertiesPropertySource customizePropertySource = new PropertiesPropertySource(properties);
|
||||
JvmArgsPropertySource jvmArgsPropertySource = new JvmArgsPropertySource();
|
||||
SystemEnvPropertySource systemEnvPropertySource = new SystemEnvPropertySource();
|
||||
|
||||
String searchPattern = jvmArgsPropertySource.getProperty(Constants.SysEnv.NACOS_ENVS_SEARCH);
|
||||
if (StringUtils.isBlank(searchPattern)) {
|
||||
searchPattern = systemEnvPropertySource.getProperty(Constants.SysEnv.NACOS_ENVS_SEARCH);
|
||||
}
|
||||
|
||||
return resolve(searchPattern, customizePropertySource, jvmArgsPropertySource, systemEnvPropertySource);
|
||||
}
|
||||
|
||||
private static PropertySourceSearch resolve(String pattern, AbstractPropertySource... propertySources) {
|
||||
|
||||
if (StringUtils.isBlank(pattern)) {
|
||||
return createPropertySourceSearchWithDefaultOrder(propertySources);
|
||||
}
|
||||
|
||||
try {
|
||||
final SourceType sourceType = SourceType.valueOf(pattern.toUpperCase());
|
||||
return createPropertySourceSearchByFirstType(sourceType, propertySources);
|
||||
} catch (Exception e) {
|
||||
LOGGER.error("first source type parse error, it will be use default order!");
|
||||
return createPropertySourceSearchWithDefaultOrder(propertySources);
|
||||
}
|
||||
}
|
||||
|
||||
private static PropertySourceSearch createPropertySourceSearchWithDefaultOrder(AbstractPropertySource... propertySources) {
|
||||
final Map<SourceType, AbstractPropertySource> sourceMap = Arrays.stream(propertySources)
|
||||
.collect(Collectors.toMap(AbstractPropertySource::getType, propertySource -> propertySource));
|
||||
final List<AbstractPropertySource> collect = DEFAULT_ORDER.stream().map(sourceMap::get).collect(Collectors.toList());
|
||||
return new PropertySourceSearch(collect);
|
||||
}
|
||||
|
||||
private static PropertySourceSearch createPropertySourceSearchByFirstType(SourceType firstType,
|
||||
AbstractPropertySource... propertySources) {
|
||||
|
||||
List<SourceType> tempList = new ArrayList<>(4);
|
||||
tempList.add(firstType);
|
||||
|
||||
final Map<SourceType, AbstractPropertySource> sourceMap = Arrays.stream(propertySources)
|
||||
.collect(Collectors.toMap(AbstractPropertySource::getType, propertySource -> propertySource));
|
||||
final List<AbstractPropertySource> collect = DEFAULT_ORDER.stream().filter(sourceType -> !sourceType.equals(firstType))
|
||||
.collect(() -> tempList, List::add, List::addAll).stream().map(sourceMap::get)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
return new PropertySourceSearch(collect);
|
||||
}
|
||||
|
||||
<T> Optional<T> search(String key, Class<T> targetType) {
|
||||
if (targetType == null) {
|
||||
throw new IllegalArgumentException("target type must be not null!");
|
||||
}
|
||||
|
||||
for (AbstractPropertySource propertySource : propertySources) {
|
||||
final String value = propertySource.getProperty(key);
|
||||
if (value != null) {
|
||||
if (String.class.isAssignableFrom(targetType)) {
|
||||
return (Optional<T>) Optional.of(value);
|
||||
}
|
||||
return Optional.ofNullable(converter.convert(value, targetType));
|
||||
}
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
@ -1,74 +0,0 @@
|
||||
/*
|
||||
* Copyright 1999-2022 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.client.env;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* Searchable environment.
|
||||
*
|
||||
* @author onewe
|
||||
*/
|
||||
class SearchableEnvironment implements NacosEnvironment {
|
||||
|
||||
private final PropertySourceSearch sourceSearch;
|
||||
|
||||
SearchableEnvironment(Properties properties) {
|
||||
this.sourceSearch = PropertySourceSearch.build(properties);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getProperty(String key) {
|
||||
return getProperty(key, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getProperty(String key, String defaultValue) {
|
||||
return sourceSearch.search(key, String.class).orElse(defaultValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean getBoolean(String key) {
|
||||
return getBoolean(key, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean getBoolean(String key, Boolean defaultValue) {
|
||||
return sourceSearch.search(key, Boolean.class).orElse(defaultValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getInteger(String key) {
|
||||
return getInteger(key, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getInteger(String key, Integer defaultValue) {
|
||||
return sourceSearch.search(key, Integer.class).orElse(defaultValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long getLong(String key) {
|
||||
return getLong(key, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long getLong(String key, Long defaultValue) {
|
||||
return sourceSearch.search(key, Long.class).orElse(defaultValue);
|
||||
}
|
||||
|
||||
}
|
236
client/src/main/java/com/alibaba/nacos/client/env/SearchableProperties.java
vendored
Normal file
236
client/src/main/java/com/alibaba/nacos/client/env/SearchableProperties.java
vendored
Normal file
@ -0,0 +1,236 @@
|
||||
/*
|
||||
* Copyright 1999-2022 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.client.env;
|
||||
|
||||
import com.alibaba.nacos.client.constant.Constants;
|
||||
import com.alibaba.nacos.client.env.convert.CompositeConverter;
|
||||
import com.alibaba.nacos.common.utils.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.Properties;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Searchable NacosClientProperties.
|
||||
* the SearchableProperties that it can be specified search order by
|
||||
* nacos.env.first
|
||||
* @author onewe
|
||||
*/
|
||||
class SearchableProperties implements NacosClientProperties {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(SearchableProperties.class);
|
||||
|
||||
private static final JvmArgsPropertySource JVM_ARGS_PROPERTY_SOURCE = new JvmArgsPropertySource();
|
||||
|
||||
private static final SystemEnvPropertySource SYSTEM_ENV_PROPERTY_SOURCE = new SystemEnvPropertySource();
|
||||
|
||||
private static final DefaultSettingPropertySource DEFAULT_SETTING_PROPERTY_SOURCE = new DefaultSettingPropertySource();
|
||||
|
||||
private static final List<SourceType> DEFAULT_ORDER = Arrays.asList(SourceType.PROPERTIES, SourceType.JVM,
|
||||
SourceType.ENV, SourceType.DEFAULT_SETTING);
|
||||
|
||||
private static final CompositeConverter CONVERTER = new CompositeConverter();
|
||||
|
||||
static final SearchableProperties INSTANCE = new SearchableProperties();
|
||||
|
||||
private final List<AbstractPropertySource> propertySources;
|
||||
|
||||
private final PropertiesPropertySource propertiesPropertySource;
|
||||
|
||||
private SearchableProperties() {
|
||||
this(new PropertiesPropertySource());
|
||||
}
|
||||
|
||||
private SearchableProperties(PropertiesPropertySource propertiesPropertySource) {
|
||||
this.propertiesPropertySource = propertiesPropertySource;
|
||||
this.propertySources = build(propertiesPropertySource,
|
||||
JVM_ARGS_PROPERTY_SOURCE, SYSTEM_ENV_PROPERTY_SOURCE, DEFAULT_SETTING_PROPERTY_SOURCE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getProperty(String key) {
|
||||
return getProperty(key, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getProperty(String key, String defaultValue) {
|
||||
return this.search(key, String.class).orElse(defaultValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean getBoolean(String key) {
|
||||
return getBoolean(key, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean getBoolean(String key, Boolean defaultValue) {
|
||||
return this.search(key, Boolean.class).orElse(defaultValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getInteger(String key) {
|
||||
return getInteger(key, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getInteger(String key, Integer defaultValue) {
|
||||
return this.search(key, Integer.class).orElse(defaultValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long getLong(String key) {
|
||||
return getLong(key, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long getLong(String key, Long defaultValue) {
|
||||
return this.search(key, Long.class).orElse(defaultValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setProperty(String key, String value) {
|
||||
propertiesPropertySource.setProperty(key, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addProperties(Properties properties) {
|
||||
propertiesPropertySource.addProperties(properties);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Properties asProperties() {
|
||||
Properties properties = new Properties();
|
||||
final ListIterator<AbstractPropertySource> iterator = propertySources.listIterator(
|
||||
propertySources.size());
|
||||
while (iterator.hasPrevious()) {
|
||||
final AbstractPropertySource previous = iterator.previous();
|
||||
properties.putAll(previous.asProperties());
|
||||
}
|
||||
return properties;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsKey(String key) {
|
||||
for (AbstractPropertySource propertySource : propertySources) {
|
||||
final boolean containing = propertySource.containsKey(key);
|
||||
if (containing) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private <T> Optional<T> search(String key, Class<T> targetType) {
|
||||
if (targetType == null) {
|
||||
throw new IllegalArgumentException("target type must not be null!");
|
||||
}
|
||||
|
||||
for (AbstractPropertySource propertySource : propertySources) {
|
||||
final String value = propertySource.getProperty(key);
|
||||
if (value != null) {
|
||||
if (String.class.isAssignableFrom(targetType)) {
|
||||
try {
|
||||
return (Optional<T>) Optional.of(value);
|
||||
} catch (Exception e) {
|
||||
LOGGER.error("target type convert error", e);
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
}
|
||||
return Optional.ofNullable(CONVERTER.convert(value, targetType));
|
||||
}
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
private List<AbstractPropertySource> build(AbstractPropertySource... propertySources) {
|
||||
|
||||
String firstEnv = JVM_ARGS_PROPERTY_SOURCE.getProperty(Constants.SysEnv.NACOS_ENV_FIRST);
|
||||
if (StringUtils.isBlank(firstEnv)) {
|
||||
firstEnv = SYSTEM_ENV_PROPERTY_SOURCE.getProperty(Constants.SysEnv.NACOS_ENV_FIRST);
|
||||
}
|
||||
|
||||
if (StringUtils.isBlank(firstEnv)) {
|
||||
return sortPropertySourceDefaultOrder(propertySources);
|
||||
}
|
||||
|
||||
try {
|
||||
final SourceType sourceType = SourceType.valueOf(firstEnv.toUpperCase());
|
||||
if (SourceType.DEFAULT_SETTING.equals(sourceType) || SourceType.PROPERTIES.equals(sourceType)) {
|
||||
return sortPropertySourceDefaultOrder(propertySources);
|
||||
}
|
||||
return sortPropertySource(sourceType, propertySources);
|
||||
} catch (Exception e) {
|
||||
LOGGER.error("first source type parse error, it will be used default order!", e);
|
||||
return sortPropertySourceDefaultOrder(propertySources);
|
||||
}
|
||||
}
|
||||
|
||||
private List<AbstractPropertySource> sortPropertySourceDefaultOrder(
|
||||
AbstractPropertySource... propertySources) {
|
||||
final Map<SourceType, AbstractPropertySource> sourceMap = Arrays.stream(propertySources)
|
||||
.collect(Collectors.toMap(AbstractPropertySource::getType, propertySource -> propertySource));
|
||||
final List<AbstractPropertySource> collect = DEFAULT_ORDER.stream().map(sourceMap::get)
|
||||
.collect(Collectors.toList());
|
||||
LOGGER.info("properties search order:PROPERTIES->JVM->ENV->DEFAULT_SETTING");
|
||||
return collect;
|
||||
}
|
||||
|
||||
private List<AbstractPropertySource> sortPropertySource(SourceType firstType,
|
||||
AbstractPropertySource... propertySources) {
|
||||
List<SourceType> tempList = new ArrayList<>(4);
|
||||
tempList.add(firstType);
|
||||
|
||||
final Map<SourceType, AbstractPropertySource> sourceMap = Arrays.stream(propertySources)
|
||||
.collect(Collectors.toMap(AbstractPropertySource::getType, propertySource -> propertySource));
|
||||
final List<AbstractPropertySource> collect = DEFAULT_ORDER.stream()
|
||||
.filter(sourceType -> !sourceType.equals(firstType)).collect(() -> tempList, List::add, List::addAll)
|
||||
.stream().map(sourceMap::get).filter(Objects::nonNull).collect(Collectors.toList());
|
||||
|
||||
StringBuilder orderInfo = new StringBuilder("properties search order:");
|
||||
for (int i = 0; i < collect.size(); i++) {
|
||||
final AbstractPropertySource abstractPropertySource = collect.get(i);
|
||||
orderInfo.append(abstractPropertySource.getType().toString());
|
||||
if (i < collect.size() - 1) {
|
||||
orderInfo.append("->");
|
||||
}
|
||||
}
|
||||
LOGGER.info(orderInfo.toString());
|
||||
|
||||
return collect;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NacosClientProperties derive() {
|
||||
return new SearchableProperties(new PropertiesPropertySource(this.propertiesPropertySource));
|
||||
}
|
||||
|
||||
@Override
|
||||
public NacosClientProperties derive(Properties properties) {
|
||||
final NacosClientProperties nacosClientProperties = this.derive();
|
||||
nacosClientProperties.addProperties(properties);
|
||||
return nacosClientProperties;
|
||||
}
|
||||
}
|
@ -18,17 +18,17 @@ package com.alibaba.nacos.client.env;
|
||||
|
||||
enum SourceType {
|
||||
/**
|
||||
* get value from system environment.
|
||||
* get value from properties.
|
||||
*/
|
||||
SYS,
|
||||
PROPERTIES,
|
||||
/**
|
||||
* get value from jvm args.
|
||||
*/
|
||||
JVM,
|
||||
/**
|
||||
* get value from properties.
|
||||
* get value from system environment.
|
||||
*/
|
||||
PROPERTIES,
|
||||
ENV,
|
||||
/**
|
||||
* get value from default setting.
|
||||
*/
|
||||
|
@ -17,18 +17,15 @@
|
||||
package com.alibaba.nacos.client.env;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
class SystemEnvPropertySource extends AbstractPropertySource {
|
||||
|
||||
private final Map<String, String> env;
|
||||
|
||||
SystemEnvPropertySource() {
|
||||
this.env = System.getenv();
|
||||
}
|
||||
private final Map<String, String> env = System.getenv();
|
||||
|
||||
@Override
|
||||
SourceType getType() {
|
||||
return SourceType.SYS;
|
||||
return SourceType.ENV;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -78,7 +75,15 @@ class SystemEnvPropertySource extends AbstractPropertySource {
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean containsKey(String name) {
|
||||
@Override
|
||||
boolean containsKey(String name) {
|
||||
return this.env.containsKey(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
Properties asProperties() {
|
||||
Properties properties = new Properties();
|
||||
properties.putAll(this.env);
|
||||
return properties;
|
||||
}
|
||||
}
|
||||
|
@ -156,6 +156,13 @@ public class NacosNamingService implements NamingService {
|
||||
clientProxy.batchRegisterService(serviceName, groupName, instances);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void batchDeregisterInstance(String serviceName, String groupName, List<Instance> instances)
|
||||
throws NacosException {
|
||||
NamingUtils.batchCheckInstanceIsLegal(instances);
|
||||
clientProxy.batchDeregisterService(serviceName, groupName, instances);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deregisterInstance(String serviceName, String ip, int port) throws NacosException {
|
||||
deregisterInstance(serviceName, ip, port, Constants.DEFAULT_CLUSTER_NAME);
|
||||
|
@ -61,8 +61,11 @@ public class ServiceInfoUpdateService implements Closeable {
|
||||
|
||||
private final InstancesChangeNotifier changeNotifier;
|
||||
|
||||
private final boolean asyncQuerySubscribeService;
|
||||
|
||||
public ServiceInfoUpdateService(Properties properties, ServiceInfoHolder serviceInfoHolder,
|
||||
NamingClientProxy namingClientProxy, InstancesChangeNotifier changeNotifier) {
|
||||
this.asyncQuerySubscribeService = isAsyncQueryForSubscribeService(properties);
|
||||
this.executor = new ScheduledThreadPoolExecutor(initPollingThreadCount(properties),
|
||||
new NameThreadFactory("com.alibaba.nacos.client.naming.updater"));
|
||||
this.serviceInfoHolder = serviceInfoHolder;
|
||||
@ -70,6 +73,13 @@ public class ServiceInfoUpdateService implements Closeable {
|
||||
this.changeNotifier = changeNotifier;
|
||||
}
|
||||
|
||||
private boolean isAsyncQueryForSubscribeService(Properties properties) {
|
||||
if (properties == null || !properties.containsKey(PropertyKeyConst.NAMING_ASYNC_QUERY_SUBSCRIBE_SERVICE)) {
|
||||
return true;
|
||||
}
|
||||
return ConvertUtils.toBoolean(properties.getProperty(PropertyKeyConst.NAMING_ASYNC_QUERY_SUBSCRIBE_SERVICE), true);
|
||||
}
|
||||
|
||||
private int initPollingThreadCount(Properties properties) {
|
||||
if (properties == null) {
|
||||
return UtilAndComs.DEFAULT_POLLING_THREAD_COUNT;
|
||||
@ -86,6 +96,9 @@ public class ServiceInfoUpdateService implements Closeable {
|
||||
* @param clusters clusters
|
||||
*/
|
||||
public void scheduleUpdateIfAbsent(String serviceName, String groupName, String clusters) {
|
||||
if (!asyncQuerySubscribeService) {
|
||||
return;
|
||||
}
|
||||
String serviceKey = ServiceInfo.getKey(NamingUtils.getGroupedName(serviceName, groupName), clusters);
|
||||
if (futureMap.get(serviceKey) != null) {
|
||||
return;
|
||||
@ -193,9 +206,10 @@ public class ServiceInfoUpdateService implements Closeable {
|
||||
// TODO multiple time can be configured.
|
||||
delayTime = serviceObj.getCacheMillis() * DEFAULT_UPDATE_CACHE_TIME_MULTIPLE;
|
||||
resetFailCount();
|
||||
} catch (NacosException e) {
|
||||
handleNacosException(e);
|
||||
} catch (Throwable e) {
|
||||
incFailCount();
|
||||
NAMING_LOGGER.warn("[NA] failed to update serviceName: {}", groupedServiceName, e);
|
||||
handleUnknownException(e);
|
||||
} finally {
|
||||
if (!isCancel) {
|
||||
executor.schedule(this, Math.min(delayTime << failCount, DEFAULT_DELAY * 60),
|
||||
@ -204,6 +218,20 @@ public class ServiceInfoUpdateService implements Closeable {
|
||||
}
|
||||
}
|
||||
|
||||
private void handleNacosException(NacosException e) {
|
||||
incFailCount();
|
||||
int errorCode = e.getErrCode();
|
||||
if (NacosException.SERVER_ERROR == errorCode) {
|
||||
handleUnknownException(e);
|
||||
}
|
||||
NAMING_LOGGER.warn("Can't update serviceName: {}, reason: {}", groupedServiceName, e.getErrMsg());
|
||||
}
|
||||
|
||||
private void handleUnknownException(Throwable throwable) {
|
||||
incFailCount();
|
||||
NAMING_LOGGER.warn("[NA] failed to update serviceName: {}", groupedServiceName, throwable);
|
||||
}
|
||||
|
||||
private void incFailCount() {
|
||||
int limit = 6;
|
||||
if (failCount == limit) {
|
||||
|
@ -55,6 +55,17 @@ public interface NamingClientProxy extends Closeable {
|
||||
*/
|
||||
void batchRegisterService(String serviceName, String groupName, List<Instance> instances) throws NacosException;
|
||||
|
||||
/**
|
||||
* Batch register instance to service with specified instance properties.
|
||||
*
|
||||
* @param serviceName service name
|
||||
* @param groupName group name
|
||||
* @param instances deRegister instance
|
||||
* @throws NacosException nacos exception
|
||||
* @since 2.2.0
|
||||
*/
|
||||
void batchDeregisterService(String serviceName, String groupName, List<Instance> instances) throws NacosException;
|
||||
|
||||
/**
|
||||
* Deregister instance from a service.
|
||||
*
|
||||
|
@ -107,6 +107,17 @@ public class NamingClientProxyDelegate implements NamingClientProxy {
|
||||
NAMING_LOGGER.info("batchRegisterInstance instances: {} ,serviceName: {} finish.", instances, serviceName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void batchDeregisterService(String serviceName, String groupName, List<Instance> instances)
|
||||
throws NacosException {
|
||||
NAMING_LOGGER.info("batch DeregisterInstance instances: {} ,serviceName: {} begin.", instances, serviceName);
|
||||
if (CollectionUtils.isEmpty(instances)) {
|
||||
NAMING_LOGGER.warn("batch DeregisterInstance instances is Empty:{}", instances);
|
||||
}
|
||||
grpcClientProxy.batchDeregisterService(serviceName, groupName, instances);
|
||||
NAMING_LOGGER.info("batch DeregisterInstance instances: {} ,serviceName: {} finish.", instances, serviceName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deregisterService(String serviceName, String groupName, Instance instance) throws NacosException {
|
||||
getExecuteClientProxy(instance).deregisterService(serviceName, groupName, instance);
|
||||
|
@ -33,6 +33,7 @@ import com.alibaba.nacos.api.naming.remote.response.BatchInstanceResponse;
|
||||
import com.alibaba.nacos.api.naming.remote.response.QueryServiceResponse;
|
||||
import com.alibaba.nacos.api.naming.remote.response.ServiceListResponse;
|
||||
import com.alibaba.nacos.api.naming.remote.response.SubscribeServiceResponse;
|
||||
import com.alibaba.nacos.api.naming.utils.NamingUtils;
|
||||
import com.alibaba.nacos.api.remote.RemoteConstants;
|
||||
import com.alibaba.nacos.api.remote.response.Response;
|
||||
import com.alibaba.nacos.api.remote.response.ResponseCode;
|
||||
@ -42,6 +43,8 @@ import com.alibaba.nacos.client.naming.cache.ServiceInfoHolder;
|
||||
import com.alibaba.nacos.client.naming.event.ServerListChangedEvent;
|
||||
import com.alibaba.nacos.client.naming.remote.AbstractNamingClientProxy;
|
||||
import com.alibaba.nacos.client.naming.remote.gprc.redo.NamingGrpcRedoService;
|
||||
import com.alibaba.nacos.client.naming.remote.gprc.redo.data.BatchInstanceRedoData;
|
||||
import com.alibaba.nacos.client.naming.remote.gprc.redo.data.InstanceRedoData;
|
||||
import com.alibaba.nacos.client.security.SecurityProxy;
|
||||
import com.alibaba.nacos.common.notify.Event;
|
||||
import com.alibaba.nacos.common.notify.NotifyCenter;
|
||||
@ -49,14 +52,18 @@ import com.alibaba.nacos.common.remote.ConnectionType;
|
||||
import com.alibaba.nacos.common.remote.client.RpcClient;
|
||||
import com.alibaba.nacos.common.remote.client.RpcClientFactory;
|
||||
import com.alibaba.nacos.common.remote.client.ServerListFactory;
|
||||
import com.alibaba.nacos.common.utils.CollectionUtils;
|
||||
import com.alibaba.nacos.common.utils.JacksonUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static com.alibaba.nacos.client.utils.LogUtils.NAMING_LOGGER;
|
||||
|
||||
@ -124,6 +131,50 @@ public class NamingGrpcClientProxy extends AbstractNamingClientProxy {
|
||||
doBatchRegisterService(serviceName, groupName, instances);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void batchDeregisterService(String serviceName, String groupName, List<Instance> instances)
|
||||
throws NacosException {
|
||||
List<Instance> retainInstance = getRetainInstance(serviceName, groupName, instances);
|
||||
batchRegisterService(serviceName, groupName, retainInstance);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get instance list that need to be deregistered.
|
||||
* @param serviceName service name
|
||||
* @param groupName group name
|
||||
* @param instances instance list
|
||||
* @return instance list that need to be deregistered.
|
||||
*/
|
||||
private List<Instance> getRetainInstance(String serviceName, String groupName, List<Instance> instances) throws NacosException {
|
||||
if (CollectionUtils.isEmpty(instances)) {
|
||||
throw new NacosException(NacosException.INVALID_PARAM,
|
||||
String.format("[Batch deRegistration] need deRegister instance is empty, instances: %s,", instances));
|
||||
}
|
||||
String combinedServiceName = NamingUtils.getGroupedName(serviceName, groupName);
|
||||
InstanceRedoData instanceRedoData = redoService.getRegisteredInstancesBykey(combinedServiceName);
|
||||
if (!(instanceRedoData instanceof BatchInstanceRedoData)) {
|
||||
throw new NacosException(NacosException.INVALID_PARAM,
|
||||
String.format("[Batch deRegistration] batch deRegister is not BatchInstanceRedoData type , instances: %s,", instances));
|
||||
}
|
||||
|
||||
BatchInstanceRedoData batchInstanceRedoData = (BatchInstanceRedoData) instanceRedoData;
|
||||
List<Instance> allInstance = batchInstanceRedoData.getInstances();
|
||||
if (CollectionUtils.isEmpty(allInstance)) {
|
||||
throw new NacosException(NacosException.INVALID_PARAM,
|
||||
String.format("[Batch deRegistration] not found all registerInstance , serviceName:%s , groupName: %s", serviceName, groupName));
|
||||
}
|
||||
|
||||
Map<Instance, Instance> instanceMap = instances
|
||||
.stream().collect(Collectors.toMap(Function.identity(), Function.identity()));
|
||||
List<Instance> retainInstances = new ArrayList<>();
|
||||
for (Instance instance : allInstance) {
|
||||
if (!instanceMap.containsKey(instance)) {
|
||||
retainInstances.add(instance);
|
||||
}
|
||||
}
|
||||
return retainInstances;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute batch register operation.
|
||||
*
|
||||
@ -280,7 +331,7 @@ public class NamingGrpcClientProxy extends AbstractNamingClientProxy {
|
||||
* @throws NacosException nacos exception
|
||||
*/
|
||||
public void doUnsubscribe(String serviceName, String groupName, String clusters) throws NacosException {
|
||||
SubscribeServiceRequest request = new SubscribeServiceRequest(namespaceId, serviceName, groupName, clusters,
|
||||
SubscribeServiceRequest request = new SubscribeServiceRequest(namespaceId, groupName, serviceName, clusters,
|
||||
false);
|
||||
requestToServer(request, SubscribeServiceResponse.class);
|
||||
redoService.removeSubscriberForRedo(serviceName, groupName, clusters);
|
||||
|
@ -277,6 +277,14 @@ public class NamingGrpcRedoService implements ConnectionEventListener {
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* get Cache service.
|
||||
* @return cache service
|
||||
*/
|
||||
public InstanceRedoData getRegisteredInstancesBykey(String combinedServiceName) {
|
||||
return registeredInstances.get(combinedServiceName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Shutdown redo service.
|
||||
*/
|
||||
|
@ -172,6 +172,12 @@ public class NamingHttpClientProxy extends AbstractNamingClientProxy {
|
||||
throw new UnsupportedOperationException("Do not support persistent instances to perform batch registration methods.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void batchDeregisterService(String serviceName, String groupName, List<Instance> instances)
|
||||
throws NacosException {
|
||||
throw new UnsupportedOperationException("Do not support persistent instances to perform batch de registration methods.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deregisterService(String serviceName, String groupName, Instance instance) throws NacosException {
|
||||
NAMING_LOGGER
|
||||
|
@ -95,21 +95,6 @@ public class InitUtils {
|
||||
UtilAndComs.nacosUrlBase = UtilAndComs.webContext + "/v1/ns";
|
||||
UtilAndComs.nacosUrlInstance = UtilAndComs.nacosUrlBase + "/instance";
|
||||
});
|
||||
initWebRootContext();
|
||||
}
|
||||
|
||||
/**
|
||||
* Init web root context.
|
||||
*/
|
||||
@Deprecated
|
||||
public static void initWebRootContext() {
|
||||
// support the web context with ali-yun if the app deploy by EDAS
|
||||
final String webContext = System.getProperty(SystemPropertyKeyConst.NAMING_WEB_CONTEXT);
|
||||
TemplateUtils.stringNotEmptyAndThenExecute(webContext, () -> {
|
||||
UtilAndComs.webContext = ContextPathUtil.normalizeContextPath(webContext);
|
||||
UtilAndComs.nacosUrlBase = UtilAndComs.webContext + "/v1/ns";
|
||||
UtilAndComs.nacosUrlInstance = UtilAndComs.nacosUrlBase + "/instance";
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -17,7 +17,6 @@
|
||||
package com.alibaba.nacos.client.naming.utils;
|
||||
|
||||
import com.alibaba.nacos.common.utils.ThreadUtils;
|
||||
import com.alibaba.nacos.common.utils.VersionUtils;
|
||||
|
||||
/**
|
||||
* Util and constants.
|
||||
@ -26,10 +25,6 @@ import com.alibaba.nacos.common.utils.VersionUtils;
|
||||
*/
|
||||
public class UtilAndComs {
|
||||
|
||||
// using com.alibaba.nacos.common.utils.VersionUtils.getFullClientVersion instead.
|
||||
@Deprecated
|
||||
public static final String VERSION = VersionUtils.getFullClientVersion();
|
||||
|
||||
public static String webContext = "/nacos";
|
||||
|
||||
public static String nacosUrlBase = webContext + "/v1/ns";
|
||||
|
@ -116,31 +116,4 @@ public class CredentialServiceTest extends TestCase {
|
||||
Assert.assertEquals(expect, actual);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetAkAndSk() {
|
||||
CredentialService credentialService1 = CredentialService.getInstance();
|
||||
Credentials c = new Credentials();
|
||||
c.setAccessKey("ak");
|
||||
c.setSecretKey("sk");
|
||||
credentialService1.setCredential(c);
|
||||
|
||||
Assert.assertEquals("ak", credentialService1.getAccessKey());
|
||||
Assert.assertEquals("sk", credentialService1.getSecretKey());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetSecretKey() {
|
||||
CredentialService credentialService1 = CredentialService.getInstance();
|
||||
Credentials c = new Credentials();
|
||||
c.setAccessKey("ak");
|
||||
c.setSecretKey("sk");
|
||||
credentialService1.setCredential(c);
|
||||
credentialService1.setAccessKey("ak1");
|
||||
credentialService1.setSecretKey("sk1");
|
||||
|
||||
Assert.assertEquals("ak1", credentialService1.getAccessKey());
|
||||
Assert.assertEquals("sk1", credentialService1.getSecretKey());
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -21,7 +21,6 @@ import com.alibaba.nacos.api.config.filter.IConfigFilter;
|
||||
import com.alibaba.nacos.api.config.filter.IConfigFilterChain;
|
||||
import com.alibaba.nacos.api.config.filter.IConfigRequest;
|
||||
import com.alibaba.nacos.api.config.filter.IConfigResponse;
|
||||
import com.alibaba.nacos.api.config.filter.IFilterConfig;
|
||||
import com.alibaba.nacos.api.exception.NacosException;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
@ -43,11 +42,7 @@ public class ConfigFilterChainManagerTest {
|
||||
this.name = name;
|
||||
this.order = order;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(IFilterConfig filterConfig) {
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void init(Properties properties) {
|
||||
}
|
||||
@ -135,4 +130,4 @@ public class ConfigFilterChainManagerTest {
|
||||
|
||||
Assert.assertEquals(2, configContext.getParameter("filterCount"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -20,7 +20,6 @@ import com.alibaba.nacos.api.config.filter.IConfigFilter;
|
||||
import com.alibaba.nacos.api.config.filter.IConfigFilterChain;
|
||||
import com.alibaba.nacos.api.config.filter.IConfigRequest;
|
||||
import com.alibaba.nacos.api.config.filter.IConfigResponse;
|
||||
import com.alibaba.nacos.api.config.filter.IFilterConfig;
|
||||
import com.alibaba.nacos.api.exception.NacosException;
|
||||
|
||||
import java.util.Properties;
|
||||
@ -29,11 +28,6 @@ public class DemoFilter1 implements IConfigFilter {
|
||||
|
||||
private static final String DEFAULT_NAME = DemoFilter1.class.getName();
|
||||
|
||||
@Override
|
||||
public void init(IFilterConfig filterConfig) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(Properties properties) {
|
||||
|
||||
|
@ -20,7 +20,6 @@ import com.alibaba.nacos.api.config.filter.IConfigFilter;
|
||||
import com.alibaba.nacos.api.config.filter.IConfigFilterChain;
|
||||
import com.alibaba.nacos.api.config.filter.IConfigRequest;
|
||||
import com.alibaba.nacos.api.config.filter.IConfigResponse;
|
||||
import com.alibaba.nacos.api.config.filter.IFilterConfig;
|
||||
import com.alibaba.nacos.api.exception.NacosException;
|
||||
|
||||
import java.util.Properties;
|
||||
@ -29,11 +28,6 @@ public class DemoFilter2 implements IConfigFilter {
|
||||
|
||||
private static final String DEFAULT_NAME = DemoFilter2.class.getName();
|
||||
|
||||
@Override
|
||||
public void init(IFilterConfig filterConfig) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(Properties properties) {
|
||||
|
||||
|
308
client/src/test/java/com/alibaba/nacos/client/env/NacosClientPropertiesTest.java
vendored
Normal file
308
client/src/test/java/com/alibaba/nacos/client/env/NacosClientPropertiesTest.java
vendored
Normal file
@ -0,0 +1,308 @@
|
||||
/*
|
||||
* Copyright 1999-2022 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.client.env;
|
||||
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Assert;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
public class NacosClientPropertiesTest {
|
||||
|
||||
@BeforeClass
|
||||
public static void init() {
|
||||
System.setProperty("nacos.env.first", "jvm");
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void teardown() {
|
||||
System.clearProperty("nacos.env.first");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetProperty() {
|
||||
NacosClientProperties.PROTOTYPE.setProperty("nacos.home", "/home/nacos");
|
||||
final String value = NacosClientProperties.PROTOTYPE.getProperty("nacos.home");
|
||||
Assert.assertEquals("/home/nacos", value);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetPropertyMultiLayer() {
|
||||
|
||||
NacosClientProperties.PROTOTYPE.setProperty("top.layer", "top");
|
||||
|
||||
final NacosClientProperties layerAEnv = NacosClientProperties.PROTOTYPE.derive();
|
||||
layerAEnv.setProperty("a.layer", "a");
|
||||
|
||||
final NacosClientProperties layerBEnv = layerAEnv.derive();
|
||||
layerBEnv.setProperty("b.layer", "b");
|
||||
|
||||
final NacosClientProperties layerCEnv = layerBEnv.derive();
|
||||
layerCEnv.setProperty("c.layer", "c");
|
||||
|
||||
String value = layerCEnv.getProperty("c.layer");
|
||||
Assert.assertEquals("c", value);
|
||||
|
||||
value = layerCEnv.getProperty("b.layer");
|
||||
Assert.assertEquals("b", value);
|
||||
|
||||
value = layerCEnv.getProperty("a.layer");
|
||||
Assert.assertEquals("a", value);
|
||||
|
||||
value = layerCEnv.getProperty("top.layer");
|
||||
Assert.assertEquals("top", value);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetPropertyDefaultValue() {
|
||||
final String value = NacosClientProperties.PROTOTYPE.getProperty("nacos.home.default", "/home/default_value");
|
||||
Assert.assertEquals("/home/default_value", value);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetBoolean() {
|
||||
NacosClientProperties.PROTOTYPE.setProperty("use.cluster", "true");
|
||||
final Boolean value = NacosClientProperties.PROTOTYPE.getBoolean("use.cluster");
|
||||
Assert.assertTrue(value);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetBooleanDefaultValue() {
|
||||
final Boolean value = NacosClientProperties.PROTOTYPE.getBoolean("use.cluster.default", false);
|
||||
Assert.assertFalse(value);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetInteger() {
|
||||
NacosClientProperties.PROTOTYPE.setProperty("max.timeout", "200");
|
||||
final Integer value = NacosClientProperties.PROTOTYPE.getInteger("max.timeout");
|
||||
Assert.assertEquals(200, value.intValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetIntegerDefaultValue() {
|
||||
final Integer value = NacosClientProperties.PROTOTYPE.getInteger("max.timeout.default", 400);
|
||||
Assert.assertEquals(400, value.intValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetLong() {
|
||||
NacosClientProperties.PROTOTYPE.setProperty("connection.timeout", "200");
|
||||
final Long value = NacosClientProperties.PROTOTYPE.getLong("connection.timeout");
|
||||
Assert.assertEquals(200L, value.longValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetLongDefault() {
|
||||
final Long value = NacosClientProperties.PROTOTYPE.getLong("connection.timeout.default", 400L);
|
||||
Assert.assertEquals(400L, value.longValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetPropertyDefaultSetting() {
|
||||
|
||||
final String value = NacosClientProperties.PROTOTYPE.getProperty("nacos.home.default.test");
|
||||
Assert.assertEquals("/home/default_setting", value);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setProperty() {
|
||||
NacosClientProperties.PROTOTYPE.setProperty("nacos.set.property", "true");
|
||||
final String ret = NacosClientProperties.PROTOTYPE.getProperty("nacos.set.property");
|
||||
Assert.assertEquals("true", ret);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setPropertyWithScope() {
|
||||
|
||||
final NacosClientProperties properties = NacosClientProperties.PROTOTYPE.derive();
|
||||
properties.setProperty("nacos.set.property.scope", "config");
|
||||
|
||||
String ret = NacosClientProperties.PROTOTYPE.getProperty("nacos.set.property.scope");
|
||||
Assert.assertNull(ret);
|
||||
|
||||
ret = properties.getProperty("nacos.set.property.scope");
|
||||
Assert.assertEquals("config", ret);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddProperties() {
|
||||
Properties properties = new Properties();
|
||||
properties.setProperty("nacos.add.properties", "true");
|
||||
|
||||
NacosClientProperties.PROTOTYPE.addProperties(properties);
|
||||
|
||||
final String ret = NacosClientProperties.PROTOTYPE.getProperty("nacos.add.properties");
|
||||
|
||||
Assert.assertEquals("true", ret);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddPropertiesWithScope() {
|
||||
|
||||
Properties properties = new Properties();
|
||||
properties.setProperty("nacos.add.properties.scope", "config");
|
||||
|
||||
final NacosClientProperties nacosClientProperties = NacosClientProperties.PROTOTYPE.derive();
|
||||
nacosClientProperties.addProperties(properties);
|
||||
|
||||
String ret = NacosClientProperties.PROTOTYPE.getProperty("nacos.add.properties.scope");
|
||||
Assert.assertNull(ret);
|
||||
|
||||
ret = nacosClientProperties.getProperty("nacos.add.properties.scope");
|
||||
Assert.assertEquals("config", ret);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTestDerive() {
|
||||
Properties properties = new Properties();
|
||||
properties.setProperty("nacos.derive.properties.scope", "derive");
|
||||
|
||||
final NacosClientProperties nacosClientProperties = NacosClientProperties.PROTOTYPE.derive(properties);
|
||||
|
||||
final String value = nacosClientProperties.getProperty("nacos.derive.properties.scope");
|
||||
|
||||
Assert.assertEquals("derive", value);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testContainsKey() {
|
||||
NacosClientProperties.PROTOTYPE.setProperty("nacos.contains.key", "true");
|
||||
|
||||
boolean ret = NacosClientProperties.PROTOTYPE.containsKey("nacos.contains.key");
|
||||
Assert.assertTrue(ret);
|
||||
|
||||
ret = NacosClientProperties.PROTOTYPE.containsKey("nacos.contains.key.in.sys");
|
||||
Assert.assertFalse(ret);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testContainsKeyMultiLayers() {
|
||||
|
||||
NacosClientProperties.PROTOTYPE.setProperty("top.layer", "top");
|
||||
|
||||
final NacosClientProperties layerAEnv = NacosClientProperties.PROTOTYPE.derive();
|
||||
layerAEnv.setProperty("a.layer", "a");
|
||||
|
||||
final NacosClientProperties layerBEnv = layerAEnv.derive();
|
||||
layerBEnv.setProperty("b.layer", "b");
|
||||
|
||||
final NacosClientProperties layerCEnv = layerBEnv.derive();
|
||||
layerCEnv.setProperty("c.layer", "c");
|
||||
|
||||
boolean exist = layerCEnv.containsKey("c.layer");
|
||||
Assert.assertTrue(exist);
|
||||
|
||||
exist = layerCEnv.containsKey("b.layer");
|
||||
Assert.assertTrue(exist);
|
||||
|
||||
exist = layerCEnv.containsKey("a.layer");
|
||||
Assert.assertTrue(exist);
|
||||
|
||||
exist = layerCEnv.containsKey("top.layer");
|
||||
Assert.assertTrue(exist);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testContainsKeyWithScope() {
|
||||
NacosClientProperties.PROTOTYPE.setProperty("nacos.contains.global.scope", "global");
|
||||
final NacosClientProperties namingProperties = NacosClientProperties.PROTOTYPE.derive();
|
||||
namingProperties.setProperty("nacos.contains.naming.scope", "naming");
|
||||
|
||||
boolean ret = NacosClientProperties.PROTOTYPE.containsKey("nacos.contains.global.scope");
|
||||
Assert.assertTrue(ret);
|
||||
|
||||
ret = NacosClientProperties.PROTOTYPE.containsKey("nacos.contains.naming.scope");
|
||||
Assert.assertFalse(ret);
|
||||
|
||||
ret = namingProperties.containsKey("nacos.contains.naming.scope");
|
||||
Assert.assertTrue(ret);
|
||||
|
||||
ret = namingProperties.containsKey("nacos.contains.global.scope");
|
||||
Assert.assertTrue(ret);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAsProperties() {
|
||||
NacosClientProperties.PROTOTYPE.setProperty("nacos.as.properties", "true");
|
||||
final Properties properties = NacosClientProperties.PROTOTYPE.asProperties();
|
||||
Assert.assertNotNull(properties);
|
||||
Assert.assertEquals("true", properties.getProperty("nacos.as.properties"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAsPropertiesWithScope() {
|
||||
|
||||
NacosClientProperties.PROTOTYPE.setProperty("nacos.as.properties.global.scope", "global");
|
||||
NacosClientProperties.PROTOTYPE.setProperty("nacos.server.addr.scope", "global");
|
||||
|
||||
final NacosClientProperties configProperties = NacosClientProperties.PROTOTYPE.derive();
|
||||
configProperties.setProperty("nacos.server.addr.scope", "config");
|
||||
|
||||
final Properties properties = configProperties.asProperties();
|
||||
Assert.assertNotNull(properties);
|
||||
|
||||
String ret = properties.getProperty("nacos.as.properties.global.scope");
|
||||
Assert.assertEquals("global", ret);
|
||||
|
||||
ret = properties.getProperty("nacos.server.addr.scope");
|
||||
Assert.assertEquals("config", ret);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetPropertyWithScope() {
|
||||
|
||||
NacosClientProperties.PROTOTYPE.setProperty("nacos.global.scope", "global");
|
||||
|
||||
final NacosClientProperties configProperties = NacosClientProperties.PROTOTYPE.derive();
|
||||
configProperties.setProperty("nacos.config.scope", "config");
|
||||
|
||||
final NacosClientProperties namingProperties = NacosClientProperties.PROTOTYPE.derive();
|
||||
namingProperties.setProperty("nacos.naming.scope", "naming");
|
||||
|
||||
String ret = NacosClientProperties.PROTOTYPE.getProperty("nacos.global.scope");
|
||||
Assert.assertEquals("global", ret);
|
||||
|
||||
ret = NacosClientProperties.PROTOTYPE.getProperty("nacos.config.scope");
|
||||
Assert.assertNull(ret);
|
||||
|
||||
ret = NacosClientProperties.PROTOTYPE.getProperty("nacos.naming.scope");
|
||||
Assert.assertNull(ret);
|
||||
|
||||
ret = configProperties.getProperty("nacos.config.scope");
|
||||
Assert.assertEquals("config", ret);
|
||||
ret = configProperties.getProperty("nacos.global.scope");
|
||||
Assert.assertEquals("global", ret);
|
||||
ret = configProperties.getProperty("nacos.naming.scope");
|
||||
Assert.assertNull(ret);
|
||||
|
||||
ret = namingProperties.getProperty("nacos.naming.scope");
|
||||
Assert.assertEquals("naming", ret);
|
||||
ret = namingProperties.getProperty("nacos.global.scope");
|
||||
Assert.assertEquals("global", ret);
|
||||
ret = namingProperties.getProperty("nacos.config.scope");
|
||||
Assert.assertNull(ret);
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -1,50 +0,0 @@
|
||||
/*
|
||||
* Copyright 1999-2022 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.client.env;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.util.Properties;
|
||||
|
||||
public class NacosEnvironmentFactoryTest {
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void testCreateEnvironment() {
|
||||
final NacosEnvironment environment = NacosEnvironmentFactory.createEnvironment();
|
||||
Assert.assertNotNull(environment);
|
||||
Assert.assertTrue(Proxy.isProxyClass(environment.getClass()));
|
||||
environment.getProperty("test.exception");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNacosEnvInit() {
|
||||
final NacosEnvironment environment = NacosEnvironmentFactory.createEnvironment();
|
||||
final NacosEnvironmentFactory.NacosEnvironmentDelegate invocationHandler =
|
||||
(NacosEnvironmentFactory.NacosEnvironmentDelegate) Proxy.getInvocationHandler(
|
||||
environment);
|
||||
Properties properties = new Properties();
|
||||
properties.setProperty("init.nacos", "true");
|
||||
|
||||
invocationHandler.init(properties);
|
||||
|
||||
final String property = environment.getProperty("init.nacos");
|
||||
Assert.assertEquals("true", property);
|
||||
}
|
||||
|
||||
}
|
@ -1,174 +0,0 @@
|
||||
/*
|
||||
* Copyright 1999-2022 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.client.env;
|
||||
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Assert;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.mockito.MockedStatic;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.util.Properties;
|
||||
|
||||
public class NacosEnvsTest {
|
||||
|
||||
static MockedStatic<NacosEnvironmentFactory> mockedStatic;
|
||||
|
||||
@BeforeClass
|
||||
public static void before() {
|
||||
mockedStatic = Mockito.mockStatic(NacosEnvironmentFactory.class);
|
||||
mockedStatic.when(NacosEnvironmentFactory::createEnvironment).thenReturn(createProxy());
|
||||
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void teardown() {
|
||||
if (mockedStatic != null) {
|
||||
mockedStatic.close();
|
||||
}
|
||||
}
|
||||
|
||||
private static NacosEnvironment createProxy() {
|
||||
return (NacosEnvironment) Proxy.newProxyInstance(NacosEnvironmentFactory.class.getClassLoader(),
|
||||
new Class[] {NacosEnvironment.class}, new NacosEnvironmentFactory.NacosEnvironmentDelegate() {
|
||||
volatile NacosEnvironment environment;
|
||||
|
||||
@Override
|
||||
public void init(Properties properties) {
|
||||
environment = new SearchableEnvironment(properties);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
|
||||
if (environment == null) {
|
||||
throw new IllegalStateException(
|
||||
"Nacos environment doesn't init, please call NEnvs#init method then try it again.");
|
||||
}
|
||||
return method.invoke(environment, args);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetProperty() {
|
||||
|
||||
final Properties properties = new Properties();
|
||||
properties.setProperty("nacos.home", "/home/nacos");
|
||||
NacosEnvs.init(properties);
|
||||
final String value = NacosEnvs.getProperty("nacos.home");
|
||||
|
||||
Assert.assertEquals("/home/nacos", value);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetPropertyDefaultValue() {
|
||||
|
||||
final Properties properties = new Properties();
|
||||
NacosEnvs.init(properties);
|
||||
final String value = NacosEnvs.getProperty("nacos.home", "/home/default_value");
|
||||
|
||||
Assert.assertEquals("/home/default_value", value);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetBoolean() {
|
||||
final Properties properties = new Properties();
|
||||
properties.setProperty("use.cluster", "true");
|
||||
NacosEnvs.init(properties);
|
||||
|
||||
final Boolean value = NacosEnvs.getBoolean("use.cluster");
|
||||
Assert.assertTrue(value);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetBooleanDefaultValue() {
|
||||
final Properties properties = new Properties();
|
||||
NacosEnvs.init(properties);
|
||||
|
||||
final Boolean value = NacosEnvs.getBoolean("use.cluster", false);
|
||||
Assert.assertFalse(value);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetInteger() {
|
||||
final Properties properties = new Properties();
|
||||
properties.setProperty("max.timeout", "200");
|
||||
NacosEnvs.init(properties);
|
||||
|
||||
final Integer value = NacosEnvs.getInteger("max.timeout");
|
||||
|
||||
Assert.assertEquals(200, value.intValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetIntegerDefaultValue() {
|
||||
final Properties properties = new Properties();
|
||||
NacosEnvs.init(properties);
|
||||
|
||||
final Integer value = NacosEnvs.getInteger("max.timeout", 400);
|
||||
Assert.assertEquals(400, value.intValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetLong() {
|
||||
final Properties properties = new Properties();
|
||||
properties.setProperty("connection.timeout", "200");
|
||||
NacosEnvs.init(properties);
|
||||
|
||||
final Long value = NacosEnvs.getLong("connection.timeout");
|
||||
Assert.assertEquals(200L, value.longValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetLongDefault() {
|
||||
final Properties properties = new Properties();
|
||||
NacosEnvs.init(properties);
|
||||
final Long value = NacosEnvs.getLong("connection.timeout", 400L);
|
||||
Assert.assertEquals(400L, value.longValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetPropertyJvmFirst() {
|
||||
System.setProperty("nacos.envs.search", "jvm");
|
||||
System.setProperty("nacos.home", "/home/jvm_first");
|
||||
|
||||
Properties properties = new Properties();
|
||||
properties.setProperty("nacos.home", "/home/properties_first");
|
||||
|
||||
NacosEnvs.init(properties);
|
||||
final String value = NacosEnvs.getProperty("nacos.home");
|
||||
|
||||
Assert.assertEquals("/home/jvm_first", value);
|
||||
System.clearProperty("nacos.envs.search");
|
||||
System.clearProperty("nacos.home");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetPropertyDefaultSetting() {
|
||||
Properties properties = new Properties();
|
||||
|
||||
NacosEnvs.init(properties);
|
||||
final String value = NacosEnvs.getProperty("nacos.home.default.test");
|
||||
|
||||
Assert.assertEquals("/home/default_setting", value);
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -116,6 +116,27 @@ public class NacosNamingServiceTest {
|
||||
instances -> CollectionUtils.isEqualCollection(instanceList, instances)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBatchDeRegisterInstance() throws NacosException {
|
||||
Instance instance = new Instance();
|
||||
String serviceName = "service1";
|
||||
String ip = "1.1.1.1";
|
||||
int port = 10000;
|
||||
instance.setServiceName(serviceName);
|
||||
instance.setEphemeral(true);
|
||||
instance.setPort(port);
|
||||
instance.setIp(ip);
|
||||
List<Instance> instanceList = new ArrayList<>();
|
||||
instanceList.add(instance);
|
||||
//when
|
||||
try {
|
||||
client.batchDeregisterInstance(serviceName, Constants.DEFAULT_GROUP, instanceList);
|
||||
} catch (Exception e) {
|
||||
Assert.assertTrue(e instanceof NacosException);
|
||||
Assert.assertTrue(e.getMessage().contains("not found"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRegisterInstance2() throws NacosException {
|
||||
//given
|
||||
|
@ -109,6 +109,12 @@ public class AbstractNamingClientProxyTest {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void batchDeregisterService(String serviceName, String groupName, List<Instance> instances)
|
||||
throws NacosException {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deregisterService(String serviceName, String groupName, Instance instance) throws NacosException {
|
||||
|
||||
|
@ -48,6 +48,7 @@ import com.alibaba.nacos.common.notify.NotifyCenter;
|
||||
import com.alibaba.nacos.common.remote.ConnectionType;
|
||||
import com.alibaba.nacos.common.remote.client.Connection;
|
||||
import com.alibaba.nacos.common.remote.client.RpcClient;
|
||||
import com.alibaba.nacos.common.remote.client.RpcClientConfig;
|
||||
import com.alibaba.nacos.common.remote.client.ServerListFactory;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
@ -62,8 +63,10 @@ import org.mockito.junit.MockitoJUnitRunner;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
@ -77,7 +80,7 @@ import static org.mockito.Mockito.when;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class NamingGrpcClientProxyTest {
|
||||
|
||||
|
||||
@Rule
|
||||
public ExpectedException expectedException = ExpectedException.none();
|
||||
|
||||
@ -165,7 +168,7 @@ public class NamingGrpcClientProxyTest {
|
||||
public void testRegisterServiceThrowsException() throws NacosException {
|
||||
expectedException.expect(NacosException.class);
|
||||
expectedException.expectMessage("Request nacos server failed: ");
|
||||
|
||||
|
||||
when(this.rpcClient.request(Mockito.any())).thenReturn(null);
|
||||
|
||||
try {
|
||||
@ -284,8 +287,11 @@ public class NamingGrpcClientProxyTest {
|
||||
verify(this.rpcClient, times(1)).request(argThat(request -> {
|
||||
if (request instanceof SubscribeServiceRequest) {
|
||||
SubscribeServiceRequest request1 = (SubscribeServiceRequest) request;
|
||||
// not subscribe
|
||||
return !request1.isSubscribe();
|
||||
|
||||
// verify request fields
|
||||
return !request1.isSubscribe() && SERVICE_NAME.equals(request1.getServiceName()) && GROUP_NAME.equals(
|
||||
request1.getGroupName()) && CLUSTERS.equals(request1.getClusters()) && NAMESPACE_ID.equals(
|
||||
request1.getNamespace());
|
||||
}
|
||||
return false;
|
||||
}));
|
||||
@ -320,7 +326,42 @@ public class NamingGrpcClientProxyTest {
|
||||
@Test
|
||||
public void testServerListChanged() throws Exception {
|
||||
|
||||
RpcClient rpc = new RpcClient("testServerListHasChanged", factory) {
|
||||
RpcClient rpc = new RpcClient(new RpcClientConfig() {
|
||||
@Override
|
||||
public String name() {
|
||||
return "testServerListHasChanged";
|
||||
}
|
||||
|
||||
@Override
|
||||
public int retryTimes() {
|
||||
return 3;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long timeOutMills() {
|
||||
return 3000L;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long connectionKeepAlive() {
|
||||
return 5000L;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int healthCheckRetryTimes() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long healthCheckTimeOut() {
|
||||
return 3000L;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String> labels() {
|
||||
return new HashMap<>();
|
||||
}
|
||||
}, factory) {
|
||||
@Override
|
||||
public ConnectionType getConnectionType() {
|
||||
return ConnectionType.GRPC;
|
||||
|
@ -34,5 +34,7 @@ public interface HttpHeaderConsts {
|
||||
String CONNECTION = "Requester";
|
||||
String REQUEST_ID = "RequestId";
|
||||
String REQUEST_MODULE = "Request-Module";
|
||||
String APP_FILED = "app";
|
||||
String CLIENT_IP = "clientIp";
|
||||
|
||||
}
|
||||
|
@ -27,11 +27,11 @@ import java.util.concurrent.atomic.AtomicLong;
|
||||
*/
|
||||
@SuppressWarnings({"PMD.AbstractClassShouldStartWithAbstractNamingRule"})
|
||||
public abstract class Event implements Serializable {
|
||||
|
||||
|
||||
private static final long serialVersionUID = -3731383194964997493L;
|
||||
|
||||
|
||||
private static final AtomicLong SEQUENCE = new AtomicLong(0);
|
||||
|
||||
|
||||
private final long sequence = SEQUENCE.getAndIncrement();
|
||||
|
||||
/**
|
||||
@ -51,5 +51,15 @@ public abstract class Event implements Serializable {
|
||||
public String scope() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether is plugin event. If so, the event can be dropped when no publish and subscriber without any hint. Default
|
||||
* false
|
||||
*
|
||||
* @return {@code true} if is plugin event, otherwise {@code false}
|
||||
*/
|
||||
public boolean isPluginEvent() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -301,6 +301,9 @@ public class NotifyCenter {
|
||||
if (publisher != null) {
|
||||
return publisher.publish(event);
|
||||
}
|
||||
if (event.isPluginEvent()) {
|
||||
return true;
|
||||
}
|
||||
LOGGER.warn("There are no [{}] publishers for this event, please register", topic);
|
||||
return false;
|
||||
}
|
||||
|
@ -30,9 +30,9 @@ import java.util.List;
|
||||
public abstract class SmartSubscriber extends Subscriber {
|
||||
|
||||
/**
|
||||
* Returns which event type are smartsubscriber interested in.
|
||||
* Returns which event type are smart subscriber interested in.
|
||||
*
|
||||
* @return The interestd event types.
|
||||
* @return The interested event types.
|
||||
*/
|
||||
public abstract List<Class<? extends Event>> subscribeTypes();
|
||||
|
||||
|
@ -69,6 +69,6 @@ public abstract class Subscriber<T extends Event> {
|
||||
* @return Whether the event's scope matches current subscriber
|
||||
*/
|
||||
public boolean scopeMatches(T event) {
|
||||
return event.scope() == null;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -33,6 +33,7 @@ import com.alibaba.nacos.common.lifecycle.Closeable;
|
||||
import com.alibaba.nacos.common.remote.ConnectionType;
|
||||
import com.alibaba.nacos.common.remote.PayloadRegistry;
|
||||
import com.alibaba.nacos.common.utils.CollectionUtils;
|
||||
import com.alibaba.nacos.common.utils.InternetAddressUtil;
|
||||
import com.alibaba.nacos.common.utils.LoggerUtils;
|
||||
import com.alibaba.nacos.common.utils.NumberUtils;
|
||||
import com.alibaba.nacos.common.utils.StringUtils;
|
||||
@ -40,7 +41,7 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ArrayBlockingQueue;
|
||||
@ -79,23 +80,10 @@ public abstract class RpcClient implements Closeable {
|
||||
|
||||
protected volatile Connection currentConnection;
|
||||
|
||||
protected Map<String, String> labels = new HashMap<>();
|
||||
|
||||
private String name;
|
||||
|
||||
private String tenant;
|
||||
|
||||
private static final int RETRY_TIMES = 3;
|
||||
|
||||
private static final long DEFAULT_TIMEOUT_MILLS = 3000L;
|
||||
|
||||
protected ClientAbilities clientAbilities;
|
||||
|
||||
/**
|
||||
* default keep alive time 5s.
|
||||
*/
|
||||
private long keepAliveTime = 5000L;
|
||||
|
||||
private long lastActiveTimeStamp = System.currentTimeMillis();
|
||||
|
||||
/**
|
||||
@ -110,28 +98,34 @@ public abstract class RpcClient implements Closeable {
|
||||
|
||||
private static final Pattern EXCLUDE_PROTOCOL_PATTERN = Pattern.compile("(?<=\\w{1,5}://)(.*)");
|
||||
|
||||
protected RpcClientConfig rpcClientConfig;
|
||||
|
||||
static {
|
||||
PayloadRegistry.init();
|
||||
}
|
||||
|
||||
public RpcClient(String name) {
|
||||
this(name, null);
|
||||
public RpcClient(RpcClientConfig rpcClientConfig) {
|
||||
this(rpcClientConfig, null);
|
||||
}
|
||||
|
||||
public RpcClient(ServerListFactory serverListFactory) {
|
||||
this(null, serverListFactory);
|
||||
public RpcClient(RpcClientConfig rpcClientConfig, ServerListFactory serverListFactory) {
|
||||
this.rpcClientConfig = rpcClientConfig;
|
||||
this.serverListFactory = serverListFactory;
|
||||
init();
|
||||
}
|
||||
|
||||
public RpcClient(String name, ServerListFactory serverListFactory) {
|
||||
this.name = name;
|
||||
if (serverListFactory != null) {
|
||||
this.serverListFactory = serverListFactory;
|
||||
protected void init() {
|
||||
if (this.serverListFactory != null) {
|
||||
rpcClientStatus.compareAndSet(RpcClientStatus.WAIT_INIT, RpcClientStatus.INITIALIZED);
|
||||
LoggerUtils.printIfInfoEnabled(LOGGER, "RpcClient init in constructor, ServerListFactory = {}",
|
||||
serverListFactory.getClass().getName());
|
||||
}
|
||||
}
|
||||
|
||||
public Map<String, String> labels() {
|
||||
return Collections.unmodifiableMap(rpcClientConfig.labels());
|
||||
}
|
||||
|
||||
/**
|
||||
* init client abilities.
|
||||
*
|
||||
@ -154,35 +148,11 @@ public abstract class RpcClient implements Closeable {
|
||||
this.serverListFactory = serverListFactory;
|
||||
rpcClientStatus.compareAndSet(RpcClientStatus.WAIT_INIT, RpcClientStatus.INITIALIZED);
|
||||
|
||||
LoggerUtils.printIfInfoEnabled(LOGGER, "[{}] RpcClient init, ServerListFactory = {}", name,
|
||||
LoggerUtils.printIfInfoEnabled(LOGGER, "[{}] RpcClient init, ServerListFactory = {}", rpcClientConfig.name(),
|
||||
serverListFactory.getClass().getName());
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* init labels.
|
||||
*
|
||||
* @param labels labels
|
||||
*/
|
||||
public RpcClient labels(Map<String, String> labels) {
|
||||
this.labels.putAll(labels);
|
||||
LoggerUtils.printIfInfoEnabled(LOGGER, "[{}] RpcClient init label, labels = {}", name, this.labels);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* init keepalive time.
|
||||
*
|
||||
* @param keepAliveTime keepAliveTime
|
||||
* @param timeUnit timeUnit
|
||||
*/
|
||||
public RpcClient keepAlive(long keepAliveTime, TimeUnit timeUnit) {
|
||||
this.keepAliveTime = keepAliveTime * timeUnit.toMillis(keepAliveTime);
|
||||
LoggerUtils.printIfInfoEnabled(LOGGER, "[{}] RpcClient init keepalive time, keepAliveTimeMillis = {}", name,
|
||||
keepAliveTime);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify when client disconnected.
|
||||
*/
|
||||
@ -190,13 +160,13 @@ public abstract class RpcClient implements Closeable {
|
||||
if (connectionEventListeners.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
LoggerUtils.printIfInfoEnabled(LOGGER, "[{}] Notify disconnected event to listeners", name);
|
||||
LoggerUtils.printIfInfoEnabled(LOGGER, "[{}] Notify disconnected event to listeners", rpcClientConfig.name());
|
||||
for (ConnectionEventListener connectionEventListener : connectionEventListeners) {
|
||||
try {
|
||||
connectionEventListener.onDisConnect();
|
||||
} catch (Throwable throwable) {
|
||||
LoggerUtils.printIfErrorEnabled(LOGGER, "[{}] Notify disconnect listener error, listener = {}", name,
|
||||
connectionEventListener.getClass().getName());
|
||||
LoggerUtils.printIfErrorEnabled(LOGGER, "[{}] Notify disconnect listener error, listener = {}",
|
||||
rpcClientConfig.name(), connectionEventListener.getClass().getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -208,13 +178,13 @@ public abstract class RpcClient implements Closeable {
|
||||
if (connectionEventListeners.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
LoggerUtils.printIfInfoEnabled(LOGGER, "[{}] Notify connected event to listeners.", name);
|
||||
LoggerUtils.printIfInfoEnabled(LOGGER, "[{}] Notify connected event to listeners.", rpcClientConfig.name());
|
||||
for (ConnectionEventListener connectionEventListener : connectionEventListeners) {
|
||||
try {
|
||||
connectionEventListener.onConnected();
|
||||
} catch (Throwable throwable) {
|
||||
LoggerUtils.printIfErrorEnabled(LOGGER, "[{}] Notify connect listener error, listener = {}", name,
|
||||
connectionEventListener.getClass().getName());
|
||||
LoggerUtils.printIfErrorEnabled(LOGGER, "[{}] Notify connect listener error, listener = {}",
|
||||
rpcClientConfig.name(), connectionEventListener.getClass().getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -310,18 +280,18 @@ public abstract class RpcClient implements Closeable {
|
||||
break;
|
||||
}
|
||||
ReconnectContext reconnectContext = reconnectionSignal
|
||||
.poll(keepAliveTime, TimeUnit.MILLISECONDS);
|
||||
.poll(rpcClientConfig.connectionKeepAlive(), TimeUnit.MILLISECONDS);
|
||||
if (reconnectContext == null) {
|
||||
// check alive time.
|
||||
if (System.currentTimeMillis() - lastActiveTimeStamp >= keepAliveTime) {
|
||||
if (System.currentTimeMillis() - lastActiveTimeStamp >= rpcClientConfig.connectionKeepAlive()) {
|
||||
boolean isHealthy = healthCheck();
|
||||
if (!isHealthy) {
|
||||
if (currentConnection == null) {
|
||||
continue;
|
||||
}
|
||||
LoggerUtils.printIfInfoEnabled(LOGGER,
|
||||
"[{}] Server healthy check fail, currentConnection = {}", name,
|
||||
currentConnection.getConnectionId());
|
||||
"[{}] Server healthy check fail, currentConnection = {}",
|
||||
rpcClientConfig.name(), currentConnection.getConnectionId());
|
||||
|
||||
RpcClientStatus rpcClientStatus = RpcClient.this.rpcClientStatus.get();
|
||||
if (RpcClientStatus.SHUTDOWN.equals(rpcClientStatus)) {
|
||||
@ -359,8 +329,8 @@ public abstract class RpcClient implements Closeable {
|
||||
}
|
||||
if (!serverExist) {
|
||||
LoggerUtils.printIfInfoEnabled(LOGGER,
|
||||
"[{}] Recommend server is not in server list, ignore recommend server {}", name,
|
||||
reconnectContext.serverInfo.getAddress());
|
||||
"[{}] Recommend server is not in server list, ignore recommend server {}",
|
||||
rpcClientConfig.name(), reconnectContext.serverInfo.getAddress());
|
||||
|
||||
reconnectContext.serverInfo = null;
|
||||
|
||||
@ -373,31 +343,33 @@ public abstract class RpcClient implements Closeable {
|
||||
}
|
||||
});
|
||||
|
||||
// connect to server, try to connect to server sync RETRY_TIMES times, async starting if failed.
|
||||
// connect to server, try to connect to server sync retryTimes times, async starting if failed.
|
||||
Connection connectToServer = null;
|
||||
rpcClientStatus.set(RpcClientStatus.STARTING);
|
||||
|
||||
int startUpRetryTimes = RETRY_TIMES;
|
||||
int startUpRetryTimes = rpcClientConfig.retryTimes();
|
||||
while (startUpRetryTimes > 0 && connectToServer == null) {
|
||||
try {
|
||||
startUpRetryTimes--;
|
||||
ServerInfo serverInfo = nextRpcServer();
|
||||
|
||||
LoggerUtils.printIfInfoEnabled(LOGGER, "[{}] Try to connect to server on start up, server: {}", name,
|
||||
serverInfo);
|
||||
LoggerUtils.printIfInfoEnabled(LOGGER, "[{}] Try to connect to server on start up, server: {}",
|
||||
rpcClientConfig.name(), serverInfo);
|
||||
|
||||
connectToServer = connectToServer(serverInfo);
|
||||
} catch (Throwable e) {
|
||||
LoggerUtils.printIfWarnEnabled(LOGGER,
|
||||
"[{}] Fail to connect to server on start up, error message = {}, start up retry times left: {}",
|
||||
name, e.getMessage(), startUpRetryTimes, e);
|
||||
rpcClientConfig.name(), e.getMessage(), startUpRetryTimes, e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (connectToServer != null) {
|
||||
LoggerUtils.printIfInfoEnabled(LOGGER, "[{}] Success to connect to server [{}] on start up, connectionId = {}",
|
||||
name, connectToServer.serverInfo.getAddress(), connectToServer.getConnectionId());
|
||||
LoggerUtils
|
||||
.printIfInfoEnabled(LOGGER, "[{}] Success to connect to server [{}] on start up, connectionId = {}",
|
||||
rpcClientConfig.name(), connectToServer.serverInfo.getAddress(),
|
||||
connectToServer.getConnectionId());
|
||||
this.currentConnection = connectToServer;
|
||||
rpcClientStatus.set(RpcClientStatus.RUNNING);
|
||||
eventLinkedBlockingQueue.offer(new ConnectionEvent(ConnectionEvent.CONNECTED));
|
||||
@ -440,7 +412,7 @@ public abstract class RpcClient implements Closeable {
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LoggerUtils.printIfErrorEnabled(LOGGER, "[{}] Switch server error, {}", name, e);
|
||||
LoggerUtils.printIfErrorEnabled(LOGGER, "[{}] Switch server error, {}", rpcClientConfig.name(), e);
|
||||
}
|
||||
return new ConnectResetResponse();
|
||||
}
|
||||
@ -464,12 +436,17 @@ public abstract class RpcClient implements Closeable {
|
||||
if (this.currentConnection == null) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
Response response = this.currentConnection.request(healthCheckRequest, 3000L);
|
||||
// not only check server is ok, also check connection is register.
|
||||
return response != null && response.isSuccess();
|
||||
} catch (NacosException e) {
|
||||
// ignore
|
||||
int reTryTimes = rpcClientConfig.healthCheckRetryTimes();
|
||||
while (reTryTimes >= 0) {
|
||||
reTryTimes--;
|
||||
try {
|
||||
Response response = this.currentConnection
|
||||
.request(healthCheckRequest, rpcClientConfig.healthCheckTimeOut());
|
||||
// not only check server is ok, also check connection is register.
|
||||
return response != null && response.isSuccess();
|
||||
} catch (NacosException e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@ -495,14 +472,14 @@ public abstract class RpcClient implements Closeable {
|
||||
|
||||
AtomicReference<ServerInfo> recommendServer = new AtomicReference<>(recommendServerInfo);
|
||||
if (onRequestFail && healthCheck()) {
|
||||
LoggerUtils.printIfInfoEnabled(LOGGER, "[{}] Server check success, currentServer is {} ", name,
|
||||
currentConnection.serverInfo.getAddress());
|
||||
LoggerUtils.printIfInfoEnabled(LOGGER, "[{}] Server check success, currentServer is {} ",
|
||||
rpcClientConfig.name(), currentConnection.serverInfo.getAddress());
|
||||
rpcClientStatus.set(RpcClientStatus.RUNNING);
|
||||
return;
|
||||
}
|
||||
|
||||
LoggerUtils.printIfInfoEnabled(LOGGER, "[{}] Try to reconnect to a new server, server is {}", name,
|
||||
recommendServerInfo == null ? " not appointed, will choose a random server."
|
||||
LoggerUtils.printIfInfoEnabled(LOGGER, "[{}] Try to reconnect to a new server, server is {}",
|
||||
rpcClientConfig.name(), recommendServerInfo == null ? " not appointed, will choose a random server."
|
||||
: (recommendServerInfo.getAddress() + ", will try it once."));
|
||||
|
||||
// loop until start client success.
|
||||
@ -520,13 +497,16 @@ public abstract class RpcClient implements Closeable {
|
||||
// 2.create a new channel to new server
|
||||
Connection connectionNew = connectToServer(serverInfo);
|
||||
if (connectionNew != null) {
|
||||
LoggerUtils.printIfInfoEnabled(LOGGER, "[{}] Success to connect a server [{}], connectionId = {}",
|
||||
name, serverInfo.getAddress(), connectionNew.getConnectionId());
|
||||
LoggerUtils
|
||||
.printIfInfoEnabled(LOGGER, "[{}] Success to connect a server [{}], connectionId = {}",
|
||||
rpcClientConfig.name(), serverInfo.getAddress(),
|
||||
connectionNew.getConnectionId());
|
||||
// successfully create a new connect.
|
||||
if (currentConnection != null) {
|
||||
LoggerUtils.printIfInfoEnabled(LOGGER,
|
||||
"[{}] Abandon prev connection, server is {}, connectionId is {}", name,
|
||||
currentConnection.serverInfo.getAddress(), currentConnection.getConnectionId());
|
||||
"[{}] Abandon prev connection, server is {}, connectionId is {}",
|
||||
rpcClientConfig.name(), currentConnection.serverInfo.getAddress(),
|
||||
currentConnection.getConnectionId());
|
||||
// set current connection to enable connection event.
|
||||
currentConnection.setAbandon(true);
|
||||
closeConnection(currentConnection);
|
||||
@ -558,8 +538,9 @@ public abstract class RpcClient implements Closeable {
|
||||
if (reConnectTimes > 0
|
||||
&& reConnectTimes % RpcClient.this.serverListFactory.getServerList().size() == 0) {
|
||||
LoggerUtils.printIfInfoEnabled(LOGGER,
|
||||
"[{}] Fail to connect server, after trying {} times, last try server is {}, error = {}", name,
|
||||
reConnectTimes, serverInfo, lastException == null ? "unknown" : lastException);
|
||||
"[{}] Fail to connect server, after trying {} times, last try server is {}, error = {}",
|
||||
rpcClientConfig.name(), reConnectTimes, serverInfo,
|
||||
lastException == null ? "unknown" : lastException);
|
||||
if (Integer.MAX_VALUE == retryTurns) {
|
||||
retryTurns = 50;
|
||||
} else {
|
||||
@ -583,11 +564,14 @@ public abstract class RpcClient implements Closeable {
|
||||
}
|
||||
|
||||
if (isShutdown()) {
|
||||
LoggerUtils.printIfInfoEnabled(LOGGER, "[{}] Client is shutdown, stop reconnect to server", name);
|
||||
LoggerUtils.printIfInfoEnabled(LOGGER, "[{}] Client is shutdown, stop reconnect to server",
|
||||
rpcClientConfig.name());
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
LoggerUtils.printIfWarnEnabled(LOGGER, "[{}] Fail to reconnect to server, error is {}", name, e);
|
||||
LoggerUtils
|
||||
.printIfWarnEnabled(LOGGER, "[{}] Fail to reconnect to server, error is {}", rpcClientConfig.name(),
|
||||
e);
|
||||
}
|
||||
}
|
||||
|
||||
@ -632,7 +616,7 @@ public abstract class RpcClient implements Closeable {
|
||||
* @return response from server.
|
||||
*/
|
||||
public Response request(Request request) throws NacosException {
|
||||
return request(request, DEFAULT_TIMEOUT_MILLS);
|
||||
return request(request, rpcClientConfig.timeOutMills());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -646,7 +630,7 @@ public abstract class RpcClient implements Closeable {
|
||||
Response response;
|
||||
Exception exceptionThrow = null;
|
||||
long start = System.currentTimeMillis();
|
||||
while (retryTimes < RETRY_TIMES && System.currentTimeMillis() < timeoutMills + start) {
|
||||
while (retryTimes < rpcClientConfig.retryTimes() && System.currentTimeMillis() < timeoutMills + start) {
|
||||
boolean waitReconnect = false;
|
||||
try {
|
||||
if (this.currentConnection == null || !isRunning()) {
|
||||
@ -687,8 +671,9 @@ public abstract class RpcClient implements Closeable {
|
||||
}
|
||||
}
|
||||
|
||||
LoggerUtils.printIfErrorEnabled(LOGGER, "Send request fail, request = {}, retryTimes = {}, errorMessage = {}",
|
||||
request, retryTimes, e.getMessage());
|
||||
LoggerUtils.printIfErrorEnabled(LOGGER,
|
||||
"Send request fail, request = {}, retryTimes = {}, errorMessage = {}", request, retryTimes,
|
||||
e.getMessage());
|
||||
|
||||
exceptionThrow = e;
|
||||
|
||||
@ -719,7 +704,8 @@ public abstract class RpcClient implements Closeable {
|
||||
|
||||
Exception exceptionToThrow = null;
|
||||
long start = System.currentTimeMillis();
|
||||
while (retryTimes < RETRY_TIMES && System.currentTimeMillis() < start + callback.getTimeout()) {
|
||||
while (retryTimes < rpcClientConfig.retryTimes() && System.currentTimeMillis() < start + callback
|
||||
.getTimeout()) {
|
||||
boolean waitReconnect = false;
|
||||
try {
|
||||
if (this.currentConnection == null || !isRunning()) {
|
||||
@ -737,9 +723,9 @@ public abstract class RpcClient implements Closeable {
|
||||
// Do nothing.
|
||||
}
|
||||
}
|
||||
LoggerUtils
|
||||
.printIfErrorEnabled(LOGGER, "[{}] Send request fail, request = {}, retryTimes = {}, errorMessage = {}",
|
||||
name, request, retryTimes, e.getMessage());
|
||||
LoggerUtils.printIfErrorEnabled(LOGGER,
|
||||
"[{}] Send request fail, request = {}, retryTimes = {}, errorMessage = {}",
|
||||
rpcClientConfig.name(), request, retryTimes, e.getMessage());
|
||||
exceptionToThrow = e;
|
||||
|
||||
}
|
||||
@ -768,7 +754,8 @@ public abstract class RpcClient implements Closeable {
|
||||
int retryTimes = 0;
|
||||
long start = System.currentTimeMillis();
|
||||
Exception exceptionToThrow = null;
|
||||
while (retryTimes < RETRY_TIMES && System.currentTimeMillis() < start + DEFAULT_TIMEOUT_MILLS) {
|
||||
while (retryTimes < rpcClientConfig.retryTimes() && System.currentTimeMillis() < start + rpcClientConfig
|
||||
.timeOutMills()) {
|
||||
boolean waitReconnect = false;
|
||||
try {
|
||||
if (this.currentConnection == null || !isRunning()) {
|
||||
@ -785,9 +772,9 @@ public abstract class RpcClient implements Closeable {
|
||||
// Do nothing.
|
||||
}
|
||||
}
|
||||
LoggerUtils
|
||||
.printIfErrorEnabled(LOGGER, "[{}] Send request fail, request = {}, retryTimes = {}, errorMessage = {}",
|
||||
name, request, retryTimes, e.getMessage());
|
||||
LoggerUtils.printIfErrorEnabled(LOGGER,
|
||||
"[{}] Send request fail, request = {}, retryTimes = {}, errorMessage = {}",
|
||||
rpcClientConfig.name(), request, retryTimes, e.getMessage());
|
||||
exceptionToThrow = e;
|
||||
|
||||
}
|
||||
@ -824,21 +811,21 @@ public abstract class RpcClient implements Closeable {
|
||||
*/
|
||||
protected Response handleServerRequest(final Request request) {
|
||||
|
||||
LoggerUtils.printIfInfoEnabled(LOGGER, "[{}] Receive server push request, request = {}, requestId = {}", name,
|
||||
request.getClass().getSimpleName(), request.getRequestId());
|
||||
LoggerUtils.printIfInfoEnabled(LOGGER, "[{}] Receive server push request, request = {}, requestId = {}",
|
||||
rpcClientConfig.name(), request.getClass().getSimpleName(), request.getRequestId());
|
||||
lastActiveTimeStamp = System.currentTimeMillis();
|
||||
for (ServerRequestHandler serverRequestHandler : serverRequestHandlers) {
|
||||
try {
|
||||
Response response = serverRequestHandler.requestReply(request);
|
||||
|
||||
if (response != null) {
|
||||
LoggerUtils.printIfInfoEnabled(LOGGER, "[{}] Ack server push request, request = {}, requestId = {}", name,
|
||||
request.getClass().getSimpleName(), request.getRequestId());
|
||||
LoggerUtils.printIfInfoEnabled(LOGGER, "[{}] Ack server push request, request = {}, requestId = {}",
|
||||
rpcClientConfig.name(), request.getClass().getSimpleName(), request.getRequestId());
|
||||
return response;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LoggerUtils.printIfInfoEnabled(LOGGER, "[{}] HandleServerRequest:{}, errorMessage = {}", name,
|
||||
serverRequestHandler.getClass().getName(), e.getMessage());
|
||||
LoggerUtils.printIfInfoEnabled(LOGGER, "[{}] HandleServerRequest:{}, errorMessage = {}",
|
||||
rpcClientConfig.name(), serverRequestHandler.getClass().getName(), e.getMessage());
|
||||
}
|
||||
|
||||
}
|
||||
@ -852,8 +839,8 @@ public abstract class RpcClient implements Closeable {
|
||||
*/
|
||||
public synchronized void registerConnectionListener(ConnectionEventListener connectionEventListener) {
|
||||
|
||||
LoggerUtils.printIfInfoEnabled(LOGGER, "[{}] Registry connection listener to current client:{}", name,
|
||||
connectionEventListener.getClass().getName());
|
||||
LoggerUtils.printIfInfoEnabled(LOGGER, "[{}] Registry connection listener to current client:{}",
|
||||
rpcClientConfig.name(), connectionEventListener.getClass().getName());
|
||||
this.connectionEventListeners.add(connectionEventListener);
|
||||
}
|
||||
|
||||
@ -863,7 +850,7 @@ public abstract class RpcClient implements Closeable {
|
||||
* @param serverRequestHandler serverRequestHandler
|
||||
*/
|
||||
public synchronized void registerServerRequestHandler(ServerRequestHandler serverRequestHandler) {
|
||||
LoggerUtils.printIfInfoEnabled(LOGGER, "[{}] Register server push request handler:{}", name,
|
||||
LoggerUtils.printIfInfoEnabled(LOGGER, "[{}] Register server push request handler:{}", rpcClientConfig.name(),
|
||||
serverRequestHandler.getClass().getName());
|
||||
|
||||
this.serverRequestHandlers.add(serverRequestHandler);
|
||||
@ -875,16 +862,7 @@ public abstract class RpcClient implements Closeable {
|
||||
* @return property value of name
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter method for property <tt>name</tt>.
|
||||
*
|
||||
* @param name value to be assigned to property name
|
||||
*/
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
return rpcClientConfig.name();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -918,8 +896,7 @@ public abstract class RpcClient implements Closeable {
|
||||
if (matcher.find()) {
|
||||
serverAddress = matcher.group(1);
|
||||
}
|
||||
|
||||
String[] ipPortTuple = serverAddress.split(Constants.COLON, 2);
|
||||
String[] ipPortTuple = InternetAddressUtil.splitIPPortStr(serverAddress);
|
||||
int defaultPort = Integer.parseInt(System.getProperty("nacos.server.port", "8848"));
|
||||
String serverPort = CollectionUtils.getOrDefault(ipPortTuple, 1, Integer.toString(defaultPort));
|
||||
|
||||
@ -1019,7 +996,7 @@ public abstract class RpcClient implements Closeable {
|
||||
* @return property value of labels
|
||||
*/
|
||||
public Map<String, String> getLabels() {
|
||||
return labels;
|
||||
return rpcClientConfig.labels();
|
||||
}
|
||||
|
||||
class ReconnectContext {
|
||||
|
@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright 1999-2020 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.common.remote.client;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* RpcClientConfig.
|
||||
*
|
||||
* @author karsonto
|
||||
*/
|
||||
public interface RpcClientConfig {
|
||||
|
||||
/**
|
||||
* get name.
|
||||
*
|
||||
* @return name.
|
||||
*/
|
||||
String name();
|
||||
|
||||
/**
|
||||
* get request retry times.
|
||||
*
|
||||
* @return retryTimes.
|
||||
*/
|
||||
int retryTimes();
|
||||
|
||||
/**
|
||||
* get time out mills.
|
||||
*
|
||||
* @return timeOutMills.
|
||||
*/
|
||||
long timeOutMills();
|
||||
|
||||
/**
|
||||
* get connection keep alive time.
|
||||
*
|
||||
* @return connectionKeepAlive.
|
||||
*/
|
||||
long connectionKeepAlive();
|
||||
|
||||
/**
|
||||
* get health check retry times.
|
||||
*
|
||||
* @return healthCheckRetryTimes.
|
||||
*/
|
||||
int healthCheckRetryTimes();
|
||||
|
||||
/**
|
||||
* get health check time out.
|
||||
*
|
||||
* @return healthCheckTimeOut.
|
||||
*/
|
||||
long healthCheckTimeOut();
|
||||
|
||||
/**
|
||||
* get map of labels.
|
||||
*
|
||||
* @return labels.
|
||||
*/
|
||||
Map<String, String> labels();
|
||||
|
||||
}
|
@ -18,7 +18,6 @@ package com.alibaba.nacos.common.remote.client;
|
||||
|
||||
import com.alibaba.nacos.api.exception.NacosException;
|
||||
import com.alibaba.nacos.common.remote.ConnectionType;
|
||||
import com.alibaba.nacos.common.remote.client.grpc.GrpcClient;
|
||||
import com.alibaba.nacos.common.remote.client.grpc.GrpcClusterClient;
|
||||
import com.alibaba.nacos.common.remote.client.grpc.GrpcSdkClient;
|
||||
import org.slf4j.Logger;
|
||||
@ -94,11 +93,7 @@ public class RpcClientFactory {
|
||||
return CLIENT_MAP.computeIfAbsent(clientName, clientNameInner -> {
|
||||
LOGGER.info("[RpcClientFactory] create a new rpc client of " + clientName);
|
||||
try {
|
||||
GrpcClient client = new GrpcSdkClient(clientNameInner);
|
||||
client.setThreadPoolCoreSize(threadPoolCoreSize);
|
||||
client.setThreadPoolMaxSize(threadPoolMaxSize);
|
||||
client.labels(labels);
|
||||
return client;
|
||||
return new GrpcSdkClient(clientNameInner, threadPoolCoreSize, threadPoolMaxSize, labels);
|
||||
} catch (Throwable throwable) {
|
||||
LOGGER.error("Error to init GrpcSdkClient for client name :" + clientName, throwable);
|
||||
throw throwable;
|
||||
@ -134,13 +129,9 @@ public class RpcClientFactory {
|
||||
throw new UnsupportedOperationException("unsupported connection type :" + connectionType.getType());
|
||||
}
|
||||
|
||||
return CLIENT_MAP.computeIfAbsent(clientName, clientNameInner -> {
|
||||
GrpcClient client = new GrpcClusterClient(clientNameInner);
|
||||
client.setThreadPoolCoreSize(threadPoolCoreSize);
|
||||
client.setThreadPoolMaxSize(threadPoolMaxSize);
|
||||
client.labels(labels);
|
||||
return client;
|
||||
});
|
||||
return CLIENT_MAP.computeIfAbsent(clientName,
|
||||
clientNameInner -> new GrpcClusterClient(clientNameInner, threadPoolCoreSize, threadPoolMaxSize,
|
||||
labels));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,385 @@
|
||||
/*
|
||||
* Copyright 1999-2020 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.common.remote.client.grpc;
|
||||
|
||||
import com.alibaba.nacos.common.utils.ThreadUtils;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* Default grpc client config.
|
||||
*
|
||||
* @author karsonto
|
||||
*/
|
||||
public class DefaultGrpcClientConfig implements GrpcClientConfig {
|
||||
|
||||
private String name;
|
||||
|
||||
private int retryTimes;
|
||||
|
||||
private long timeOutMills;
|
||||
|
||||
private long connectionKeepAlive;
|
||||
|
||||
private long threadPoolKeepAlive;
|
||||
|
||||
private int threadPoolCoreSize;
|
||||
|
||||
private int threadPoolMaxSize;
|
||||
|
||||
private long serverCheckTimeOut;
|
||||
|
||||
private int threadPoolQueueSize;
|
||||
|
||||
private int maxInboundMessageSize;
|
||||
|
||||
private int channelKeepAlive;
|
||||
|
||||
private int healthCheckRetryTimes;
|
||||
|
||||
private long healthCheckTimeOut;
|
||||
|
||||
private Map<String, String> labels;
|
||||
|
||||
/**
|
||||
* constructor.
|
||||
*
|
||||
* @param builder builder of DefaultGrpcClientConfig builder.
|
||||
*/
|
||||
private DefaultGrpcClientConfig(Builder builder) {
|
||||
this.name = builder.name;
|
||||
this.retryTimes = loadIntegerConfig(GrpcConstants.GRPC_RETRY_TIMES, builder.retryTimes);
|
||||
this.timeOutMills = loadLongConfig(GrpcConstants.GRPC_TIMEOUT_MILLS, builder.timeOutMills);
|
||||
this.connectionKeepAlive = loadLongConfig(GrpcConstants.GRPC_CONNECT_KEEP_ALIVE_TIME,
|
||||
builder.connectionKeepAlive);
|
||||
this.threadPoolKeepAlive = loadLongConfig(GrpcConstants.GRPC_THREADPOOL_KEEPALIVETIME,
|
||||
builder.threadPoolKeepAlive);
|
||||
this.threadPoolCoreSize = loadIntegerConfig(GrpcConstants.GRPC_THREADPOOL_CORE_SIZE,
|
||||
builder.threadPoolCoreSize);
|
||||
this.threadPoolMaxSize = loadIntegerConfig(GrpcConstants.GRPC_THREADPOOL_MAX_SIZE, builder.threadPoolMaxSize);
|
||||
this.serverCheckTimeOut = loadLongConfig(GrpcConstants.GRPC_SERVER_CHECK_TIMEOUT, builder.serverCheckTimeOut);
|
||||
this.threadPoolQueueSize = loadIntegerConfig(GrpcConstants.GRPC_QUEUESIZE, builder.threadPoolQueueSize);
|
||||
this.maxInboundMessageSize = loadIntegerConfig(GrpcConstants.GRPC_MAX_INBOUND_MESSAGE_SIZE,
|
||||
builder.maxInboundMessageSize);
|
||||
this.channelKeepAlive = loadIntegerConfig(GrpcConstants.GRPC_CHANNEL_KEEP_ALIVE_TIME, builder.channelKeepAlive);
|
||||
this.healthCheckRetryTimes = loadIntegerConfig(GrpcConstants.GRPC_HEALTHCHECK_RETRY_TIMES,
|
||||
builder.healthCheckRetryTimes);
|
||||
this.healthCheckTimeOut = loadLongConfig(GrpcConstants.GRPC_HEALTHCHECK_TIMEOUT, builder.healthCheckTimeOut);
|
||||
this.labels = builder.labels;
|
||||
}
|
||||
|
||||
private int loadIntegerConfig(String key, int builderValue) {
|
||||
return Integer.getInteger(key, builderValue);
|
||||
}
|
||||
|
||||
private long loadLongConfig(String key, long builderValue) {
|
||||
return Long.getLong(key, builderValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String name() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int retryTimes() {
|
||||
return retryTimes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long timeOutMills() {
|
||||
return timeOutMills;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long connectionKeepAlive() {
|
||||
return connectionKeepAlive;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int threadPoolCoreSize() {
|
||||
return threadPoolCoreSize;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int threadPoolMaxSize() {
|
||||
return threadPoolMaxSize;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long threadPoolKeepAlive() {
|
||||
return threadPoolKeepAlive;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long serverCheckTimeOut() {
|
||||
return serverCheckTimeOut;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int threadPoolQueueSize() {
|
||||
return threadPoolQueueSize;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int maxInboundMessageSize() {
|
||||
return maxInboundMessageSize;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int channelKeepAlive() {
|
||||
return channelKeepAlive;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int healthCheckRetryTimes() {
|
||||
return healthCheckRetryTimes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long healthCheckTimeOut() {
|
||||
return healthCheckTimeOut;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String> labels() {
|
||||
return this.labels;
|
||||
}
|
||||
|
||||
public static Builder newBuilder() {
|
||||
return new Builder();
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
|
||||
private String name;
|
||||
|
||||
private int retryTimes = 3;
|
||||
|
||||
private long timeOutMills = 3000L;
|
||||
|
||||
private long connectionKeepAlive = 5000L;
|
||||
|
||||
private long threadPoolKeepAlive = 10000L;
|
||||
|
||||
private int threadPoolCoreSize = ThreadUtils.getSuitableThreadCount(2);
|
||||
|
||||
private int threadPoolMaxSize = ThreadUtils.getSuitableThreadCount(8);
|
||||
|
||||
private long serverCheckTimeOut = 3000L;
|
||||
|
||||
private int threadPoolQueueSize = 10000;
|
||||
|
||||
private int maxInboundMessageSize = 10 * 1024 * 1024;
|
||||
|
||||
private int channelKeepAlive = 6 * 60 * 1000;
|
||||
|
||||
private int healthCheckRetryTimes = 3;
|
||||
|
||||
private long healthCheckTimeOut = 3000L;
|
||||
|
||||
private Map<String, String> labels = new HashMap<>();
|
||||
|
||||
private Builder() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Set config from properties.
|
||||
*
|
||||
* @param properties properties
|
||||
* @return Builder
|
||||
*/
|
||||
public Builder fromProperties(Properties properties) {
|
||||
if (properties.contains(GrpcConstants.GRPC_NAME)) {
|
||||
this.name = properties.getProperty(GrpcConstants.GRPC_NAME);
|
||||
}
|
||||
if (properties.contains(GrpcConstants.GRPC_RETRY_TIMES)) {
|
||||
this.retryTimes = Integer.parseInt(properties.getProperty(GrpcConstants.GRPC_RETRY_TIMES));
|
||||
}
|
||||
if (properties.contains(GrpcConstants.GRPC_TIMEOUT_MILLS)) {
|
||||
this.timeOutMills = Long.parseLong(properties.getProperty(GrpcConstants.GRPC_TIMEOUT_MILLS));
|
||||
}
|
||||
if (properties.contains(GrpcConstants.GRPC_CONNECT_KEEP_ALIVE_TIME)) {
|
||||
this.connectionKeepAlive = Long
|
||||
.parseLong(properties.getProperty(GrpcConstants.GRPC_CONNECT_KEEP_ALIVE_TIME));
|
||||
}
|
||||
if (properties.contains(GrpcConstants.GRPC_THREADPOOL_KEEPALIVETIME)) {
|
||||
this.threadPoolKeepAlive = Long
|
||||
.parseLong(properties.getProperty(GrpcConstants.GRPC_THREADPOOL_KEEPALIVETIME));
|
||||
}
|
||||
if (properties.contains(GrpcConstants.GRPC_THREADPOOL_CORE_SIZE)) {
|
||||
this.threadPoolCoreSize = Integer
|
||||
.parseInt(properties.getProperty(GrpcConstants.GRPC_THREADPOOL_CORE_SIZE));
|
||||
}
|
||||
if (properties.contains(GrpcConstants.GRPC_THREADPOOL_MAX_SIZE)) {
|
||||
this.threadPoolMaxSize = Integer
|
||||
.parseInt(properties.getProperty(GrpcConstants.GRPC_THREADPOOL_MAX_SIZE));
|
||||
}
|
||||
if (properties.contains(GrpcConstants.GRPC_SERVER_CHECK_TIMEOUT)) {
|
||||
this.serverCheckTimeOut = Long
|
||||
.parseLong(properties.getProperty(GrpcConstants.GRPC_SERVER_CHECK_TIMEOUT));
|
||||
}
|
||||
if (properties.contains(GrpcConstants.GRPC_QUEUESIZE)) {
|
||||
this.threadPoolQueueSize = Integer.parseInt(properties.getProperty(GrpcConstants.GRPC_QUEUESIZE));
|
||||
}
|
||||
if (properties.contains(GrpcConstants.GRPC_MAX_INBOUND_MESSAGE_SIZE)) {
|
||||
this.maxInboundMessageSize = Integer
|
||||
.parseInt(properties.getProperty(GrpcConstants.GRPC_MAX_INBOUND_MESSAGE_SIZE));
|
||||
}
|
||||
if (properties.contains(GrpcConstants.GRPC_CHANNEL_KEEP_ALIVE_TIME)) {
|
||||
this.channelKeepAlive = Integer
|
||||
.parseInt(properties.getProperty(GrpcConstants.GRPC_CHANNEL_KEEP_ALIVE_TIME));
|
||||
}
|
||||
if (properties.contains(GrpcConstants.GRPC_HEALTHCHECK_RETRY_TIMES)) {
|
||||
this.healthCheckRetryTimes = Integer
|
||||
.parseInt(properties.getProperty(GrpcConstants.GRPC_HEALTHCHECK_RETRY_TIMES));
|
||||
}
|
||||
if (properties.contains(GrpcConstants.GRPC_HEALTHCHECK_TIMEOUT)) {
|
||||
this.healthCheckTimeOut = Long
|
||||
.parseLong(properties.getProperty(GrpcConstants.GRPC_HEALTHCHECK_TIMEOUT));
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* set client name.
|
||||
*/
|
||||
public Builder setName(String name) {
|
||||
this.name = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* set retryTimes.
|
||||
*/
|
||||
public Builder setRetryTimes(int retryTimes) {
|
||||
this.retryTimes = retryTimes;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* set timeOutMills.
|
||||
*/
|
||||
public Builder setTimeOutMills(long timeOutMills) {
|
||||
this.timeOutMills = timeOutMills;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* set connectionKeepAlive.
|
||||
*/
|
||||
public Builder setConnectionKeepAlive(long connectionKeepAlive) {
|
||||
this.connectionKeepAlive = connectionKeepAlive;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* set threadPoolKeepAlive.
|
||||
*/
|
||||
public Builder setThreadPoolKeepAlive(Long threadPoolKeepAlive) {
|
||||
this.threadPoolKeepAlive = threadPoolKeepAlive;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* set threadPoolCoreSize.
|
||||
*/
|
||||
public Builder setThreadPoolCoreSize(Integer threadPoolCoreSize) {
|
||||
if (!Objects.isNull(threadPoolCoreSize)) {
|
||||
this.threadPoolCoreSize = threadPoolCoreSize;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* set threadPoolMaxSize.
|
||||
*/
|
||||
public Builder setThreadPoolMaxSize(Integer threadPoolMaxSize) {
|
||||
if (!Objects.isNull(threadPoolMaxSize)) {
|
||||
this.threadPoolMaxSize = threadPoolMaxSize;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* set serverCheckTimeOut.
|
||||
*/
|
||||
public Builder setServerCheckTimeOut(Long serverCheckTimeOut) {
|
||||
this.serverCheckTimeOut = serverCheckTimeOut;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* set threadPoolQueueSize.
|
||||
*/
|
||||
public Builder setThreadPoolQueueSize(int threadPoolQueueSize) {
|
||||
this.threadPoolQueueSize = threadPoolQueueSize;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* set maxInboundMessageSize.
|
||||
*/
|
||||
public Builder setMaxInboundMessageSize(int maxInboundMessageSize) {
|
||||
this.maxInboundMessageSize = maxInboundMessageSize;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* set channelKeepAlive.
|
||||
*/
|
||||
public Builder setChannelKeepAlive(int channelKeepAlive) {
|
||||
this.channelKeepAlive = channelKeepAlive;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* set healthCheckRetryTimes.
|
||||
*/
|
||||
public Builder setHealthCheckRetryTimes(int healthCheckRetryTimes) {
|
||||
this.healthCheckRetryTimes = healthCheckRetryTimes;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* set healthCheckTimeOut.
|
||||
*/
|
||||
public Builder setHealthCheckTimeOut(long healthCheckTimeOut) {
|
||||
this.healthCheckTimeOut = healthCheckTimeOut;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* set labels.
|
||||
*/
|
||||
public Builder setLabels(Map<String, String> labels) {
|
||||
this.labels.putAll(labels);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* build GrpcClientConfig.
|
||||
*/
|
||||
public GrpcClientConfig build() {
|
||||
return new DefaultGrpcClientConfig(this);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -30,9 +30,9 @@ import com.alibaba.nacos.common.remote.ConnectionType;
|
||||
import com.alibaba.nacos.common.remote.client.Connection;
|
||||
import com.alibaba.nacos.common.remote.client.RpcClient;
|
||||
import com.alibaba.nacos.common.remote.client.RpcClientStatus;
|
||||
import com.alibaba.nacos.common.remote.client.ServerListFactory;
|
||||
import com.alibaba.nacos.common.utils.LoggerUtils;
|
||||
import com.alibaba.nacos.common.utils.ThreadFactoryBuilder;
|
||||
import com.alibaba.nacos.common.utils.ThreadUtils;
|
||||
import com.alibaba.nacos.common.utils.VersionUtils;
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
import io.grpc.CompressorRegistry;
|
||||
@ -43,6 +43,8 @@ import io.grpc.stub.StreamObserver;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
@ -56,19 +58,11 @@ import java.util.concurrent.TimeUnit;
|
||||
@SuppressWarnings("PMD.AbstractClassShouldStartWithAbstractNamingRule")
|
||||
public abstract class GrpcClient extends RpcClient {
|
||||
|
||||
static final Logger LOGGER = LoggerFactory.getLogger(GrpcClient.class);
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(GrpcClient.class);
|
||||
|
||||
protected static final String NACOS_SERVER_GRPC_PORT_OFFSET_KEY = "nacos.server.grpc.port.offset";
|
||||
private final GrpcClientConfig clientConfig;
|
||||
|
||||
private ThreadPoolExecutor grpcExecutor = null;
|
||||
|
||||
private Integer threadPoolCoreSize;
|
||||
|
||||
private Integer threadPoolMaxSize;
|
||||
|
||||
private static final long DEFAULT_MAX_INBOUND_MESSAGE_SIZE = 10 * 1024 * 1024L;
|
||||
|
||||
private static final long DEFAULT_KEEP_ALIVE_TIME = 6 * 60 * 1000;
|
||||
private ThreadPoolExecutor grpcExecutor;
|
||||
|
||||
@Override
|
||||
public ConnectionType getConnectionType() {
|
||||
@ -76,47 +70,64 @@ public abstract class GrpcClient extends RpcClient {
|
||||
}
|
||||
|
||||
/**
|
||||
* Empty constructor.
|
||||
* constructor.
|
||||
*
|
||||
* @param name .
|
||||
*/
|
||||
public GrpcClient(String name) {
|
||||
super(name);
|
||||
this(DefaultGrpcClientConfig.newBuilder().setName(name).build());
|
||||
}
|
||||
|
||||
/**
|
||||
* Set core size of thread pool.
|
||||
* constructor.
|
||||
*
|
||||
* @param threadPoolCoreSize core size of thread pool for grpc.
|
||||
* @param properties .
|
||||
*/
|
||||
public void setThreadPoolCoreSize(Integer threadPoolCoreSize) {
|
||||
this.threadPoolCoreSize = threadPoolCoreSize;
|
||||
public GrpcClient(Properties properties) {
|
||||
this(DefaultGrpcClientConfig.newBuilder().fromProperties(properties).build());
|
||||
}
|
||||
|
||||
/**
|
||||
* Set max size of thread pool.
|
||||
* constructor.
|
||||
*
|
||||
* @param threadPoolMaxSize max size of thread pool for grpc.
|
||||
* @param clientConfig .
|
||||
*/
|
||||
public void setThreadPoolMaxSize(Integer threadPoolMaxSize) {
|
||||
this.threadPoolMaxSize = threadPoolMaxSize;
|
||||
public GrpcClient(GrpcClientConfig clientConfig) {
|
||||
super(clientConfig);
|
||||
this.clientConfig = clientConfig;
|
||||
}
|
||||
|
||||
protected Integer getThreadPoolCoreSize() {
|
||||
return threadPoolCoreSize != null ? threadPoolCoreSize : ThreadUtils.getSuitableThreadCount(2);
|
||||
/**
|
||||
* constructor.
|
||||
*
|
||||
* @param clientConfig .
|
||||
* @param serverListFactory .
|
||||
*/
|
||||
public GrpcClient(GrpcClientConfig clientConfig, ServerListFactory serverListFactory) {
|
||||
super(clientConfig, serverListFactory);
|
||||
this.clientConfig = clientConfig;
|
||||
}
|
||||
|
||||
protected Integer getThreadPoolMaxSize() {
|
||||
return threadPoolMaxSize != null ? threadPoolMaxSize : ThreadUtils.getSuitableThreadCount(8);
|
||||
/**
|
||||
* constructor.
|
||||
*
|
||||
* @param name .
|
||||
* @param threadPoolCoreSize .
|
||||
* @param threadPoolMaxSize .
|
||||
* @param labels .
|
||||
*/
|
||||
public GrpcClient(String name, Integer threadPoolCoreSize, Integer threadPoolMaxSize, Map<String, String> labels) {
|
||||
this(DefaultGrpcClientConfig.newBuilder().setName(name).setThreadPoolCoreSize(threadPoolCoreSize)
|
||||
.setThreadPoolMaxSize(threadPoolMaxSize).setLabels(labels).build());
|
||||
}
|
||||
|
||||
protected ThreadPoolExecutor createGrpcExecutor(String serverIp) {
|
||||
ThreadPoolExecutor grpcExecutor = new ThreadPoolExecutor(
|
||||
getThreadPoolCoreSize(),
|
||||
getThreadPoolMaxSize(),
|
||||
10L, TimeUnit.SECONDS,
|
||||
new LinkedBlockingQueue<>(10000),
|
||||
new ThreadFactoryBuilder()
|
||||
.daemon(true)
|
||||
.nameFormat("nacos-grpc-client-executor-" + serverIp + "-%d")
|
||||
// Thread name will use String.format, ipv6 maybe contain special word %, so handle it first.
|
||||
serverIp = serverIp.replaceAll("%", "-");
|
||||
ThreadPoolExecutor grpcExecutor = new ThreadPoolExecutor(clientConfig.threadPoolCoreSize(),
|
||||
clientConfig.threadPoolMaxSize(), clientConfig.threadPoolKeepAlive(), TimeUnit.MILLISECONDS,
|
||||
new LinkedBlockingQueue<>(clientConfig.threadPoolQueueSize()),
|
||||
new ThreadFactoryBuilder().daemon(true).nameFormat("nacos-grpc-client-executor-" + serverIp + "-%d")
|
||||
.build());
|
||||
grpcExecutor.allowCoreThreadTimeOut(true);
|
||||
return grpcExecutor;
|
||||
@ -130,7 +141,7 @@ public abstract class GrpcClient extends RpcClient {
|
||||
grpcExecutor.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a stub using a channel.
|
||||
*
|
||||
@ -140,7 +151,7 @@ public abstract class GrpcClient extends RpcClient {
|
||||
private RequestGrpc.RequestFutureStub createNewChannelStub(ManagedChannel managedChannelTemp) {
|
||||
return RequestGrpc.newFutureStub(managedChannelTemp);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* create a new channel with specific server address.
|
||||
*
|
||||
@ -149,24 +160,14 @@ public abstract class GrpcClient extends RpcClient {
|
||||
* @return if server check success,return a non-null channel.
|
||||
*/
|
||||
private ManagedChannel createNewManagedChannel(String serverIp, int serverPort) {
|
||||
ManagedChannelBuilder<?> managedChannelBuilder = ManagedChannelBuilder.forAddress(serverIp, serverPort).executor(grpcExecutor)
|
||||
.compressorRegistry(CompressorRegistry.getDefaultInstance()).decompressorRegistry(DecompressorRegistry.getDefaultInstance())
|
||||
.maxInboundMessageSize(getInboundMessageSize()).keepAliveTime(keepAliveTimeMillis(), TimeUnit.MILLISECONDS).usePlaintext();
|
||||
ManagedChannelBuilder<?> managedChannelBuilder = ManagedChannelBuilder.forAddress(serverIp, serverPort)
|
||||
.executor(grpcExecutor).compressorRegistry(CompressorRegistry.getDefaultInstance())
|
||||
.decompressorRegistry(DecompressorRegistry.getDefaultInstance())
|
||||
.maxInboundMessageSize(clientConfig.maxInboundMessageSize())
|
||||
.keepAliveTime(clientConfig.channelKeepAlive(), TimeUnit.MILLISECONDS).usePlaintext();
|
||||
return managedChannelBuilder.build();
|
||||
}
|
||||
|
||||
private int getInboundMessageSize() {
|
||||
String messageSize = System.getProperty("nacos.remote.client.grpc.maxinbound.message.size",
|
||||
String.valueOf(DEFAULT_MAX_INBOUND_MESSAGE_SIZE));
|
||||
return Integer.parseInt(messageSize);
|
||||
}
|
||||
|
||||
private int keepAliveTimeMillis() {
|
||||
String keepAliveTimeMillis = System
|
||||
.getProperty("nacos.remote.grpc.keep.alive.millis", String.valueOf(DEFAULT_KEEP_ALIVE_TIME));
|
||||
return Integer.parseInt(keepAliveTimeMillis);
|
||||
}
|
||||
|
||||
/**
|
||||
* shutdown a channel.
|
||||
*
|
||||
@ -192,7 +193,7 @@ public abstract class GrpcClient extends RpcClient {
|
||||
ServerCheckRequest serverCheckRequest = new ServerCheckRequest();
|
||||
Payload grpcRequest = GrpcUtils.convert(serverCheckRequest);
|
||||
ListenableFuture<Payload> responseFuture = requestBlockingStub.request(grpcRequest);
|
||||
Payload response = responseFuture.get(3000L, TimeUnit.MILLISECONDS);
|
||||
Payload response = responseFuture.get(clientConfig.serverCheckTimeOut(), TimeUnit.MILLISECONDS);
|
||||
//receive connection unregister response here,not check response is success.
|
||||
return (Response) GrpcUtils.parse(response);
|
||||
} catch (Exception e) {
|
||||
|
@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright 1999-2020 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.common.remote.client.grpc;
|
||||
|
||||
import com.alibaba.nacos.common.remote.client.RpcClientConfig;
|
||||
|
||||
/**
|
||||
* GrpcCleint config. Use to collect and init Grpc client configuration.
|
||||
*
|
||||
* @author karsonto
|
||||
*/
|
||||
public interface GrpcClientConfig extends RpcClientConfig {
|
||||
|
||||
/**
|
||||
* get threadPoolCoreSize.
|
||||
*
|
||||
* @return threadPoolCoreSize.
|
||||
*/
|
||||
int threadPoolCoreSize();
|
||||
|
||||
/**
|
||||
* get threadPoolMaxSize.
|
||||
*
|
||||
* @return threadPoolMaxSize.
|
||||
*/
|
||||
int threadPoolMaxSize();
|
||||
|
||||
/**
|
||||
* get thread pool keep alive time.
|
||||
*
|
||||
* @return threadPoolKeepAlive.
|
||||
*/
|
||||
long threadPoolKeepAlive();
|
||||
|
||||
/**
|
||||
* get server check time out.
|
||||
*
|
||||
* @return serverCheckTimeOut.
|
||||
*/
|
||||
long serverCheckTimeOut();
|
||||
|
||||
/**
|
||||
* get thread pool queue size.
|
||||
*
|
||||
* @return threadPoolQueueSize.
|
||||
*/
|
||||
int threadPoolQueueSize();
|
||||
|
||||
/**
|
||||
* get maxInboundMessage size.
|
||||
*
|
||||
* @return maxInboundMessageSize.
|
||||
*/
|
||||
int maxInboundMessageSize();
|
||||
|
||||
/**
|
||||
* get channelKeepAlive time.
|
||||
*
|
||||
* @return channelKeepAlive.
|
||||
*/
|
||||
int channelKeepAlive();
|
||||
|
||||
}
|
@ -18,6 +18,9 @@ package com.alibaba.nacos.common.remote.client.grpc;
|
||||
|
||||
import com.alibaba.nacos.api.common.Constants;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* gRPC client for cluster.
|
||||
*
|
||||
@ -35,9 +38,40 @@ public class GrpcClusterClient extends GrpcClient {
|
||||
super(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Empty constructor.
|
||||
*
|
||||
* @param config of GrpcClientConfig.
|
||||
*/
|
||||
public GrpcClusterClient(GrpcClientConfig config) {
|
||||
super(config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param properties .
|
||||
*/
|
||||
public GrpcClusterClient(Properties properties) {
|
||||
super(properties);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param name name of client.
|
||||
* @param threadPoolCoreSize .
|
||||
* @param threadPoolMaxSize .
|
||||
* @param labels .
|
||||
*/
|
||||
public GrpcClusterClient(String name, Integer threadPoolCoreSize, Integer threadPoolMaxSize,
|
||||
Map<String, String> labels) {
|
||||
super(name, threadPoolCoreSize, threadPoolMaxSize, labels);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int rpcPortOffset() {
|
||||
return Integer.parseInt(System.getProperty(NACOS_SERVER_GRPC_PORT_OFFSET_KEY,
|
||||
return Integer.parseInt(System.getProperty(GrpcConstants.NACOS_SERVER_GRPC_PORT_OFFSET_KEY,
|
||||
String.valueOf(Constants.CLUSTER_GRPC_PORT_DEFAULT_OFFSET)));
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Copyright 1999-2020 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.common.remote.client.grpc;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* GrpcConsts.
|
||||
*
|
||||
* @author karsonto
|
||||
*/
|
||||
public class GrpcConstants {
|
||||
|
||||
public static final String NACOS_SERVER_GRPC_PORT_OFFSET_KEY = "nacos.server.grpc.port.offset";
|
||||
|
||||
public static final String NACOS_CLIENT_GRPC = "nacos.remote.client.grpc";
|
||||
|
||||
@GRpcConfigLabel
|
||||
public static final String GRPC_NAME = NACOS_CLIENT_GRPC + ".name";
|
||||
|
||||
@GRpcConfigLabel
|
||||
public static final String GRPC_THREADPOOL_KEEPALIVETIME = NACOS_CLIENT_GRPC + ".pool.alive";
|
||||
|
||||
@GRpcConfigLabel
|
||||
public static final String GRPC_THREADPOOL_CORE_SIZE = NACOS_CLIENT_GRPC + ".pool.core.size";
|
||||
|
||||
@GRpcConfigLabel
|
||||
public static final String GRPC_RETRY_TIMES = NACOS_CLIENT_GRPC + ".retry.times";
|
||||
|
||||
@GRpcConfigLabel
|
||||
public static final String GRPC_TIMEOUT_MILLS = NACOS_CLIENT_GRPC + ".timeout";
|
||||
|
||||
@GRpcConfigLabel
|
||||
public static final String GRPC_CONNECT_KEEP_ALIVE_TIME = NACOS_CLIENT_GRPC + ".connect.keep.alive";
|
||||
|
||||
@GRpcConfigLabel
|
||||
public static final String GRPC_THREADPOOL_MAX_SIZE = NACOS_CLIENT_GRPC + ".pool.max.size";
|
||||
|
||||
@GRpcConfigLabel
|
||||
public static final String GRPC_SERVER_CHECK_TIMEOUT = NACOS_CLIENT_GRPC + ".server.check.timeout";
|
||||
|
||||
@GRpcConfigLabel
|
||||
public static final String GRPC_QUEUESIZE = NACOS_CLIENT_GRPC + ".queue.size";
|
||||
|
||||
@GRpcConfigLabel
|
||||
public static final String GRPC_HEALTHCHECK_RETRY_TIMES = NACOS_CLIENT_GRPC + ".health.retry";
|
||||
|
||||
@GRpcConfigLabel
|
||||
public static final String GRPC_HEALTHCHECK_TIMEOUT = NACOS_CLIENT_GRPC + ".health.timeout";
|
||||
|
||||
@GRpcConfigLabel
|
||||
public static final String GRPC_MAX_INBOUND_MESSAGE_SIZE = NACOS_CLIENT_GRPC + ".maxinbound.message.size";
|
||||
|
||||
@GRpcConfigLabel
|
||||
public static final String GRPC_CHANNEL_KEEP_ALIVE_TIME = NACOS_CLIENT_GRPC + ".channel.keep.alive";
|
||||
|
||||
private static final Set<String> CONFIG_NAMES = new HashSet<>();
|
||||
|
||||
@Documented
|
||||
@Target(ElementType.FIELD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
protected @interface GRpcConfigLabel {
|
||||
|
||||
}
|
||||
|
||||
static {
|
||||
Class clazz = GrpcConstants.class;
|
||||
Field[] declaredFields = clazz.getDeclaredFields();
|
||||
for (Field declaredField : declaredFields) {
|
||||
declaredField.setAccessible(true);
|
||||
if (declaredField.getType().equals(String.class) && null != declaredField.getAnnotation(
|
||||
GRpcConfigLabel.class)) {
|
||||
try {
|
||||
CONFIG_NAMES.add((String) declaredField.get(null));
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static Set<String> getRpcParams() {
|
||||
return Collections.unmodifiableSet(CONFIG_NAMES);
|
||||
}
|
||||
}
|
@ -18,6 +18,9 @@ package com.alibaba.nacos.common.remote.client.grpc;
|
||||
|
||||
import com.alibaba.nacos.api.common.Constants;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* gRPC client for sdk.
|
||||
*
|
||||
@ -27,7 +30,7 @@ import com.alibaba.nacos.api.common.Constants;
|
||||
public class GrpcSdkClient extends GrpcClient {
|
||||
|
||||
/**
|
||||
* Empty constructor.
|
||||
* Constructor.
|
||||
*
|
||||
* @param name name of client.
|
||||
*/
|
||||
@ -35,9 +38,40 @@ public class GrpcSdkClient extends GrpcClient {
|
||||
super(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param properties .
|
||||
*/
|
||||
public GrpcSdkClient(Properties properties) {
|
||||
super(properties);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param name name of client.
|
||||
* @param threadPoolCoreSize .
|
||||
* @param threadPoolMaxSize .
|
||||
* @param labels .
|
||||
*/
|
||||
public GrpcSdkClient(String name, Integer threadPoolCoreSize, Integer threadPoolMaxSize,
|
||||
Map<String, String> labels) {
|
||||
super(name, threadPoolCoreSize, threadPoolMaxSize, labels);
|
||||
}
|
||||
|
||||
/**
|
||||
* constructor.
|
||||
*
|
||||
* @param config of GrpcClientConfig.
|
||||
*/
|
||||
public GrpcSdkClient(GrpcClientConfig config) {
|
||||
super(config);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int rpcPortOffset() {
|
||||
return Integer.parseInt(System.getProperty(NACOS_SERVER_GRPC_PORT_OFFSET_KEY,
|
||||
return Integer.parseInt(System.getProperty(GrpcConstants.NACOS_SERVER_GRPC_PORT_OFFSET_KEY,
|
||||
String.valueOf(Constants.SDK_GRPC_PORT_DEFAULT_OFFSET)));
|
||||
}
|
||||
|
||||
|
@ -32,6 +32,8 @@ import com.google.protobuf.ByteString;
|
||||
import com.google.protobuf.UnsafeByteOperations;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* gRPC utils, use to parse request and response.
|
||||
@ -59,8 +61,7 @@ public class GrpcUtils {
|
||||
payloadBuilder.setMetadata(metaBuilder.build());
|
||||
|
||||
// request body .
|
||||
request.clearHeaders();
|
||||
byte[] jsonBytes = JacksonUtils.toJsonBytes(request);
|
||||
byte[] jsonBytes = convertRequestToByte(request);
|
||||
return payloadBuilder
|
||||
.setBody(Any.newBuilder().setValue(UnsafeByteOperations.unsafeWrap(jsonBytes)))
|
||||
.build();
|
||||
@ -77,11 +78,11 @@ public class GrpcUtils {
|
||||
|
||||
Metadata newMeta = Metadata.newBuilder().setType(request.getClass().getSimpleName())
|
||||
.setClientIp(NetUtils.localIP()).putAllHeaders(request.getHeaders()).build();
|
||||
request.clearHeaders();
|
||||
byte[] jsonBytes = JacksonUtils.toJsonBytes(request);
|
||||
|
||||
byte[] jsonBytes = convertRequestToByte(request);
|
||||
|
||||
Payload.Builder builder = Payload.newBuilder();
|
||||
|
||||
|
||||
return builder
|
||||
.setBody(Any.newBuilder().setValue(UnsafeByteOperations.unsafeWrap(jsonBytes)))
|
||||
.setMetadata(newMeta).build();
|
||||
@ -103,6 +104,14 @@ public class GrpcUtils {
|
||||
.setMetadata(metaBuilder.build()).build();
|
||||
}
|
||||
|
||||
private static byte[] convertRequestToByte(Request request) {
|
||||
Map<String, String> requestHeaders = new HashMap<>(request.getHeaders());
|
||||
request.clearHeaders();
|
||||
byte[] jsonBytes = JacksonUtils.toJsonBytes(request);
|
||||
request.putAllHeader(requestHeaders);
|
||||
return jsonBytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* parse payload to request/response model.
|
||||
*
|
||||
|
@ -31,4 +31,9 @@ public class NamingTraceEvent extends TraceEvent {
|
||||
String serviceNamespace, String serviceGroup, String name) {
|
||||
super(eventType, eventTime, serviceNamespace, serviceGroup, name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPluginEvent() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -103,7 +103,6 @@ public class TraceEventPublisher extends Thread implements ShardedEventPublisher
|
||||
boolean success = this.queue.offer(event);
|
||||
if (!success) {
|
||||
LOGGER.warn("Trace Event Publish failed, event : {}, publish queue size : {}", event, currentEventSize());
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -50,7 +50,6 @@ public class TraceEventPublisherFactory implements EventPublisherFactory {
|
||||
|
||||
@Override
|
||||
public EventPublisher apply(final Class<? extends Event> eventType, final Integer maxQueueSize) {
|
||||
// Like ClientEvent$ClientChangeEvent cache by ClientEvent
|
||||
Class<? extends Event> cachedEventType = TraceEvent.class;
|
||||
|
||||
for (Class<? extends Event> publisherEvent : publisherEvents) {
|
||||
|
@ -104,7 +104,7 @@ public class RpcClientFactoryTest {
|
||||
RpcClient client = RpcClientFactory
|
||||
.createClient("testClient", ConnectionType.GRPC, Collections.singletonMap("labelKey", "labelValue"));
|
||||
|
||||
Assert.assertEquals(Collections.singletonMap("labelKey", "labelValue"), client.labels);
|
||||
Assert.assertEquals(Collections.singletonMap("labelKey", "labelValue"), client.rpcClientConfig.labels());
|
||||
Assert.assertEquals(ConnectionType.GRPC, client.getConnectionType());
|
||||
Assert.assertEquals("testClient", CollectionUtils.getOnlyElement(RpcClientFactory.getAllClientEntries()).getKey());
|
||||
}
|
||||
@ -134,7 +134,7 @@ public class RpcClientFactoryTest {
|
||||
Collections.singletonMap("labelKey", "labelValue")
|
||||
);
|
||||
|
||||
Assert.assertEquals(Collections.singletonMap("labelKey", "labelValue"), client.labels);
|
||||
Assert.assertEquals(Collections.singletonMap("labelKey", "labelValue"), client.rpcClientConfig.labels());
|
||||
Assert.assertEquals(ConnectionType.GRPC, client.getConnectionType());
|
||||
Assert.assertEquals("testClient", CollectionUtils.getOnlyElement(RpcClientFactory.getAllClientEntries()).getKey());
|
||||
}
|
||||
|
@ -21,6 +21,7 @@ import com.alibaba.nacos.api.remote.RequestCallBack;
|
||||
import com.alibaba.nacos.api.remote.request.Request;
|
||||
import com.alibaba.nacos.api.remote.response.ErrorResponse;
|
||||
import com.alibaba.nacos.common.remote.ConnectionType;
|
||||
import com.alibaba.nacos.common.remote.client.grpc.DefaultGrpcClientConfig;
|
||||
import com.alibaba.nacos.common.remote.client.grpc.GrpcConnection;
|
||||
import org.junit.After;
|
||||
import org.junit.Assert;
|
||||
@ -36,10 +37,12 @@ import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Queue;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.Random;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyLong;
|
||||
import static org.mockito.Mockito.atLeastOnce;
|
||||
@ -49,24 +52,21 @@ import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class RpcClientTest {
|
||||
|
||||
RpcClient rpcClient;
|
||||
|
||||
Field keepAliveTimeField;
|
||||
|
||||
Field serverListFactoryField;
|
||||
|
||||
Field reconnectionSignalField;
|
||||
|
||||
Field retryTimesField;
|
||||
|
||||
Field timeoutMillsField;
|
||||
|
||||
Method resolveServerInfoMethod;
|
||||
|
||||
Method healthCheck;
|
||||
|
||||
Answer<?> runAsSync;
|
||||
|
||||
Answer<?> notInvoke;
|
||||
@ -77,9 +77,47 @@ public class RpcClientTest {
|
||||
@Mock
|
||||
Connection connection;
|
||||
|
||||
RpcClientConfig rpcClientConfig;
|
||||
|
||||
@Before
|
||||
public void setUp() throws NoSuchFieldException, IllegalAccessException, NoSuchMethodException {
|
||||
rpcClient = spy(new RpcClient("testClient") {
|
||||
rpcClientConfig = spy(new RpcClientConfig() {
|
||||
@Override
|
||||
public String name() {
|
||||
return "test";
|
||||
}
|
||||
|
||||
@Override
|
||||
public int retryTimes() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long timeOutMills() {
|
||||
return 3000L;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long connectionKeepAlive() {
|
||||
return 5000L;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int healthCheckRetryTimes() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long healthCheckTimeOut() {
|
||||
return 3000L;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String> labels() {
|
||||
return new HashMap<>();
|
||||
}
|
||||
});
|
||||
rpcClient = spy(new RpcClient(rpcClientConfig) {
|
||||
@Override
|
||||
public ConnectionType getConnectionType() {
|
||||
return null;
|
||||
@ -96,9 +134,6 @@ public class RpcClientTest {
|
||||
}
|
||||
});
|
||||
|
||||
keepAliveTimeField = RpcClient.class.getDeclaredField("keepAliveTime");
|
||||
keepAliveTimeField.setAccessible(true);
|
||||
|
||||
serverListFactoryField = RpcClient.class.getDeclaredField("serverListFactory");
|
||||
serverListFactoryField.setAccessible(true);
|
||||
|
||||
@ -108,21 +143,12 @@ public class RpcClientTest {
|
||||
modifiersField1.setAccessible(true);
|
||||
modifiersField1.setInt(reconnectionSignalField, reconnectionSignalField.getModifiers() & ~Modifier.FINAL);
|
||||
|
||||
retryTimesField = RpcClient.class.getDeclaredField("RETRY_TIMES");
|
||||
retryTimesField.setAccessible(true);
|
||||
Field modifiersField3 = Field.class.getDeclaredField("modifiers");
|
||||
modifiersField3.setAccessible(true);
|
||||
modifiersField3.setInt(retryTimesField, retryTimesField.getModifiers() & ~Modifier.FINAL);
|
||||
|
||||
timeoutMillsField = RpcClient.class.getDeclaredField("DEFAULT_TIMEOUT_MILLS");
|
||||
timeoutMillsField.setAccessible(true);
|
||||
Field modifiersField4 = Field.class.getDeclaredField("modifiers");
|
||||
modifiersField4.setAccessible(true);
|
||||
modifiersField4.setInt(timeoutMillsField, timeoutMillsField.getModifiers() & ~Modifier.FINAL);
|
||||
|
||||
resolveServerInfoMethod = RpcClient.class.getDeclaredMethod("resolveServerInfo", String.class);
|
||||
resolveServerInfoMethod.setAccessible(true);
|
||||
|
||||
healthCheck = RpcClient.class.getDeclaredMethod("healthCheck");
|
||||
healthCheck.setAccessible(true);
|
||||
|
||||
runAsSync = invocationOnMock -> {
|
||||
Runnable runnable = (Runnable) invocationOnMock.getArguments()[0];
|
||||
runnable.run();
|
||||
@ -134,7 +160,7 @@ public class RpcClientTest {
|
||||
|
||||
@After
|
||||
public void tearDown() throws IllegalAccessException {
|
||||
rpcClient.labels.clear();
|
||||
rpcClientConfig.labels().clear();
|
||||
rpcClient.rpcClientStatus.set(RpcClientStatus.WAIT_INIT);
|
||||
serverListFactoryField.set(rpcClient, null);
|
||||
((Queue<?>) reconnectionSignalField.get(rpcClient)).clear();
|
||||
@ -147,13 +173,48 @@ public class RpcClientTest {
|
||||
public void testInitServerListFactory() {
|
||||
rpcClient.rpcClientStatus.set(RpcClientStatus.WAIT_INIT);
|
||||
rpcClient.serverListFactory(serverListFactory);
|
||||
Assert.assertEquals(RpcClientStatus.INITIALIZED, rpcClient.rpcClientStatus.get());
|
||||
assertEquals(RpcClientStatus.INITIALIZED, rpcClient.rpcClientStatus.get());
|
||||
|
||||
rpcClient.rpcClientStatus.set(RpcClientStatus.INITIALIZED);
|
||||
rpcClient.serverListFactory(serverListFactory);
|
||||
Assert.assertEquals(RpcClientStatus.INITIALIZED, rpcClient.rpcClientStatus.get());
|
||||
assertEquals(RpcClientStatus.INITIALIZED, rpcClient.rpcClientStatus.get());
|
||||
|
||||
RpcClient client1 = new RpcClient("test", serverListFactory) {
|
||||
RpcClient client1 = new RpcClient(new RpcClientConfig() {
|
||||
@Override
|
||||
public String name() {
|
||||
return "test";
|
||||
}
|
||||
|
||||
@Override
|
||||
public int retryTimes() {
|
||||
return 3;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long timeOutMills() {
|
||||
return 3000L;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long connectionKeepAlive() {
|
||||
return 5000L;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int healthCheckRetryTimes() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long healthCheckTimeOut() {
|
||||
return 3000L;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String> labels() {
|
||||
return new HashMap<>();
|
||||
}
|
||||
}, serverListFactory) {
|
||||
@Override
|
||||
public ConnectionType getConnectionType() {
|
||||
return null;
|
||||
@ -169,9 +230,9 @@ public class RpcClientTest {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
Assert.assertEquals(RpcClientStatus.INITIALIZED, client1.rpcClientStatus.get());
|
||||
assertEquals(RpcClientStatus.INITIALIZED, client1.rpcClientStatus.get());
|
||||
|
||||
RpcClient client2 = new RpcClient(serverListFactory) {
|
||||
RpcClient client2 = new RpcClient(rpcClientConfig, serverListFactory) {
|
||||
@Override
|
||||
public ConnectionType getConnectionType() {
|
||||
return null;
|
||||
@ -187,30 +248,21 @@ public class RpcClientTest {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
Assert.assertEquals(RpcClientStatus.INITIALIZED, client2.rpcClientStatus.get());
|
||||
assertEquals(RpcClientStatus.INITIALIZED, client2.rpcClientStatus.get());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLabels() {
|
||||
rpcClient.labels(Collections.singletonMap("labelKey1", "labelValue1"));
|
||||
when(rpcClientConfig.labels()).thenReturn(Collections.singletonMap("labelKey1", "labelValue1"));
|
||||
Map.Entry<String, String> element = rpcClient.getLabels().entrySet().iterator().next();
|
||||
Assert.assertEquals("labelKey1", element.getKey());
|
||||
Assert.assertEquals("labelValue1", element.getValue());
|
||||
assertEquals("labelKey1", element.getKey());
|
||||
assertEquals("labelValue1", element.getValue());
|
||||
|
||||
// accumulate labels
|
||||
rpcClient.labels(Collections.singletonMap("labelKey2", "labelValue2"));
|
||||
Assert.assertEquals(2, rpcClient.getLabels().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testKeepAlive() throws IllegalAccessException {
|
||||
rpcClient.keepAlive(1, TimeUnit.SECONDS);
|
||||
long keepAliveTime = (long) keepAliveTimeField.get(rpcClient);
|
||||
Assert.assertEquals(1000L, keepAliveTime);
|
||||
|
||||
rpcClient.keepAlive(1, TimeUnit.MINUTES);
|
||||
keepAliveTime = (long) keepAliveTimeField.get(rpcClient);
|
||||
Assert.assertEquals(60000L, keepAliveTime);
|
||||
Map<String, String> map = new HashMap<>();
|
||||
map.put("labelKey2", "labelValue2");
|
||||
when(rpcClientConfig.labels()).thenReturn(map);
|
||||
assertEquals(1, rpcClient.getLabels().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -221,7 +273,7 @@ public class RpcClientTest {
|
||||
rpcClient.onServerListChange();
|
||||
|
||||
int afterSize = ((Queue<?>) reconnectionSignalField.get(rpcClient)).size();
|
||||
Assert.assertEquals(beforeSize, afterSize);
|
||||
assertEquals(beforeSize, afterSize);
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -232,7 +284,7 @@ public class RpcClientTest {
|
||||
rpcClient.onServerListChange();
|
||||
|
||||
int afterSize = ((Queue<?>) reconnectionSignalField.get(rpcClient)).size();
|
||||
Assert.assertEquals(beforeSize, afterSize);
|
||||
assertEquals(beforeSize, afterSize);
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -242,11 +294,11 @@ public class RpcClientTest {
|
||||
rpcClient.serverListFactory(serverListFactory);
|
||||
rpcClient.currentConnection = new GrpcConnection(new RpcClient.ServerInfo("10.10.10.10", 8848), null);
|
||||
doReturn(Collections.singletonList("")).when(serverListFactory).getServerList();
|
||||
|
||||
when(serverListFactory.getServerList()).thenReturn(Collections.singletonList("127.0.0.1"));
|
||||
rpcClient.onServerListChange();
|
||||
|
||||
int afterSize = ((Queue<?>) reconnectionSignalField.get(rpcClient)).size();
|
||||
Assert.assertEquals(beforeSize + 1, afterSize);
|
||||
assertEquals(beforeSize + 1, afterSize);
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -255,35 +307,35 @@ public class RpcClientTest {
|
||||
rpcClient.serverListFactory(serverListFactory);
|
||||
rpcClient.currentConnection = new GrpcConnection(new RpcClient.ServerInfo("10.10.10.10", 8848), null);
|
||||
doReturn(Collections.singletonList("http://10.10.10.10:8848")).when(serverListFactory).getServerList();
|
||||
|
||||
rpcClient.onServerListChange();
|
||||
|
||||
int afterSize = ((Queue<?>) reconnectionSignalField.get(rpcClient)).size();
|
||||
Assert.assertEquals(beforeSize, afterSize);
|
||||
assertEquals(beforeSize, afterSize);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResolveServerInfo1() throws InvocationTargetException, IllegalAccessException {
|
||||
Assert.assertEquals(":8848",
|
||||
((RpcClient.ServerInfo) resolveServerInfoMethod.invoke(rpcClient, "")).getAddress());
|
||||
Assert.assertEquals("10.10.10.10:8848",
|
||||
assertEquals("10.10.10.10:8848",
|
||||
((RpcClient.ServerInfo) resolveServerInfoMethod.invoke(rpcClient, "10.10.10.10::8848")).getAddress());
|
||||
Assert.assertEquals("10.10.10.10:8848",
|
||||
assertEquals("10.10.10.10:8848",
|
||||
((RpcClient.ServerInfo) resolveServerInfoMethod.invoke(rpcClient, "10.10.10.10:8848")).getAddress());
|
||||
Assert.assertEquals("10.10.10.10:8848", ((RpcClient.ServerInfo) resolveServerInfoMethod.invoke(rpcClient,
|
||||
"http://10.10.10.10:8848")).getAddress());
|
||||
Assert.assertEquals("10.10.10.10:8848", ((RpcClient.ServerInfo) resolveServerInfoMethod.invoke(rpcClient,
|
||||
"http://10.10.10.10::8848")).getAddress());
|
||||
Assert.assertEquals("10.10.10.10:8848",
|
||||
assertEquals("10.10.10.10:8848",
|
||||
((RpcClient.ServerInfo) resolveServerInfoMethod.invoke(rpcClient, "http://10.10.10.10:8848"))
|
||||
.getAddress());
|
||||
assertEquals("10.10.10.10:8848",
|
||||
((RpcClient.ServerInfo) resolveServerInfoMethod.invoke(rpcClient, "http://10.10.10.10::8848"))
|
||||
.getAddress());
|
||||
assertEquals("10.10.10.10:8848",
|
||||
((RpcClient.ServerInfo) resolveServerInfoMethod.invoke(rpcClient, "http://10.10.10.10")).getAddress());
|
||||
Assert.assertEquals("10.10.10.10:8848", ((RpcClient.ServerInfo) resolveServerInfoMethod.invoke(rpcClient,
|
||||
"https://10.10.10.10::8848")).getAddress());
|
||||
assertEquals("10.10.10.10:8848",
|
||||
((RpcClient.ServerInfo) resolveServerInfoMethod.invoke(rpcClient, "https://10.10.10.10::8848"))
|
||||
.getAddress());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResolveServerInfo2() throws InvocationTargetException, IllegalAccessException {
|
||||
System.setProperty("nacos.server.port", "4424");
|
||||
Assert.assertEquals("10.10.10.10:4424",
|
||||
assertEquals("10.10.10.10:4424",
|
||||
((RpcClient.ServerInfo) resolveServerInfoMethod.invoke(rpcClient, "http://10.10.10.10")).getAddress());
|
||||
}
|
||||
|
||||
@ -308,7 +360,7 @@ public class RpcClientTest {
|
||||
rpcClient.rpcClientStatus.set(RpcClientStatus.RUNNING);
|
||||
rpcClient.currentConnection = connection;
|
||||
doReturn(new ErrorResponse()).when(connection).request(any(), anyLong());
|
||||
|
||||
|
||||
rpcClient.request(null, 10000);
|
||||
}
|
||||
|
||||
@ -327,7 +379,7 @@ public class RpcClientTest {
|
||||
exception = e;
|
||||
}
|
||||
|
||||
Assert.assertEquals(RpcClientStatus.UNHEALTHY, rpcClient.rpcClientStatus.get());
|
||||
assertEquals(RpcClientStatus.UNHEALTHY, rpcClient.rpcClientStatus.get());
|
||||
verify(rpcClient).switchServerAsync();
|
||||
Assert.assertNotNull(exception);
|
||||
}
|
||||
@ -349,7 +401,7 @@ public class RpcClientTest {
|
||||
RequestCallBack<?> requestCallBack = mock(RequestCallBack.class);
|
||||
doReturn(10000L).when(requestCallBack).getTimeout();
|
||||
Exception exception = null;
|
||||
|
||||
|
||||
try {
|
||||
rpcClient.asyncRequest(null, requestCallBack);
|
||||
} catch (NacosException e) {
|
||||
@ -359,7 +411,7 @@ public class RpcClientTest {
|
||||
verify(connection, atLeastOnce()).asyncRequest(any(), any());
|
||||
verify(rpcClient).switchServerAsyncOnRequestFail();
|
||||
Assert.assertNotNull(exception);
|
||||
Assert.assertEquals(RpcClientStatus.UNHEALTHY, rpcClient.rpcClientStatus.get());
|
||||
assertEquals(RpcClientStatus.UNHEALTHY, rpcClient.rpcClientStatus.get());
|
||||
}
|
||||
|
||||
@Test(expected = NacosException.class)
|
||||
@ -370,9 +422,10 @@ public class RpcClientTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRequestFutureWhenRetryReachMaxRetryTimesThenSwitchServer() throws NacosException, IllegalAccessException {
|
||||
timeoutMillsField.set(rpcClient, 5000L);
|
||||
retryTimesField.set(rpcClient, 3);
|
||||
public void testRequestFutureWhenRetryReachMaxRetryTimesThenSwitchServer()
|
||||
throws NacosException, IllegalAccessException {
|
||||
when(rpcClientConfig.timeOutMills()).thenReturn(5000L);
|
||||
when(rpcClientConfig.retryTimes()).thenReturn(3);
|
||||
rpcClient.rpcClientStatus.set(RpcClientStatus.RUNNING);
|
||||
rpcClient.currentConnection = connection;
|
||||
doThrow(NacosException.class).when(connection).requestFuture(any());
|
||||
@ -387,22 +440,57 @@ public class RpcClientTest {
|
||||
verify(connection, times(3)).requestFuture(any());
|
||||
verify(rpcClient).switchServerAsyncOnRequestFail();
|
||||
Assert.assertNotNull(exception);
|
||||
Assert.assertEquals(RpcClientStatus.UNHEALTHY, rpcClient.rpcClientStatus.get());
|
||||
assertEquals(RpcClientStatus.UNHEALTHY, rpcClient.rpcClientStatus.get());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRpcClientShutdownWhenClientDidntStart() throws NacosException {
|
||||
RpcClient rpcClient = new RpcClient("test-client") {
|
||||
RpcClient rpcClient = new RpcClient(new RpcClientConfig() {
|
||||
@Override
|
||||
public String name() {
|
||||
return "test-client";
|
||||
}
|
||||
|
||||
@Override
|
||||
public int retryTimes() {
|
||||
return 3;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long timeOutMills() {
|
||||
return 3000L;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long connectionKeepAlive() {
|
||||
return 5000L;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int healthCheckRetryTimes() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long healthCheckTimeOut() {
|
||||
return 3000L;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String> labels() {
|
||||
return new HashMap<>();
|
||||
}
|
||||
}) {
|
||||
@Override
|
||||
public ConnectionType getConnectionType() {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int rpcPortOffset() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Connection connectToServer(ServerInfo serverInfo) throws Exception {
|
||||
return null;
|
||||
@ -411,4 +499,140 @@ public class RpcClientTest {
|
||||
|
||||
rpcClient.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHealthCheck() throws IllegalAccessException, NacosException {
|
||||
Random random = new Random();
|
||||
int retry = random.nextInt(10);
|
||||
when(rpcClientConfig.healthCheckRetryTimes()).thenReturn(retry);
|
||||
rpcClient.rpcClientStatus.set(RpcClientStatus.RUNNING);
|
||||
rpcClient.currentConnection = connection;
|
||||
doThrow(new NacosException()).when(connection).request(any(), anyLong());
|
||||
try {
|
||||
healthCheck.invoke(rpcClient);
|
||||
} catch (InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
verify(connection, times(retry + 1)).request(any(), anyLong());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNextRpcServerForIpv4WithPort() {
|
||||
RpcClient rpcClient = buildTestNextRpcServerClient();
|
||||
rpcClient.serverListFactory(serverListFactory);
|
||||
when(serverListFactory.genNextServer()).thenReturn("127.0.0.1:7777");
|
||||
RpcClient.ServerInfo actual = rpcClient.nextRpcServer();
|
||||
assertEquals("127.0.0.1:7777", actual.getAddress());
|
||||
assertEquals("127.0.0.1", actual.getServerIp());
|
||||
assertEquals(7777, actual.getServerPort());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNextRpcServerForIpv4WithoutPort() {
|
||||
RpcClient rpcClient = buildTestNextRpcServerClient();
|
||||
rpcClient.serverListFactory(serverListFactory);
|
||||
when(serverListFactory.genNextServer()).thenReturn("127.0.0.1");
|
||||
RpcClient.ServerInfo actual = rpcClient.nextRpcServer();
|
||||
assertEquals("127.0.0.1:8848", actual.getAddress());
|
||||
assertEquals("127.0.0.1", actual.getServerIp());
|
||||
assertEquals(8848, actual.getServerPort());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNextRpcServerForIpv6WithPort() {
|
||||
RpcClient rpcClient = buildTestNextRpcServerClient();
|
||||
rpcClient.serverListFactory(serverListFactory);
|
||||
when(serverListFactory.genNextServer()).thenReturn("[fe80::35ba:6827:c5ff:d161%11]:7777");
|
||||
RpcClient.ServerInfo actual = rpcClient.nextRpcServer();
|
||||
assertEquals("[fe80::35ba:6827:c5ff:d161%11]:7777", actual.getAddress());
|
||||
assertEquals("[fe80::35ba:6827:c5ff:d161%11]", actual.getServerIp());
|
||||
assertEquals(7777, actual.getServerPort());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNextRpcServerForIpv6WithoutPort() {
|
||||
RpcClient rpcClient = buildTestNextRpcServerClient();
|
||||
rpcClient.serverListFactory(serverListFactory);
|
||||
when(serverListFactory.genNextServer()).thenReturn("[fe80::35ba:6827:c5ff:d161%11]");
|
||||
RpcClient.ServerInfo actual = rpcClient.nextRpcServer();
|
||||
assertEquals("[fe80::35ba:6827:c5ff:d161%11]:8848", actual.getAddress());
|
||||
assertEquals("[fe80::35ba:6827:c5ff:d161%11]", actual.getServerIp());
|
||||
assertEquals(8848, actual.getServerPort());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNextRpcServerForDomainWithPort() {
|
||||
RpcClient rpcClient = buildTestNextRpcServerClient();
|
||||
rpcClient.serverListFactory(serverListFactory);
|
||||
when(serverListFactory.genNextServer()).thenReturn("nacos.io:7777");
|
||||
RpcClient.ServerInfo actual = rpcClient.nextRpcServer();
|
||||
assertEquals("nacos.io:7777", actual.getAddress());
|
||||
assertEquals("nacos.io", actual.getServerIp());
|
||||
assertEquals(7777, actual.getServerPort());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNextRpcServerForDomainWithoutPort() {
|
||||
RpcClient rpcClient = buildTestNextRpcServerClient();
|
||||
rpcClient.serverListFactory(serverListFactory);
|
||||
when(serverListFactory.genNextServer()).thenReturn("nacos.io");
|
||||
RpcClient.ServerInfo actual = rpcClient.nextRpcServer();
|
||||
assertEquals("nacos.io:8848", actual.getAddress());
|
||||
assertEquals("nacos.io", actual.getServerIp());
|
||||
assertEquals(8848, actual.getServerPort());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNextRpcServerForLocalhostWithPort() {
|
||||
RpcClient rpcClient = buildTestNextRpcServerClient();
|
||||
rpcClient.serverListFactory(serverListFactory);
|
||||
when(serverListFactory.genNextServer()).thenReturn("localhost:7777");
|
||||
RpcClient.ServerInfo actual = rpcClient.nextRpcServer();
|
||||
assertEquals("localhost:7777", actual.getAddress());
|
||||
assertEquals("localhost", actual.getServerIp());
|
||||
assertEquals(7777, actual.getServerPort());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNextRpcServerForLocalhostWithoutPort() {
|
||||
RpcClient rpcClient = buildTestNextRpcServerClient();
|
||||
rpcClient.serverListFactory(serverListFactory);
|
||||
when(serverListFactory.genNextServer()).thenReturn("localhost");
|
||||
RpcClient.ServerInfo actual = rpcClient.nextRpcServer();
|
||||
assertEquals("localhost:8848", actual.getAddress());
|
||||
assertEquals("localhost", actual.getServerIp());
|
||||
assertEquals(8848, actual.getServerPort());
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testNextRpcServerForEmpty() {
|
||||
RpcClient rpcClient = buildTestNextRpcServerClient();
|
||||
rpcClient.serverListFactory(serverListFactory);
|
||||
when(serverListFactory.genNextServer()).thenReturn("");
|
||||
rpcClient.nextRpcServer();
|
||||
}
|
||||
|
||||
private RpcClient buildTestNextRpcServerClient() {
|
||||
return new RpcClient(DefaultGrpcClientConfig.newBuilder().build()) {
|
||||
@Override
|
||||
public ConnectionType getConnectionType() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int rpcPortOffset() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Connection connectToServer(ServerInfo serverInfo) throws Exception {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServerInfo nextRpcServer() {
|
||||
return super.nextRpcServer();
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -33,38 +33,41 @@ import static org.mockito.Mockito.spy;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class GrpcClientTest {
|
||||
|
||||
|
||||
GrpcClient grpcClient;
|
||||
|
||||
|
||||
Method createNewManagedChannelMethod;
|
||||
|
||||
|
||||
Method createNewChannelStubMethod;
|
||||
|
||||
|
||||
ManagedChannel managedChannel;
|
||||
|
||||
|
||||
RpcClient.ServerInfo serverInfo;
|
||||
|
||||
|
||||
@Before
|
||||
public void setUp() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
|
||||
grpcClient = spy(new GrpcClient("testClient") {
|
||||
GrpcClientConfig clientConfig = DefaultGrpcClientConfig.newBuilder().setName("testClient").build();
|
||||
grpcClient = spy(new GrpcClient(clientConfig) {
|
||||
@Override
|
||||
public int rpcPortOffset() {
|
||||
return 1000;
|
||||
}
|
||||
});
|
||||
RpcClient.ServerInfo serverInfo = spy(new RpcClient.ServerInfo("10.10.10.10", 8848));
|
||||
createNewManagedChannelMethod = GrpcClient.class.getDeclaredMethod("createNewManagedChannel", String.class, int.class);
|
||||
createNewManagedChannelMethod = GrpcClient.class.getDeclaredMethod("createNewManagedChannel", String.class,
|
||||
int.class);
|
||||
createNewManagedChannelMethod.setAccessible(true);
|
||||
int port = serverInfo.getServerPort() + grpcClient.rpcPortOffset();
|
||||
managedChannel = (ManagedChannel) createNewManagedChannelMethod.invoke(grpcClient, serverInfo.getServerIp(), port);
|
||||
managedChannel = (ManagedChannel) createNewManagedChannelMethod.invoke(grpcClient, serverInfo.getServerIp(),
|
||||
port);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testCreateNewManagedChannel() throws InvocationTargetException, IllegalAccessException {
|
||||
GrpcConnection grpcConnection = new GrpcConnection(serverInfo, null);
|
||||
grpcConnection.setChannel(managedChannel);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void createNewChannelStub() throws InvocationTargetException, IllegalAccessException, NoSuchMethodException {
|
||||
createNewChannelStubMethod = GrpcClient.class.getDeclaredMethod("createNewChannelStub", ManagedChannel.class);
|
||||
@ -72,10 +75,10 @@ public class GrpcClientTest {
|
||||
Object invoke = createNewChannelStubMethod.invoke(grpcClient, managedChannel);
|
||||
Assert.assertTrue(invoke instanceof RequestGrpc.RequestFutureStub);
|
||||
}
|
||||
|
||||
|
||||
@After
|
||||
public void close() {
|
||||
managedChannel.shutdownNow();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright 1999-2020 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.common.remote.client.grpc;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
public class GrpcConstantsTest {
|
||||
|
||||
@Test
|
||||
public void testGetRpcParams() {
|
||||
Class clazz = GrpcConstants.class;
|
||||
Field[] declaredFields = clazz.getDeclaredFields();
|
||||
int i = 0;
|
||||
for (Field declaredField : declaredFields) {
|
||||
declaredField.setAccessible(true);
|
||||
if (declaredField.getType().equals(String.class) && null != declaredField.getAnnotation(
|
||||
GrpcConstants.GRpcConfigLabel.class)) {
|
||||
i++;
|
||||
}
|
||||
}
|
||||
assertEquals(i, GrpcConstants.getRpcParams().size());
|
||||
}
|
||||
}
|
@ -17,12 +17,12 @@
|
||||
package com.alibaba.nacos.common.utils;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import java.util.ConcurrentModificationException;
|
||||
import java.util.HashSet;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* ConcurrentHashSet Test.
|
||||
@ -32,108 +32,200 @@ import java.util.Set;
|
||||
*/
|
||||
public class ConcurrentHashSetTest {
|
||||
|
||||
Set<Integer> concurrentHashSet;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
concurrentHashSet = new ConcurrentHashSet<>();
|
||||
concurrentHashSet.add(1);
|
||||
concurrentHashSet.add(2);
|
||||
concurrentHashSet.add(3);
|
||||
concurrentHashSet.add(4);
|
||||
concurrentHashSet.add(5);
|
||||
@Test
|
||||
public void testBasicOps() {
|
||||
Set<Integer> set = new ConcurrentHashSet<>();
|
||||
|
||||
// addition
|
||||
Assert.assertTrue(set.add(0));
|
||||
Assert.assertTrue(set.add(1));
|
||||
Assert.assertTrue(set.contains(0));
|
||||
Assert.assertTrue(set.contains(1));
|
||||
Assert.assertFalse(set.contains(-1));
|
||||
Assert.assertEquals(2, set.size());
|
||||
|
||||
// iter
|
||||
for (int i : set) {
|
||||
Assert.assertTrue(i == 0 || i == 1);
|
||||
}
|
||||
|
||||
// removal
|
||||
Assert.assertTrue(set.remove(0));
|
||||
Assert.assertFalse(set.remove(0));
|
||||
Assert.assertFalse(set.contains(0));
|
||||
Assert.assertTrue(set.contains(1));
|
||||
Assert.assertEquals(1, set.size());
|
||||
|
||||
// clear
|
||||
Assert.assertFalse(set.isEmpty());
|
||||
set.clear();
|
||||
Assert.assertEquals(0, set.size());
|
||||
Assert.assertTrue(set.isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultiThread() throws Exception {
|
||||
int count = 5;
|
||||
SetMultiThreadChecker hashSetChecker = new SetMultiThreadChecker(new HashSet<>());
|
||||
hashSetChecker.start();
|
||||
while (!hashSetChecker.hasConcurrentError() && hashSetChecker.isRunning()) {
|
||||
TimeUnit.SECONDS.sleep(1);
|
||||
if (count <= 0) {
|
||||
hashSetChecker.stop();
|
||||
}
|
||||
count--;
|
||||
}
|
||||
Assert.assertTrue(hashSetChecker.hasConcurrentError());
|
||||
|
||||
count = 5;
|
||||
SetMultiThreadChecker concurrentSetChecker = new SetMultiThreadChecker(new ConcurrentHashSet<>());
|
||||
concurrentSetChecker.start();
|
||||
while (!concurrentSetChecker.hasConcurrentError() && concurrentSetChecker.isRunning()) {
|
||||
TimeUnit.SECONDS.sleep(1);
|
||||
if (count == 0) {
|
||||
concurrentSetChecker.stop();
|
||||
}
|
||||
count--;
|
||||
}
|
||||
Assert.assertFalse(concurrentSetChecker.hasConcurrentError());
|
||||
}
|
||||
|
||||
static class SetMultiThreadChecker {
|
||||
|
||||
private final AddDataThread addThread;
|
||||
|
||||
private final DeleteDataThread deleteThread;
|
||||
|
||||
private final IteratorThread iteratorThread;
|
||||
|
||||
public SetMultiThreadChecker(Set<Integer> setToCheck) {
|
||||
for (int i = 0; i < 1000; i++) {
|
||||
setToCheck.add(i);
|
||||
}
|
||||
this.addThread = new AddDataThread(setToCheck);
|
||||
this.deleteThread = new DeleteDataThread(setToCheck);
|
||||
this.iteratorThread = new IteratorThread(setToCheck);
|
||||
}
|
||||
|
||||
public void start() {
|
||||
new Thread(addThread).start();
|
||||
new Thread(deleteThread).start();
|
||||
new Thread(iteratorThread).start();
|
||||
}
|
||||
|
||||
public boolean hasConcurrentError() {
|
||||
return addThread.hasConcurrentError() || deleteThread.hasConcurrentError() || iteratorThread.hasConcurrentError();
|
||||
}
|
||||
|
||||
public boolean isRunning() {
|
||||
return addThread.isRunning() || deleteThread.isRunning() || iteratorThread.isRunning();
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
addThread.stop();
|
||||
deleteThread.stop();
|
||||
iteratorThread.stop();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void size() {
|
||||
Assert.assertEquals(concurrentHashSet.size(), 5);
|
||||
}
|
||||
abstract static class ConcurrentCheckThread implements Runnable {
|
||||
|
||||
@Test
|
||||
public void contains() {
|
||||
Assert.assertTrue(concurrentHashSet.contains(1));
|
||||
}
|
||||
protected final Set<Integer> hashSet;
|
||||
|
||||
@Test
|
||||
public void testMultithreaded() {
|
||||
try {
|
||||
concurrentHashSet = new HashSet<>();
|
||||
executeThread();
|
||||
} catch (Exception e) {
|
||||
Assert.assertTrue(e instanceof ConcurrentModificationException);
|
||||
protected boolean concurrentError = false;
|
||||
|
||||
protected boolean finish = false;
|
||||
|
||||
public ConcurrentCheckThread(Set<Integer> hashSet) {
|
||||
this.hashSet = hashSet;
|
||||
}
|
||||
|
||||
public boolean hasConcurrentError() {
|
||||
return concurrentError;
|
||||
}
|
||||
|
||||
try {
|
||||
concurrentHashSet = new ConcurrentHashSet<>();
|
||||
executeThread();
|
||||
} catch (Exception e) {
|
||||
Assert.assertNull(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* execute muti thread.
|
||||
*/
|
||||
public void executeThread() throws Exception {
|
||||
for (int i = 0; i < 1000; i++) {
|
||||
concurrentHashSet.add(i);
|
||||
public void stop() {
|
||||
finish = true;
|
||||
}
|
||||
|
||||
new Thread(new AddDataThread(concurrentHashSet)).start();
|
||||
new Thread(new DeleteDataThread(concurrentHashSet)).start();
|
||||
new Thread(new IteratorThread(concurrentHashSet)).start();
|
||||
public boolean isRunning() {
|
||||
return !finish;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
while (isRunning()) {
|
||||
process();
|
||||
}
|
||||
} catch (ConcurrentModificationException e) {
|
||||
concurrentError = true;
|
||||
} finally {
|
||||
finish = true;
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract void process();
|
||||
}
|
||||
|
||||
//add data thread
|
||||
static class AddDataThread implements Runnable {
|
||||
Set<Integer> hashSet;
|
||||
static class AddDataThread extends ConcurrentCheckThread implements Runnable {
|
||||
|
||||
public AddDataThread(Set<Integer> hashSet) {
|
||||
this.hashSet = hashSet;
|
||||
super(hashSet);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
while (true) {
|
||||
int random = new Random().nextInt();
|
||||
hashSet.add(random);
|
||||
}
|
||||
protected void process() {
|
||||
int random = new Random().nextInt(1000);
|
||||
hashSet.add(random);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// delete data thread
|
||||
static class DeleteDataThread implements Runnable {
|
||||
Set<Integer> hashSet;
|
||||
static class DeleteDataThread extends ConcurrentCheckThread implements Runnable {
|
||||
|
||||
public DeleteDataThread(Set<Integer> hashSet) {
|
||||
this.hashSet = hashSet;
|
||||
super(hashSet);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
protected void process() {
|
||||
int random = new Random().nextInt(1000);
|
||||
while (true) {
|
||||
hashSet.remove(random);
|
||||
}
|
||||
hashSet.remove(random);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static class IteratorThread implements Runnable {
|
||||
|
||||
Set<Integer> hashSet;
|
||||
static class IteratorThread extends ConcurrentCheckThread implements Runnable {
|
||||
|
||||
public IteratorThread(Set<Integer> hashSet) {
|
||||
this.hashSet = hashSet;
|
||||
super(hashSet);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
System.out.println("start -- hashSet.size() : " + hashSet.size());
|
||||
for (Integer str : hashSet) {
|
||||
System.out.println("value : " + str);
|
||||
Integer f = null;
|
||||
try {
|
||||
while (isRunning()) {
|
||||
for (Integer i : hashSet) {
|
||||
f = i;
|
||||
}
|
||||
}
|
||||
} catch (ConcurrentModificationException e) {
|
||||
concurrentError = true;
|
||||
} finally {
|
||||
finish = true;
|
||||
}
|
||||
System.out.println("finished at " + f);
|
||||
System.out.println("end -- hashSet.size() : " + hashSet.size());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void process() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -23,6 +23,7 @@ import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
|
||||
import com.fasterxml.jackson.annotation.JsonSubTypes;
|
||||
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
@ -474,6 +475,7 @@ public class JacksonUtilsTest {
|
||||
Assert.assertEquals(999, restResult.getData().get("integer"));
|
||||
}
|
||||
|
||||
@JsonPropertyOrder({ "aLong", "aInteger", "aBoolean"})
|
||||
static class TestOfAtomicObject {
|
||||
|
||||
public AtomicLong aLong = new AtomicLong(0);
|
||||
@ -558,6 +560,7 @@ public class JacksonUtilsTest {
|
||||
}
|
||||
}
|
||||
|
||||
@JsonPropertyOrder({ "value", "key" })
|
||||
static class TestOfGetter {
|
||||
|
||||
public String getKey() {
|
||||
@ -749,4 +752,4 @@ public class JacksonUtilsTest {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -117,6 +117,10 @@
|
||||
<groupId>org.yaml</groupId>
|
||||
<artifactId>snakeyaml</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.alibaba.nacos</groupId>
|
||||
<artifactId>nacos-datasource-plugin</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
|
@ -37,6 +37,11 @@ public class Constants {
|
||||
*/
|
||||
public static final String BASE_DIR = "config-data";
|
||||
|
||||
/**
|
||||
* The derby base dir.
|
||||
*/
|
||||
public static final String DERBY_BASE_DIR = "derby-data";
|
||||
|
||||
/**
|
||||
* Back up file directory in server side.
|
||||
*
|
||||
@ -111,6 +116,8 @@ public class Constants {
|
||||
|
||||
public static final String BASE_PATH = "/v1/cs";
|
||||
|
||||
public static final String BASE_V2_PATH = "/v2/cs";
|
||||
|
||||
public static final String OPS_CONTROLLER_PATH = BASE_PATH + "/ops";
|
||||
|
||||
public static final String CAPACITY_CONTROLLER_PATH = BASE_PATH + "/capacity";
|
||||
@ -119,10 +126,14 @@ public class Constants {
|
||||
|
||||
public static final String CONFIG_CONTROLLER_PATH = BASE_PATH + "/configs";
|
||||
|
||||
public static final String CONFIG_CONTROLLER_V2_PATH = BASE_V2_PATH + "/config";
|
||||
|
||||
public static final String HEALTH_CONTROLLER_PATH = BASE_PATH + "/health";
|
||||
|
||||
public static final String HISTORY_CONTROLLER_PATH = BASE_PATH + "/history";
|
||||
|
||||
public static final String HISTORY_CONTROLLER_V2_PATH = BASE_V2_PATH + "/history";
|
||||
|
||||
public static final String LISTENER_CONTROLLER_PATH = BASE_PATH + "/listener";
|
||||
|
||||
public static final String NAMESPACE_CONTROLLER_PATH = BASE_PATH + "/namespaces";
|
||||
|
@ -22,7 +22,6 @@ import com.alibaba.nacos.auth.annotation.Secured;
|
||||
import com.alibaba.nacos.common.model.RestResult;
|
||||
import com.alibaba.nacos.common.model.RestResultUtils;
|
||||
import com.alibaba.nacos.common.utils.DateFormatUtils;
|
||||
import com.alibaba.nacos.common.utils.MapUtil;
|
||||
import com.alibaba.nacos.common.utils.NamespaceUtil;
|
||||
import com.alibaba.nacos.common.utils.Pair;
|
||||
import com.alibaba.nacos.common.utils.StringUtils;
|
||||
@ -38,10 +37,12 @@ import com.alibaba.nacos.config.server.model.Page;
|
||||
import com.alibaba.nacos.config.server.model.SameConfigPolicy;
|
||||
import com.alibaba.nacos.config.server.model.SampleResult;
|
||||
import com.alibaba.nacos.config.server.model.event.ConfigDataChangeEvent;
|
||||
import com.alibaba.nacos.config.server.model.ConfigRequestInfo;
|
||||
import com.alibaba.nacos.config.server.model.form.ConfigForm;
|
||||
import com.alibaba.nacos.config.server.monitor.MetricsMonitor;
|
||||
import com.alibaba.nacos.config.server.result.code.ResultCodeEnum;
|
||||
import com.alibaba.nacos.config.server.service.AggrWhitelist;
|
||||
import com.alibaba.nacos.config.server.service.ConfigChangePublisher;
|
||||
import com.alibaba.nacos.config.server.service.ConfigOperationService;
|
||||
import com.alibaba.nacos.config.server.service.ConfigSubService;
|
||||
import com.alibaba.nacos.config.server.service.repository.PersistService;
|
||||
import com.alibaba.nacos.config.server.service.trace.ConfigTraceService;
|
||||
@ -108,12 +109,15 @@ public class ConfigController {
|
||||
|
||||
private final PersistService persistService;
|
||||
|
||||
private final ConfigOperationService configOperationService;
|
||||
|
||||
private final ConfigSubService configSubService;
|
||||
|
||||
public ConfigController(ConfigServletInner inner, PersistService persistService,
|
||||
public ConfigController(ConfigServletInner inner, PersistService persistService, ConfigOperationService configOperationService,
|
||||
ConfigSubService configSubService) {
|
||||
this.inner = inner;
|
||||
this.persistService = persistService;
|
||||
this.configOperationService = configOperationService;
|
||||
this.configSubService = configSubService;
|
||||
}
|
||||
|
||||
@ -142,16 +146,6 @@ public class ConfigController {
|
||||
@RequestParam(value = "type", required = false) String type,
|
||||
@RequestParam(value = "schema", required = false) String schema) throws NacosException {
|
||||
|
||||
final String srcIp = RequestUtil.getRemoteIp(request);
|
||||
final String requestIpApp = RequestUtil.getAppName(request);
|
||||
if (StringUtils.isBlank(srcUser)) {
|
||||
srcUser = RequestUtil.getSrcUserName(request);
|
||||
}
|
||||
//check type
|
||||
if (!ConfigType.isValidType(type)) {
|
||||
type = ConfigType.getDefaultType().getType();
|
||||
}
|
||||
|
||||
// encrypted
|
||||
Pair<String, String> pair = EncryptionHandler.encryptHandler(dataId, content);
|
||||
content = pair.getSecond();
|
||||
@ -160,47 +154,37 @@ public class ConfigController {
|
||||
ParamUtils.checkTenant(tenant);
|
||||
ParamUtils.checkParam(dataId, group, "datumId", content);
|
||||
ParamUtils.checkParam(tag);
|
||||
Map<String, Object> configAdvanceInfo = new HashMap<>(10);
|
||||
MapUtil.putIfValNoNull(configAdvanceInfo, "config_tags", configTags);
|
||||
MapUtil.putIfValNoNull(configAdvanceInfo, "desc", desc);
|
||||
MapUtil.putIfValNoNull(configAdvanceInfo, "use", use);
|
||||
MapUtil.putIfValNoNull(configAdvanceInfo, "effect", effect);
|
||||
MapUtil.putIfValNoNull(configAdvanceInfo, "type", type);
|
||||
MapUtil.putIfValNoNull(configAdvanceInfo, "schema", schema);
|
||||
ParamUtils.checkParam(configAdvanceInfo);
|
||||
|
||||
if (AggrWhitelist.isAggrDataId(dataId)) {
|
||||
LOGGER.warn("[aggr-conflict] {} attempt to publish single data, {}, {}", RequestUtil.getRemoteIp(request),
|
||||
dataId, group);
|
||||
throw new NacosException(NacosException.NO_RIGHT, "dataId:" + dataId + " is aggr");
|
||||
|
||||
ConfigForm configForm = new ConfigForm();
|
||||
configForm.setDataId(dataId);
|
||||
configForm.setGroup(group);
|
||||
configForm.setNamespaceId(tenant);
|
||||
configForm.setContent(content);
|
||||
configForm.setTag(tag);
|
||||
configForm.setAppName(appName);
|
||||
configForm.setSrcUser(srcUser);
|
||||
configForm.setConfigTags(configTags);
|
||||
configForm.setDesc(desc);
|
||||
configForm.setUse(use);
|
||||
configForm.setEffect(effect);
|
||||
configForm.setType(type);
|
||||
configForm.setSchema(schema);
|
||||
|
||||
if (StringUtils.isBlank(srcUser)) {
|
||||
configForm.setSrcUser(RequestUtil.getSrcUserName(request));
|
||||
}
|
||||
|
||||
final Timestamp time = TimeUtils.getCurrentTime();
|
||||
String betaIps = request.getHeader("betaIps");
|
||||
ConfigInfo configInfo = new ConfigInfo(dataId, group, tenant, appName, content);
|
||||
configInfo.setType(type);
|
||||
if (!ConfigType.isValidType(type)) {
|
||||
configForm.setType(ConfigType.getDefaultType().getType());
|
||||
}
|
||||
|
||||
ConfigRequestInfo configRequestInfo = new ConfigRequestInfo();
|
||||
configRequestInfo.setSrcIp(RequestUtil.getRemoteIp(request));
|
||||
configRequestInfo.setRequestIpApp(RequestUtil.getAppName(request));
|
||||
configRequestInfo.setBetaIps(request.getHeader("betaIps"));
|
||||
|
||||
String encryptedDataKey = pair.getFirst();
|
||||
configInfo.setEncryptedDataKey(encryptedDataKey);
|
||||
if (StringUtils.isBlank(betaIps)) {
|
||||
if (StringUtils.isBlank(tag)) {
|
||||
persistService.insertOrUpdate(srcIp, srcUser, configInfo, time, configAdvanceInfo, false);
|
||||
ConfigChangePublisher.notifyConfigChange(
|
||||
new ConfigDataChangeEvent(false, dataId, group, tenant, time.getTime()));
|
||||
} else {
|
||||
persistService.insertOrUpdateTag(configInfo, tag, srcIp, srcUser, time, false);
|
||||
ConfigChangePublisher.notifyConfigChange(
|
||||
new ConfigDataChangeEvent(false, dataId, group, tenant, tag, time.getTime()));
|
||||
}
|
||||
} else {
|
||||
// beta publish
|
||||
configInfo.setEncryptedDataKey(encryptedDataKey);
|
||||
persistService.insertOrUpdateBeta(configInfo, betaIps, srcIp, srcUser, time, false);
|
||||
ConfigChangePublisher.notifyConfigChange(
|
||||
new ConfigDataChangeEvent(true, dataId, group, tenant, time.getTime()));
|
||||
}
|
||||
ConfigTraceService.logPersistenceEvent(dataId, group, tenant, requestIpApp, time.getTime(),
|
||||
InetUtils.getSelfIP(), ConfigTraceService.PERSISTENCE_EVENT_PUB, content);
|
||||
return true;
|
||||
|
||||
return configOperationService.publishConfig(configForm, configRequestInfo, encryptedDataKey);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -276,19 +260,11 @@ public class ConfigController {
|
||||
ParamUtils.checkTenant(tenant);
|
||||
ParamUtils.checkParam(dataId, group, "datumId", "rm");
|
||||
ParamUtils.checkParam(tag);
|
||||
|
||||
String clientIp = RequestUtil.getRemoteIp(request);
|
||||
String srcUser = RequestUtil.getSrcUserName(request);
|
||||
if (StringUtils.isBlank(tag)) {
|
||||
persistService.removeConfigInfo(dataId, group, tenant, clientIp, srcUser);
|
||||
} else {
|
||||
persistService.removeConfigInfoTag(dataId, group, tenant, tag, clientIp, srcUser);
|
||||
}
|
||||
final Timestamp time = TimeUtils.getCurrentTime();
|
||||
ConfigTraceService.logPersistenceEvent(dataId, group, tenant, null, time.getTime(), clientIp,
|
||||
ConfigTraceService.PERSISTENCE_EVENT_REMOVE, null);
|
||||
ConfigChangePublisher.notifyConfigChange(
|
||||
new ConfigDataChangeEvent(false, dataId, group, tenant, tag, time.getTime()));
|
||||
return true;
|
||||
|
||||
return configOperationService.deleteConfig(dataId, group, tenant, tag, clientIp, srcUser);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -475,10 +451,10 @@ public class ConfigController {
|
||||
Pair<String, String> pair = EncryptionHandler.decryptHandler(dataId, encryptedDataKey, ci.getContent());
|
||||
ci.setContent(pair.getSecond());
|
||||
}
|
||||
return RestResultUtils.success("stop beta ok", ci);
|
||||
return RestResultUtils.success("query beta ok", ci);
|
||||
} catch (Throwable e) {
|
||||
LOGGER.error("remove beta data error", e);
|
||||
return RestResultUtils.failed("remove beta data error");
|
||||
LOGGER.error("query beta data error", e);
|
||||
return RestResultUtils.failed("query beta data error");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -16,10 +16,14 @@
|
||||
|
||||
package com.alibaba.nacos.config.server.controller;
|
||||
|
||||
import com.alibaba.nacos.api.model.v2.ErrorCode;
|
||||
import com.alibaba.nacos.api.model.v2.Result;
|
||||
import com.alibaba.nacos.common.constant.HttpHeaderConsts;
|
||||
import com.alibaba.nacos.common.http.param.MediaType;
|
||||
import com.alibaba.nacos.common.utils.IoUtils;
|
||||
import com.alibaba.nacos.common.utils.StringUtils;
|
||||
import com.alibaba.nacos.common.utils.JacksonUtils;
|
||||
import com.alibaba.nacos.common.utils.Pair;
|
||||
import com.alibaba.nacos.common.utils.StringUtils;
|
||||
import com.alibaba.nacos.config.server.constant.Constants;
|
||||
import com.alibaba.nacos.config.server.enums.FileTypeEnum;
|
||||
import com.alibaba.nacos.config.server.model.CacheItem;
|
||||
@ -37,6 +41,8 @@ import com.alibaba.nacos.config.server.utils.Protocol;
|
||||
import com.alibaba.nacos.config.server.utils.RequestUtil;
|
||||
import com.alibaba.nacos.config.server.utils.TimeUtils;
|
||||
import com.alibaba.nacos.plugin.encryption.handler.EncryptionHandler;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
@ -65,6 +71,8 @@ public class ConfigServletInner {
|
||||
|
||||
private static final int START_LONG_POLLING_VERSION_NUM = 204;
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(ConfigServletInner.class);
|
||||
|
||||
private final LongPollingService longPollingService;
|
||||
|
||||
private final PersistService persistService;
|
||||
@ -116,16 +124,29 @@ public class ConfigServletInner {
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute to get config API.
|
||||
* Execute to get config [API V1].
|
||||
*/
|
||||
public String doGetConfig(HttpServletRequest request, HttpServletResponse response, String dataId, String group,
|
||||
String tenant, String tag, String isNotify, String clientIp) throws IOException, ServletException {
|
||||
return doGetConfig(request, response, dataId, group, tenant, tag, isNotify, clientIp, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute to get config [API V1] or [API V2].
|
||||
*/
|
||||
public String doGetConfig(HttpServletRequest request, HttpServletResponse response, String dataId, String group,
|
||||
String tenant, String tag, String isNotify, String clientIp, boolean isV2)
|
||||
throws IOException, ServletException {
|
||||
|
||||
boolean notify = false;
|
||||
if (StringUtils.isNotBlank(isNotify)) {
|
||||
notify = Boolean.parseBoolean(isNotify);
|
||||
}
|
||||
|
||||
if (isV2) {
|
||||
response.setHeader(HttpHeaderConsts.CONTENT_TYPE, MediaType.APPLICATION_JSON);
|
||||
}
|
||||
|
||||
final String groupKey = GroupKey2.getKey(dataId, group, tenant);
|
||||
String autoTag = request.getHeader("Vipserver-Tag");
|
||||
|
||||
@ -153,6 +174,10 @@ public class ConfigServletInner {
|
||||
String contentTypeHeader = fileTypeEnum.getContentType();
|
||||
response.setHeader(HttpHeaderConsts.CONTENT_TYPE, contentTypeHeader);
|
||||
|
||||
if (isV2) {
|
||||
response.setHeader(HttpHeaderConsts.CONTENT_TYPE, MediaType.APPLICATION_JSON);
|
||||
}
|
||||
|
||||
File file = null;
|
||||
ConfigInfoBase configInfoBase = null;
|
||||
PrintWriter out;
|
||||
@ -200,7 +225,7 @@ public class ConfigServletInner {
|
||||
// no data",
|
||||
// new Object[]{clientIp, groupKey});
|
||||
|
||||
return get404Result(response);
|
||||
return get404Result(response, isV2);
|
||||
}
|
||||
isSli = true;
|
||||
}
|
||||
@ -229,9 +254,7 @@ public class ConfigServletInner {
|
||||
// no data",
|
||||
// new Object[]{clientIp, groupKey});
|
||||
|
||||
response.setStatus(HttpServletResponse.SC_NOT_FOUND);
|
||||
response.getWriter().println("config data not exist");
|
||||
return HttpServletResponse.SC_NOT_FOUND + "";
|
||||
return get404Result(response, isV2);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -250,10 +273,14 @@ public class ConfigServletInner {
|
||||
}
|
||||
|
||||
if (PropertyUtil.isDirectRead()) {
|
||||
Pair<String, String> pair = EncryptionHandler.decryptHandler(dataId,
|
||||
configInfoBase.getEncryptedDataKey(), configInfoBase.getContent());
|
||||
Pair<String, String> pair = EncryptionHandler
|
||||
.decryptHandler(dataId, configInfoBase.getEncryptedDataKey(), configInfoBase.getContent());
|
||||
out = response.getWriter();
|
||||
out.print(pair.getSecond());
|
||||
if (isV2) {
|
||||
out.print(JacksonUtils.toJson(Result.success(pair.getSecond())));
|
||||
} else {
|
||||
out.print(pair.getSecond());
|
||||
}
|
||||
out.flush();
|
||||
out.close();
|
||||
} else {
|
||||
@ -262,7 +289,11 @@ public class ConfigServletInner {
|
||||
Pair<String, String> pair = EncryptionHandler.decryptHandler(dataId, encryptedDataKey, fileContent);
|
||||
String decryptContent = pair.getSecond();
|
||||
out = response.getWriter();
|
||||
out.print(decryptContent);
|
||||
if (isV2) {
|
||||
out.print(JacksonUtils.toJson(Result.success(decryptContent)));
|
||||
} else {
|
||||
out.print(decryptContent);
|
||||
}
|
||||
out.flush();
|
||||
out.close();
|
||||
}
|
||||
@ -290,15 +321,12 @@ public class ConfigServletInner {
|
||||
.logPullEvent(dataId, group, tenant, requestIpApp, -1, ConfigTraceService.PULL_EVENT_NOTFOUND, -1,
|
||||
requestIp, notify && isSli);
|
||||
|
||||
return get404Result(response);
|
||||
return get404Result(response, isV2);
|
||||
|
||||
} else {
|
||||
|
||||
PULL_LOG.info("[client-get] clientIp={}, {}, get data during dump", clientIp, groupKey);
|
||||
|
||||
response.setStatus(HttpServletResponse.SC_CONFLICT);
|
||||
response.getWriter().println("requested file is being modified, please try later.");
|
||||
return HttpServletResponse.SC_CONFLICT + "";
|
||||
return get409Result(response, isV2);
|
||||
|
||||
}
|
||||
|
||||
@ -309,12 +337,29 @@ public class ConfigServletInner {
|
||||
ConfigCacheService.releaseReadLock(groupKey);
|
||||
}
|
||||
|
||||
private String get404Result(HttpServletResponse response) throws IOException {
|
||||
private String get404Result(HttpServletResponse response, boolean isV2) throws IOException {
|
||||
response.setStatus(HttpServletResponse.SC_NOT_FOUND);
|
||||
response.getWriter().println("config data not exist");
|
||||
PrintWriter writer = response.getWriter();
|
||||
if (isV2) {
|
||||
writer.println(JacksonUtils.toJson(Result.failure(ErrorCode.RESOURCE_NOT_FOUND, "config data not exist")));
|
||||
} else {
|
||||
writer.println("config data not exist");
|
||||
}
|
||||
return HttpServletResponse.SC_NOT_FOUND + "";
|
||||
}
|
||||
|
||||
private String get409Result(HttpServletResponse response, boolean isV2) throws IOException {
|
||||
response.setStatus(HttpServletResponse.SC_CONFLICT);
|
||||
PrintWriter writer = response.getWriter();
|
||||
if (isV2) {
|
||||
writer.println(JacksonUtils.toJson(Result
|
||||
.failure(ErrorCode.RESOURCE_CONFLICT, "requested file is being modified, please try later.")));
|
||||
} else {
|
||||
writer.println("requested file is being modified, please try later.");
|
||||
}
|
||||
return HttpServletResponse.SC_CONFLICT + "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to add read lock.
|
||||
*
|
||||
|
@ -18,18 +18,16 @@ package com.alibaba.nacos.config.server.controller;
|
||||
|
||||
import com.alibaba.nacos.auth.annotation.Secured;
|
||||
import com.alibaba.nacos.common.utils.NamespaceUtil;
|
||||
import com.alibaba.nacos.common.utils.Pair;
|
||||
import com.alibaba.nacos.common.utils.StringUtils;
|
||||
import com.alibaba.nacos.config.server.constant.Constants;
|
||||
import com.alibaba.nacos.config.server.model.ConfigHistoryInfo;
|
||||
import com.alibaba.nacos.config.server.model.ConfigInfoWrapper;
|
||||
import com.alibaba.nacos.config.server.model.Page;
|
||||
import com.alibaba.nacos.config.server.service.repository.PersistService;
|
||||
import com.alibaba.nacos.config.server.service.HistoryService;
|
||||
import com.alibaba.nacos.config.server.utils.ParamUtils;
|
||||
import com.alibaba.nacos.plugin.auth.constant.ActionTypes;
|
||||
import com.alibaba.nacos.plugin.auth.constant.SignType;
|
||||
import com.alibaba.nacos.plugin.auth.exception.AccessException;
|
||||
import com.alibaba.nacos.plugin.encryption.handler.EncryptionHandler;
|
||||
import org.springframework.ui.ModelMap;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
@ -37,7 +35,6 @@ import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* History management controller.
|
||||
@ -48,10 +45,10 @@ import java.util.Objects;
|
||||
@RequestMapping(Constants.HISTORY_CONTROLLER_PATH)
|
||||
public class HistoryController {
|
||||
|
||||
private final PersistService persistService;
|
||||
private final HistoryService historyService;
|
||||
|
||||
public HistoryController(PersistService persistService) {
|
||||
this.persistService = persistService;
|
||||
public HistoryController(HistoryService historyService) {
|
||||
this.historyService = historyService;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -79,7 +76,7 @@ public class HistoryController {
|
||||
pageSize = null == pageSize ? 100 : pageSize;
|
||||
pageSize = Math.min(500, pageSize);
|
||||
// configInfoBase has no appName field.
|
||||
return persistService.findConfigHistory(dataId, group, tenant, pageNo, pageSize);
|
||||
return historyService.listConfigHistory(dataId, group, tenant, pageNo, pageSize);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -98,38 +95,7 @@ public class HistoryController {
|
||||
@RequestParam("group") String group,
|
||||
@RequestParam(value = "tenant", required = false, defaultValue = StringUtils.EMPTY) String tenant,
|
||||
@RequestParam("nid") Long nid) throws AccessException {
|
||||
ConfigHistoryInfo configHistoryInfo = persistService.detailConfigHistory(nid);
|
||||
if (Objects.isNull(configHistoryInfo)) {
|
||||
return null;
|
||||
}
|
||||
// check if history config match the input
|
||||
checkHistoryInfoPermission(configHistoryInfo, dataId, group, tenant);
|
||||
|
||||
String encryptedDataKey = configHistoryInfo.getEncryptedDataKey();
|
||||
Pair<String, String> pair = EncryptionHandler.decryptHandler(dataId, encryptedDataKey,
|
||||
configHistoryInfo.getContent());
|
||||
configHistoryInfo.setContent(pair.getSecond());
|
||||
|
||||
return configHistoryInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the input dataId,group and tenant match the history config.
|
||||
*
|
||||
* @param configHistoryInfo history config.
|
||||
* @param dataId dataId
|
||||
* @param group group
|
||||
* @param tenant tenant
|
||||
* @throws AccessException not match exception.
|
||||
* @since 2.0.3
|
||||
*/
|
||||
private void checkHistoryInfoPermission(ConfigHistoryInfo configHistoryInfo, String dataId, String group,
|
||||
String tenant) throws AccessException {
|
||||
if (!Objects.equals(configHistoryInfo.getDataId(), dataId)
|
||||
|| !Objects.equals(configHistoryInfo.getGroup(), group)
|
||||
|| !Objects.equals(configHistoryInfo.getTenant(), tenant)) {
|
||||
throw new AccessException("Please check dataId, group or tenant.");
|
||||
}
|
||||
return historyService.getConfigHistoryInfo(dataId, group, tenant, nid);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -149,13 +115,7 @@ public class HistoryController {
|
||||
@RequestParam("group") String group,
|
||||
@RequestParam(value = "tenant", required = false, defaultValue = StringUtils.EMPTY) String tenant,
|
||||
@RequestParam("id") Long id) throws AccessException {
|
||||
ConfigHistoryInfo configHistoryInfo = persistService.detailPreviousConfigHistory(id);
|
||||
if (Objects.isNull(configHistoryInfo)) {
|
||||
return null;
|
||||
}
|
||||
// check if history config match the input
|
||||
checkHistoryInfoPermission(configHistoryInfo, dataId, group, tenant);
|
||||
return configHistoryInfo;
|
||||
return historyService.getPreviousConfigHistoryInfo(dataId, group, tenant, id);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -171,7 +131,7 @@ public class HistoryController {
|
||||
// check tenant
|
||||
ParamUtils.checkTenant(tenant);
|
||||
tenant = NamespaceUtil.processNamespaceParameter(tenant);
|
||||
return persistService.queryConfigInfoByNamespace(tenant);
|
||||
return historyService.getConfigListByNamespace(tenant);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,151 @@
|
||||
/*
|
||||
* Copyright 1999-2022 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.config.server.controller.v2;
|
||||
|
||||
import com.alibaba.nacos.api.annotation.NacosApi;
|
||||
import com.alibaba.nacos.api.config.ConfigType;
|
||||
import com.alibaba.nacos.api.exception.NacosException;
|
||||
import com.alibaba.nacos.api.exception.api.NacosApiException;
|
||||
import com.alibaba.nacos.api.model.v2.Result;
|
||||
import com.alibaba.nacos.auth.annotation.Secured;
|
||||
import com.alibaba.nacos.common.utils.NamespaceUtil;
|
||||
import com.alibaba.nacos.common.utils.Pair;
|
||||
import com.alibaba.nacos.common.utils.StringUtils;
|
||||
import com.alibaba.nacos.config.server.constant.Constants;
|
||||
import com.alibaba.nacos.config.server.controller.ConfigServletInner;
|
||||
import com.alibaba.nacos.config.server.model.ConfigRequestInfo;
|
||||
import com.alibaba.nacos.config.server.model.form.ConfigForm;
|
||||
import com.alibaba.nacos.config.server.service.ConfigOperationService;
|
||||
import com.alibaba.nacos.config.server.utils.ParamUtils;
|
||||
import com.alibaba.nacos.config.server.utils.RequestUtil;
|
||||
import com.alibaba.nacos.plugin.auth.constant.ActionTypes;
|
||||
import com.alibaba.nacos.plugin.auth.constant.SignType;
|
||||
import com.alibaba.nacos.plugin.encryption.handler.EncryptionHandler;
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Special controller v2 for soft load client to publish data.
|
||||
*
|
||||
* @author dongyafei
|
||||
* @date 2022/7/22
|
||||
*/
|
||||
|
||||
@NacosApi
|
||||
@RestController
|
||||
@RequestMapping(Constants.CONFIG_CONTROLLER_V2_PATH)
|
||||
public class ConfigControllerV2 {
|
||||
|
||||
private final ConfigServletInner inner;
|
||||
|
||||
private final ConfigOperationService configOperationService;
|
||||
|
||||
public ConfigControllerV2(ConfigServletInner inner, ConfigOperationService configOperationService) {
|
||||
this.inner = inner;
|
||||
this.configOperationService = configOperationService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get configure board information fail.
|
||||
*
|
||||
* @throws ServletException ServletException.
|
||||
* @throws IOException IOException.
|
||||
* @throws NacosApiException NacosApiException.
|
||||
*/
|
||||
@GetMapping
|
||||
@Secured(action = ActionTypes.READ, signType = SignType.CONFIG)
|
||||
public void getConfig(HttpServletRequest request, HttpServletResponse response,
|
||||
@RequestParam("dataId") String dataId, @RequestParam("group") String group,
|
||||
@RequestParam(value = "namespaceId", required = false, defaultValue = StringUtils.EMPTY) String namespaceId,
|
||||
@RequestParam(value = "tag", required = false) String tag)
|
||||
throws NacosException, IOException, ServletException {
|
||||
// check namespaceId
|
||||
ParamUtils.checkTenantV2(namespaceId);
|
||||
namespaceId = NamespaceUtil.processNamespaceParameter(namespaceId);
|
||||
// check params
|
||||
ParamUtils.checkParam(dataId, group, "datumId", "content");
|
||||
ParamUtils.checkParamV2(tag);
|
||||
final String clientIp = RequestUtil.getRemoteIp(request);
|
||||
String isNotify = request.getHeader("notify");
|
||||
inner.doGetConfig(request, response, dataId, group, namespaceId, tag, isNotify, clientIp, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds or updates non-aggregated data.
|
||||
*
|
||||
* @throws NacosException NacosException.
|
||||
*/
|
||||
@PostMapping()
|
||||
@Secured(action = ActionTypes.WRITE, signType = SignType.CONFIG)
|
||||
public Result<Boolean> publishConfig(ConfigForm configForm, HttpServletRequest request) throws NacosException {
|
||||
// check required field
|
||||
configForm.validate();
|
||||
// encrypted
|
||||
Pair<String, String> pair = EncryptionHandler.encryptHandler(configForm.getDataId(), configForm.getContent());
|
||||
configForm.setContent(pair.getSecond());
|
||||
// check param
|
||||
ParamUtils.checkTenantV2(configForm.getNamespaceId());
|
||||
ParamUtils.checkParam(configForm.getDataId(), configForm.getGroup(), "datumId", configForm.getContent());
|
||||
ParamUtils.checkParamV2(configForm.getTag());
|
||||
|
||||
if (StringUtils.isBlank(configForm.getSrcUser())) {
|
||||
configForm.setSrcUser(RequestUtil.getSrcUserName(request));
|
||||
}
|
||||
if (!ConfigType.isValidType(configForm.getType())) {
|
||||
configForm.setType(ConfigType.getDefaultType().getType());
|
||||
}
|
||||
|
||||
ConfigRequestInfo configRequestInfo = new ConfigRequestInfo();
|
||||
configRequestInfo.setSrcIp(RequestUtil.getRemoteIp(request));
|
||||
configRequestInfo.setRequestIpApp(RequestUtil.getAppName(request));
|
||||
configRequestInfo.setBetaIps(request.getHeader("betaIps"));
|
||||
|
||||
String encryptedDataKey = pair.getFirst();
|
||||
|
||||
return Result.success(configOperationService.publishConfig(configForm, configRequestInfo, encryptedDataKey));
|
||||
}
|
||||
|
||||
/**
|
||||
* Synchronously delete all pre-aggregation data under a dataId.
|
||||
*
|
||||
* @throws NacosApiException NacosApiException.
|
||||
*/
|
||||
@DeleteMapping
|
||||
@Secured(action = ActionTypes.WRITE, signType = SignType.CONFIG)
|
||||
public Result<Boolean> deleteConfig(HttpServletRequest request, @RequestParam("dataId") String dataId,
|
||||
@RequestParam("group") String group,
|
||||
@RequestParam(value = "namespaceId", required = false, defaultValue = StringUtils.EMPTY) String namespaceId,
|
||||
@RequestParam(value = "tag", required = false) String tag) throws NacosException {
|
||||
// check namespaceId
|
||||
ParamUtils.checkTenantV2(namespaceId);
|
||||
ParamUtils.checkParam(dataId, group, "datumId", "rm");
|
||||
ParamUtils.checkParamV2(tag);
|
||||
|
||||
String clientIp = RequestUtil.getRemoteIp(request);
|
||||
String srcUser = RequestUtil.getSrcUserName(request);
|
||||
return Result.success(configOperationService.deleteConfig(dataId, group, namespaceId, tag, clientIp, srcUser));
|
||||
}
|
||||
}
|
@ -0,0 +1,154 @@
|
||||
/*
|
||||
* Copyright 1999-2022 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.config.server.controller.v2;
|
||||
|
||||
import com.alibaba.nacos.api.annotation.NacosApi;
|
||||
import com.alibaba.nacos.api.exception.api.NacosApiException;
|
||||
import com.alibaba.nacos.api.model.v2.ErrorCode;
|
||||
import com.alibaba.nacos.api.model.v2.Result;
|
||||
import com.alibaba.nacos.auth.annotation.Secured;
|
||||
import com.alibaba.nacos.common.utils.NamespaceUtil;
|
||||
import com.alibaba.nacos.common.utils.StringUtils;
|
||||
import com.alibaba.nacos.config.server.constant.Constants;
|
||||
import com.alibaba.nacos.config.server.model.ConfigHistoryInfo;
|
||||
import com.alibaba.nacos.config.server.model.ConfigInfoWrapper;
|
||||
import com.alibaba.nacos.config.server.model.Page;
|
||||
import com.alibaba.nacos.config.server.service.HistoryService;
|
||||
import com.alibaba.nacos.config.server.utils.ParamUtils;
|
||||
import com.alibaba.nacos.plugin.auth.constant.ActionTypes;
|
||||
import com.alibaba.nacos.plugin.auth.constant.SignType;
|
||||
import com.alibaba.nacos.plugin.auth.exception.AccessException;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* config history management controller [v2].
|
||||
* @author dongyafei
|
||||
* @date 2022/7/25
|
||||
*/
|
||||
|
||||
@NacosApi
|
||||
@RestController
|
||||
@RequestMapping(Constants.HISTORY_CONTROLLER_V2_PATH)
|
||||
public class HistoryControllerV2 {
|
||||
|
||||
private final HistoryService historyService;
|
||||
|
||||
public HistoryControllerV2(HistoryService historyService) {
|
||||
this.historyService = historyService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Query the list history config. notes:
|
||||
*
|
||||
* @param dataId dataId string value [required].
|
||||
* @param group group string value [required].
|
||||
* @param namespaceId namespaceId.
|
||||
* @param pageNo pageNo integer value.
|
||||
* @param pageSize pageSize integer value.
|
||||
* @return the page of history config.
|
||||
* @since 2.0.3 add {@link Secured} for history config permission check.
|
||||
*/
|
||||
@GetMapping("/list")
|
||||
@Secured(action = ActionTypes.READ, signType = SignType.CONFIG)
|
||||
public Result<Page<ConfigHistoryInfo>> listConfigHistory(
|
||||
@RequestParam("dataId") String dataId,
|
||||
@RequestParam("group") String group,
|
||||
@RequestParam(value = "namespaceId", required = false, defaultValue = StringUtils.EMPTY) String namespaceId,
|
||||
@RequestParam(value = "pageNo", required = false, defaultValue = "1") Integer pageNo,
|
||||
@RequestParam(value = "pageSize", required = false, defaultValue = "100") Integer pageSize) {
|
||||
pageSize = Math.min(500, pageSize);
|
||||
return Result.success(historyService.listConfigHistory(dataId, group, namespaceId, pageNo, pageSize));
|
||||
}
|
||||
|
||||
/**
|
||||
* Query the detailed configuration history information. notes:
|
||||
*
|
||||
* @param nid history_config_info nid
|
||||
* @param dataId dataId @since 2.0.3
|
||||
* @param group groupId @since 2.0.3
|
||||
* @param namespaceId namespaceId @since 2.0.3
|
||||
* @return history config info
|
||||
* @since 2.0.3 add {@link Secured}, dataId, groupId and tenant for history config permission check.
|
||||
*/
|
||||
@GetMapping
|
||||
@Secured(action = ActionTypes.READ, signType = SignType.CONFIG)
|
||||
public Result<ConfigHistoryInfo> getConfigHistoryInfo(
|
||||
@RequestParam("dataId") String dataId,
|
||||
@RequestParam("group") String group,
|
||||
@RequestParam(value = "namespaceId", required = false, defaultValue = StringUtils.EMPTY) String namespaceId,
|
||||
@RequestParam("nid") Long nid) throws AccessException, NacosApiException {
|
||||
ConfigHistoryInfo configHistoryInfo;
|
||||
try {
|
||||
configHistoryInfo = historyService.getConfigHistoryInfo(dataId, group, namespaceId, nid);
|
||||
} catch (DataAccessException e) {
|
||||
throw new NacosApiException(HttpStatus.NOT_FOUND.value(), ErrorCode.RESOURCE_NOT_FOUND,
|
||||
"certain config history for nid = " + nid + " not exist");
|
||||
}
|
||||
return Result.success(configHistoryInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* Query previous config history information. notes:
|
||||
*
|
||||
* @param id config_info id
|
||||
* @param dataId dataId @since 2.0.3
|
||||
* @param group groupId @since 2.0.3
|
||||
* @param namespaceId namespaceId @since 2.0.3
|
||||
* @return history config info
|
||||
* @since 2.0.3 add {@link Secured}, dataId, groupId and tenant for history config permission check.
|
||||
*/
|
||||
@GetMapping(value = "/previous")
|
||||
@Secured(action = ActionTypes.READ, signType = SignType.CONFIG)
|
||||
public Result<ConfigHistoryInfo> getPreviousConfigHistoryInfo(
|
||||
@RequestParam("dataId") String dataId,
|
||||
@RequestParam("group") String group,
|
||||
@RequestParam(value = "namespaceId", required = false, defaultValue = StringUtils.EMPTY) String namespaceId,
|
||||
@RequestParam("id") Long id) throws AccessException, NacosApiException {
|
||||
ConfigHistoryInfo configHistoryInfo;
|
||||
try {
|
||||
configHistoryInfo = historyService.getPreviousConfigHistoryInfo(dataId, group, namespaceId, id);
|
||||
} catch (DataAccessException e) {
|
||||
throw new NacosApiException(HttpStatus.NOT_FOUND.value(), ErrorCode.RESOURCE_NOT_FOUND,
|
||||
"previous config history for id = " + id + " not exist");
|
||||
}
|
||||
return Result.success(configHistoryInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* Query configs list by namespace.
|
||||
*
|
||||
* @param namespaceId config_info namespace
|
||||
* @return list
|
||||
* @since 2.1.1
|
||||
*/
|
||||
@GetMapping(value = "/configs")
|
||||
@Secured(action = ActionTypes.READ, signType = SignType.CONFIG)
|
||||
public Result<List<ConfigInfoWrapper>> getConfigsByTenant(@RequestParam("namespaceId") String namespaceId)
|
||||
throws NacosApiException {
|
||||
// check namespaceId
|
||||
ParamUtils.checkTenantV2(namespaceId);
|
||||
namespaceId = NamespaceUtil.processNamespaceParameter(namespaceId);
|
||||
return Result.success(historyService.getConfigListByNamespace(namespaceId));
|
||||
}
|
||||
}
|
@ -19,6 +19,7 @@ package com.alibaba.nacos.config.server.exception;
|
||||
import com.alibaba.nacos.api.exception.NacosException;
|
||||
import com.alibaba.nacos.common.utils.ExceptionUtil;
|
||||
import com.alibaba.nacos.config.server.monitor.MetricsMonitor;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.ControllerAdvice;
|
||||
@ -31,6 +32,7 @@ import java.io.IOException;
|
||||
*
|
||||
* @author Nacos
|
||||
*/
|
||||
@Order(0)
|
||||
@ControllerAdvice
|
||||
public class GlobalExceptionHandler {
|
||||
|
||||
|
@ -25,7 +25,7 @@ import java.io.Serializable;
|
||||
*/
|
||||
public class ConfigAdvanceInfo implements Serializable {
|
||||
|
||||
static final long serialVersionUID = -1L;
|
||||
static final long serialVersionUID = 3148031484920416869L;
|
||||
|
||||
private long createTime;
|
||||
|
||||
|
@ -24,7 +24,7 @@ package com.alibaba.nacos.config.server.model;
|
||||
*/
|
||||
public class ConfigInfo extends ConfigInfoBase {
|
||||
|
||||
static final long serialVersionUID = -1L;
|
||||
static final long serialVersionUID = 3115358782431229202L;
|
||||
|
||||
private String tenant;
|
||||
|
||||
|
@ -32,7 +32,7 @@ import java.io.Serializable;
|
||||
*/
|
||||
public class ConfigInfoBase implements Serializable, Comparable<ConfigInfoBase> {
|
||||
|
||||
static final long serialVersionUID = -1L;
|
||||
static final long serialVersionUID = 265316491795790798L;
|
||||
|
||||
@JsonSerialize(using = ToStringSerializer.class)
|
||||
private long id;
|
||||
|
@ -24,7 +24,7 @@ package com.alibaba.nacos.config.server.model;
|
||||
*/
|
||||
public class ConfigInfoBaseEx extends ConfigInfoBase {
|
||||
|
||||
private static final long serialVersionUID = -1L;
|
||||
private static final long serialVersionUID = 5802322506486922169L;
|
||||
|
||||
/**
|
||||
* Single message status code, when querying for batch.
|
||||
|
@ -23,7 +23,7 @@ package com.alibaba.nacos.config.server.model;
|
||||
*/
|
||||
public class ConfigInfoEx extends ConfigInfo {
|
||||
|
||||
private static final long serialVersionUID = -1L;
|
||||
private static final long serialVersionUID = 8905036592920606608L;
|
||||
|
||||
/**
|
||||
* Single message status code, when querying for batch.
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user