Merge branch 'develop' of https://github.com/alibaba/nacos into new_develop
This commit is contained in:
commit
abee9c4dcf
@ -22,7 +22,7 @@ Nacos provides four major functions.
|
||||
|
||||
* **Dynamic Configuration Management**
|
||||
|
||||
Dynamic Configuration Service allows you to manage configurations of all services in a centralized and dynamic manner across all environments. Nacos eliminates the need to redeploy applications and services when configurations are updated,which makes configuration changes more efficient and agile.
|
||||
Dynamic Configuration Service allows you to manage configurations of all services in a centralized and dynamic manner across all environments. Nacos eliminates the need to redeploy applications and services when configurations are updated, which makes configuration changes more efficient and agile.
|
||||
|
||||
* **Dynamic DNS Service**
|
||||
|
||||
|
@ -15,26 +15,26 @@
|
||||
~ limitations under the License.
|
||||
-->
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>nacos-all</artifactId>
|
||||
<groupId>com.alibaba.nacos</groupId>
|
||||
<version>1.3.1-BETA</version>
|
||||
<version>1.3.1</version>
|
||||
</parent>
|
||||
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>nacos-address</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
|
||||
<name>nacos-address ${project.version}</name>
|
||||
<url>http://nacos.io</url>
|
||||
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<maven.compiler.source>1.8</maven.compiler.source>
|
||||
<maven.compiler.target>1.8</maven.compiler.target>
|
||||
</properties>
|
||||
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
@ -62,7 +62,7 @@
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
|
||||
<build>
|
||||
<resources>
|
||||
<resource>
|
||||
@ -70,7 +70,7 @@
|
||||
</resource>
|
||||
</resources>
|
||||
</build>
|
||||
|
||||
|
||||
<reporting>
|
||||
<plugins>
|
||||
<plugin>
|
||||
@ -79,7 +79,7 @@
|
||||
</plugin>
|
||||
</plugins>
|
||||
</reporting>
|
||||
|
||||
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>release-address</id>
|
||||
|
@ -13,6 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.address;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
@ -26,8 +27,9 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
*/
|
||||
@SpringBootApplication(scanBasePackages = "com.alibaba.nacos")
|
||||
public class AddressServer {
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
|
||||
SpringApplication.run(AddressServer.class, args);
|
||||
}
|
||||
}
|
||||
|
@ -13,6 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.address.component;
|
||||
|
||||
import com.alibaba.nacos.address.constant.AddressServerConstants;
|
||||
@ -34,32 +35,38 @@ import java.util.List;
|
||||
*/
|
||||
@Component
|
||||
public class AddressServerGeneratorManager {
|
||||
|
||||
|
||||
/**
|
||||
* Generate product name.
|
||||
*
|
||||
* @param name name
|
||||
* @return product
|
||||
*/
|
||||
public String generateProductName(String name) {
|
||||
|
||||
|
||||
if (StringUtils.isBlank(name) || AddressServerConstants.DEFAULT_PRODUCT.equals(name)) {
|
||||
|
||||
|
||||
return AddressServerConstants.ALIWARE_NACOS_DEFAULT_PRODUCT_NAME;
|
||||
}
|
||||
|
||||
|
||||
return String.format(AddressServerConstants.ALIWARE_NACOS_PRODUCT_DOM_TEMPLATE, name);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Note: if the parameter inputted is empty then will return the empty list.
|
||||
*
|
||||
* @param serviceName
|
||||
* @param clusterName
|
||||
* @param ipArray
|
||||
* @return
|
||||
* @param serviceName service name
|
||||
* @param clusterName cluster name
|
||||
* @param ipArray array of ips
|
||||
* @return instance list
|
||||
*/
|
||||
public List<Instance> generateInstancesByIps(String serviceName, String rawProductName, String clusterName, String[] ipArray) {
|
||||
if (StringUtils.isEmpty(serviceName)
|
||||
|| StringUtils.isEmpty(clusterName)
|
||||
|| ipArray == null || ipArray.length == 0) {
|
||||
public List<Instance> generateInstancesByIps(String serviceName, String rawProductName, String clusterName,
|
||||
String[] ipArray) {
|
||||
if (StringUtils.isEmpty(serviceName) || StringUtils.isEmpty(clusterName) || ipArray == null
|
||||
|| ipArray.length == 0) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
|
||||
List<Instance> instanceList = new ArrayList<>(ipArray.length);
|
||||
for (String ip : ipArray) {
|
||||
String[] ipAndPort = generateIpAndPort(ip);
|
||||
@ -73,46 +80,50 @@ public class AddressServerGeneratorManager {
|
||||
instance.setEphemeral(false);
|
||||
instanceList.add(instance);
|
||||
}
|
||||
|
||||
|
||||
return instanceList;
|
||||
}
|
||||
|
||||
public String[] generateIpAndPort(String ip) {
|
||||
|
||||
|
||||
private String[] generateIpAndPort(String ip) {
|
||||
|
||||
int index = ip.indexOf(AddressServerConstants.IP_PORT_SEPARATOR);
|
||||
if (index != -1) {
|
||||
|
||||
return new String[]{ip.substring(0, index), ip.substring(index + 1)};
|
||||
|
||||
return new String[] {ip.substring(0, index), ip.substring(index + 1)};
|
||||
}
|
||||
|
||||
return new String[]{ip, String.valueOf(AddressServerConstants.DEFAULT_SERVER_PORT)};
|
||||
|
||||
return new String[] {ip, String.valueOf(AddressServerConstants.DEFAULT_SERVER_PORT)};
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Generate response ips.
|
||||
*
|
||||
* @param instanceList a instance set will generate string response to client.
|
||||
* @return the result of response to client
|
||||
*/
|
||||
public String generateResponseIps(List<Instance> instanceList) {
|
||||
|
||||
|
||||
StringBuilder ips = new StringBuilder();
|
||||
instanceList.forEach(instance -> {
|
||||
ips.append(instance.getIp() + ":" + instance.getPort());
|
||||
ips.append("\n");
|
||||
});
|
||||
|
||||
|
||||
return ips.toString();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param rawServiceName the raw service name will not contains the {@Constans.DEFAULT_GROUP}
|
||||
* Generate nacos service name.
|
||||
*
|
||||
* @param rawServiceName the raw service name will not contains the {@link Constants#DEFAULT_GROUP}.
|
||||
* @return the nacos service name
|
||||
*/
|
||||
public String generateNacosServiceName(String rawServiceName) {
|
||||
|
||||
|
||||
if (rawServiceName.indexOf(Constants.DEFAULT_GROUP) != -1) {
|
||||
return rawServiceName;
|
||||
}
|
||||
|
||||
|
||||
return Constants.DEFAULT_GROUP + AddressServerConstants.GROUP_SERVICE_NAME_SEP + rawServiceName;
|
||||
}
|
||||
}
|
||||
|
@ -13,9 +13,11 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.address.component;
|
||||
|
||||
import com.alibaba.nacos.address.constant.AddressServerConstants;
|
||||
import com.alibaba.nacos.naming.misc.UtilsAndCommons;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@ -28,51 +30,51 @@ import org.springframework.stereotype.Component;
|
||||
*/
|
||||
@Component
|
||||
public class AddressServerManager {
|
||||
|
||||
|
||||
public String getRawProductName(String name) {
|
||||
|
||||
|
||||
if (StringUtils.isBlank(name) || AddressServerConstants.DEFAULT_PRODUCT.equals(name)) {
|
||||
|
||||
|
||||
return AddressServerConstants.DEFAULT_PRODUCT;
|
||||
}
|
||||
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* if the name is empty then return the default {@UtilAndCommons#DEFAULT_CLUSTER_NAME},
|
||||
* <p>
|
||||
* or return the source name by input
|
||||
* If the name is empty then return the default {@link UtilsAndCommons#DEFAULT_CLUSTER_NAME}, or return the source
|
||||
* name by input.
|
||||
*
|
||||
* @param name
|
||||
* @return
|
||||
* @param name name
|
||||
* @return default cluster name
|
||||
*/
|
||||
public String getDefaultClusterNameIfEmpty(String name) {
|
||||
|
||||
|
||||
if (StringUtils.isEmpty(name) || AddressServerConstants.DEFAULT_GET_CLUSTER.equals(name)) {
|
||||
return AddressServerConstants.DEFAULT_GET_CLUSTER;
|
||||
}
|
||||
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
|
||||
public String getRawClusterName(String name) {
|
||||
|
||||
|
||||
return getDefaultClusterNameIfEmpty(name);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Split ips.
|
||||
*
|
||||
* @param ips multi ip will separator by the ','
|
||||
* @return
|
||||
* @return array of ip
|
||||
*/
|
||||
public String[] splitIps(String ips) {
|
||||
|
||||
|
||||
if (StringUtils.isBlank(ips)) {
|
||||
|
||||
|
||||
return new String[0];
|
||||
}
|
||||
|
||||
|
||||
return ips.split(AddressServerConstants.MULTI_IPS_SEPARATOR);
|
||||
}
|
||||
}
|
||||
|
@ -13,64 +13,65 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.address.constant;
|
||||
|
||||
import com.alibaba.nacos.naming.misc.UtilsAndCommons;
|
||||
|
||||
/**
|
||||
* Uniform constant parameter naming for address servers and default values for related parameters
|
||||
* Uniform constant parameter naming for address servers and default values for related parameters.
|
||||
*
|
||||
* @author pbting
|
||||
* @date 2019-06-17 7:23 PM
|
||||
* @since 1.1.0
|
||||
*/
|
||||
public interface AddressServerConstants {
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* the default server port when create the Instance object.
|
||||
*/
|
||||
int DEFAULT_SERVER_PORT = 8848;
|
||||
|
||||
|
||||
/**
|
||||
* when post ips is not given the product,then use the default.
|
||||
*/
|
||||
String DEFAULT_PRODUCT = "nacos";
|
||||
|
||||
|
||||
/**
|
||||
* the separator between ip and port.
|
||||
*/
|
||||
String IP_PORT_SEPARATOR = ":";
|
||||
|
||||
|
||||
/**
|
||||
* the separator for {@Service#name} between raw service name and group
|
||||
* the separator for service name between raw service name and group.
|
||||
*/
|
||||
String GROUP_SERVICE_NAME_SEP = "@@";
|
||||
|
||||
|
||||
/**
|
||||
* when post ips is not given the cluster,then use the default.
|
||||
*/
|
||||
String DEFAULT_GET_CLUSTER = "serverlist";
|
||||
|
||||
|
||||
/**
|
||||
* post multi ip will use the "," to separator
|
||||
* post multi ip will use the "," to separator.
|
||||
*/
|
||||
String MULTI_IPS_SEPARATOR = ",";
|
||||
|
||||
|
||||
/**
|
||||
* the default product name when deploy nacos with naming and config
|
||||
* the default product name when deploy nacos with naming and config.
|
||||
*/
|
||||
String ALIWARE_NACOS_DEFAULT_PRODUCT_NAME = "nacos.as.default";
|
||||
|
||||
|
||||
/**
|
||||
* when the config and naming will separate deploy,then must specify product name by the client。
|
||||
* when the config and naming will separate deploy,then must specify product name by the client.
|
||||
*/
|
||||
String ALIWARE_NACOS_PRODUCT_DOM_TEMPLATE = "nacos.as.%s";
|
||||
|
||||
|
||||
/**
|
||||
* the url for address server prefix
|
||||
* the url for address server prefix.
|
||||
*/
|
||||
String ADDRESS_SERVER_REQUEST_URL =
|
||||
UtilsAndCommons.NACOS_SERVER_CONTEXT + UtilsAndCommons.NACOS_SERVER_VERSION + "/as";
|
||||
|
||||
UtilsAndCommons.NACOS_SERVER_CONTEXT + UtilsAndCommons.NACOS_SERVER_VERSION + "/as";
|
||||
|
||||
}
|
||||
|
@ -13,6 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.address.controller;
|
||||
|
||||
import com.alibaba.nacos.address.component.AddressServerGeneratorManager;
|
||||
@ -38,46 +39,49 @@ import org.springframework.web.bind.annotation.RestController;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Address server cluster controller.
|
||||
*
|
||||
* @author pbting
|
||||
* @date 2019-06-10 9:59 AM
|
||||
* @since 1.1.0
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping({AddressServerConstants.ADDRESS_SERVER_REQUEST_URL + "/nodes"})
|
||||
public class AddressServerClusterController {
|
||||
|
||||
|
||||
@Autowired
|
||||
private ServiceManager serviceManager;
|
||||
|
||||
|
||||
@Autowired
|
||||
private AddressServerManager addressServerManager;
|
||||
|
||||
|
||||
@Autowired
|
||||
private AddressServerGeneratorManager addressServerGeneratorManager;
|
||||
|
||||
|
||||
/**
|
||||
* Create new cluster.
|
||||
*
|
||||
* @param product Ip list of products to be associated
|
||||
* @param cluster Ip list of product cluster to be associated
|
||||
* @param ips will post ip list.
|
||||
* @return
|
||||
* @return result of create new cluster
|
||||
*/
|
||||
@RequestMapping(value = "", method = RequestMethod.POST)
|
||||
public ResponseEntity postCluster(@RequestParam(required = false) String product,
|
||||
@RequestParam(required = false) String cluster,
|
||||
@RequestParam(name = "ips") String ips) {
|
||||
|
||||
@RequestParam(required = false) String cluster, @RequestParam(name = "ips") String ips) {
|
||||
|
||||
//1. prepare the storage name for product and cluster
|
||||
String productName = addressServerGeneratorManager.generateProductName(product);
|
||||
String clusterName = addressServerManager.getDefaultClusterNameIfEmpty(cluster);
|
||||
|
||||
|
||||
//2. prepare the response name for product and cluster to client
|
||||
String rawProductName = addressServerManager.getRawProductName(product);
|
||||
String rawClusterName = addressServerManager.getRawClusterName(cluster);
|
||||
Loggers.addressLogger.info("put cluster node,the cluster name is " + cluster + "; the product name=" + product + "; the ip list=" + ips);
|
||||
Loggers.ADDRESS_LOGGER.info("put cluster node,the cluster name is " + cluster + "; the product name=" + product
|
||||
+ "; the ip list=" + ips);
|
||||
ResponseEntity responseEntity;
|
||||
try {
|
||||
String serviceName = addressServerGeneratorManager.generateNacosServiceName(productName);
|
||||
|
||||
|
||||
Cluster clusterObj = new Cluster();
|
||||
clusterObj.setName(clusterName);
|
||||
clusterObj.setHealthChecker(new AbstractHealthChecker.None());
|
||||
@ -85,48 +89,54 @@ public class AddressServerClusterController {
|
||||
String[] ipArray = addressServerManager.splitIps(ips);
|
||||
String checkResult = AddressServerParamCheckUtil.checkIps(ipArray);
|
||||
if (AddressServerParamCheckUtil.CHECK_OK.equals(checkResult)) {
|
||||
List<Instance> instanceList = addressServerGeneratorManager.generateInstancesByIps(serviceName, rawProductName, clusterName, ipArray);
|
||||
List<Instance> instanceList = addressServerGeneratorManager
|
||||
.generateInstancesByIps(serviceName, rawProductName, clusterName, ipArray);
|
||||
for (Instance instance : instanceList) {
|
||||
serviceManager.registerInstance(Constants.DEFAULT_NAMESPACE_ID, serviceName, instance);
|
||||
}
|
||||
responseEntity = ResponseEntity.ok("product=" + rawProductName + ",cluster=" + rawClusterName + "; put success with size=" + instanceList.size());
|
||||
responseEntity = ResponseEntity
|
||||
.ok("product=" + rawProductName + ",cluster=" + rawClusterName + "; put success with size="
|
||||
+ instanceList.size());
|
||||
} else {
|
||||
responseEntity = ResponseEntity.status(HttpStatus.BAD_REQUEST).body(checkResult);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
responseEntity = ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(e.getMessage());
|
||||
}
|
||||
|
||||
|
||||
return responseEntity;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Delete cluster.
|
||||
*
|
||||
* @param product Ip list of products to be associated
|
||||
* @param cluster Ip list of product cluster to be associated
|
||||
* @param ips will delete ips.
|
||||
* @return
|
||||
* @return delete result
|
||||
*/
|
||||
@RequestMapping(value = "", method = RequestMethod.DELETE)
|
||||
public ResponseEntity deleteCluster(@RequestParam(required = false) String product,
|
||||
@RequestParam(required = false) String cluster,
|
||||
@RequestParam String ips) {
|
||||
@RequestParam(required = false) String cluster, @RequestParam String ips) {
|
||||
//1. prepare the storage name for product and cluster
|
||||
String productName = addressServerGeneratorManager.generateProductName(product);
|
||||
String clusterName = addressServerManager.getDefaultClusterNameIfEmpty(cluster);
|
||||
|
||||
|
||||
//2. prepare the response name for product and cluster to client
|
||||
String rawProductName = addressServerManager.getRawProductName(product);
|
||||
String rawClusterName = addressServerManager.getRawClusterName(cluster);
|
||||
ResponseEntity responseEntity = ResponseEntity.status(HttpStatus.OK).body("product=" + rawProductName + ", cluster=" + rawClusterName + " delete success.");
|
||||
ResponseEntity responseEntity = ResponseEntity.status(HttpStatus.OK)
|
||||
.body("product=" + rawProductName + ", cluster=" + rawClusterName + " delete success.");
|
||||
try {
|
||||
|
||||
|
||||
String serviceName = addressServerGeneratorManager.generateNacosServiceName(productName);
|
||||
Service service = serviceManager.getService(Constants.DEFAULT_NAMESPACE_ID, serviceName);
|
||||
|
||||
|
||||
if (service == null) {
|
||||
responseEntity = ResponseEntity.status(HttpStatus.NOT_FOUND).body("product=" + rawProductName + " not found.");
|
||||
responseEntity = ResponseEntity.status(HttpStatus.NOT_FOUND)
|
||||
.body("product=" + rawProductName + " not found.");
|
||||
} else {
|
||||
|
||||
|
||||
if (StringUtils.isBlank(ips)) {
|
||||
// delete all ips from the cluster
|
||||
responseEntity = ResponseEntity.status(HttpStatus.BAD_REQUEST).body("ips must not be empty.");
|
||||
@ -135,19 +145,21 @@ public class AddressServerClusterController {
|
||||
String[] ipArray = addressServerManager.splitIps(ips);
|
||||
String checkResult = AddressServerParamCheckUtil.checkIps(ipArray);
|
||||
if (AddressServerParamCheckUtil.CHECK_OK.equals(checkResult)) {
|
||||
List<Instance> instanceList = addressServerGeneratorManager.generateInstancesByIps(serviceName, rawProductName, clusterName, ipArray);
|
||||
serviceManager.removeInstance(Constants.DEFAULT_NAMESPACE_ID, serviceName, false, instanceList.toArray(new Instance[instanceList.size()]));
|
||||
List<Instance> instanceList = addressServerGeneratorManager
|
||||
.generateInstancesByIps(serviceName, rawProductName, clusterName, ipArray);
|
||||
serviceManager.removeInstance(Constants.DEFAULT_NAMESPACE_ID, serviceName, false,
|
||||
instanceList.toArray(new Instance[instanceList.size()]));
|
||||
} else {
|
||||
responseEntity = ResponseEntity.status(HttpStatus.BAD_REQUEST).body(checkResult);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
|
||||
|
||||
responseEntity = ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(e.getCause());
|
||||
}
|
||||
|
||||
|
||||
return responseEntity;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -13,6 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.address.controller;
|
||||
|
||||
import com.alibaba.nacos.address.component.AddressServerGeneratorManager;
|
||||
@ -29,42 +30,46 @@ import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* Server list controller.
|
||||
*
|
||||
* @author pbting
|
||||
* @date 2019-06-18 5:04 PM
|
||||
* @since 1.1.0
|
||||
*/
|
||||
@RestController
|
||||
public class ServerListController {
|
||||
|
||||
|
||||
@Autowired
|
||||
private ServiceManager serviceManager;
|
||||
|
||||
|
||||
@Autowired
|
||||
private AddressServerGeneratorManager addressServerBuilderManager;
|
||||
|
||||
|
||||
/**
|
||||
* Get cluster.
|
||||
*
|
||||
* @param product will get Ip list of that products to be associated
|
||||
* @param cluster will get Ip list of that product cluster to be associated
|
||||
* @return
|
||||
* @return result of get
|
||||
*/
|
||||
@RequestMapping(value = "/{product}/{cluster}", method = RequestMethod.GET)
|
||||
public ResponseEntity getCluster(@PathVariable String product,
|
||||
@PathVariable String cluster) {
|
||||
|
||||
public ResponseEntity getCluster(@PathVariable String product, @PathVariable String cluster) {
|
||||
|
||||
String productName = addressServerBuilderManager.generateProductName(product);
|
||||
String serviceName = addressServerBuilderManager.generateNacosServiceName(productName);
|
||||
Service service = serviceManager.getService(Constants.DEFAULT_NAMESPACE_ID, serviceName);
|
||||
if (service == null) {
|
||||
|
||||
|
||||
return ResponseEntity.status(HttpStatus.NOT_FOUND).body("product=" + product + " not found.");
|
||||
}
|
||||
|
||||
|
||||
if (!service.getClusterMap().containsKey(cluster)) {
|
||||
|
||||
return ResponseEntity.status(HttpStatus.NOT_FOUND).body("product=" + product + ",cluster=" + cluster + " not found.");
|
||||
|
||||
return ResponseEntity.status(HttpStatus.NOT_FOUND)
|
||||
.body("product=" + product + ",cluster=" + cluster + " not found.");
|
||||
}
|
||||
|
||||
|
||||
Cluster clusterObj = service.getClusterMap().get(cluster);
|
||||
return ResponseEntity.status(HttpStatus.OK).body(addressServerBuilderManager.generateResponseIps(clusterObj.allIPs(false)));
|
||||
return ResponseEntity.status(HttpStatus.OK)
|
||||
.body(addressServerBuilderManager.generateResponseIps(clusterObj.allIPs(false)));
|
||||
}
|
||||
}
|
||||
|
@ -13,16 +13,19 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.address.misc;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Loggers holder.
|
||||
*
|
||||
* @author pbting
|
||||
* @date 2019-07-04 4:34 PM
|
||||
*/
|
||||
public class Loggers {
|
||||
|
||||
public static final Logger addressLogger = LoggerFactory.getLogger("com.alibaba.nacos.address.main");
|
||||
|
||||
public static final Logger ADDRESS_LOGGER = LoggerFactory.getLogger("com.alibaba.nacos.address.main");
|
||||
}
|
||||
|
@ -13,32 +13,39 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.address.util;
|
||||
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Provides a unified tool class for address server parameter verification
|
||||
* Provides a unified tool class for address server parameter verification.
|
||||
*
|
||||
* @author pbting
|
||||
* @date 2019-06-19 11:19 AM
|
||||
* @since 1.1.0
|
||||
*/
|
||||
public class AddressServerParamCheckUtil {
|
||||
|
||||
|
||||
public static final String CHECK_OK = "ok";
|
||||
|
||||
|
||||
public static final String ILLEGAL_IP_PREFIX = "illegal ip: ";
|
||||
|
||||
|
||||
private static final String IP_REGEX = "(2(5[0-5]{1}|[0-4]\\d{1})|[0-1]?\\d{1,2})(\\.(2(5[0-5]{1}|[0-4]\\d{1})|[0-1]?\\d{1,2})){3}";
|
||||
|
||||
|
||||
private static final Pattern IP_PATTERN = Pattern.compile(IP_REGEX);
|
||||
|
||||
|
||||
/**
|
||||
* Check ips.
|
||||
*
|
||||
* @param ips ips
|
||||
* @return 'ok' if check passed, otherwise illegal ip
|
||||
*/
|
||||
public static String checkIps(String... ips) {
|
||||
|
||||
|
||||
if (ips == null || ips.length == 0) {
|
||||
|
||||
|
||||
return CHECK_OK;
|
||||
}
|
||||
// illegal response
|
||||
@ -50,11 +57,11 @@ public class AddressServerParamCheckUtil {
|
||||
}
|
||||
illegalResponse.append(ip + ",");
|
||||
}
|
||||
|
||||
|
||||
if (illegalResponse.length() == 0) {
|
||||
return CHECK_OK;
|
||||
}
|
||||
|
||||
|
||||
return ILLEGAL_IP_PREFIX + illegalResponse.substring(0, illegalResponse.length() - 1);
|
||||
}
|
||||
}
|
||||
|
@ -16,12 +16,12 @@
|
||||
-->
|
||||
|
||||
<included>
|
||||
|
||||
|
||||
<springProperty scope="context" name="logPath" source="nacos.logs.path" defaultValue="${user.home}/nacos/logs"/>
|
||||
<property name="LOG_HOME" value="${logPath}"/>
|
||||
|
||||
|
||||
<appender name="nacos-address"
|
||||
class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<file>${LOG_HOME}/nacos-address.log</file>
|
||||
<append>true</append>
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
|
||||
@ -36,7 +36,7 @@
|
||||
<charset>UTF-8</charset>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
|
||||
<logger name="com.alibaba.nacos.address.main" additivity="false">
|
||||
<level value="INFO"/>
|
||||
<appender-ref ref="nacos-address"/>
|
||||
|
@ -13,6 +13,5 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
server.port=8080
|
||||
server.servlet.context-path=/
|
||||
|
@ -13,6 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.address;
|
||||
|
||||
import org.junit.Ignore;
|
||||
@ -20,43 +21,39 @@ import org.junit.Test;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* @author pbting
|
||||
* @date 2019-06-18 2:37 PM
|
||||
*/
|
||||
@Ignore
|
||||
public class AddressServerControllerTests {
|
||||
|
||||
|
||||
private static final String PRODUCT_NACOS = "nacos";
|
||||
|
||||
private static final String PRODUCT_CONFIG = "config";
|
||||
|
||||
private static final String PRODUCT_NAMING = "naming";
|
||||
|
||||
private static final String DEFAULT_URL_CLUSTER = "serverlist";
|
||||
|
||||
|
||||
private static final String GET_SERVERLIST_URL_FORMART = "http://127.0.0.1:8080/%s/%s";
|
||||
|
||||
|
||||
//-----------------product=nacos,cluster=DEFAULT -------------------//
|
||||
|
||||
/**
|
||||
* test the default product and cluster
|
||||
*/
|
||||
|
||||
@Test
|
||||
public void postCluster() {
|
||||
|
||||
|
||||
String ips = "127.0.0.100,127.0.0.102,127.0.0.104";
|
||||
HashMap<String, String> params = new HashMap<>();
|
||||
params.put("ips", ips);
|
||||
String response = SimpleHttpTestUtils.doPost("http://127.0.0.1:8080/nacos/v1/as/nodes", params, "UTF-8");
|
||||
System.err.println(response);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void getCluster() {
|
||||
|
||||
|
||||
String getUrl = String.format(GET_SERVERLIST_URL_FORMART, PRODUCT_NACOS, DEFAULT_URL_CLUSTER);
|
||||
String response = SimpleHttpTestUtils.doGet(getUrl, new HashMap<>(), "UTF-8");
|
||||
System.err.println(response);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void deleteCluster() {
|
||||
HashMap<String, String> deleteIp = new HashMap<>();
|
||||
@ -64,7 +61,7 @@ public class AddressServerControllerTests {
|
||||
String response = SimpleHttpTestUtils.doDelete("http://127.0.0.1:8080/nacos/v1/as/nodes", deleteIp, "UTF-8");
|
||||
System.err.println(response);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void deleteClusterWithSpecIp() {
|
||||
HashMap<String, String> params = new HashMap<>();
|
||||
@ -72,26 +69,22 @@ public class AddressServerControllerTests {
|
||||
String response = SimpleHttpTestUtils.doDelete("http://127.0.0.1:8080/nacos/v1/as/nodes", params, "UTF-8");
|
||||
System.err.println(response);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void putCluster() {
|
||||
|
||||
|
||||
String ips = "127.0.0.114";
|
||||
HashMap<String, String> params = new HashMap<>();
|
||||
params.put("ips", ips);
|
||||
String response = SimpleHttpTestUtils.doPut("http://127.0.0.1:8080/nacos/v1/as/nodes", params, "UTF-8");
|
||||
System.err.println(response);
|
||||
}
|
||||
|
||||
|
||||
//-----------------product=config,cluster=cluster01 -------------------//
|
||||
|
||||
/**
|
||||
* test with product
|
||||
*/
|
||||
|
||||
|
||||
@Test
|
||||
public void postClusterWithProduct() {
|
||||
|
||||
|
||||
String ips = "127.0.0.101,127.0.0.102,127.0.0.103";
|
||||
HashMap<String, String> params = new HashMap<>();
|
||||
params.put("ips", ips);
|
||||
@ -99,7 +92,7 @@ public class AddressServerControllerTests {
|
||||
String response = SimpleHttpTestUtils.doPost("http://127.0.0.1:8080/nacos/v1/as/nodes", params, "UTF-8");
|
||||
System.err.println(response);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void getClusterWithProduct() {
|
||||
HashMap<String, String> params = new HashMap<>();
|
||||
@ -107,7 +100,7 @@ public class AddressServerControllerTests {
|
||||
String response = SimpleHttpTestUtils.doGet(getUrl, params, "UTF-8");
|
||||
System.err.println(response);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void deleteClusterWithProduct() {
|
||||
HashMap<String, String> params = new HashMap<>();
|
||||
@ -115,7 +108,7 @@ public class AddressServerControllerTests {
|
||||
String response = SimpleHttpTestUtils.doDelete("http://127.0.0.1:8080/nacos/v1/as/nodes", params, "UTF-8");
|
||||
System.err.println(response);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void deleteClusterWithProductAndIp() {
|
||||
HashMap<String, String> params = new HashMap<>();
|
||||
@ -124,10 +117,10 @@ public class AddressServerControllerTests {
|
||||
String response = SimpleHttpTestUtils.doDelete("http://127.0.0.1:8080/nacos/v1/as/nodes", params, "UTF-8");
|
||||
System.err.println(response);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void putClusterWithProduct() {
|
||||
|
||||
|
||||
String ips = "127.0.0.196";
|
||||
HashMap<String, String> params = new HashMap<>();
|
||||
params.put("ips", ips);
|
||||
@ -135,16 +128,12 @@ public class AddressServerControllerTests {
|
||||
String response = SimpleHttpTestUtils.doPut("http://127.0.0.1:8080/nacos/v1/as/nodes", params, "UTF-8");
|
||||
System.err.println(response);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//-----------------product=naming,cluster=cluster01 -------------------//
|
||||
|
||||
/**
|
||||
* test with product and cluster
|
||||
*/
|
||||
|
||||
@Test
|
||||
public void postClusterWithProductAndCluster() {
|
||||
|
||||
|
||||
String ips = "127.0.0.100,127.0.0.200,127.0.0.31";
|
||||
HashMap<String, String> params = new HashMap<>();
|
||||
params.put("ips", ips);
|
||||
@ -153,7 +142,7 @@ public class AddressServerControllerTests {
|
||||
String response = SimpleHttpTestUtils.doPost("http://127.0.0.1:8080/nacos/v1/as/nodes", params, "UTF-8");
|
||||
System.err.println(response);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void getClusterWithProductAndCluster() {
|
||||
HashMap<String, String> params = new HashMap<>();
|
||||
@ -161,7 +150,7 @@ public class AddressServerControllerTests {
|
||||
String response = SimpleHttpTestUtils.doGet(getUrl, params, "UTF-8");
|
||||
System.err.println(response);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void deleteClusterWithProductAndCluster() {
|
||||
HashMap<String, String> params = new HashMap<>();
|
||||
@ -170,7 +159,7 @@ public class AddressServerControllerTests {
|
||||
String response = SimpleHttpTestUtils.doDelete("http://127.0.0.1:8080/nacos/v1/as/nodes", params, "UTF-8");
|
||||
System.err.println(response);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void deleteClusterWithProductAndClusterAndIp() {
|
||||
HashMap<String, String> params = new HashMap<>();
|
||||
@ -180,10 +169,10 @@ public class AddressServerControllerTests {
|
||||
String response = SimpleHttpTestUtils.doDelete("http://127.0.0.1:8080/nacos/v1/as/nodes", params, "UTF-8");
|
||||
System.err.println(response);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void putClusterWithProductAndCluster() {
|
||||
|
||||
|
||||
String ips = "127.0.0.171";
|
||||
HashMap<String, String> params = new HashMap<>();
|
||||
params.put("ips", ips);
|
||||
|
@ -13,22 +13,19 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.address;
|
||||
|
||||
import com.alibaba.nacos.address.util.AddressServerParamCheckUtil;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* @author pbting
|
||||
* @date 2019-06-19 11:31 AM
|
||||
*/
|
||||
public class ParamCheckUtilTests {
|
||||
|
||||
|
||||
@Test
|
||||
public void checkIps() {
|
||||
String[] ips = {"127.0.0.1"};
|
||||
System.out.println(AddressServerParamCheckUtil.checkIps(ips));
|
||||
|
||||
|
||||
String[] illlegalIps = {"127.100.19", "127.0.0.1"};
|
||||
System.err.println(AddressServerParamCheckUtil.checkIps(illlegalIps));
|
||||
}
|
||||
|
@ -13,6 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.address;
|
||||
|
||||
import com.alibaba.nacos.common.utils.IoUtils;
|
||||
@ -26,49 +27,46 @@ import java.net.URL;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author pbting
|
||||
* @date 2019-06-18 2:40 PM
|
||||
*/
|
||||
public class SimpleHttpTestUtils {
|
||||
|
||||
|
||||
private static final String REQUEST_METHOD_DELETE = "DELETE";
|
||||
|
||||
private static final String REQUEST_METHOD_PUT = "PUT";
|
||||
|
||||
private static final String REQUEST_METHOD_POST = "POST";
|
||||
|
||||
private static final String REQUEST_METHOD_GET = "GET";
|
||||
|
||||
|
||||
/**
|
||||
* 连接超时
|
||||
* 连接超时.
|
||||
*/
|
||||
private static int CONNECT_TIME_OUT = 2000;
|
||||
|
||||
private static final int CONNECT_TIME_OUT = 2000;
|
||||
|
||||
/**
|
||||
* 读取数据超时
|
||||
* 读取数据超时.
|
||||
*/
|
||||
private static int READ_TIME_OUT = 2000;
|
||||
|
||||
private static final int READ_TIME_OUT = 2000;
|
||||
|
||||
/**
|
||||
* 请求编码
|
||||
* 请求编码.
|
||||
*/
|
||||
public static String REQUEST_ENCODING = "UTF-8";
|
||||
|
||||
public static final String REQUEST_ENCODING = "UTF-8";
|
||||
|
||||
/**
|
||||
* 接收编码
|
||||
* 接收编码.
|
||||
*/
|
||||
public static String RESPONSE_ENCODING = "UTF-8";
|
||||
|
||||
public static final String RESPONSE_ENCODING = "UTF-8";
|
||||
|
||||
public static final short OK = 200;
|
||||
|
||||
public static final short Bad_Request = 400;
|
||||
|
||||
public static final short Internal_Server_Error = 500;
|
||||
|
||||
|
||||
public static final short BAD_REQUEST = 400;
|
||||
|
||||
public static final short INTERNAL_SERVER_ERROR = 500;
|
||||
|
||||
public static final short PARAM_ERROR_NO_ANALYSESOR = 1000;
|
||||
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 发送带参数的GET的HTTP请求
|
||||
* </pre>
|
||||
* 发送带参数的GET的HTTP请求.
|
||||
*
|
||||
* @param reqUrl HTTP请求URL
|
||||
* @param paramMap 参数映射表
|
||||
@ -77,11 +75,9 @@ public class SimpleHttpTestUtils {
|
||||
public static String doGet(String reqUrl, Map<String, String> paramMap, String recvEncoding) {
|
||||
return doRequest(reqUrl, paramMap, REQUEST_METHOD_GET, recvEncoding);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 发送带参数的POST的HTTP请求
|
||||
* </pre>
|
||||
* 发送带参数的POST的HTTP请求.
|
||||
*
|
||||
* @param reqUrl HTTP请求URL
|
||||
* @param paramMap 参数映射表
|
||||
@ -90,11 +86,9 @@ public class SimpleHttpTestUtils {
|
||||
public static String doPost(String reqUrl, Map<String, String> paramMap, String recvEncoding) {
|
||||
return doRequest(reqUrl, paramMap, REQUEST_METHOD_POST, recvEncoding);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 发送带参数的 PUT 的 HTTP 请求
|
||||
* </pre>
|
||||
* 发送带参数的 PUT 的 HTTP 请求.
|
||||
*
|
||||
* @param reqUrl HTTP请求URL
|
||||
* @param paramMap 参数映射表
|
||||
@ -103,11 +97,9 @@ public class SimpleHttpTestUtils {
|
||||
public static String doPut(String reqUrl, Map<String, String> paramMap, String recvEncoding) {
|
||||
return doRequest(reqUrl, paramMap, REQUEST_METHOD_PUT, recvEncoding);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 发送带参数的 DELETE 的 HTTP 请求
|
||||
* </pre>
|
||||
* 发送带参数的 DELETE 的 HTTP 请求.
|
||||
*
|
||||
* @param reqUrl HTTP请求URL
|
||||
* @param paramMap 参数映射表
|
||||
@ -116,13 +108,15 @@ public class SimpleHttpTestUtils {
|
||||
public static String doDelete(String reqUrl, Map<String, String> paramMap, String recvEncoding) {
|
||||
return doRequest(reqUrl, paramMap, REQUEST_METHOD_DELETE, recvEncoding);
|
||||
}
|
||||
|
||||
private static String doRequest(String reqUrl, Map<String, String> paramMap, String reqMethod, String recvEncoding) {
|
||||
|
||||
|
||||
private static String doRequest(String reqUrl, Map<String, String> paramMap, String reqMethod,
|
||||
String recvEncoding) {
|
||||
|
||||
return doExecute(reqUrl, paramMap, reqMethod, recvEncoding);
|
||||
}
|
||||
|
||||
private static String doExecute(String reqUrl, Map<String, String> paramMap, String reqMethod, String recvEncoding) {
|
||||
|
||||
private static String doExecute(String reqUrl, Map<String, String> paramMap, String reqMethod,
|
||||
String recvEncoding) {
|
||||
HttpURLConnection urlCon = null;
|
||||
String responseContent = null;
|
||||
try {
|
||||
@ -134,13 +128,13 @@ public class SimpleHttpTestUtils {
|
||||
params.append(URLEncoder.encode(element.getValue(), REQUEST_ENCODING));
|
||||
params.append("&");
|
||||
}
|
||||
|
||||
|
||||
if (params.length() > 0) {
|
||||
params = params.deleteCharAt(params.length() - 1);
|
||||
}
|
||||
|
||||
if (params.length() > 0 &&
|
||||
(REQUEST_METHOD_GET.equals(reqMethod) || REQUEST_METHOD_DELETE.equals(reqMethod))) {
|
||||
|
||||
if (params.length() > 0 && (REQUEST_METHOD_GET.equals(reqMethod) || REQUEST_METHOD_DELETE
|
||||
.equals(reqMethod))) {
|
||||
reqUrl = reqUrl + "?" + params.toString();
|
||||
}
|
||||
}
|
||||
@ -169,7 +163,7 @@ public class SimpleHttpTestUtils {
|
||||
responseContent = tempStr.toString();
|
||||
rd.close();
|
||||
in.close();
|
||||
|
||||
|
||||
urlCon.getResponseMessage();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
@ -178,5 +172,5 @@ public class SimpleHttpTestUtils {
|
||||
}
|
||||
return responseContent;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -19,7 +19,7 @@
|
||||
<parent>
|
||||
<groupId>com.alibaba.nacos</groupId>
|
||||
<artifactId>nacos-all</artifactId>
|
||||
<version>1.3.1-BETA</version>
|
||||
<version>1.3.1</version>
|
||||
</parent>
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
@ -154,4 +154,10 @@ public class NacosException extends Exception {
|
||||
public static final int OVER_THRESHOLD = 503;
|
||||
|
||||
public static final int RESOURCE_NOT_FOUND = -404;
|
||||
|
||||
/**
|
||||
* http client error code,
|
||||
* ome exceptions that occurred when the use the Nacos RestTemplate and Nacos AsyncRestTemplate.
|
||||
*/
|
||||
public static final int HTTP_CLIENT_ERROR_CODE = -500;
|
||||
}
|
||||
|
@ -16,6 +16,8 @@
|
||||
|
||||
package com.alibaba.nacos.api.naming.pojo.healthcheck;
|
||||
|
||||
import com.alibaba.nacos.api.exception.runtime.NacosDeserializationException;
|
||||
import com.alibaba.nacos.api.exception.runtime.NacosSerializationException;
|
||||
import com.alibaba.nacos.api.naming.pojo.healthcheck.AbstractHealthChecker.None;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||
@ -76,8 +78,7 @@ public class HealthCheckerFactory {
|
||||
try {
|
||||
return MAPPER.readValue(jsonString, AbstractHealthChecker.class);
|
||||
} catch (IOException e) {
|
||||
// TODO replace with NacosDeserializeException.
|
||||
throw new RuntimeException("Deserialize health checker from json failed", e);
|
||||
throw new NacosDeserializationException(AbstractHealthChecker.class, e);
|
||||
}
|
||||
}
|
||||
|
||||
@ -91,8 +92,7 @@ public class HealthCheckerFactory {
|
||||
try {
|
||||
return MAPPER.writeValueAsString(healthChecker);
|
||||
} catch (JsonProcessingException e) {
|
||||
// TODO replace with NacosSerializeException.
|
||||
throw new RuntimeException("Serialize health checker to json failed", e);
|
||||
throw new NacosSerializationException(healthChecker.getClass(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -15,100 +15,106 @@
|
||||
~ limitations under the License.
|
||||
-->
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<groupId>com.alibaba.nacos</groupId>
|
||||
<artifactId>nacos-all</artifactId>
|
||||
<version>1.3.1-BETA</version>
|
||||
<version>1.3.1</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
<artifactId>nacos-client</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
|
||||
<name>nacos-client ${project.version}</name>
|
||||
<url>http://nacos.io</url>
|
||||
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
|
||||
<dependencies>
|
||||
|
||||
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.logging.log4j</groupId>
|
||||
<artifactId>log4j-core</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.logging.log4j</groupId>
|
||||
<artifactId>log4j-api</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.logging.log4j</groupId>
|
||||
<artifactId>log4j-slf4j-impl</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>nacos-common</artifactId>
|
||||
</dependency>
|
||||
|
||||
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>nacos-api</artifactId>
|
||||
</dependency>
|
||||
|
||||
|
||||
<dependency>
|
||||
<groupId>ch.qos.logback</groupId>
|
||||
<artifactId>logback-classic</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
|
||||
<dependency>
|
||||
<groupId>ch.qos.logback</groupId>
|
||||
<artifactId>logback-core</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
</dependency>
|
||||
|
||||
|
||||
<dependency>
|
||||
<artifactId>commons-codec</artifactId>
|
||||
<groupId>commons-codec</groupId>
|
||||
</dependency>
|
||||
|
||||
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-core</artifactId>
|
||||
</dependency>
|
||||
|
||||
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
</dependency>
|
||||
|
||||
|
||||
<dependency>
|
||||
<groupId>net.jcip</groupId>
|
||||
<artifactId>jcip-annotations</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
<dependency>
|
||||
<groupId>io.prometheus</groupId>
|
||||
<artifactId>simpleclient</artifactId>
|
||||
@ -122,17 +128,17 @@
|
||||
<groupId>org.yaml</groupId>
|
||||
<artifactId>snakeyaml</artifactId>
|
||||
</dependency>
|
||||
|
||||
|
||||
</dependencies>
|
||||
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<source>7</source>
|
||||
<target>7</target>
|
||||
<source>6</source>
|
||||
<target>6</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
|
@ -13,6 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.client.config;
|
||||
|
||||
import com.alibaba.nacos.api.PropertyKeyConst;
|
||||
@ -45,29 +46,33 @@ import java.util.List;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* Config Impl
|
||||
* Config Impl.
|
||||
*
|
||||
* @author Nacos
|
||||
*/
|
||||
@SuppressWarnings("PMD.ServiceOrDaoClassShouldEndWithImplRule")
|
||||
public class NacosConfigService implements ConfigService {
|
||||
|
||||
|
||||
private static final Logger LOGGER = LogUtils.logger(NacosConfigService.class);
|
||||
|
||||
|
||||
private static final long POST_TIMEOUT = 3000L;
|
||||
|
||||
|
||||
/**
|
||||
* http agent
|
||||
* http agent.
|
||||
*/
|
||||
private HttpAgent agent;
|
||||
private final HttpAgent agent;
|
||||
|
||||
/**
|
||||
* longpolling
|
||||
* long polling.
|
||||
*/
|
||||
private ClientWorker worker;
|
||||
private final ClientWorker worker;
|
||||
|
||||
private String namespace;
|
||||
private String encode;
|
||||
private ConfigFilterChainManager configFilterChainManager = new ConfigFilterChainManager();
|
||||
|
||||
|
||||
private final String encode;
|
||||
|
||||
private final ConfigFilterChainManager configFilterChainManager = new ConfigFilterChainManager();
|
||||
|
||||
public NacosConfigService(Properties properties) throws NacosException {
|
||||
ValidatorUtils.checkInitParam(properties);
|
||||
String encodeTmp = properties.getProperty(PropertyKeyConst.ENCODE);
|
||||
@ -77,98 +82,99 @@ public class NacosConfigService implements ConfigService {
|
||||
this.encode = encodeTmp.trim();
|
||||
}
|
||||
initNamespace(properties);
|
||||
|
||||
|
||||
this.agent = new MetricsHttpAgent(new ServerHttpAgent(properties));
|
||||
this.agent.start();
|
||||
this.worker = new ClientWorker(this.agent, this.configFilterChainManager, properties);
|
||||
}
|
||||
|
||||
|
||||
private void initNamespace(Properties properties) {
|
||||
namespace = ParamUtil.parseNamespace(properties);
|
||||
properties.put(PropertyKeyConst.NAMESPACE, namespace);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getConfig(String dataId, String group, long timeoutMs) throws NacosException {
|
||||
return getConfigInner(namespace, dataId, group, timeoutMs);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getConfigAndSignListener(String dataId, String group, long timeoutMs, Listener listener) throws NacosException {
|
||||
public String getConfigAndSignListener(String dataId, String group, long timeoutMs, Listener listener)
|
||||
throws NacosException {
|
||||
String content = getConfig(dataId, group, timeoutMs);
|
||||
worker.addTenantListenersWithContent(dataId, group, content, Arrays.asList(listener));
|
||||
return content;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void addListener(String dataId, String group, Listener listener) throws NacosException {
|
||||
worker.addTenantListeners(dataId, group, Arrays.asList(listener));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean publishConfig(String dataId, String group, String content) throws NacosException {
|
||||
return publishConfigInner(namespace, dataId, group, null, null, null, content);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean removeConfig(String dataId, String group) throws NacosException {
|
||||
return removeConfigInner(namespace, dataId, group, null);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void removeListener(String dataId, String group, Listener listener) {
|
||||
worker.removeTenantListener(dataId, group, listener);
|
||||
}
|
||||
|
||||
|
||||
private String getConfigInner(String tenant, String dataId, String group, long timeoutMs) throws NacosException {
|
||||
group = null2defaultGroup(group);
|
||||
ParamUtils.checkKeyParam(dataId, group);
|
||||
ConfigResponse cr = new ConfigResponse();
|
||||
|
||||
|
||||
cr.setDataId(dataId);
|
||||
cr.setTenant(tenant);
|
||||
cr.setGroup(group);
|
||||
|
||||
|
||||
// 优先使用本地配置
|
||||
String content = LocalConfigInfoProcessor.getFailover(agent.getName(), dataId, group, tenant);
|
||||
if (content != null) {
|
||||
LOGGER.warn("[{}] [get-config] get failover ok, dataId={}, group={}, tenant={}, config={}", agent.getName(),
|
||||
dataId, group, tenant, ContentUtils.truncateContent(content));
|
||||
dataId, group, tenant, ContentUtils.truncateContent(content));
|
||||
cr.setContent(content);
|
||||
configFilterChainManager.doFilter(null, cr);
|
||||
content = cr.getContent();
|
||||
return content;
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
String[] ct = worker.getServerConfig(dataId, group, tenant, timeoutMs);
|
||||
cr.setContent(ct[0]);
|
||||
|
||||
|
||||
configFilterChainManager.doFilter(null, cr);
|
||||
content = cr.getContent();
|
||||
|
||||
|
||||
return content;
|
||||
} catch (NacosException ioe) {
|
||||
if (NacosException.NO_RIGHT == ioe.getErrCode()) {
|
||||
throw ioe;
|
||||
}
|
||||
LOGGER.warn("[{}] [get-config] get from server error, dataId={}, group={}, tenant={}, msg={}",
|
||||
agent.getName(), dataId, group, tenant, ioe.toString());
|
||||
agent.getName(), dataId, group, tenant, ioe.toString());
|
||||
}
|
||||
|
||||
|
||||
LOGGER.warn("[{}] [get-config] get snapshot ok, dataId={}, group={}, tenant={}, config={}", agent.getName(),
|
||||
dataId, group, tenant, ContentUtils.truncateContent(content));
|
||||
dataId, group, tenant, ContentUtils.truncateContent(content));
|
||||
content = LocalConfigInfoProcessor.getSnapshot(agent.getName(), dataId, group, tenant);
|
||||
cr.setContent(content);
|
||||
configFilterChainManager.doFilter(null, cr);
|
||||
content = cr.getContent();
|
||||
return content;
|
||||
}
|
||||
|
||||
|
||||
private String null2defaultGroup(String group) {
|
||||
return (null == group) ? Constants.DEFAULT_GROUP : group.trim();
|
||||
}
|
||||
|
||||
|
||||
private boolean removeConfigInner(String tenant, String dataId, String group, String tag) throws NacosException {
|
||||
group = null2defaultGroup(group);
|
||||
ParamUtils.checkKeyParam(dataId, group);
|
||||
@ -193,26 +199,26 @@ public class NacosConfigService implements ConfigService {
|
||||
LOGGER.warn("[remove] error, " + dataId + ", " + group + ", " + tenant + ", msg: " + ioe.toString());
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
if (HttpURLConnection.HTTP_OK == result.code) {
|
||||
LOGGER.info("[{}] [remove] ok, dataId={}, group={}, tenant={}", agent.getName(), dataId, group, tenant);
|
||||
return true;
|
||||
} else if (HttpURLConnection.HTTP_FORBIDDEN == result.code) {
|
||||
LOGGER.warn("[{}] [remove] error, dataId={}, group={}, tenant={}, code={}, msg={}", agent.getName(), dataId,
|
||||
group, tenant, result.code, result.content);
|
||||
group, tenant, result.code, result.content);
|
||||
throw new NacosException(result.code, result.content);
|
||||
} else {
|
||||
LOGGER.warn("[{}] [remove] error, dataId={}, group={}, tenant={}, code={}, msg={}", agent.getName(), dataId,
|
||||
group, tenant, result.code, result.content);
|
||||
group, tenant, result.code, result.content);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private boolean publishConfigInner(String tenant, String dataId, String group, String tag, String appName,
|
||||
String betaIps, String content) throws NacosException {
|
||||
String betaIps, String content) throws NacosException {
|
||||
group = null2defaultGroup(group);
|
||||
ParamUtils.checkParam(dataId, group, content);
|
||||
|
||||
|
||||
ConfigRequest cr = new ConfigRequest();
|
||||
cr.setDataId(dataId);
|
||||
cr.setTenant(tenant);
|
||||
@ -220,7 +226,7 @@ public class NacosConfigService implements ConfigService {
|
||||
cr.setContent(content);
|
||||
configFilterChainManager.doFilter(cr, null);
|
||||
content = cr.getContent();
|
||||
|
||||
|
||||
String url = Constants.CONFIG_CONTROLLER_PATH;
|
||||
List<String> params = new ArrayList<String>();
|
||||
params.add("dataId");
|
||||
@ -241,38 +247,38 @@ public class NacosConfigService implements ConfigService {
|
||||
params.add("tag");
|
||||
params.add(tag);
|
||||
}
|
||||
|
||||
|
||||
List<String> headers = new ArrayList<String>();
|
||||
if (StringUtils.isNotEmpty(betaIps)) {
|
||||
headers.add("betaIps");
|
||||
headers.add(betaIps);
|
||||
}
|
||||
|
||||
|
||||
HttpResult result = null;
|
||||
try {
|
||||
result = agent.httpPost(url, headers, params, encode, POST_TIMEOUT);
|
||||
} catch (IOException ioe) {
|
||||
LOGGER.warn("[{}] [publish-single] exception, dataId={}, group={}, msg={}", agent.getName(), dataId,
|
||||
group, ioe.toString());
|
||||
LOGGER.warn("[{}] [publish-single] exception, dataId={}, group={}, msg={}", agent.getName(), dataId, group,
|
||||
ioe.toString());
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
if (HttpURLConnection.HTTP_OK == result.code) {
|
||||
LOGGER.info("[{}] [publish-single] ok, dataId={}, group={}, tenant={}, config={}", agent.getName(), dataId,
|
||||
group, tenant, ContentUtils.truncateContent(content));
|
||||
group, tenant, ContentUtils.truncateContent(content));
|
||||
return true;
|
||||
} else if (HttpURLConnection.HTTP_FORBIDDEN == result.code) {
|
||||
LOGGER.warn("[{}] [publish-single] error, dataId={}, group={}, tenant={}, code={}, msg={}", agent.getName(),
|
||||
dataId, group, tenant, result.code, result.content);
|
||||
dataId, group, tenant, result.code, result.content);
|
||||
throw new NacosException(result.code, result.content);
|
||||
} else {
|
||||
LOGGER.warn("[{}] [publish-single] error, dataId={}, group={}, tenant={}, code={}, msg={}", agent.getName(),
|
||||
dataId, group, tenant, result.code, result.content);
|
||||
dataId, group, tenant, result.code, result.content);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getServerStatus() {
|
||||
if (worker.isHealthServer()) {
|
||||
@ -281,9 +287,9 @@ public class NacosConfigService implements ConfigService {
|
||||
return "DOWN";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void shutDown() throws NacosException{
|
||||
public void shutDown() throws NacosException {
|
||||
agent.shutdown();
|
||||
worker.shutdown();
|
||||
}
|
||||
|
@ -13,6 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.client.config.common;
|
||||
|
||||
import com.alibaba.nacos.common.utils.StringUtils;
|
||||
@ -23,19 +24,19 @@ import com.alibaba.nacos.common.utils.StringUtils;
|
||||
* @author Nacos
|
||||
*/
|
||||
public class GroupKey {
|
||||
|
||||
|
||||
public static String getKey(String dataId, String group) {
|
||||
return doGetKey(dataId, group, "");
|
||||
return getKey(dataId, group, "");
|
||||
}
|
||||
|
||||
public static String getKeyTenant(String dataId, String group, String tenant) {
|
||||
return doGetKey(dataId, group, tenant);
|
||||
}
|
||||
|
||||
|
||||
public static String getKey(String dataId, String group, String datumStr) {
|
||||
return doGetKey(dataId, group, datumStr);
|
||||
}
|
||||
|
||||
|
||||
public static String getKeyTenant(String dataId, String group, String tenant) {
|
||||
return doGetKey(dataId, group, tenant);
|
||||
}
|
||||
|
||||
private static String doGetKey(String dataId, String group, String datumStr) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
urlEncode(dataId, sb);
|
||||
@ -45,16 +46,22 @@ public class GroupKey {
|
||||
sb.append('+');
|
||||
urlEncode(datumStr, sb);
|
||||
}
|
||||
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
static public String[] parseKey(String groupKey) {
|
||||
|
||||
/**
|
||||
* Parse key.
|
||||
*
|
||||
* @param groupKey group key
|
||||
* @return parsed key
|
||||
*/
|
||||
public static String[] parseKey(String groupKey) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
String dataId = null;
|
||||
String group = null;
|
||||
String tenant = null;
|
||||
|
||||
|
||||
for (int i = 0; i < groupKey.length(); ++i) {
|
||||
char c = groupKey.charAt(i);
|
||||
if ('+' == c) {
|
||||
@ -81,7 +88,7 @@ public class GroupKey {
|
||||
sb.append(c);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (StringUtils.isBlank(group)) {
|
||||
group = sb.toString();
|
||||
if (group.length() == 0) {
|
||||
@ -93,12 +100,12 @@ public class GroupKey {
|
||||
throw new IllegalArgumentException("invalid groupkey:" + groupKey);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return new String[] {dataId, group, tenant};
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* + -> %2B % -> %25
|
||||
* + -> %2B % -> %25.
|
||||
*/
|
||||
static void urlEncode(String str, StringBuilder sb) {
|
||||
for (int idx = 0; idx < str.length(); ++idx) {
|
||||
@ -112,5 +119,5 @@ public class GroupKey {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -13,6 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.client.config.filter.impl;
|
||||
|
||||
import com.alibaba.nacos.api.config.filter.IConfigContext;
|
||||
@ -21,22 +22,22 @@ import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Config Context
|
||||
* Config Context.
|
||||
*
|
||||
* @author Nacos
|
||||
*/
|
||||
public class ConfigContext implements IConfigContext {
|
||||
|
||||
private Map<String, Object> param = new HashMap<String, Object>();
|
||||
|
||||
|
||||
private final Map<String, Object> param = new HashMap<String, Object>();
|
||||
|
||||
@Override
|
||||
public Object getParameter(String key) {
|
||||
return param.get(key);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setParameter(String key, Object value) {
|
||||
param.put(key, value);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -13,6 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.client.config.filter.impl;
|
||||
|
||||
import com.alibaba.nacos.api.config.filter.IConfigFilter;
|
||||
@ -25,14 +26,20 @@ import com.google.common.collect.Lists;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Config Filter Chain Management
|
||||
* Config Filter Chain Management.
|
||||
*
|
||||
* @author Nacos
|
||||
*/
|
||||
public class ConfigFilterChainManager implements IConfigFilterChain {
|
||||
|
||||
private List<IConfigFilter> filters = Lists.newArrayList();
|
||||
|
||||
|
||||
private final List<IConfigFilter> filters = Lists.newArrayList();
|
||||
|
||||
/**
|
||||
* Add filter.
|
||||
*
|
||||
* @param filter filter
|
||||
* @return this
|
||||
*/
|
||||
public synchronized ConfigFilterChainManager addFilter(IConfigFilter filter) {
|
||||
// 根据order大小顺序插入
|
||||
int i = 0;
|
||||
@ -48,28 +55,28 @@ public class ConfigFilterChainManager implements IConfigFilterChain {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (i == this.filters.size()) {
|
||||
this.filters.add(i, filter);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void doFilter(IConfigRequest request, IConfigResponse response) throws NacosException {
|
||||
new VirtualFilterChain(this.filters).doFilter(request, response);
|
||||
}
|
||||
|
||||
|
||||
private static class VirtualFilterChain implements IConfigFilterChain {
|
||||
|
||||
|
||||
private final List<? extends IConfigFilter> additionalFilters;
|
||||
|
||||
|
||||
private int currentPosition = 0;
|
||||
|
||||
|
||||
public VirtualFilterChain(List<? extends IConfigFilter> additionalFilters) {
|
||||
this.additionalFilters = additionalFilters;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void doFilter(final IConfigRequest request, final IConfigResponse response) throws NacosException {
|
||||
if (this.currentPosition != this.additionalFilters.size()) {
|
||||
@ -79,5 +86,5 @@ public class ConfigFilterChainManager implements IConfigFilterChain {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -13,6 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.client.config.filter.impl;
|
||||
|
||||
import com.alibaba.nacos.api.config.filter.IConfigContext;
|
||||
@ -22,56 +23,56 @@ import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Config Request
|
||||
* Config Request.
|
||||
*
|
||||
* @author Nacos
|
||||
*/
|
||||
public class ConfigRequest implements IConfigRequest {
|
||||
|
||||
private Map<String, Object> param = new HashMap<String, Object>();
|
||||
|
||||
private IConfigContext configContext = new ConfigContext();
|
||||
|
||||
|
||||
private final Map<String, Object> param = new HashMap<String, Object>();
|
||||
|
||||
private final IConfigContext configContext = new ConfigContext();
|
||||
|
||||
public String getTenant() {
|
||||
return (String)param.get("tenant");
|
||||
return (String) param.get("tenant");
|
||||
}
|
||||
|
||||
|
||||
public void setTenant(String tenant) {
|
||||
param.put("tenant", tenant);
|
||||
}
|
||||
|
||||
|
||||
public String getDataId() {
|
||||
return (String)param.get("dataId");
|
||||
return (String) param.get("dataId");
|
||||
}
|
||||
|
||||
|
||||
public void setDataId(String dataId) {
|
||||
param.put("dataId", dataId);
|
||||
}
|
||||
|
||||
|
||||
public String getGroup() {
|
||||
return (String)param.get("group");
|
||||
return (String) param.get("group");
|
||||
}
|
||||
|
||||
|
||||
public void setGroup(String group) {
|
||||
param.put("group", group);
|
||||
}
|
||||
|
||||
|
||||
public String getContent() {
|
||||
return (String)param.get("content");
|
||||
return (String) param.get("content");
|
||||
}
|
||||
|
||||
|
||||
public void setContent(String content) {
|
||||
param.put("content", content);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Object getParameter(String key) {
|
||||
return param.get(key);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public IConfigContext getConfigContext() {
|
||||
return configContext;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -13,6 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.client.config.filter.impl;
|
||||
|
||||
import com.alibaba.nacos.api.config.filter.IConfigContext;
|
||||
@ -22,56 +23,56 @@ import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Config Response
|
||||
* Config Response.
|
||||
*
|
||||
* @author Nacos
|
||||
*/
|
||||
public class ConfigResponse implements IConfigResponse {
|
||||
|
||||
private Map<String, Object> param = new HashMap<String, Object>();
|
||||
|
||||
private IConfigContext configContext = new ConfigContext();
|
||||
|
||||
|
||||
private final Map<String, Object> param = new HashMap<String, Object>();
|
||||
|
||||
private final IConfigContext configContext = new ConfigContext();
|
||||
|
||||
public String getTenant() {
|
||||
return (String)param.get("tenant");
|
||||
return (String) param.get("tenant");
|
||||
}
|
||||
|
||||
|
||||
public void setTenant(String tenant) {
|
||||
param.put("tenant", tenant);
|
||||
}
|
||||
|
||||
|
||||
public String getDataId() {
|
||||
return (String)param.get("dataId");
|
||||
return (String) param.get("dataId");
|
||||
}
|
||||
|
||||
|
||||
public void setDataId(String dataId) {
|
||||
param.put("dataId", dataId);
|
||||
}
|
||||
|
||||
|
||||
public String getGroup() {
|
||||
return (String)param.get("group");
|
||||
return (String) param.get("group");
|
||||
}
|
||||
|
||||
|
||||
public void setGroup(String group) {
|
||||
param.put("group", group);
|
||||
}
|
||||
|
||||
|
||||
public String getContent() {
|
||||
return (String)param.get("content");
|
||||
return (String) param.get("content");
|
||||
}
|
||||
|
||||
|
||||
public void setContent(String content) {
|
||||
param.put("content", content);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Object getParameter(String key) {
|
||||
return param.get(key);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public IConfigContext getConfigContext() {
|
||||
return configContext;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -13,6 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.client.config.http;
|
||||
|
||||
import com.alibaba.nacos.api.exception.NacosException;
|
||||
@ -22,78 +23,87 @@ import com.alibaba.nacos.common.lifecycle.Closeable;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
* HttpAgent
|
||||
* HttpAgent.
|
||||
*
|
||||
* @author Nacos
|
||||
*/
|
||||
public interface HttpAgent extends Closeable {
|
||||
|
||||
|
||||
/**
|
||||
* start to get nacos ip list
|
||||
* @return Nothing.
|
||||
* start to get nacos ip list.
|
||||
*
|
||||
* @throws NacosException on get ip list error.
|
||||
*/
|
||||
void start() throws NacosException;
|
||||
|
||||
|
||||
/**
|
||||
* invoke http get method
|
||||
* @param path http path
|
||||
* @param headers http headers
|
||||
* @param paramValues http paramValues http
|
||||
* @param encoding http encode
|
||||
* invoke http get method.
|
||||
*
|
||||
* @param path http path
|
||||
* @param headers http headers
|
||||
* @param paramValues http paramValues http
|
||||
* @param encoding http encode
|
||||
* @param readTimeoutMs http timeout
|
||||
* @return HttpResult http response
|
||||
* @throws IOException If an input or output exception occurred
|
||||
*/
|
||||
|
||||
HttpResult httpGet(String path, List<String> headers, List<String> paramValues, String encoding, long readTimeoutMs) throws IOException;
|
||||
|
||||
|
||||
HttpResult httpGet(String path, List<String> headers, List<String> paramValues, String encoding, long readTimeoutMs)
|
||||
throws IOException;
|
||||
|
||||
/**
|
||||
* invoke http post method
|
||||
* @param path http path
|
||||
* @param headers http headers
|
||||
* @param paramValues http paramValues http
|
||||
* @param encoding http encode
|
||||
* invoke http post method.
|
||||
*
|
||||
* @param path http path
|
||||
* @param headers http headers
|
||||
* @param paramValues http paramValues http
|
||||
* @param encoding http encode
|
||||
* @param readTimeoutMs http timeout
|
||||
* @return HttpResult http response
|
||||
* @throws IOException If an input or output exception occurred
|
||||
*/
|
||||
HttpResult httpPost(String path, List<String> headers, List<String> paramValues, String encoding, long readTimeoutMs) throws IOException;
|
||||
|
||||
HttpResult httpPost(String path, List<String> headers, List<String> paramValues, String encoding,
|
||||
long readTimeoutMs) throws IOException;
|
||||
|
||||
/**
|
||||
* invoke http delete method
|
||||
* @param path http path
|
||||
* @param headers http headers
|
||||
* @param paramValues http paramValues http
|
||||
* @param encoding http encode
|
||||
* invoke http delete method.
|
||||
*
|
||||
* @param path http path
|
||||
* @param headers http headers
|
||||
* @param paramValues http paramValues http
|
||||
* @param encoding http encode
|
||||
* @param readTimeoutMs http timeout
|
||||
* @return HttpResult http response
|
||||
* @throws IOException If an input or output exception occurred
|
||||
*/
|
||||
HttpResult httpDelete(String path, List<String> headers, List<String> paramValues, String encoding, long readTimeoutMs) throws IOException;
|
||||
|
||||
HttpResult httpDelete(String path, List<String> headers, List<String> paramValues, String encoding,
|
||||
long readTimeoutMs) throws IOException;
|
||||
|
||||
/**
|
||||
* get name
|
||||
* get name.
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
String getName();
|
||||
|
||||
|
||||
/**
|
||||
* get namespace
|
||||
* get namespace.
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
String getNamespace();
|
||||
|
||||
|
||||
/**
|
||||
* get tenant
|
||||
* get tenant.
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
String getTenant();
|
||||
|
||||
|
||||
/**
|
||||
* get encode
|
||||
* get encode.
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
String getEncode();
|
||||
|
@ -13,11 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
/**
|
||||
* MetricsHttpAgent
|
||||
*
|
||||
* @author Nacos
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.client.config.http;
|
||||
|
||||
import com.alibaba.nacos.api.exception.NacosException;
|
||||
@ -29,25 +25,26 @@ import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* MetricsHttpAgent
|
||||
* MetricsHttpAgent.
|
||||
*
|
||||
* @author Nacos
|
||||
*/
|
||||
public class MetricsHttpAgent implements HttpAgent {
|
||||
|
||||
private HttpAgent httpAgent;
|
||||
|
||||
|
||||
private final HttpAgent httpAgent;
|
||||
|
||||
public MetricsHttpAgent(HttpAgent httpAgent) {
|
||||
this.httpAgent = httpAgent;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void start() throws NacosException {
|
||||
httpAgent.start();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public HttpResult httpGet(String path, List<String> headers, List<String> paramValues, String encoding, long readTimeoutMs) throws IOException {
|
||||
public HttpResult httpGet(String path, List<String> headers, List<String> paramValues, String encoding,
|
||||
long readTimeoutMs) throws IOException {
|
||||
Histogram.Timer timer = MetricsMonitor.getConfigRequestMonitor("GET", path, "NA");
|
||||
HttpResult result;
|
||||
try {
|
||||
@ -58,12 +55,13 @@ public class MetricsHttpAgent implements HttpAgent {
|
||||
timer.observeDuration();
|
||||
timer.close();
|
||||
}
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public HttpResult httpPost(String path, List<String> headers, List<String> paramValues, String encoding, long readTimeoutMs) throws IOException {
|
||||
public HttpResult httpPost(String path, List<String> headers, List<String> paramValues, String encoding,
|
||||
long readTimeoutMs) throws IOException {
|
||||
Histogram.Timer timer = MetricsMonitor.getConfigRequestMonitor("POST", path, "NA");
|
||||
HttpResult result;
|
||||
try {
|
||||
@ -74,49 +72,50 @@ public class MetricsHttpAgent implements HttpAgent {
|
||||
timer.observeDuration();
|
||||
timer.close();
|
||||
}
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public HttpResult httpDelete(String path, List<String> headers, List<String> paramValues, String encoding, long readTimeoutMs) throws IOException {
|
||||
public HttpResult httpDelete(String path, List<String> headers, List<String> paramValues, String encoding,
|
||||
long readTimeoutMs) throws IOException {
|
||||
Histogram.Timer timer = MetricsMonitor.getConfigRequestMonitor("DELETE", path, "NA");
|
||||
HttpResult result;
|
||||
try {
|
||||
result = httpAgent.httpDelete(path, headers, paramValues, encoding, readTimeoutMs);
|
||||
} catch (IOException e) {
|
||||
|
||||
|
||||
throw e;
|
||||
} finally {
|
||||
timer.observeDuration();
|
||||
timer.close();
|
||||
}
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return httpAgent.getName();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getNamespace() {
|
||||
return httpAgent.getNamespace();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getTenant() {
|
||||
return httpAgent.getTenant();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getEncode() {
|
||||
return httpAgent.getEncode();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void shutdown() throws NacosException{
|
||||
public void shutdown() throws NacosException {
|
||||
httpAgent.shutdown();
|
||||
}
|
||||
}
|
||||
|
@ -13,6 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.client.config.http;
|
||||
|
||||
import com.alibaba.nacos.api.PropertyKeyConst;
|
||||
@ -22,7 +23,7 @@ import com.alibaba.nacos.client.config.impl.HttpSimpleClient;
|
||||
import com.alibaba.nacos.client.config.impl.HttpSimpleClient.HttpResult;
|
||||
import com.alibaba.nacos.client.config.impl.ServerListManager;
|
||||
import com.alibaba.nacos.client.config.impl.SpasAdapter;
|
||||
import com.alibaba.nacos.client.identify.STSConfig;
|
||||
import com.alibaba.nacos.client.identify.StsConfig;
|
||||
import com.alibaba.nacos.client.security.SecurityProxy;
|
||||
import com.alibaba.nacos.client.utils.LogUtils;
|
||||
import com.alibaba.nacos.client.utils.ParamUtil;
|
||||
@ -45,228 +46,241 @@ import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ScheduledThreadPoolExecutor;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.ScheduledThreadPoolExecutor;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
/**
|
||||
* Server Agent
|
||||
* Server Agent.
|
||||
*
|
||||
* @author water.lyl
|
||||
*/
|
||||
public class ServerHttpAgent implements HttpAgent {
|
||||
|
||||
|
||||
private static final Logger LOGGER = LogUtils.logger(ServerHttpAgent.class);
|
||||
|
||||
|
||||
private SecurityProxy securityProxy;
|
||||
|
||||
|
||||
private String namespaceId;
|
||||
|
||||
private long securityInfoRefreshIntervalMills = TimeUnit.SECONDS.toMillis(5);
|
||||
|
||||
|
||||
private final long securityInfoRefreshIntervalMills = TimeUnit.SECONDS.toMillis(5);
|
||||
|
||||
private ScheduledExecutorService executorService;
|
||||
|
||||
|
||||
/**
|
||||
* Invoke http get method.
|
||||
*
|
||||
* @param path 相对于web应用根,以/开头
|
||||
* @param headers
|
||||
* @param paramValues
|
||||
* @param encoding
|
||||
* @param readTimeoutMs
|
||||
* @return
|
||||
* @throws IOException
|
||||
* @param headers headers
|
||||
* @param paramValues parameters
|
||||
* @param encoding encoding
|
||||
* @param readTimeoutMs time out milliseconds
|
||||
* @return http result
|
||||
* @throws IOException io exception
|
||||
*/
|
||||
@Override
|
||||
public HttpResult httpGet(String path, List<String> headers, List<String> paramValues, String encoding,
|
||||
long readTimeoutMs) throws IOException {
|
||||
long readTimeoutMs) throws IOException {
|
||||
final long endTime = System.currentTimeMillis() + readTimeoutMs;
|
||||
final boolean isSSL = false;
|
||||
final boolean isSsl = false;
|
||||
injectSecurityInfo(paramValues);
|
||||
String currentServerAddr = serverListMgr.getCurrentServerAddr();
|
||||
int maxRetry = this.maxRetry;
|
||||
|
||||
|
||||
do {
|
||||
try {
|
||||
List<String> newHeaders = getSpasHeaders(paramValues);
|
||||
if (headers != null) {
|
||||
newHeaders.addAll(headers);
|
||||
}
|
||||
HttpResult result = HttpSimpleClient.httpGet(
|
||||
getUrl(currentServerAddr, path), newHeaders, paramValues, encoding,
|
||||
readTimeoutMs, isSSL);
|
||||
HttpResult result = HttpSimpleClient
|
||||
.httpGet(getUrl(currentServerAddr, path), newHeaders, paramValues, encoding, readTimeoutMs,
|
||||
isSsl);
|
||||
if (result.code == HttpURLConnection.HTTP_INTERNAL_ERROR
|
||||
|| result.code == HttpURLConnection.HTTP_BAD_GATEWAY
|
||||
|| result.code == HttpURLConnection.HTTP_UNAVAILABLE) {
|
||||
|| result.code == HttpURLConnection.HTTP_BAD_GATEWAY
|
||||
|| result.code == HttpURLConnection.HTTP_UNAVAILABLE) {
|
||||
LOGGER.error("[NACOS ConnectException] currentServerAddr: {}, httpCode: {}",
|
||||
serverListMgr.getCurrentServerAddr(), result.code);
|
||||
serverListMgr.getCurrentServerAddr(), result.code);
|
||||
} else {
|
||||
// Update the currently available server addr
|
||||
serverListMgr.updateCurrentServerAddr(currentServerAddr);
|
||||
return result;
|
||||
}
|
||||
} catch (ConnectException ce) {
|
||||
LOGGER.error("[NACOS ConnectException httpGet] currentServerAddr:{}, err : {}", serverListMgr.getCurrentServerAddr(), ce.getMessage());
|
||||
} catch (SocketTimeoutException stoe) {
|
||||
LOGGER.error("[NACOS SocketTimeoutException httpGet] currentServerAddr:{}, err : {}", serverListMgr.getCurrentServerAddr(), stoe.getMessage());
|
||||
} catch (IOException ioe) {
|
||||
LOGGER.error("[NACOS IOException httpGet] currentServerAddr: " + serverListMgr.getCurrentServerAddr(), ioe);
|
||||
throw ioe;
|
||||
} catch (ConnectException connectException) {
|
||||
LOGGER.error("[NACOS ConnectException httpGet] currentServerAddr:{}, err : {}",
|
||||
serverListMgr.getCurrentServerAddr(), connectException.getMessage());
|
||||
} catch (SocketTimeoutException socketTimeoutException) {
|
||||
LOGGER.error("[NACOS SocketTimeoutException httpGet] currentServerAddr:{}, err : {}",
|
||||
serverListMgr.getCurrentServerAddr(), socketTimeoutException.getMessage());
|
||||
} catch (IOException ioException) {
|
||||
LOGGER.error("[NACOS IOException httpGet] currentServerAddr: " + serverListMgr.getCurrentServerAddr(),
|
||||
ioException);
|
||||
throw ioException;
|
||||
}
|
||||
|
||||
|
||||
if (serverListMgr.getIterator().hasNext()) {
|
||||
currentServerAddr = serverListMgr.getIterator().next();
|
||||
} else {
|
||||
maxRetry--;
|
||||
if (maxRetry < 0) {
|
||||
throw new ConnectException("[NACOS HTTP-GET] The maximum number of tolerable server reconnection errors has been reached");
|
||||
throw new ConnectException(
|
||||
"[NACOS HTTP-GET] The maximum number of tolerable server reconnection errors has been reached");
|
||||
}
|
||||
serverListMgr.refreshCurrentServerAddr();
|
||||
}
|
||||
|
||||
|
||||
} while (System.currentTimeMillis() <= endTime);
|
||||
|
||||
|
||||
LOGGER.error("no available server");
|
||||
throw new ConnectException("no available server");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public HttpResult httpPost(String path, List<String> headers, List<String> paramValues, String encoding,
|
||||
long readTimeoutMs) throws IOException {
|
||||
long readTimeoutMs) throws IOException {
|
||||
final long endTime = System.currentTimeMillis() + readTimeoutMs;
|
||||
boolean isSSL = false;
|
||||
boolean isSsl = false;
|
||||
injectSecurityInfo(paramValues);
|
||||
String currentServerAddr = serverListMgr.getCurrentServerAddr();
|
||||
int maxRetry = this.maxRetry;
|
||||
|
||||
|
||||
do {
|
||||
|
||||
|
||||
try {
|
||||
List<String> newHeaders = getSpasHeaders(paramValues);
|
||||
if (headers != null) {
|
||||
newHeaders.addAll(headers);
|
||||
}
|
||||
|
||||
HttpResult result = HttpSimpleClient.httpPost(
|
||||
getUrl(currentServerAddr, path), newHeaders, paramValues, encoding,
|
||||
readTimeoutMs, isSSL);
|
||||
|
||||
HttpResult result = HttpSimpleClient
|
||||
.httpPost(getUrl(currentServerAddr, path), newHeaders, paramValues, encoding, readTimeoutMs,
|
||||
isSsl);
|
||||
if (result.code == HttpURLConnection.HTTP_INTERNAL_ERROR
|
||||
|| result.code == HttpURLConnection.HTTP_BAD_GATEWAY
|
||||
|| result.code == HttpURLConnection.HTTP_UNAVAILABLE) {
|
||||
LOGGER.error("[NACOS ConnectException] currentServerAddr: {}, httpCode: {}",
|
||||
currentServerAddr, result.code);
|
||||
|| result.code == HttpURLConnection.HTTP_BAD_GATEWAY
|
||||
|| result.code == HttpURLConnection.HTTP_UNAVAILABLE) {
|
||||
LOGGER.error("[NACOS ConnectException] currentServerAddr: {}, httpCode: {}", currentServerAddr,
|
||||
result.code);
|
||||
} else {
|
||||
// Update the currently available server addr
|
||||
serverListMgr.updateCurrentServerAddr(currentServerAddr);
|
||||
return result;
|
||||
}
|
||||
} catch (ConnectException ce) {
|
||||
LOGGER.error("[NACOS ConnectException httpPost] currentServerAddr: {}, err : {}", currentServerAddr, ce.getMessage());
|
||||
} catch (SocketTimeoutException stoe) {
|
||||
LOGGER.error("[NACOS SocketTimeoutException httpPost] currentServerAddr: {}, err : {}", currentServerAddr, stoe.getMessage());
|
||||
} catch (ConnectException connectException) {
|
||||
LOGGER.error("[NACOS ConnectException httpPost] currentServerAddr: {}, err : {}", currentServerAddr,
|
||||
connectException.getMessage());
|
||||
} catch (SocketTimeoutException socketTimeoutException) {
|
||||
LOGGER.error("[NACOS SocketTimeoutException httpPost] currentServerAddr: {}, err : {}",
|
||||
currentServerAddr, socketTimeoutException.getMessage());
|
||||
} catch (IOException ioe) {
|
||||
LOGGER.error("[NACOS IOException httpPost] currentServerAddr: " + currentServerAddr, ioe);
|
||||
throw ioe;
|
||||
}
|
||||
|
||||
|
||||
if (serverListMgr.getIterator().hasNext()) {
|
||||
currentServerAddr = serverListMgr.getIterator().next();
|
||||
} else {
|
||||
maxRetry--;
|
||||
if (maxRetry < 0) {
|
||||
throw new ConnectException("[NACOS HTTP-POST] The maximum number of tolerable server reconnection errors has been reached");
|
||||
throw new ConnectException(
|
||||
"[NACOS HTTP-POST] The maximum number of tolerable server reconnection errors has been reached");
|
||||
}
|
||||
serverListMgr.refreshCurrentServerAddr();
|
||||
}
|
||||
|
||||
|
||||
} while (System.currentTimeMillis() <= endTime);
|
||||
|
||||
|
||||
LOGGER.error("no available server, currentServerAddr : {}", currentServerAddr);
|
||||
throw new ConnectException("no available server, currentServerAddr : " + currentServerAddr);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public HttpResult httpDelete(String path, List<String> headers, List<String> paramValues, String encoding,
|
||||
long readTimeoutMs) throws IOException {
|
||||
long readTimeoutMs) throws IOException {
|
||||
final long endTime = System.currentTimeMillis() + readTimeoutMs;
|
||||
boolean isSSL = false;
|
||||
boolean isSsl = false;
|
||||
injectSecurityInfo(paramValues);
|
||||
String currentServerAddr = serverListMgr.getCurrentServerAddr();
|
||||
int maxRetry = this.maxRetry;
|
||||
|
||||
|
||||
do {
|
||||
try {
|
||||
List<String> newHeaders = getSpasHeaders(paramValues);
|
||||
if (headers != null) {
|
||||
newHeaders.addAll(headers);
|
||||
}
|
||||
HttpResult result = HttpSimpleClient.httpDelete(
|
||||
getUrl(currentServerAddr, path), newHeaders, paramValues, encoding,
|
||||
readTimeoutMs, isSSL);
|
||||
HttpResult result = HttpSimpleClient
|
||||
.httpDelete(getUrl(currentServerAddr, path), newHeaders, paramValues, encoding, readTimeoutMs,
|
||||
isSsl);
|
||||
if (result.code == HttpURLConnection.HTTP_INTERNAL_ERROR
|
||||
|| result.code == HttpURLConnection.HTTP_BAD_GATEWAY
|
||||
|| result.code == HttpURLConnection.HTTP_UNAVAILABLE) {
|
||||
|| result.code == HttpURLConnection.HTTP_BAD_GATEWAY
|
||||
|| result.code == HttpURLConnection.HTTP_UNAVAILABLE) {
|
||||
LOGGER.error("[NACOS ConnectException] currentServerAddr: {}, httpCode: {}",
|
||||
serverListMgr.getCurrentServerAddr(), result.code);
|
||||
serverListMgr.getCurrentServerAddr(), result.code);
|
||||
} else {
|
||||
// Update the currently available server addr
|
||||
serverListMgr.updateCurrentServerAddr(currentServerAddr);
|
||||
return result;
|
||||
}
|
||||
} catch (ConnectException ce) {
|
||||
ce.printStackTrace();
|
||||
LOGGER.error("[NACOS ConnectException httpDelete] currentServerAddr:{}, err : {}", serverListMgr.getCurrentServerAddr(), ce.getMessage());
|
||||
} catch (ConnectException connectException) {
|
||||
connectException.printStackTrace();
|
||||
LOGGER.error("[NACOS ConnectException httpDelete] currentServerAddr:{}, err : {}",
|
||||
serverListMgr.getCurrentServerAddr(), connectException.getMessage());
|
||||
} catch (SocketTimeoutException stoe) {
|
||||
stoe.printStackTrace();
|
||||
LOGGER.error("[NACOS SocketTimeoutException httpDelete] currentServerAddr:{}, err : {}", serverListMgr.getCurrentServerAddr(), stoe.getMessage());
|
||||
LOGGER.error("[NACOS SocketTimeoutException httpDelete] currentServerAddr:{}, err : {}",
|
||||
serverListMgr.getCurrentServerAddr(), stoe.getMessage());
|
||||
} catch (IOException ioe) {
|
||||
LOGGER.error("[NACOS IOException httpDelete] currentServerAddr: " + serverListMgr.getCurrentServerAddr(), ioe);
|
||||
LOGGER.error(
|
||||
"[NACOS IOException httpDelete] currentServerAddr: " + serverListMgr.getCurrentServerAddr(),
|
||||
ioe);
|
||||
throw ioe;
|
||||
}
|
||||
|
||||
|
||||
if (serverListMgr.getIterator().hasNext()) {
|
||||
currentServerAddr = serverListMgr.getIterator().next();
|
||||
} else {
|
||||
maxRetry--;
|
||||
if (maxRetry < 0) {
|
||||
throw new ConnectException("[NACOS HTTP-DELETE] The maximum number of tolerable server reconnection errors has been reached");
|
||||
throw new ConnectException(
|
||||
"[NACOS HTTP-DELETE] The maximum number of tolerable server reconnection errors has been reached");
|
||||
}
|
||||
serverListMgr.refreshCurrentServerAddr();
|
||||
}
|
||||
|
||||
|
||||
} while (System.currentTimeMillis() <= endTime);
|
||||
|
||||
|
||||
LOGGER.error("no available server");
|
||||
throw new ConnectException("no available server");
|
||||
}
|
||||
|
||||
|
||||
private String getUrl(String serverAddr, String relativePath) {
|
||||
String contextPath = serverListMgr.getContentPath().startsWith("/") ?
|
||||
serverListMgr.getContentPath() : "/" + serverListMgr.getContentPath();
|
||||
String contextPath = serverListMgr.getContentPath().startsWith("/") ? serverListMgr.getContentPath()
|
||||
: "/" + serverListMgr.getContentPath();
|
||||
return serverAddr + contextPath + relativePath;
|
||||
}
|
||||
|
||||
|
||||
public static String getAppname() {
|
||||
return ParamUtil.getAppName();
|
||||
}
|
||||
|
||||
|
||||
public ServerHttpAgent(ServerListManager mgr) {
|
||||
this.serverListMgr = mgr;
|
||||
}
|
||||
|
||||
|
||||
public ServerHttpAgent(ServerListManager mgr, Properties properties) {
|
||||
this.serverListMgr = mgr;
|
||||
init(properties);
|
||||
}
|
||||
|
||||
|
||||
public ServerHttpAgent(Properties properties) throws NacosException {
|
||||
this.serverListMgr = new ServerListManager(properties);
|
||||
this.securityProxy = new SecurityProxy(properties);
|
||||
this.namespaceId = properties.getProperty(PropertyKeyConst.NAMESPACE);
|
||||
init(properties);
|
||||
this.securityProxy.login(this.serverListMgr.getServerUrls());
|
||||
|
||||
|
||||
|
||||
// init executorService
|
||||
this.executorService = new ScheduledThreadPoolExecutor(1, new ThreadFactory() {
|
||||
@Override
|
||||
@ -277,16 +291,16 @@ public class ServerHttpAgent implements HttpAgent {
|
||||
return t;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
this.executorService.scheduleWithFixedDelay(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
securityProxy.login(serverListMgr.getServerUrls());
|
||||
}
|
||||
}, 0, this.securityInfoRefreshIntervalMills, TimeUnit.MILLISECONDS);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
private void injectSecurityInfo(List<String> params) {
|
||||
if (StringUtils.isNotBlank(securityProxy.getAccessToken())) {
|
||||
params.add(Constants.ACCESS_TOKEN);
|
||||
@ -297,35 +311,36 @@ public class ServerHttpAgent implements HttpAgent {
|
||||
params.add(namespaceId);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void init(Properties properties) {
|
||||
initEncode(properties);
|
||||
initAkSk(properties);
|
||||
initMaxRetry(properties);
|
||||
}
|
||||
|
||||
|
||||
private void initEncode(Properties properties) {
|
||||
encode = TemplateUtils.stringEmptyAndThenExecute(properties.getProperty(PropertyKeyConst.ENCODE), new Callable<String>() {
|
||||
@Override
|
||||
public String call() throws Exception {
|
||||
return Constants.ENCODE;
|
||||
}
|
||||
});
|
||||
encode = TemplateUtils
|
||||
.stringEmptyAndThenExecute(properties.getProperty(PropertyKeyConst.ENCODE), new Callable<String>() {
|
||||
@Override
|
||||
public String call() throws Exception {
|
||||
return Constants.ENCODE;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
private void initAkSk(Properties properties) {
|
||||
String ramRoleName = properties.getProperty(PropertyKeyConst.RAM_ROLE_NAME);
|
||||
if (!StringUtils.isBlank(ramRoleName)) {
|
||||
STSConfig.getInstance().setRamRoleName(ramRoleName);
|
||||
StsConfig.getInstance().setRamRoleName(ramRoleName);
|
||||
}
|
||||
|
||||
|
||||
String ak = properties.getProperty(PropertyKeyConst.ACCESS_KEY);
|
||||
if (StringUtils.isBlank(ak)) {
|
||||
accessKey = SpasAdapter.getAk();
|
||||
} else {
|
||||
accessKey = ak;
|
||||
}
|
||||
|
||||
|
||||
String sk = properties.getProperty(PropertyKeyConst.SECRET_KEY);
|
||||
if (StringUtils.isBlank(sk)) {
|
||||
secretKey = SpasAdapter.getSk();
|
||||
@ -333,27 +348,27 @@ public class ServerHttpAgent implements HttpAgent {
|
||||
secretKey = sk;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void initMaxRetry(Properties properties) {
|
||||
maxRetry = ConvertUtils.toInt(String.valueOf(properties.get(PropertyKeyConst.MAX_RETRY)), Constants.MAX_RETRY);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void start() throws NacosException {
|
||||
serverListMgr.start();
|
||||
}
|
||||
|
||||
|
||||
private List<String> getSpasHeaders(List<String> paramValues) throws IOException {
|
||||
List<String> newHeaders = new ArrayList<String>();
|
||||
// STS 临时凭证鉴权的优先级高于 AK/SK 鉴权
|
||||
if (STSConfig.getInstance().isSTSOn()) {
|
||||
STSCredential sTSCredential = getSTSCredential();
|
||||
accessKey = sTSCredential.accessKeyId;
|
||||
secretKey = sTSCredential.accessKeySecret;
|
||||
if (StsConfig.getInstance().isStsOn()) {
|
||||
StsCredential stsCredential = getStsCredential();
|
||||
accessKey = stsCredential.accessKeyId;
|
||||
secretKey = stsCredential.accessKeySecret;
|
||||
newHeaders.add("Spas-SecurityToken");
|
||||
newHeaders.add(sTSCredential.securityToken);
|
||||
newHeaders.add(stsCredential.securityToken);
|
||||
}
|
||||
|
||||
|
||||
if (StringUtils.isNotEmpty(accessKey) && StringUtils.isNotEmpty(secretKey)) {
|
||||
newHeaders.add("Spas-AccessKey");
|
||||
newHeaders.add(accessKey);
|
||||
@ -364,32 +379,33 @@ public class ServerHttpAgent implements HttpAgent {
|
||||
}
|
||||
return newHeaders;
|
||||
}
|
||||
|
||||
private STSCredential getSTSCredential() throws IOException {
|
||||
boolean cacheSecurityCredentials = STSConfig.getInstance().isCacheSecurityCredentials();
|
||||
if (cacheSecurityCredentials && sTSCredential != null) {
|
||||
|
||||
private StsCredential getStsCredential() throws IOException {
|
||||
boolean cacheSecurityCredentials = StsConfig.getInstance().isCacheSecurityCredentials();
|
||||
if (cacheSecurityCredentials && stsCredential != null) {
|
||||
long currentTime = System.currentTimeMillis();
|
||||
long expirationTime = sTSCredential.expiration.getTime();
|
||||
int timeToRefreshInMillisecond = STSConfig.getInstance().getTimeToRefreshInMillisecond();
|
||||
long expirationTime = stsCredential.expiration.getTime();
|
||||
int timeToRefreshInMillisecond = StsConfig.getInstance().getTimeToRefreshInMillisecond();
|
||||
if (expirationTime - currentTime > timeToRefreshInMillisecond) {
|
||||
return sTSCredential;
|
||||
return stsCredential;
|
||||
}
|
||||
}
|
||||
String stsResponse = getSTSResponse();
|
||||
STSCredential stsCredentialTmp = JacksonUtils.toObj(stsResponse, new TypeReference<STSCredential>() {
|
||||
});
|
||||
sTSCredential = stsCredentialTmp;
|
||||
LOGGER.info("[getSTSCredential] code:{}, accessKeyId:{}, lastUpdated:{}, expiration:{}", sTSCredential.getCode(),
|
||||
sTSCredential.getAccessKeyId(), sTSCredential.getLastUpdated(), sTSCredential.getExpiration());
|
||||
return sTSCredential;
|
||||
String stsResponse = getStsResponse();
|
||||
StsCredential stsCredentialTmp = JacksonUtils.toObj(stsResponse, new TypeReference<StsCredential>() {
|
||||
});
|
||||
stsCredential = stsCredentialTmp;
|
||||
LOGGER.info("[getSTSCredential] code:{}, accessKeyId:{}, lastUpdated:{}, expiration:{}",
|
||||
stsCredential.getCode(), stsCredential.getAccessKeyId(), stsCredential.getLastUpdated(),
|
||||
stsCredential.getExpiration());
|
||||
return stsCredential;
|
||||
}
|
||||
|
||||
private static String getSTSResponse() throws IOException {
|
||||
String securityCredentials = STSConfig.getInstance().getSecurityCredentials();
|
||||
|
||||
private static String getStsResponse() throws IOException {
|
||||
String securityCredentials = StsConfig.getInstance().getSecurityCredentials();
|
||||
if (securityCredentials != null) {
|
||||
return securityCredentials;
|
||||
}
|
||||
String securityCredentialsUrl = STSConfig.getInstance().getSecurityCredentialsUrl();
|
||||
String securityCredentialsUrl = StsConfig.getInstance().getSecurityCredentialsUrl();
|
||||
HttpURLConnection conn = null;
|
||||
int respCode;
|
||||
String response;
|
||||
@ -415,88 +431,93 @@ public class ServerHttpAgent implements HttpAgent {
|
||||
return response;
|
||||
}
|
||||
LOGGER.error("can not get security credentials, securityCredentialsUrl: {}, responseCode: {}, response: {}",
|
||||
securityCredentialsUrl, respCode, response);
|
||||
securityCredentialsUrl, respCode, response);
|
||||
throw new IOException(
|
||||
"can not get security credentials, responseCode: " + respCode + ", response: " + response);
|
||||
"can not get security credentials, responseCode: " + respCode + ", response: " + response);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return serverListMgr.getName();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getNamespace() {
|
||||
return serverListMgr.getNamespace();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getTenant() {
|
||||
return serverListMgr.getTenant();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getEncode() {
|
||||
return encode;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void shutdown() throws NacosException{
|
||||
public void shutdown() throws NacosException {
|
||||
String className = this.getClass().getName();
|
||||
LOGGER.info("{} do shutdown begin", className);
|
||||
ThreadUtils.shutdownThreadPool(executorService, LOGGER);
|
||||
LOGGER.info("{} do shutdown stop", className);
|
||||
}
|
||||
|
||||
@SuppressWarnings("PMD.ClassNamingShouldBeCamelRule")
|
||||
private static class STSCredential {
|
||||
|
||||
private static class StsCredential {
|
||||
|
||||
@JsonProperty(value = "AccessKeyId")
|
||||
private String accessKeyId;
|
||||
|
||||
@JsonProperty(value = "AccessKeySecret")
|
||||
private String accessKeySecret;
|
||||
|
||||
@JsonProperty(value = "Expiration")
|
||||
private Date expiration;
|
||||
|
||||
@JsonProperty(value = "SecurityToken")
|
||||
private String securityToken;
|
||||
|
||||
@JsonProperty(value = "LastUpdated")
|
||||
private Date lastUpdated;
|
||||
|
||||
@JsonProperty(value = "Code")
|
||||
private String code;
|
||||
|
||||
|
||||
public String getAccessKeyId() {
|
||||
return accessKeyId;
|
||||
}
|
||||
|
||||
|
||||
public Date getExpiration() {
|
||||
return expiration;
|
||||
}
|
||||
|
||||
|
||||
public Date getLastUpdated() {
|
||||
return lastUpdated;
|
||||
}
|
||||
|
||||
|
||||
public String getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "STSCredential{" +
|
||||
"accessKeyId='" + accessKeyId + '\'' +
|
||||
", accessKeySecret='" + accessKeySecret + '\'' +
|
||||
", expiration=" + expiration +
|
||||
", securityToken='" + securityToken + '\'' +
|
||||
", lastUpdated=" + lastUpdated +
|
||||
", code='" + code + '\'' +
|
||||
'}';
|
||||
return "STSCredential{" + "accessKeyId='" + accessKeyId + '\'' + ", accessKeySecret='" + accessKeySecret
|
||||
+ '\'' + ", expiration=" + expiration + ", securityToken='" + securityToken + '\''
|
||||
+ ", lastUpdated=" + lastUpdated + ", code='" + code + '\'' + '}';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private String accessKey;
|
||||
|
||||
private String secretKey;
|
||||
|
||||
private String encode;
|
||||
|
||||
private int maxRetry = 3;
|
||||
private volatile STSCredential sTSCredential;
|
||||
|
||||
private volatile StsCredential stsCredential;
|
||||
|
||||
final ServerListManager serverListMgr;
|
||||
|
||||
|
||||
}
|
||||
|
@ -13,6 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.client.config.impl;
|
||||
|
||||
import com.alibaba.nacos.api.config.ConfigChangeItem;
|
||||
@ -20,32 +21,31 @@ import com.alibaba.nacos.api.config.PropertyChangeType;
|
||||
import com.alibaba.nacos.api.config.listener.ConfigChangeParser;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* AbstractConfigChangeParser
|
||||
* AbstractConfigChangeParser.
|
||||
*
|
||||
* @author rushsky518
|
||||
*/
|
||||
public abstract class AbstractConfigChangeParser implements ConfigChangeParser {
|
||||
private String configType;
|
||||
|
||||
|
||||
private final String configType;
|
||||
|
||||
public AbstractConfigChangeParser(String configType) {
|
||||
this.configType = configType;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isResponsibleFor(String type) {
|
||||
return this.configType.equalsIgnoreCase(type);
|
||||
}
|
||||
|
||||
|
||||
protected Map<String, ConfigChangeItem> filterChangeData(Map oldMap, Map newMap) {
|
||||
Map<String, ConfigChangeItem> result = new HashMap<String, ConfigChangeItem>(16);
|
||||
for (Iterator<Map.Entry<String, Object>> entryItr = oldMap.entrySet().iterator(); entryItr.hasNext();) {
|
||||
Map.Entry<String, Object> e = entryItr.next();
|
||||
for (Map.Entry<String, Object> e : (Iterable<Map.Entry<String, Object>>) oldMap.entrySet()) {
|
||||
ConfigChangeItem cci;
|
||||
if (newMap.containsKey(e.getKey())) {
|
||||
if (newMap.containsKey(e.getKey())) {
|
||||
if (e.getValue().equals(newMap.get(e.getKey()))) {
|
||||
continue;
|
||||
}
|
||||
@ -55,20 +55,19 @@ public abstract class AbstractConfigChangeParser implements ConfigChangeParser {
|
||||
cci = new ConfigChangeItem(e.getKey(), e.getValue().toString(), null);
|
||||
cci.setType(PropertyChangeType.DELETED);
|
||||
}
|
||||
|
||||
|
||||
result.put(e.getKey(), cci);
|
||||
}
|
||||
|
||||
for (Iterator<Map.Entry<String, Object>> entryItr = newMap.entrySet().iterator(); entryItr.hasNext();) {
|
||||
Map.Entry<String, Object> e = entryItr.next();
|
||||
|
||||
for (Map.Entry<String, Object> e : (Iterable<Map.Entry<String, Object>>) newMap.entrySet()) {
|
||||
if (!oldMap.containsKey(e.getKey())) {
|
||||
ConfigChangeItem cci = new ConfigChangeItem(e.getKey(), null, e.getValue().toString());
|
||||
cci.setType(PropertyChangeType.ADDED);
|
||||
result.put(e.getKey(), cci);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -13,6 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.client.config.impl;
|
||||
|
||||
import com.alibaba.nacos.api.common.Constants;
|
||||
@ -23,9 +24,9 @@ import com.alibaba.nacos.api.exception.NacosException;
|
||||
import com.alibaba.nacos.client.config.filter.impl.ConfigFilterChainManager;
|
||||
import com.alibaba.nacos.client.config.filter.impl.ConfigResponse;
|
||||
import com.alibaba.nacos.client.config.listener.impl.AbstractConfigChangeListener;
|
||||
import com.alibaba.nacos.common.utils.MD5Utils;
|
||||
import com.alibaba.nacos.client.utils.LogUtils;
|
||||
import com.alibaba.nacos.client.utils.TenantUtil;
|
||||
import com.alibaba.nacos.common.utils.MD5Utils;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@ -34,50 +35,49 @@ import java.util.Map;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
/**
|
||||
* Listner Management
|
||||
* Listener Management.
|
||||
*
|
||||
* @author Nacos
|
||||
*/
|
||||
public class CacheData {
|
||||
|
||||
|
||||
private static final Logger LOGGER = LogUtils.logger(CacheData.class);
|
||||
|
||||
|
||||
public boolean isInitializing() {
|
||||
return isInitializing;
|
||||
}
|
||||
|
||||
|
||||
public void setInitializing(boolean isInitializing) {
|
||||
this.isInitializing = isInitializing;
|
||||
}
|
||||
|
||||
|
||||
public String getMd5() {
|
||||
return md5;
|
||||
}
|
||||
|
||||
|
||||
public String getTenant() {
|
||||
return tenant;
|
||||
}
|
||||
|
||||
|
||||
public String getContent() {
|
||||
return content;
|
||||
}
|
||||
|
||||
|
||||
public void setContent(String content) {
|
||||
this.content = content;
|
||||
this.md5 = getMd5String(this.content);
|
||||
}
|
||||
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add listener
|
||||
* if CacheData already set new content, Listener should init lastCallMd5 by CacheData.md5
|
||||
* Add listener if CacheData already set new content, Listener should init lastCallMd5 by CacheData.md5
|
||||
*
|
||||
* @param listener listener
|
||||
*/
|
||||
@ -85,27 +85,34 @@ public class CacheData {
|
||||
if (null == listener) {
|
||||
throw new IllegalArgumentException("listener is null");
|
||||
}
|
||||
ManagerListenerWrap wrap = (listener instanceof AbstractConfigChangeListener) ?
|
||||
new ManagerListenerWrap(listener, md5, content) : new ManagerListenerWrap(listener, md5);
|
||||
|
||||
ManagerListenerWrap wrap =
|
||||
(listener instanceof AbstractConfigChangeListener) ? new ManagerListenerWrap(listener, md5, content)
|
||||
: new ManagerListenerWrap(listener, md5);
|
||||
|
||||
if (listeners.addIfAbsent(wrap)) {
|
||||
LOGGER.info("[{}] [add-listener] ok, tenant={}, dataId={}, group={}, cnt={}", name, tenant, dataId, group,
|
||||
listeners.size());
|
||||
listeners.size());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Remove listener.
|
||||
*
|
||||
* @param listener listener
|
||||
*/
|
||||
public void removeListener(Listener listener) {
|
||||
if (null == listener) {
|
||||
throw new IllegalArgumentException("listener is null");
|
||||
}
|
||||
ManagerListenerWrap wrap = new ManagerListenerWrap(listener);
|
||||
if (listeners.remove(wrap)) {
|
||||
LOGGER.info("[{}] [remove-listener] ok, dataId={}, group={}, cnt={}", name, dataId, group, listeners.size());
|
||||
LOGGER.info("[{}] [remove-listener] ok, dataId={}, group={}, cnt={}", name, dataId, group,
|
||||
listeners.size());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 返回监听器列表上的迭代器,只读。保证不返回NULL。
|
||||
* 返回监听器列表上的迭代器,只读。保证不返回NULL.
|
||||
*/
|
||||
public List<Listener> getListeners() {
|
||||
List<Listener> result = new ArrayList<Listener>();
|
||||
@ -114,34 +121,34 @@ public class CacheData {
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
public long getLocalConfigInfoVersion() {
|
||||
return localConfigLastModified;
|
||||
}
|
||||
|
||||
|
||||
public void setLocalConfigInfoVersion(long localConfigLastModified) {
|
||||
this.localConfigLastModified = localConfigLastModified;
|
||||
}
|
||||
|
||||
|
||||
public boolean isUseLocalConfigInfo() {
|
||||
return isUseLocalConfig;
|
||||
}
|
||||
|
||||
|
||||
public void setUseLocalConfigInfo(boolean useLocalConfigInfo) {
|
||||
this.isUseLocalConfig = useLocalConfigInfo;
|
||||
if (!useLocalConfigInfo) {
|
||||
localConfigLastModified = -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public int getTaskId() {
|
||||
return taskId;
|
||||
}
|
||||
|
||||
|
||||
public void setTaskId(int taskId) {
|
||||
this.taskId = taskId;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
@ -150,7 +157,7 @@ public class CacheData {
|
||||
result = prime * result + ((group == null) ? 0 : group.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (null == obj || obj.getClass() != getClass()) {
|
||||
@ -162,12 +169,12 @@ public class CacheData {
|
||||
CacheData other = (CacheData) obj;
|
||||
return dataId.equals(other.dataId) && group.equals(other.group);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "CacheData [" + dataId + ", " + group + "]";
|
||||
}
|
||||
|
||||
|
||||
void checkListenerMd5() {
|
||||
for (ManagerListenerWrap wrap : listeners) {
|
||||
if (!md5.equals(wrap.lastCallMd5)) {
|
||||
@ -175,11 +182,11 @@ public class CacheData {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void safeNotifyListener(final String dataId, final String group, final String content, final String type,
|
||||
final String md5, final ManagerListenerWrap listenerWrap) {
|
||||
final String md5, final ManagerListenerWrap listenerWrap) {
|
||||
final Listener listener = listenerWrap.listener;
|
||||
|
||||
|
||||
Runnable job = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
@ -193,7 +200,7 @@ public class CacheData {
|
||||
}
|
||||
// 执行回调之前先将线程classloader设置为具体webapp的classloader,以免回调方法中调用spi接口是出现异常或错用(多应用部署才会有该问题)。
|
||||
Thread.currentThread().setContextClassLoader(appClassLoader);
|
||||
|
||||
|
||||
ConfigResponse cr = new ConfigResponse();
|
||||
cr.setDataId(dataId);
|
||||
cr.setGroup(group);
|
||||
@ -201,30 +208,31 @@ public class CacheData {
|
||||
configFilterChainManager.doFilter(null, cr);
|
||||
String contentTmp = cr.getContent();
|
||||
listener.receiveConfigInfo(contentTmp);
|
||||
|
||||
|
||||
// compare lastContent and content
|
||||
if (listener instanceof AbstractConfigChangeListener) {
|
||||
Map data = ConfigChangeHandler.getInstance().parseChangeData(listenerWrap.lastContent, content, type);
|
||||
Map data = ConfigChangeHandler.getInstance()
|
||||
.parseChangeData(listenerWrap.lastContent, content, type);
|
||||
ConfigChangeEvent event = new ConfigChangeEvent(data);
|
||||
((AbstractConfigChangeListener)listener).receiveConfigChange(event);
|
||||
((AbstractConfigChangeListener) listener).receiveConfigChange(event);
|
||||
listenerWrap.lastContent = content;
|
||||
}
|
||||
|
||||
|
||||
listenerWrap.lastCallMd5 = md5;
|
||||
LOGGER.info("[{}] [notify-ok] dataId={}, group={}, md5={}, listener={} ", name, dataId, group, md5,
|
||||
listener);
|
||||
} catch (NacosException de) {
|
||||
LOGGER.error("[{}] [notify-error] dataId={}, group={}, md5={}, listener={} errCode={} errMsg={}", name,
|
||||
dataId, group, md5, listener, de.getErrCode(), de.getErrMsg());
|
||||
listener);
|
||||
} catch (NacosException ex) {
|
||||
LOGGER.error("[{}] [notify-error] dataId={}, group={}, md5={}, listener={} errCode={} errMsg={}",
|
||||
name, dataId, group, md5, listener, ex.getErrCode(), ex.getErrMsg());
|
||||
} catch (Throwable t) {
|
||||
LOGGER.error("[{}] [notify-error] dataId={}, group={}, md5={}, listener={} tx={}", name, dataId, group,
|
||||
md5, listener, t.getCause());
|
||||
LOGGER.error("[{}] [notify-error] dataId={}, group={}, md5={}, listener={} tx={}", name, dataId,
|
||||
group, md5, listener, t.getCause());
|
||||
} finally {
|
||||
Thread.currentThread().setContextClassLoader(myClassLoader);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
final long startNotify = System.currentTimeMillis();
|
||||
try {
|
||||
if (null != listener.getExecutor()) {
|
||||
@ -233,25 +241,24 @@ public class CacheData {
|
||||
job.run();
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
LOGGER.error("[{}] [notify-error] dataId={}, group={}, md5={}, listener={} throwable={}", name, dataId, group,
|
||||
md5, listener, t.getCause());
|
||||
LOGGER.error("[{}] [notify-error] dataId={}, group={}, md5={}, listener={} throwable={}", name, dataId,
|
||||
group, md5, listener, t.getCause());
|
||||
}
|
||||
final long finishNotify = System.currentTimeMillis();
|
||||
LOGGER.info("[{}] [notify-listener] time cost={}ms in ClientWorker, dataId={}, group={}, md5={}, listener={} ",
|
||||
name, (finishNotify - startNotify), dataId, group, md5, listener);
|
||||
name, (finishNotify - startNotify), dataId, group, md5, listener);
|
||||
}
|
||||
|
||||
static public String getMd5String(String config) {
|
||||
|
||||
public static String getMd5String(String config) {
|
||||
return (null == config) ? Constants.NULL : MD5Utils.md5Hex(config, Constants.ENCODE);
|
||||
}
|
||||
|
||||
|
||||
private String loadCacheContentFromDiskLocal(String name, String dataId, String group, String tenant) {
|
||||
String content = LocalConfigInfoProcessor.getFailover(name, dataId, group, tenant);
|
||||
content = (null != content) ? content
|
||||
: LocalConfigInfoProcessor.getSnapshot(name, dataId, group, tenant);
|
||||
content = (null != content) ? content : LocalConfigInfoProcessor.getSnapshot(name, dataId, group, tenant);
|
||||
return content;
|
||||
}
|
||||
|
||||
|
||||
public CacheData(ConfigFilterChainManager configFilterChainManager, String name, String dataId, String group) {
|
||||
if (null == dataId || null == group) {
|
||||
throw new IllegalArgumentException("dataId=" + dataId + ", group=" + group);
|
||||
@ -266,9 +273,9 @@ public class CacheData {
|
||||
this.content = loadCacheContentFromDiskLocal(name, dataId, group, tenant);
|
||||
this.md5 = getMd5String(content);
|
||||
}
|
||||
|
||||
|
||||
public CacheData(ConfigFilterChainManager configFilterChainManager, String name, String dataId, String group,
|
||||
String tenant) {
|
||||
String tenant) {
|
||||
if (null == dataId || null == group) {
|
||||
throw new IllegalArgumentException("dataId=" + dataId + ", group=" + group);
|
||||
}
|
||||
@ -282,66 +289,80 @@ public class CacheData {
|
||||
this.content = loadCacheContentFromDiskLocal(name, dataId, group, tenant);
|
||||
this.md5 = getMd5String(content);
|
||||
}
|
||||
|
||||
|
||||
// ==================
|
||||
|
||||
|
||||
private final String name;
|
||||
|
||||
private final ConfigFilterChainManager configFilterChainManager;
|
||||
|
||||
public final String dataId;
|
||||
|
||||
public final String group;
|
||||
|
||||
public final String tenant;
|
||||
|
||||
private final CopyOnWriteArrayList<ManagerListenerWrap> listeners;
|
||||
|
||||
|
||||
private volatile String md5;
|
||||
|
||||
/**
|
||||
* whether use local config
|
||||
* whether use local config.
|
||||
*/
|
||||
private volatile boolean isUseLocalConfig = false;
|
||||
|
||||
/**
|
||||
* last modify time
|
||||
* last modify time.
|
||||
*/
|
||||
private volatile long localConfigLastModified;
|
||||
|
||||
private volatile String content;
|
||||
|
||||
private int taskId;
|
||||
|
||||
private volatile boolean isInitializing = true;
|
||||
|
||||
private String type;
|
||||
}
|
||||
|
||||
class ManagerListenerWrap {
|
||||
final Listener listener;
|
||||
String lastCallMd5 = CacheData.getMd5String(null);
|
||||
String lastContent = null;
|
||||
|
||||
ManagerListenerWrap(Listener listener) {
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
ManagerListenerWrap(Listener listener, String md5) {
|
||||
this.listener = listener;
|
||||
this.lastCallMd5 = md5;
|
||||
}
|
||||
|
||||
ManagerListenerWrap(Listener listener, String md5, String lastContent) {
|
||||
this.listener = listener;
|
||||
this.lastCallMd5 = md5;
|
||||
this.lastContent = lastContent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (null == obj || obj.getClass() != getClass()) {
|
||||
return false;
|
||||
|
||||
private static class ManagerListenerWrap {
|
||||
|
||||
final Listener listener;
|
||||
|
||||
String lastCallMd5 = CacheData.getMd5String(null);
|
||||
|
||||
String lastContent = null;
|
||||
|
||||
ManagerListenerWrap(Listener listener) {
|
||||
this.listener = listener;
|
||||
}
|
||||
if (obj == this) {
|
||||
return true;
|
||||
|
||||
ManagerListenerWrap(Listener listener, String md5) {
|
||||
this.listener = listener;
|
||||
this.lastCallMd5 = md5;
|
||||
}
|
||||
ManagerListenerWrap other = (ManagerListenerWrap) obj;
|
||||
return listener.equals(other.listener);
|
||||
|
||||
ManagerListenerWrap(Listener listener, String md5, String lastContent) {
|
||||
this.listener = listener;
|
||||
this.lastCallMd5 = md5;
|
||||
this.lastContent = lastContent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (null == obj || obj.getClass() != getClass()) {
|
||||
return false;
|
||||
}
|
||||
if (obj == this) {
|
||||
return true;
|
||||
}
|
||||
ManagerListenerWrap other = (ManagerListenerWrap) obj;
|
||||
return listener.equals(other.listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return super.hashCode();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return super.hashCode();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -13,6 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.client.config.impl;
|
||||
|
||||
import com.alibaba.nacos.api.PropertyKeyConst;
|
||||
@ -25,14 +26,14 @@ import com.alibaba.nacos.client.config.filter.impl.ConfigFilterChainManager;
|
||||
import com.alibaba.nacos.client.config.http.HttpAgent;
|
||||
import com.alibaba.nacos.client.config.impl.HttpSimpleClient.HttpResult;
|
||||
import com.alibaba.nacos.client.config.utils.ContentUtils;
|
||||
import com.alibaba.nacos.common.lifecycle.Closeable;
|
||||
import com.alibaba.nacos.common.utils.ConvertUtils;
|
||||
import com.alibaba.nacos.common.utils.MD5Utils;
|
||||
import com.alibaba.nacos.client.monitor.MetricsMonitor;
|
||||
import com.alibaba.nacos.client.naming.utils.CollectionUtils;
|
||||
import com.alibaba.nacos.client.utils.LogUtils;
|
||||
import com.alibaba.nacos.client.utils.ParamUtil;
|
||||
import com.alibaba.nacos.client.utils.TenantUtil;
|
||||
import com.alibaba.nacos.common.lifecycle.Closeable;
|
||||
import com.alibaba.nacos.common.utils.ConvertUtils;
|
||||
import com.alibaba.nacos.common.utils.MD5Utils;
|
||||
import com.alibaba.nacos.common.utils.StringUtils;
|
||||
import com.alibaba.nacos.common.utils.ThreadUtils;
|
||||
import org.slf4j.Logger;
|
||||
@ -41,13 +42,13 @@ import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URLDecoder;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.HashMap;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
@ -55,19 +56,26 @@ import java.util.concurrent.ThreadFactory;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import static com.alibaba.nacos.api.common.Constants.CONFIG_TYPE;
|
||||
import static com.alibaba.nacos.api.common.Constants.LINE_SEPARATOR;
|
||||
import static com.alibaba.nacos.api.common.Constants.WORD_SEPARATOR;
|
||||
import static com.alibaba.nacos.api.common.Constants.CONFIG_TYPE;
|
||||
|
||||
/**
|
||||
* Longpolling
|
||||
* Long polling.
|
||||
*
|
||||
* @author Nacos
|
||||
*/
|
||||
public class ClientWorker implements Closeable {
|
||||
|
||||
|
||||
private static final Logger LOGGER = LogUtils.logger(ClientWorker.class);
|
||||
|
||||
|
||||
/**
|
||||
* Add listeners for data.
|
||||
*
|
||||
* @param dataId dataId of data
|
||||
* @param group group of data
|
||||
* @param listeners listeners
|
||||
*/
|
||||
public void addListeners(String dataId, String group, List<? extends Listener> listeners) {
|
||||
group = null2defaultGroup(group);
|
||||
CacheData cache = addCacheDataIfAbsent(dataId, group);
|
||||
@ -75,7 +83,14 @@ public class ClientWorker implements Closeable {
|
||||
cache.addListener(listener);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Remove listener.
|
||||
*
|
||||
* @param dataId dataId of data
|
||||
* @param group group of data
|
||||
* @param listener listener
|
||||
*/
|
||||
public void removeListener(String dataId, String group, Listener listener) {
|
||||
group = null2defaultGroup(group);
|
||||
CacheData cache = getCache(dataId, group);
|
||||
@ -86,8 +101,17 @@ public class ClientWorker implements Closeable {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void addTenantListeners(String dataId, String group, List<? extends Listener> listeners) throws NacosException {
|
||||
|
||||
/**
|
||||
* Add listeners for tenant.
|
||||
*
|
||||
* @param dataId dataId of data
|
||||
* @param group group of data
|
||||
* @param listeners listeners
|
||||
* @throws NacosException nacos exception
|
||||
*/
|
||||
public void addTenantListeners(String dataId, String group, List<? extends Listener> listeners)
|
||||
throws NacosException {
|
||||
group = null2defaultGroup(group);
|
||||
String tenant = agent.getTenant();
|
||||
CacheData cache = addCacheDataIfAbsent(dataId, group, tenant);
|
||||
@ -95,8 +119,18 @@ public class ClientWorker implements Closeable {
|
||||
cache.addListener(listener);
|
||||
}
|
||||
}
|
||||
|
||||
public void addTenantListenersWithContent(String dataId, String group, String content, List<? extends Listener> listeners) throws NacosException {
|
||||
|
||||
/**
|
||||
* Add listeners for tenant with content.
|
||||
*
|
||||
* @param dataId dataId of data
|
||||
* @param group group of data
|
||||
* @param content content
|
||||
* @param listeners listeners
|
||||
* @throws NacosException nacos exception
|
||||
*/
|
||||
public void addTenantListenersWithContent(String dataId, String group, String content,
|
||||
List<? extends Listener> listeners) throws NacosException {
|
||||
group = null2defaultGroup(group);
|
||||
String tenant = agent.getTenant();
|
||||
CacheData cache = addCacheDataIfAbsent(dataId, group, tenant);
|
||||
@ -105,7 +139,14 @@ public class ClientWorker implements Closeable {
|
||||
cache.addListener(listener);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Remove listeners for tenant.
|
||||
*
|
||||
* @param dataId dataId of data
|
||||
* @param group group of data
|
||||
* @param listener listener
|
||||
*/
|
||||
public void removeTenantListener(String dataId, String group, Listener listener) {
|
||||
group = null2defaultGroup(group);
|
||||
String tenant = agent.getTenant();
|
||||
@ -117,8 +158,8 @@ public class ClientWorker implements Closeable {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void removeCache(String dataId, String group) {
|
||||
|
||||
private void removeCache(String dataId, String group) {
|
||||
String groupKey = GroupKey.getKey(dataId, group);
|
||||
synchronized (cacheMap) {
|
||||
Map<String, CacheData> copy = new HashMap<String, CacheData>(cacheMap.get());
|
||||
@ -126,10 +167,10 @@ public class ClientWorker implements Closeable {
|
||||
cacheMap.set(copy);
|
||||
}
|
||||
LOGGER.info("[{}] [unsubscribe] {}", this.agent.getName(), groupKey);
|
||||
|
||||
|
||||
MetricsMonitor.getListenConfigCountMonitor().set(cacheMap.get().size());
|
||||
}
|
||||
|
||||
|
||||
void removeCache(String dataId, String group, String tenant) {
|
||||
String groupKey = GroupKey.getKeyTenant(dataId, group, tenant);
|
||||
synchronized (cacheMap) {
|
||||
@ -138,19 +179,26 @@ public class ClientWorker implements Closeable {
|
||||
cacheMap.set(copy);
|
||||
}
|
||||
LOGGER.info("[{}] [unsubscribe] {}", agent.getName(), groupKey);
|
||||
|
||||
|
||||
MetricsMonitor.getListenConfigCountMonitor().set(cacheMap.get().size());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add cache data if absent.
|
||||
*
|
||||
* @param dataId data id if data
|
||||
* @param group group of data
|
||||
* @return cache data
|
||||
*/
|
||||
public CacheData addCacheDataIfAbsent(String dataId, String group) {
|
||||
CacheData cache = getCache(dataId, group);
|
||||
if (null != cache) {
|
||||
return cache;
|
||||
}
|
||||
|
||||
|
||||
String key = GroupKey.getKey(dataId, group);
|
||||
cache = new CacheData(configFilterChainManager, agent.getName(), dataId, group);
|
||||
|
||||
|
||||
synchronized (cacheMap) {
|
||||
CacheData cacheFromMap = getCache(dataId, group);
|
||||
// multiple listeners on the same dataid+group and race condition,so double check again
|
||||
@ -163,19 +211,27 @@ public class ClientWorker implements Closeable {
|
||||
int taskId = cacheMap.get().size() / (int) ParamUtil.getPerTaskConfigSize();
|
||||
cache.setTaskId(taskId);
|
||||
}
|
||||
|
||||
|
||||
Map<String, CacheData> copy = new HashMap<String, CacheData>(cacheMap.get());
|
||||
copy.put(key, cache);
|
||||
cacheMap.set(copy);
|
||||
}
|
||||
|
||||
|
||||
LOGGER.info("[{}] [subscribe] {}", this.agent.getName(), key);
|
||||
|
||||
|
||||
MetricsMonitor.getListenConfigCountMonitor().set(cacheMap.get().size());
|
||||
|
||||
|
||||
return cache;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add cache data if absent.
|
||||
*
|
||||
* @param dataId data id if data
|
||||
* @param group group of data
|
||||
* @param tenant tenant of data
|
||||
* @return cache data
|
||||
*/
|
||||
public CacheData addCacheDataIfAbsent(String dataId, String group, String tenant) throws NacosException {
|
||||
CacheData cache = getCache(dataId, group, tenant);
|
||||
if (null != cache) {
|
||||
@ -199,36 +255,36 @@ public class ClientWorker implements Closeable {
|
||||
cache.setContent(ct[0]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Map<String, CacheData> copy = new HashMap<String, CacheData>(this.cacheMap.get());
|
||||
copy.put(key, cache);
|
||||
cacheMap.set(copy);
|
||||
}
|
||||
LOGGER.info("[{}] [subscribe] {}", agent.getName(), key);
|
||||
|
||||
|
||||
MetricsMonitor.getListenConfigCountMonitor().set(cacheMap.get().size());
|
||||
|
||||
|
||||
return cache;
|
||||
}
|
||||
|
||||
|
||||
public CacheData getCache(String dataId, String group) {
|
||||
return getCache(dataId, group, TenantUtil.getUserTenantForAcm());
|
||||
}
|
||||
|
||||
|
||||
public CacheData getCache(String dataId, String group, String tenant) {
|
||||
if (null == dataId || null == group) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
return cacheMap.get().get(GroupKey.getKeyTenant(dataId, group, tenant));
|
||||
}
|
||||
|
||||
|
||||
public String[] getServerConfig(String dataId, String group, String tenant, long readTimeout)
|
||||
throws NacosException {
|
||||
throws NacosException {
|
||||
String[] ct = new String[2];
|
||||
if (StringUtils.isBlank(group)) {
|
||||
group = Constants.DEFAULT_GROUP;
|
||||
}
|
||||
|
||||
|
||||
HttpResult result = null;
|
||||
try {
|
||||
List<String> params = null;
|
||||
@ -239,13 +295,13 @@ public class ClientWorker implements Closeable {
|
||||
}
|
||||
result = agent.httpGet(Constants.CONFIG_CONTROLLER_PATH, null, params, agent.getEncode(), readTimeout);
|
||||
} catch (IOException e) {
|
||||
String message = String.format(
|
||||
"[%s] [sub-server] get server config exception, dataId=%s, group=%s, tenant=%s", agent.getName(),
|
||||
dataId, group, tenant);
|
||||
String message = String
|
||||
.format("[%s] [sub-server] get server config exception, dataId=%s, group=%s, tenant=%s",
|
||||
agent.getName(), dataId, group, tenant);
|
||||
LOGGER.error(message, e);
|
||||
throw new NacosException(NacosException.SERVER_ERROR, e);
|
||||
}
|
||||
|
||||
|
||||
switch (result.code) {
|
||||
case HttpURLConnection.HTTP_OK:
|
||||
LocalConfigInfoProcessor.saveSnapshot(agent.getName(), dataId, group, tenant, result.content);
|
||||
@ -261,68 +317,74 @@ public class ClientWorker implements Closeable {
|
||||
return ct;
|
||||
case HttpURLConnection.HTTP_CONFLICT: {
|
||||
LOGGER.error(
|
||||
"[{}] [sub-server-error] get server config being modified concurrently, dataId={}, group={}, "
|
||||
+ "tenant={}", agent.getName(), dataId, group, tenant);
|
||||
"[{}] [sub-server-error] get server config being modified concurrently, dataId={}, group={}, "
|
||||
+ "tenant={}", agent.getName(), dataId, group, tenant);
|
||||
throw new NacosException(NacosException.CONFLICT,
|
||||
"data being modified, dataId=" + dataId + ",group=" + group + ",tenant=" + tenant);
|
||||
"data being modified, dataId=" + dataId + ",group=" + group + ",tenant=" + tenant);
|
||||
}
|
||||
case HttpURLConnection.HTTP_FORBIDDEN: {
|
||||
LOGGER.error("[{}] [sub-server-error] no right, dataId={}, group={}, tenant={}", agent.getName(), dataId,
|
||||
group, tenant);
|
||||
LOGGER.error("[{}] [sub-server-error] no right, dataId={}, group={}, tenant={}", agent.getName(),
|
||||
dataId, group, tenant);
|
||||
throw new NacosException(result.code, result.content);
|
||||
}
|
||||
default: {
|
||||
LOGGER.error("[{}] [sub-server-error] dataId={}, group={}, tenant={}, code={}", agent.getName(), dataId,
|
||||
group, tenant, result.code);
|
||||
LOGGER.error("[{}] [sub-server-error] dataId={}, group={}, tenant={}, code={}", agent.getName(),
|
||||
dataId, group, tenant, result.code);
|
||||
throw new NacosException(result.code,
|
||||
"http error, code=" + result.code + ",dataId=" + dataId + ",group=" + group + ",tenant=" + tenant);
|
||||
"http error, code=" + result.code + ",dataId=" + dataId + ",group=" + group + ",tenant="
|
||||
+ tenant);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void checkLocalConfig(CacheData cacheData) {
|
||||
final String dataId = cacheData.dataId;
|
||||
final String group = cacheData.group;
|
||||
final String tenant = cacheData.tenant;
|
||||
File path = LocalConfigInfoProcessor.getFailoverFile(agent.getName(), dataId, group, tenant);
|
||||
|
||||
|
||||
if (!cacheData.isUseLocalConfigInfo() && path.exists()) {
|
||||
String content = LocalConfigInfoProcessor.getFailover(agent.getName(), dataId, group, tenant);
|
||||
String md5 = MD5Utils.md5Hex(content, Constants.ENCODE);
|
||||
final String md5 = MD5Utils.md5Hex(content, Constants.ENCODE);
|
||||
cacheData.setUseLocalConfigInfo(true);
|
||||
cacheData.setLocalConfigInfoVersion(path.lastModified());
|
||||
cacheData.setContent(content);
|
||||
|
||||
LOGGER.warn("[{}] [failover-change] failover file created. dataId={}, group={}, tenant={}, md5={}, content={}",
|
||||
agent.getName(), dataId, group, tenant, md5, ContentUtils.truncateContent(content));
|
||||
|
||||
LOGGER.warn(
|
||||
"[{}] [failover-change] failover file created. dataId={}, group={}, tenant={}, md5={}, content={}",
|
||||
agent.getName(), dataId, group, tenant, md5, ContentUtils.truncateContent(content));
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// If use local config info, then it doesn't notify business listener and notify after getting from server.
|
||||
if (cacheData.isUseLocalConfigInfo() && !path.exists()) {
|
||||
cacheData.setUseLocalConfigInfo(false);
|
||||
LOGGER.warn("[{}] [failover-change] failover file deleted. dataId={}, group={}, tenant={}", agent.getName(),
|
||||
dataId, group, tenant);
|
||||
dataId, group, tenant);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// When it changed.
|
||||
if (cacheData.isUseLocalConfigInfo() && path.exists()
|
||||
&& cacheData.getLocalConfigInfoVersion() != path.lastModified()) {
|
||||
if (cacheData.isUseLocalConfigInfo() && path.exists() && cacheData.getLocalConfigInfoVersion() != path
|
||||
.lastModified()) {
|
||||
String content = LocalConfigInfoProcessor.getFailover(agent.getName(), dataId, group, tenant);
|
||||
String md5 = MD5Utils.md5Hex(content, Constants.ENCODE);
|
||||
final String md5 = MD5Utils.md5Hex(content, Constants.ENCODE);
|
||||
cacheData.setUseLocalConfigInfo(true);
|
||||
cacheData.setLocalConfigInfoVersion(path.lastModified());
|
||||
cacheData.setContent(content);
|
||||
LOGGER.warn("[{}] [failover-change] failover file changed. dataId={}, group={}, tenant={}, md5={}, content={}",
|
||||
agent.getName(), dataId, group, tenant, md5, ContentUtils.truncateContent(content));
|
||||
LOGGER.warn(
|
||||
"[{}] [failover-change] failover file changed. dataId={}, group={}, tenant={}, md5={}, content={}",
|
||||
agent.getName(), dataId, group, tenant, md5, ContentUtils.truncateContent(content));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private String null2defaultGroup(String group) {
|
||||
return (null == group) ? Constants.DEFAULT_GROUP : group.trim();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check config info.
|
||||
*/
|
||||
public void checkConfigInfo() {
|
||||
// Dispatch taskes.
|
||||
int listenerSize = cacheMap.get().size();
|
||||
@ -336,17 +398,17 @@ public class ClientWorker implements Closeable {
|
||||
currentLongingTaskCount = longingTaskCount;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Fetch the dataId list from server.
|
||||
*
|
||||
* @param cacheDatas CacheDatas for config infomations.
|
||||
* @param cacheDatas CacheDatas for config infomations.
|
||||
* @param inInitializingCacheList initial cache lists.
|
||||
* @return String include dataId and group (ps: it maybe null).
|
||||
*
|
||||
* @throws IOException Exception.
|
||||
*/
|
||||
List<String> checkUpdateDataIds(List<CacheData> cacheDatas, List<String> inInitializingCacheList) throws IOException {
|
||||
List<String> checkUpdateDataIds(List<CacheData> cacheDatas, List<String> inInitializingCacheList)
|
||||
throws IOException {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (CacheData cacheData : cacheDatas) {
|
||||
if (!cacheData.isUseLocalConfigInfo()) {
|
||||
@ -361,52 +423,51 @@ public class ClientWorker implements Closeable {
|
||||
if (cacheData.isInitializing()) {
|
||||
// It updates when cacheData occours in cacheMap by first time.
|
||||
inInitializingCacheList
|
||||
.add(GroupKey.getKeyTenant(cacheData.dataId, cacheData.group, cacheData.tenant));
|
||||
.add(GroupKey.getKeyTenant(cacheData.dataId, cacheData.group, cacheData.tenant));
|
||||
}
|
||||
}
|
||||
}
|
||||
boolean isInitializingCacheList = !inInitializingCacheList.isEmpty();
|
||||
return checkUpdateConfigStr(sb.toString(), isInitializingCacheList);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Fetch the updated dataId list from server.
|
||||
*
|
||||
*
|
||||
* @param probeUpdateString updated attribute string value.
|
||||
* @param probeUpdateString updated attribute string value.
|
||||
* @param isInitializingCacheList initial cache lists.
|
||||
* @return The updated dataId list(ps: it maybe null).
|
||||
* @throws IOException Exception.
|
||||
*/
|
||||
List<String> checkUpdateConfigStr(String probeUpdateString, boolean isInitializingCacheList) throws IOException {
|
||||
|
||||
|
||||
|
||||
List<String> params = new ArrayList<String>(2);
|
||||
params.add(Constants.PROBE_MODIFY_REQUEST);
|
||||
params.add(probeUpdateString);
|
||||
|
||||
|
||||
List<String> headers = new ArrayList<String>(2);
|
||||
headers.add("Long-Pulling-Timeout");
|
||||
headers.add("" + timeout);
|
||||
|
||||
|
||||
// told server do not hang me up if new initializing cacheData added in
|
||||
if (isInitializingCacheList) {
|
||||
headers.add("Long-Pulling-Timeout-No-Hangup");
|
||||
headers.add("true");
|
||||
}
|
||||
|
||||
|
||||
if (StringUtils.isBlank(probeUpdateString)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
// In order to prevent the server from handling the delay of the client's long task,
|
||||
// increase the client's read timeout to avoid this problem.
|
||||
|
||||
|
||||
long readTimeoutMs = timeout + (long) Math.round(timeout >> 1);
|
||||
HttpResult result = agent.httpPost(Constants.CONFIG_CONTROLLER_PATH + "/listener", headers, params,
|
||||
agent.getEncode(), readTimeoutMs);
|
||||
|
||||
HttpResult result = agent
|
||||
.httpPost(Constants.CONFIG_CONTROLLER_PATH + "/listener", headers, params, agent.getEncode(),
|
||||
readTimeoutMs);
|
||||
|
||||
if (HttpURLConnection.HTTP_OK == result.code) {
|
||||
setHealthServer(true);
|
||||
return parseUpdateDataIdResponse(result.content);
|
||||
@ -421,7 +482,7 @@ public class ClientWorker implements Closeable {
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the groupKey list from the http response.
|
||||
*
|
||||
@ -432,15 +493,15 @@ public class ClientWorker implements Closeable {
|
||||
if (StringUtils.isBlank(response)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
response = URLDecoder.decode(response, "UTF-8");
|
||||
} catch (Exception e) {
|
||||
LOGGER.error("[" + agent.getName() + "] [polling-resp] decode modifiedDataIdsString error", e);
|
||||
}
|
||||
|
||||
|
||||
List<String> updateList = new LinkedList<String>();
|
||||
|
||||
|
||||
for (String dataIdAndGroup : response.split(LINE_SEPARATOR)) {
|
||||
if (!StringUtils.isBlank(dataIdAndGroup)) {
|
||||
String[] keyArr = dataIdAndGroup.split(WORD_SEPARATOR);
|
||||
@ -448,29 +509,32 @@ public class ClientWorker implements Closeable {
|
||||
String group = keyArr[1];
|
||||
if (keyArr.length == 2) {
|
||||
updateList.add(GroupKey.getKey(dataId, group));
|
||||
LOGGER.info("[{}] [polling-resp] config changed. dataId={}, group={}", agent.getName(), dataId, group);
|
||||
LOGGER.info("[{}] [polling-resp] config changed. dataId={}, group={}", agent.getName(), dataId,
|
||||
group);
|
||||
} else if (keyArr.length == 3) {
|
||||
String tenant = keyArr[2];
|
||||
updateList.add(GroupKey.getKeyTenant(dataId, group, tenant));
|
||||
LOGGER.info("[{}] [polling-resp] config changed. dataId={}, group={}, tenant={}", agent.getName(),
|
||||
dataId, group, tenant);
|
||||
dataId, group, tenant);
|
||||
} else {
|
||||
LOGGER.error("[{}] [polling-resp] invalid dataIdAndGroup error {}", agent.getName(), dataIdAndGroup);
|
||||
LOGGER.error("[{}] [polling-resp] invalid dataIdAndGroup error {}", agent.getName(),
|
||||
dataIdAndGroup);
|
||||
}
|
||||
}
|
||||
}
|
||||
return updateList;
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("PMD.ThreadPoolCreationRule")
|
||||
public ClientWorker(final HttpAgent agent, final ConfigFilterChainManager configFilterChainManager, final Properties properties) {
|
||||
public ClientWorker(final HttpAgent agent, final ConfigFilterChainManager configFilterChainManager,
|
||||
final Properties properties) {
|
||||
this.agent = agent;
|
||||
this.configFilterChainManager = configFilterChainManager;
|
||||
|
||||
|
||||
// Initialize the timeout parameter
|
||||
|
||||
|
||||
init(properties);
|
||||
|
||||
|
||||
this.executor = Executors.newScheduledThreadPool(1, new ThreadFactory() {
|
||||
@Override
|
||||
public Thread newThread(Runnable r) {
|
||||
@ -480,17 +544,18 @@ public class ClientWorker implements Closeable {
|
||||
return t;
|
||||
}
|
||||
});
|
||||
|
||||
this.executorService = Executors.newScheduledThreadPool(Runtime.getRuntime().availableProcessors(), new ThreadFactory() {
|
||||
@Override
|
||||
public Thread newThread(Runnable r) {
|
||||
Thread t = new Thread(r);
|
||||
t.setName("com.alibaba.nacos.client.Worker.longPolling." + agent.getName());
|
||||
t.setDaemon(true);
|
||||
return t;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
this.executorService = Executors
|
||||
.newScheduledThreadPool(Runtime.getRuntime().availableProcessors(), new ThreadFactory() {
|
||||
@Override
|
||||
public Thread newThread(Runnable r) {
|
||||
Thread t = new Thread(r);
|
||||
t.setName("com.alibaba.nacos.client.Worker.longPolling." + agent.getName());
|
||||
t.setDaemon(true);
|
||||
return t;
|
||||
}
|
||||
});
|
||||
|
||||
this.executor.scheduleWithFixedDelay(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
@ -502,17 +567,19 @@ public class ClientWorker implements Closeable {
|
||||
}
|
||||
}, 1L, 10L, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
|
||||
private void init(Properties properties) {
|
||||
|
||||
|
||||
timeout = Math.max(ConvertUtils.toInt(properties.getProperty(PropertyKeyConst.CONFIG_LONG_POLL_TIMEOUT),
|
||||
Constants.CONFIG_LONG_POLL_TIMEOUT), Constants.MIN_CONFIG_LONG_POLL_TIMEOUT);
|
||||
|
||||
taskPenaltyTime = ConvertUtils.toInt(properties.getProperty(PropertyKeyConst.CONFIG_RETRY_TIME), Constants.CONFIG_RETRY_TIME);
|
||||
|
||||
this.enableRemoteSyncConfig = Boolean.parseBoolean(properties.getProperty(PropertyKeyConst.ENABLE_REMOTE_SYNC_CONFIG));
|
||||
Constants.CONFIG_LONG_POLL_TIMEOUT), Constants.MIN_CONFIG_LONG_POLL_TIMEOUT);
|
||||
|
||||
taskPenaltyTime = ConvertUtils
|
||||
.toInt(properties.getProperty(PropertyKeyConst.CONFIG_RETRY_TIME), Constants.CONFIG_RETRY_TIME);
|
||||
|
||||
this.enableRemoteSyncConfig = Boolean
|
||||
.parseBoolean(properties.getProperty(PropertyKeyConst.ENABLE_REMOTE_SYNC_CONFIG));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void shutdown() throws NacosException {
|
||||
String className = this.getClass().getName();
|
||||
@ -521,17 +588,18 @@ public class ClientWorker implements Closeable {
|
||||
ThreadUtils.shutdownThreadPool(executor, LOGGER);
|
||||
LOGGER.info("{} do shutdown stop", className);
|
||||
}
|
||||
|
||||
|
||||
class LongPollingRunnable implements Runnable {
|
||||
private int taskId;
|
||||
|
||||
|
||||
private final int taskId;
|
||||
|
||||
public LongPollingRunnable(int taskId) {
|
||||
this.taskId = taskId;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
|
||||
List<CacheData> cacheDatas = new ArrayList<CacheData>();
|
||||
List<String> inInitializingCacheList = new ArrayList<String>();
|
||||
try {
|
||||
@ -549,14 +617,13 @@ public class ClientWorker implements Closeable {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// check server config
|
||||
List<String> changedGroupKeys = checkUpdateDataIds(cacheDatas, inInitializingCacheList);
|
||||
if (!CollectionUtils.isEmpty(changedGroupKeys)) {
|
||||
LOGGER.info("get changedGroupKeys:" + changedGroupKeys);
|
||||
}
|
||||
|
||||
|
||||
|
||||
for (String groupKey : changedGroupKeys) {
|
||||
String[] key = GroupKey.parseKey(groupKey);
|
||||
String dataId = key[0];
|
||||
@ -573,57 +640,64 @@ public class ClientWorker implements Closeable {
|
||||
cache.setType(ct[1]);
|
||||
}
|
||||
LOGGER.info("[{}] [data-received] dataId={}, group={}, tenant={}, md5={}, content={}, type={}",
|
||||
agent.getName(), dataId, group, tenant, cache.getMd5(),
|
||||
ContentUtils.truncateContent(ct[0]), ct[1]);
|
||||
agent.getName(), dataId, group, tenant, cache.getMd5(),
|
||||
ContentUtils.truncateContent(ct[0]), ct[1]);
|
||||
} catch (NacosException ioe) {
|
||||
String message = String.format(
|
||||
"[%s] [get-update] get changed config exception. dataId=%s, group=%s, tenant=%s",
|
||||
agent.getName(), dataId, group, tenant);
|
||||
String message = String
|
||||
.format("[%s] [get-update] get changed config exception. dataId=%s, group=%s, tenant=%s",
|
||||
agent.getName(), dataId, group, tenant);
|
||||
LOGGER.error(message, ioe);
|
||||
}
|
||||
}
|
||||
for (CacheData cacheData : cacheDatas) {
|
||||
if (!cacheData.isInitializing() || inInitializingCacheList
|
||||
.contains(GroupKey.getKeyTenant(cacheData.dataId, cacheData.group, cacheData.tenant))) {
|
||||
.contains(GroupKey.getKeyTenant(cacheData.dataId, cacheData.group, cacheData.tenant))) {
|
||||
cacheData.checkListenerMd5();
|
||||
cacheData.setInitializing(false);
|
||||
}
|
||||
}
|
||||
inInitializingCacheList.clear();
|
||||
|
||||
|
||||
executorService.execute(this);
|
||||
|
||||
|
||||
} catch (Throwable e) {
|
||||
|
||||
|
||||
// If the rotation training task is abnormal, the next execution time of the task will be punished
|
||||
LOGGER.error("longPolling error : ", e);
|
||||
executorService.schedule(this, taskPenaltyTime, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public boolean isHealthServer() {
|
||||
return isHealthServer;
|
||||
}
|
||||
|
||||
|
||||
private void setHealthServer(boolean isHealthServer) {
|
||||
this.isHealthServer = isHealthServer;
|
||||
}
|
||||
|
||||
|
||||
final ScheduledExecutorService executor;
|
||||
|
||||
final ScheduledExecutorService executorService;
|
||||
|
||||
|
||||
/**
|
||||
* groupKey -> cacheData
|
||||
* groupKey -> cacheData.
|
||||
*/
|
||||
private final AtomicReference<Map<String, CacheData>> cacheMap = new AtomicReference<Map<String, CacheData>>(
|
||||
new HashMap<String, CacheData>());
|
||||
|
||||
new HashMap<String, CacheData>());
|
||||
|
||||
private final HttpAgent agent;
|
||||
|
||||
private final ConfigFilterChainManager configFilterChainManager;
|
||||
|
||||
private boolean isHealthServer = true;
|
||||
|
||||
private long timeout;
|
||||
|
||||
private double currentLongingTaskCount = 0;
|
||||
|
||||
private int taskPenaltyTime;
|
||||
|
||||
private boolean enableRemoteSyncConfig = false;
|
||||
}
|
||||
|
@ -13,55 +13,67 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.client.config.impl;
|
||||
|
||||
import com.alibaba.nacos.api.config.listener.ConfigChangeParser;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.ServiceLoader;
|
||||
import java.util.Map;
|
||||
import java.util.Iterator;
|
||||
import java.util.ServiceLoader;
|
||||
|
||||
/**
|
||||
* ConfigChangeHandler
|
||||
* ConfigChangeHandler.
|
||||
*
|
||||
* @author rushsky518
|
||||
*/
|
||||
public class ConfigChangeHandler {
|
||||
|
||||
private static class ConfigChangeHandlerHolder {
|
||||
private final static ConfigChangeHandler INSTANCE = new ConfigChangeHandler();
|
||||
|
||||
private static final ConfigChangeHandler INSTANCE = new ConfigChangeHandler();
|
||||
}
|
||||
|
||||
|
||||
private ConfigChangeHandler() {
|
||||
this.parserList = new LinkedList<ConfigChangeParser>();
|
||||
|
||||
|
||||
ServiceLoader<ConfigChangeParser> loader = ServiceLoader.load(ConfigChangeParser.class);
|
||||
Iterator<ConfigChangeParser> itr = loader.iterator();
|
||||
while (itr.hasNext()) {
|
||||
this.parserList.add(itr.next());
|
||||
}
|
||||
|
||||
|
||||
this.parserList.add(new PropertiesChangeParser());
|
||||
this.parserList.add(new YmlChangeParser());
|
||||
}
|
||||
|
||||
|
||||
public static ConfigChangeHandler getInstance() {
|
||||
return ConfigChangeHandlerHolder.INSTANCE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Parse changed data.
|
||||
*
|
||||
* @param oldContent old data
|
||||
* @param newContent new data
|
||||
* @param type data type
|
||||
* @return change data map
|
||||
* @throws IOException io exception
|
||||
*/
|
||||
public Map parseChangeData(String oldContent, String newContent, String type) throws IOException {
|
||||
for (ConfigChangeParser changeParser: this.parserList) {
|
||||
for (ConfigChangeParser changeParser : this.parserList) {
|
||||
if (changeParser.isResponsibleFor(type)) {
|
||||
return changeParser.doParse(oldContent, newContent, type);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
|
||||
private List<ConfigChangeParser> parserList;
|
||||
|
||||
|
||||
private final List<ConfigChangeParser> parserList;
|
||||
|
||||
}
|
||||
|
@ -13,6 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.client.config.impl;
|
||||
|
||||
import com.alibaba.nacos.client.utils.LogUtils;
|
||||
@ -30,26 +31,26 @@ import java.util.concurrent.CopyOnWriteArrayList;
|
||||
* @author Nacos
|
||||
*/
|
||||
public class EventDispatcher {
|
||||
|
||||
|
||||
private static final Logger LOGGER = LogUtils.logger(EventDispatcher.class);
|
||||
|
||||
|
||||
/**
|
||||
* 添加事件监听器
|
||||
* 添加事件监听器.
|
||||
*/
|
||||
static public void addEventListener(AbstractEventListener listener) {
|
||||
public static void addEventListener(AbstractEventListener listener) {
|
||||
for (Class<? extends AbstractEvent> type : listener.interest()) {
|
||||
getListenerList(type).addIfAbsent(listener);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 发布事件,首先发布该事件暗示的其他事件,最后通知所有对应的监听器。
|
||||
* 发布事件,首先发布该事件暗示的其他事件,最后通知所有对应的监听器.
|
||||
*/
|
||||
static public void fireEvent(AbstractEvent abstractEvent) {
|
||||
public static void fireEvent(AbstractEvent abstractEvent) {
|
||||
if (null == abstractEvent) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// 发布该事件暗示的其他事件
|
||||
for (AbstractEvent implyEvent : abstractEvent.implyEvents()) {
|
||||
try {
|
||||
@ -61,7 +62,7 @@ public class EventDispatcher {
|
||||
LOGGER.warn(e.toString(), e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (AbstractEventListener listener : getListenerList(abstractEvent.getClass())) {
|
||||
try {
|
||||
listener.onEvent(abstractEvent);
|
||||
@ -70,9 +71,9 @@ public class EventDispatcher {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static synchronized CopyOnWriteArrayList<AbstractEventListener> getListenerList(
|
||||
Class<? extends AbstractEvent> eventType) {
|
||||
Class<? extends AbstractEvent> eventType) {
|
||||
CopyOnWriteArrayList<AbstractEventListener> listeners = LISTENER_MAP.get(eventType);
|
||||
if (null == listeners) {
|
||||
listeners = new CopyOnWriteArrayList<AbstractEventListener>();
|
||||
@ -80,54 +81,48 @@ public class EventDispatcher {
|
||||
}
|
||||
return listeners;
|
||||
}
|
||||
|
||||
// ========================
|
||||
|
||||
static final Map<Class<? extends AbstractEvent>, CopyOnWriteArrayList<AbstractEventListener>> LISTENER_MAP
|
||||
= new HashMap<Class<? extends AbstractEvent>, CopyOnWriteArrayList<AbstractEventListener>>();
|
||||
|
||||
// ========================
|
||||
|
||||
|
||||
@SuppressWarnings("checkstyle:linelength")
|
||||
static final Map<Class<? extends AbstractEvent>, CopyOnWriteArrayList<AbstractEventListener>> LISTENER_MAP = new HashMap<Class<? extends AbstractEvent>, CopyOnWriteArrayList<AbstractEventListener>>();
|
||||
|
||||
/**
|
||||
* Client事件。
|
||||
* Client事件.
|
||||
*/
|
||||
static public abstract class AbstractEvent {
|
||||
|
||||
public abstract static class AbstractEvent {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected List<AbstractEvent> implyEvents() {
|
||||
return Collections.EMPTY_LIST;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 事件监听器。
|
||||
* 事件监听器.
|
||||
*/
|
||||
static public abstract class AbstractEventListener {
|
||||
public abstract static class AbstractEventListener {
|
||||
|
||||
public AbstractEventListener() {
|
||||
/**
|
||||
* 自动注册给EventDispatcher
|
||||
*/
|
||||
EventDispatcher.addEventListener(this);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 感兴趣的事件列表
|
||||
* 感兴趣的事件列表.
|
||||
*
|
||||
* @return event list
|
||||
*/
|
||||
abstract public List<Class<? extends AbstractEvent>> interest();
|
||||
|
||||
public abstract List<Class<? extends AbstractEvent>> interest();
|
||||
|
||||
/**
|
||||
* 处理事件
|
||||
* 处理事件.
|
||||
*
|
||||
* @param abstractEvent event to do
|
||||
*/
|
||||
abstract public void onEvent(AbstractEvent abstractEvent);
|
||||
public abstract void onEvent(AbstractEvent abstractEvent);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* serverList has changed
|
||||
* serverList has changed.
|
||||
*/
|
||||
static public class ServerlistChangeEvent extends AbstractEvent {
|
||||
public static class ServerlistChangeEvent extends AbstractEvent {
|
||||
}
|
||||
}
|
||||
|
@ -13,14 +13,15 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.client.config.impl;
|
||||
|
||||
import com.alibaba.nacos.api.common.Constants;
|
||||
import com.alibaba.nacos.api.exception.NacosException;
|
||||
import com.alibaba.nacos.common.utils.MD5Utils;
|
||||
import com.alibaba.nacos.client.utils.ParamUtil;
|
||||
import com.alibaba.nacos.common.constant.HttpHeaderConsts;
|
||||
import com.alibaba.nacos.common.utils.IoUtils;
|
||||
import com.alibaba.nacos.common.utils.MD5Utils;
|
||||
import com.alibaba.nacos.common.utils.UuidUtils;
|
||||
import com.alibaba.nacos.common.utils.VersionUtils;
|
||||
|
||||
@ -29,27 +30,42 @@ import java.io.UnsupportedEncodingException;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Http tool
|
||||
* Http tool.
|
||||
*
|
||||
* @author Nacos
|
||||
*/
|
||||
public class HttpSimpleClient {
|
||||
|
||||
static public HttpResult httpGet(String url, List<String> headers, List<String> paramValues,
|
||||
String encoding, long readTimeoutMs, boolean isSSL) throws IOException {
|
||||
|
||||
/**
|
||||
* Get method.
|
||||
*
|
||||
* @param url url
|
||||
* @param headers headers
|
||||
* @param paramValues paramValues
|
||||
* @param encoding encoding
|
||||
* @param readTimeoutMs readTimeoutMs
|
||||
* @param isSsl isSsl
|
||||
* @return result
|
||||
* @throws IOException io exception
|
||||
*/
|
||||
public static HttpResult httpGet(String url, List<String> headers, List<String> paramValues, String encoding,
|
||||
long readTimeoutMs, boolean isSsl) throws IOException {
|
||||
String encodedContent = encodingParams(paramValues, encoding);
|
||||
url += (null == encodedContent) ? "" : ("?" + encodedContent);
|
||||
if (Limiter.isLimit(MD5Utils.md5Hex(
|
||||
new StringBuilder(url).append(encodedContent).toString(), Constants.ENCODE))) {
|
||||
if (Limiter
|
||||
.isLimit(MD5Utils.md5Hex(new StringBuilder(url).append(encodedContent).toString(), Constants.ENCODE))) {
|
||||
return new HttpResult(NacosException.CLIENT_OVER_THRESHOLD,
|
||||
"More than client-side current limit threshold");
|
||||
"More than client-side current limit threshold");
|
||||
}
|
||||
|
||||
|
||||
HttpURLConnection conn = null;
|
||||
|
||||
|
||||
try {
|
||||
conn = (HttpURLConnection) new URL(url).openConnection();
|
||||
conn.setRequestMethod("GET");
|
||||
@ -57,12 +73,12 @@ public class HttpSimpleClient {
|
||||
conn.setReadTimeout((int) readTimeoutMs);
|
||||
List<String> newHeaders = getHeaders(url, headers, paramValues);
|
||||
setHeaders(conn, newHeaders, encoding);
|
||||
|
||||
|
||||
conn.connect();
|
||||
|
||||
|
||||
int respCode = conn.getResponseCode();
|
||||
String resp = null;
|
||||
|
||||
|
||||
if (HttpURLConnection.HTTP_OK == respCode) {
|
||||
resp = IoUtils.toString(conn.getInputStream(), encoding);
|
||||
} else {
|
||||
@ -73,35 +89,35 @@ public class HttpSimpleClient {
|
||||
IoUtils.closeQuietly(conn);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 发送GET请求。
|
||||
* 发送GET请求.
|
||||
*/
|
||||
static public HttpResult httpGet(String url, List<String> headers, List<String> paramValues, String encoding,
|
||||
long readTimeoutMs) throws IOException {
|
||||
public static HttpResult httpGet(String url, List<String> headers, List<String> paramValues, String encoding,
|
||||
long readTimeoutMs) throws IOException {
|
||||
return httpGet(url, headers, paramValues, encoding, readTimeoutMs, false);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 发送POST请求。
|
||||
* 发送POST请求.
|
||||
*
|
||||
* @param url
|
||||
* @param url url
|
||||
* @param headers 请求Header,可以为null
|
||||
* @param paramValues 参数,可以为null
|
||||
* @param encoding URL编码使用的字符集
|
||||
* @param readTimeoutMs 响应超时
|
||||
* @param isSSL 是否https
|
||||
* @return
|
||||
* @throws IOException
|
||||
* @param isSsl 是否https
|
||||
* @return result
|
||||
* @throws IOException io exception
|
||||
*/
|
||||
static public HttpResult httpPost(String url, List<String> headers, List<String> paramValues,
|
||||
String encoding, long readTimeoutMs, boolean isSSL) throws IOException {
|
||||
public static HttpResult httpPost(String url, List<String> headers, List<String> paramValues, String encoding,
|
||||
long readTimeoutMs, boolean isSsl) throws IOException {
|
||||
String encodedContent = encodingParams(paramValues, encoding);
|
||||
encodedContent = (null == encodedContent) ? "" : encodedContent;
|
||||
if (Limiter.isLimit(MD5Utils.md5Hex(
|
||||
new StringBuilder(url).append(encodedContent).toString(), Constants.ENCODE))) {
|
||||
if (Limiter
|
||||
.isLimit(MD5Utils.md5Hex(new StringBuilder(url).append(encodedContent).toString(), Constants.ENCODE))) {
|
||||
return new HttpResult(NacosException.CLIENT_OVER_THRESHOLD,
|
||||
"More than client-side current limit threshold");
|
||||
"More than client-side current limit threshold");
|
||||
}
|
||||
HttpURLConnection conn = null;
|
||||
try {
|
||||
@ -113,12 +129,12 @@ public class HttpSimpleClient {
|
||||
conn.setDoInput(true);
|
||||
List<String> newHeaders = getHeaders(url, headers, paramValues);
|
||||
setHeaders(conn, newHeaders, encoding);
|
||||
|
||||
|
||||
conn.getOutputStream().write(encodedContent.getBytes(encoding));
|
||||
|
||||
|
||||
int respCode = conn.getResponseCode();
|
||||
String resp = null;
|
||||
|
||||
|
||||
if (HttpURLConnection.HTTP_OK == respCode) {
|
||||
resp = IoUtils.toString(conn.getInputStream(), encoding);
|
||||
} else {
|
||||
@ -129,35 +145,47 @@ public class HttpSimpleClient {
|
||||
IoUtils.closeQuietly(conn);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 发送POST请求。
|
||||
* 发送POST请求.
|
||||
*
|
||||
* @param url
|
||||
* @param url url
|
||||
* @param headers 请求Header,可以为null
|
||||
* @param paramValues 参数,可以为null
|
||||
* @param encoding URL编码使用的字符集
|
||||
* @param readTimeoutMs 响应超时
|
||||
* @return
|
||||
* @throws IOException
|
||||
* @return result
|
||||
* @throws IOException io exception
|
||||
*/
|
||||
static public HttpResult httpPost(String url, List<String> headers, List<String> paramValues, String encoding,
|
||||
long readTimeoutMs) throws IOException {
|
||||
public static HttpResult httpPost(String url, List<String> headers, List<String> paramValues, String encoding,
|
||||
long readTimeoutMs) throws IOException {
|
||||
return httpPost(url, headers, paramValues, encoding, readTimeoutMs, false);
|
||||
}
|
||||
|
||||
static public HttpResult httpDelete(String url, List<String> headers, List<String> paramValues,
|
||||
String encoding, long readTimeoutMs, boolean isSSL) throws IOException {
|
||||
|
||||
/**
|
||||
* Delete method.
|
||||
*
|
||||
* @param url url
|
||||
* @param headers 请求Header,可以为null
|
||||
* @param paramValues 参数,可以为null
|
||||
* @param encoding URL编码使用的字符集
|
||||
* @param readTimeoutMs 响应超时
|
||||
* @param isSsl 是否https
|
||||
* @return result
|
||||
* @throws IOException io exception
|
||||
*/
|
||||
public static HttpResult httpDelete(String url, List<String> headers, List<String> paramValues, String encoding,
|
||||
long readTimeoutMs, boolean isSsl) throws IOException {
|
||||
String encodedContent = encodingParams(paramValues, encoding);
|
||||
url += (null == encodedContent) ? "" : ("?" + encodedContent);
|
||||
if (Limiter.isLimit(MD5Utils.md5Hex(
|
||||
new StringBuilder(url).append(encodedContent).toString(), Constants.ENCODE))) {
|
||||
if (Limiter
|
||||
.isLimit(MD5Utils.md5Hex(new StringBuilder(url).append(encodedContent).toString(), Constants.ENCODE))) {
|
||||
return new HttpResult(NacosException.CLIENT_OVER_THRESHOLD,
|
||||
"More than client-side current limit threshold");
|
||||
"More than client-side current limit threshold");
|
||||
}
|
||||
|
||||
|
||||
HttpURLConnection conn = null;
|
||||
|
||||
|
||||
try {
|
||||
conn = (HttpURLConnection) new URL(url).openConnection();
|
||||
conn.setRequestMethod("DELETE");
|
||||
@ -165,12 +193,12 @@ public class HttpSimpleClient {
|
||||
conn.setReadTimeout((int) readTimeoutMs);
|
||||
List<String> newHeaders = getHeaders(url, headers, paramValues);
|
||||
setHeaders(conn, newHeaders, encoding);
|
||||
|
||||
|
||||
conn.connect();
|
||||
|
||||
|
||||
int respCode = conn.getResponseCode();
|
||||
String resp = null;
|
||||
|
||||
|
||||
if (HttpURLConnection.HTTP_OK == respCode) {
|
||||
resp = IoUtils.toString(conn.getInputStream(), encoding);
|
||||
} else {
|
||||
@ -181,13 +209,24 @@ public class HttpSimpleClient {
|
||||
IoUtils.closeQuietly(conn);
|
||||
}
|
||||
}
|
||||
|
||||
static public HttpResult httpDelete(String url, List<String> headers, List<String> paramValues, String encoding,
|
||||
long readTimeoutMs) throws IOException {
|
||||
|
||||
/**
|
||||
* Delete method.
|
||||
*
|
||||
* @param url url
|
||||
* @param headers 请求Header,可以为null
|
||||
* @param paramValues 参数,可以为null
|
||||
* @param encoding URL编码使用的字符集
|
||||
* @param readTimeoutMs 响应超时
|
||||
* @return result
|
||||
* @throws IOException io exception
|
||||
*/
|
||||
public static HttpResult httpDelete(String url, List<String> headers, List<String> paramValues, String encoding,
|
||||
long readTimeoutMs) throws IOException {
|
||||
return httpGet(url, headers, paramValues, encoding, readTimeoutMs, false);
|
||||
}
|
||||
|
||||
static private void setHeaders(HttpURLConnection conn, List<String> headers, String encoding) {
|
||||
|
||||
private static void setHeaders(HttpURLConnection conn, List<String> headers, String encoding) {
|
||||
if (null != headers) {
|
||||
for (Iterator<String> iter = headers.iterator(); iter.hasNext(); ) {
|
||||
conn.addRequestProperty(iter.next(), iter.next());
|
||||
@ -195,17 +234,17 @@ public class HttpSimpleClient {
|
||||
}
|
||||
conn.addRequestProperty(HttpHeaderConsts.CLIENT_VERSION_HEADER, VersionUtils.version);
|
||||
conn.addRequestProperty("Content-Type", "application/x-www-form-urlencoded;charset=" + encoding);
|
||||
|
||||
|
||||
String ts = String.valueOf(System.currentTimeMillis());
|
||||
String token = MD5Utils.md5Hex(ts + ParamUtil.getAppKey(), Constants.ENCODE);
|
||||
|
||||
|
||||
conn.addRequestProperty(Constants.CLIENT_APPNAME_HEADER, ParamUtil.getAppName());
|
||||
conn.addRequestProperty(Constants.CLIENT_REQUEST_TS_HEADER, ts);
|
||||
conn.addRequestProperty(Constants.CLIENT_REQUEST_TOKEN_HEADER, token);
|
||||
}
|
||||
|
||||
|
||||
private static List<String> getHeaders(String url, List<String> headers, List<String> paramValues)
|
||||
throws IOException {
|
||||
throws IOException {
|
||||
List<String> newHeaders = new ArrayList<String>();
|
||||
newHeaders.add("exConfigInfo");
|
||||
newHeaders.add("true");
|
||||
@ -216,14 +255,14 @@ public class HttpSimpleClient {
|
||||
}
|
||||
return newHeaders;
|
||||
}
|
||||
|
||||
static private String encodingParams(List<String> paramValues, String encoding)
|
||||
throws UnsupportedEncodingException {
|
||||
|
||||
private static String encodingParams(List<String> paramValues, String encoding)
|
||||
throws UnsupportedEncodingException {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if (null == paramValues) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
for (Iterator<String> iter = paramValues.iterator(); iter.hasNext(); ) {
|
||||
sb.append(iter.next()).append("=");
|
||||
sb.append(URLEncoder.encode(iter.next(), encoding));
|
||||
@ -233,29 +272,31 @@ public class HttpSimpleClient {
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
static public class HttpResult {
|
||||
final public int code;
|
||||
final public Map<String, List<String>> headers;
|
||||
final public String content;
|
||||
|
||||
|
||||
public static class HttpResult {
|
||||
|
||||
public final int code;
|
||||
|
||||
public final Map<String, List<String>> headers;
|
||||
|
||||
public final String content;
|
||||
|
||||
public HttpResult(int code, String content) {
|
||||
this.code = code;
|
||||
this.headers = null;
|
||||
this.content = content;
|
||||
}
|
||||
|
||||
|
||||
public HttpResult(int code, Map<String, List<String>> headers, String content) {
|
||||
this.code = code;
|
||||
this.headers = headers;
|
||||
this.content = content;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "HttpResult{" + "code=" + code + ", headers=" + headers + ", content='"
|
||||
+ content + '\'' + '}';
|
||||
return "HttpResult{" + "code=" + code + ", headers=" + headers + ", content='" + content + '\'' + '}';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -13,6 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.client.config.impl;
|
||||
|
||||
import com.alibaba.nacos.client.utils.LogUtils;
|
||||
@ -26,40 +27,46 @@ import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* Limiter
|
||||
* Limiter.
|
||||
*
|
||||
* @author Nacos
|
||||
*/
|
||||
public class Limiter {
|
||||
|
||||
|
||||
private static final Logger LOGGER = LogUtils.logger(Limiter.class);
|
||||
|
||||
|
||||
private static final int CAPACITY_SIZE = 1000;
|
||||
|
||||
private static final int LIMIT_TIME = 1000;
|
||||
private static Cache<String, RateLimiter> cache = CacheBuilder.newBuilder()
|
||||
.initialCapacity(CAPACITY_SIZE).expireAfterAccess(1, TimeUnit.MINUTES)
|
||||
.build();
|
||||
|
||||
|
||||
private static final Cache<String, RateLimiter> CACHE = CacheBuilder.newBuilder().initialCapacity(CAPACITY_SIZE)
|
||||
.expireAfterAccess(1, TimeUnit.MINUTES).build();
|
||||
|
||||
/**
|
||||
* qps 5
|
||||
* qps 5.
|
||||
*/
|
||||
private static double limit = 5;
|
||||
|
||||
|
||||
static {
|
||||
try {
|
||||
String limitTimeStr = System
|
||||
.getProperty("limitTime", String.valueOf(limit));
|
||||
String limitTimeStr = System.getProperty("limitTime", String.valueOf(limit));
|
||||
limit = Double.parseDouble(limitTimeStr);
|
||||
LOGGER.info("limitTime:{}", limit);
|
||||
} catch (Exception e) {
|
||||
LOGGER.error("init limitTime fail", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Judge whether access key is limited.
|
||||
*
|
||||
* @param accessKeyID access key
|
||||
* @return true if is limited, otherwise false
|
||||
*/
|
||||
public static boolean isLimit(String accessKeyID) {
|
||||
RateLimiter rateLimiter = null;
|
||||
try {
|
||||
rateLimiter = cache.get(accessKeyID, new Callable<RateLimiter>() {
|
||||
rateLimiter = CACHE.get(accessKeyID, new Callable<RateLimiter>() {
|
||||
@Override
|
||||
public RateLimiter call() throws Exception {
|
||||
return RateLimiter.create(limit);
|
||||
@ -74,5 +81,5 @@ public class Limiter {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -13,11 +13,12 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.client.config.impl;
|
||||
|
||||
import com.alibaba.nacos.api.common.Constants;
|
||||
import com.alibaba.nacos.client.config.utils.ConcurrentDiskUtil;
|
||||
import com.alibaba.nacos.client.config.utils.JVMUtil;
|
||||
import com.alibaba.nacos.client.config.utils.JvmUtil;
|
||||
import com.alibaba.nacos.client.config.utils.SnapShotSwitch;
|
||||
import com.alibaba.nacos.client.utils.LogUtils;
|
||||
import com.alibaba.nacos.common.utils.IoUtils;
|
||||
@ -30,20 +31,20 @@ import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
/**
|
||||
* Local Disaster Recovery Directory Tool
|
||||
* Local Disaster Recovery Directory Tool.
|
||||
*
|
||||
* @author Nacos
|
||||
*/
|
||||
public class LocalConfigInfoProcessor {
|
||||
|
||||
|
||||
private static final Logger LOGGER = LogUtils.logger(LocalConfigInfoProcessor.class);
|
||||
|
||||
static public String getFailover(String serverName, String dataId, String group, String tenant) {
|
||||
|
||||
public static String getFailover(String serverName, String dataId, String group, String tenant) {
|
||||
File localPath = getFailoverFile(serverName, dataId, group, tenant);
|
||||
if (!localPath.exists() || !localPath.isFile()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
return readFile(localPath);
|
||||
} catch (IOException ioe) {
|
||||
@ -51,11 +52,11 @@ public class LocalConfigInfoProcessor {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取本地缓存文件内容。NULL表示没有本地文件或抛出异常。
|
||||
* 获取本地缓存文件内容。NULL表示没有本地文件或抛出异常.
|
||||
*/
|
||||
static public String getSnapshot(String name, String dataId, String group, String tenant) {
|
||||
public static String getSnapshot(String name, String dataId, String group, String tenant) {
|
||||
if (!SnapShotSwitch.getIsSnapShot()) {
|
||||
return null;
|
||||
}
|
||||
@ -63,7 +64,7 @@ public class LocalConfigInfoProcessor {
|
||||
if (!file.exists() || !file.isFile()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
return readFile(file);
|
||||
} catch (IOException ioe) {
|
||||
@ -71,13 +72,13 @@ public class LocalConfigInfoProcessor {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
static private String readFile(File file) throws IOException {
|
||||
|
||||
private static String readFile(File file) throws IOException {
|
||||
if (!file.exists() || !file.isFile()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (JVMUtil.isMultiInstance()) {
|
||||
|
||||
if (JvmUtil.isMultiInstance()) {
|
||||
return ConcurrentDiskUtil.getFileContent(file, Constants.ENCODE);
|
||||
} else {
|
||||
InputStream is = null;
|
||||
@ -89,13 +90,22 @@ public class LocalConfigInfoProcessor {
|
||||
if (null != is) {
|
||||
is.close();
|
||||
}
|
||||
} catch (IOException ioe) {
|
||||
} catch (IOException ignored) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static public void saveSnapshot(String envName, String dataId, String group, String tenant, String config) {
|
||||
|
||||
/**
|
||||
* Save snapshot.
|
||||
*
|
||||
* @param envName env name
|
||||
* @param dataId data id
|
||||
* @param group group
|
||||
* @param tenant tenant
|
||||
* @param config config
|
||||
*/
|
||||
public static void saveSnapshot(String envName, String dataId, String group, String tenant, String config) {
|
||||
if (!SnapShotSwitch.getIsSnapShot()) {
|
||||
return;
|
||||
}
|
||||
@ -115,10 +125,9 @@ public class LocalConfigInfoProcessor {
|
||||
LOGGER.error("[{}] save snapshot error", envName);
|
||||
}
|
||||
}
|
||||
|
||||
if (JVMUtil.isMultiInstance()) {
|
||||
ConcurrentDiskUtil.writeFileContent(file, config,
|
||||
Constants.ENCODE);
|
||||
|
||||
if (JvmUtil.isMultiInstance()) {
|
||||
ConcurrentDiskUtil.writeFileContent(file, config, Constants.ENCODE);
|
||||
} else {
|
||||
IoUtils.writeStringToFile(file, config, Constants.ENCODE);
|
||||
}
|
||||
@ -127,11 +136,11 @@ public class LocalConfigInfoProcessor {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 清除snapshot目录下所有缓存文件。
|
||||
* 清除snapshot目录下所有缓存文件.
|
||||
*/
|
||||
static public void cleanAllSnapshot() {
|
||||
public static void cleanAllSnapshot() {
|
||||
try {
|
||||
File rootFile = new File(LOCAL_SNAPSHOT_PATH);
|
||||
File[] files = rootFile.listFiles();
|
||||
@ -147,8 +156,13 @@ public class LocalConfigInfoProcessor {
|
||||
LOGGER.error("clean all snapshot error, " + ioe.toString(), ioe);
|
||||
}
|
||||
}
|
||||
|
||||
static public void cleanEnvSnapshot(String envName) {
|
||||
|
||||
/**
|
||||
* Clean snapshot.
|
||||
*
|
||||
* @param envName env name
|
||||
*/
|
||||
public static void cleanEnvSnapshot(String envName) {
|
||||
File tmp = new File(LOCAL_SNAPSHOT_PATH, envName + "_nacos");
|
||||
tmp = new File(tmp, "snapshot");
|
||||
try {
|
||||
@ -159,7 +173,7 @@ public class LocalConfigInfoProcessor {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static File getFailoverFile(String serverName, String dataId, String group, String tenant) {
|
||||
File tmp = new File(LOCAL_SNAPSHOT_PATH, serverName + "_nacos");
|
||||
tmp = new File(tmp, "data");
|
||||
@ -171,7 +185,7 @@ public class LocalConfigInfoProcessor {
|
||||
}
|
||||
return new File(new File(tmp, group), dataId);
|
||||
}
|
||||
|
||||
|
||||
static File getSnapshotFile(String envName, String dataId, String group, String tenant) {
|
||||
File tmp = new File(LOCAL_SNAPSHOT_PATH, envName + "_nacos");
|
||||
if (StringUtils.isBlank(tenant)) {
|
||||
@ -180,19 +194,22 @@ public class LocalConfigInfoProcessor {
|
||||
tmp = new File(tmp, "snapshot-tenant");
|
||||
tmp = new File(tmp, tenant);
|
||||
}
|
||||
|
||||
|
||||
return new File(new File(tmp, group), dataId);
|
||||
}
|
||||
|
||||
|
||||
public static final String LOCAL_FILEROOT_PATH;
|
||||
|
||||
public static final String LOCAL_SNAPSHOT_PATH;
|
||||
|
||||
|
||||
static {
|
||||
LOCAL_FILEROOT_PATH = System.getProperty("JM.LOG.PATH", System.getProperty("user.home")) + File.separator
|
||||
+ "nacos" + File.separator + "config";
|
||||
LOCAL_SNAPSHOT_PATH = System.getProperty("JM.SNAPSHOT.PATH", System.getProperty("user.home")) + File.separator
|
||||
+ "nacos" + File.separator + "config";
|
||||
LOCAL_FILEROOT_PATH =
|
||||
System.getProperty("JM.LOG.PATH", System.getProperty("user.home")) + File.separator + "nacos"
|
||||
+ File.separator + "config";
|
||||
LOCAL_SNAPSHOT_PATH =
|
||||
System.getProperty("JM.SNAPSHOT.PATH", System.getProperty("user.home")) + File.separator + "nacos"
|
||||
+ File.separator + "config";
|
||||
LOGGER.info("LOCAL_SNAPSHOT_PATH:{}", LOCAL_SNAPSHOT_PATH);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -13,6 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.client.config.impl;
|
||||
|
||||
import com.alibaba.nacos.api.config.ConfigChangeItem;
|
||||
@ -24,27 +25,28 @@ import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* PropertiesChangeParser
|
||||
* PropertiesChangeParser.
|
||||
*
|
||||
* @author rushsky518
|
||||
*/
|
||||
public class PropertiesChangeParser extends AbstractConfigChangeParser {
|
||||
|
||||
public PropertiesChangeParser() {
|
||||
super("properties");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Map<String, ConfigChangeItem> doParse(String oldContent, String newContent, String type) throws IOException {
|
||||
Properties oldProps = new Properties();
|
||||
Properties newProps = new Properties();
|
||||
|
||||
|
||||
if (StringUtils.isNotBlank(oldContent)) {
|
||||
oldProps.load(new StringReader(oldContent));
|
||||
}
|
||||
if (StringUtils.isNotBlank(newContent)) {
|
||||
newProps.load(new StringReader(newContent));
|
||||
}
|
||||
|
||||
|
||||
return filterChangeData(oldProps, newProps);
|
||||
}
|
||||
}
|
||||
|
@ -13,6 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.client.config.impl;
|
||||
|
||||
import com.alibaba.nacos.api.PropertyKeyConst;
|
||||
@ -33,30 +34,32 @@ import org.slf4j.Logger;
|
||||
import java.io.IOException;
|
||||
import java.io.StringReader;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Properties;
|
||||
import java.util.Iterator;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
import java.util.Random;
|
||||
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ScheduledThreadPoolExecutor;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ScheduledThreadPoolExecutor;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* Serverlist Manager
|
||||
* Serverlist Manager.
|
||||
*
|
||||
* @author Nacos
|
||||
*/
|
||||
public class ServerListManager implements Closeable {
|
||||
|
||||
|
||||
private static final Logger LOGGER = LogUtils.logger(ServerListManager.class);
|
||||
|
||||
private static final String HTTPS = "https://";
|
||||
|
||||
private static final String HTTP = "http://";
|
||||
private ScheduledExecutorService executorService = new ScheduledThreadPoolExecutor(1, new ThreadFactory() {
|
||||
|
||||
private final ScheduledExecutorService executorService = new ScheduledThreadPoolExecutor(1, new ThreadFactory() {
|
||||
@Override
|
||||
public Thread newThread(Runnable r) {
|
||||
Thread t = new Thread(r);
|
||||
@ -65,17 +68,17 @@ public class ServerListManager implements Closeable {
|
||||
return t;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
public ServerListManager() {
|
||||
this.isFixed = false;
|
||||
this.isStarted = false;
|
||||
this.name = DEFAULT_NAME;
|
||||
}
|
||||
|
||||
|
||||
public ServerListManager(List<String> fixed) {
|
||||
this(fixed, null);
|
||||
}
|
||||
|
||||
|
||||
public ServerListManager(List<String> fixed, String namespace) {
|
||||
this.isFixed = true;
|
||||
this.isStarted = true;
|
||||
@ -94,35 +97,35 @@ public class ServerListManager implements Closeable {
|
||||
} else {
|
||||
this.namespace = namespace;
|
||||
this.name = FIXED_NAME + "-" + getFixedNameSuffix(serverAddrs.toArray(new String[serverAddrs.size()])) + "-"
|
||||
+ namespace;
|
||||
+ namespace;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public ServerListManager(String host, int port) {
|
||||
this.isFixed = false;
|
||||
this.isStarted = false;
|
||||
this.name = CUSTOM_NAME + "-" + host + "-" + port;
|
||||
this.addressServerUrl = String.format("http://%s:%d/%s/%s", host, port, this.contentPath, this.serverListName);
|
||||
}
|
||||
|
||||
|
||||
public ServerListManager(String endpoint) throws NacosException {
|
||||
this(endpoint, null);
|
||||
}
|
||||
|
||||
|
||||
public ServerListManager(String endpoint, String namespace) throws NacosException {
|
||||
this.isFixed = false;
|
||||
this.isStarted = false;
|
||||
Properties properties = new Properties();
|
||||
properties.setProperty(PropertyKeyConst.ENDPOINT, endpoint);
|
||||
endpoint = initEndpoint(properties);
|
||||
|
||||
|
||||
if (StringUtils.isBlank(endpoint)) {
|
||||
throw new NacosException(NacosException.CLIENT_INVALID_PARAM, "endpoint is blank");
|
||||
}
|
||||
if (StringUtils.isBlank(namespace)) {
|
||||
this.name = endpoint;
|
||||
this.addressServerUrl = String.format("http://%s:%d/%s/%s", endpoint, this.endpointPort, this.contentPath,
|
||||
this.serverListName);
|
||||
this.addressServerUrl = String
|
||||
.format("http://%s:%d/%s/%s", endpoint, this.endpointPort, this.contentPath, this.serverListName);
|
||||
} else {
|
||||
if (StringUtils.isBlank(endpoint)) {
|
||||
throw new NacosException(NacosException.CLIENT_INVALID_PARAM, "endpoint is blank");
|
||||
@ -130,24 +133,23 @@ public class ServerListManager implements Closeable {
|
||||
this.name = endpoint + "-" + namespace;
|
||||
this.namespace = namespace;
|
||||
this.tenant = namespace;
|
||||
this.addressServerUrl = String.format("http://%s:%d/%s/%s?namespace=%s", endpoint, this.endpointPort, this.contentPath,
|
||||
this.serverListName, namespace);
|
||||
this.addressServerUrl = String
|
||||
.format("http://%s:%d/%s/%s?namespace=%s", endpoint, this.endpointPort, this.contentPath,
|
||||
this.serverListName, namespace);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public ServerListManager(Properties properties) throws NacosException {
|
||||
this.isStarted = false;
|
||||
this.serverAddrsStr = properties.getProperty(PropertyKeyConst.SERVER_ADDR);
|
||||
String namespace = properties.getProperty(PropertyKeyConst.NAMESPACE);
|
||||
initParam(properties);
|
||||
|
||||
|
||||
if (StringUtils.isNotEmpty(serverAddrsStr)) {
|
||||
this.isFixed = true;
|
||||
List<String> serverAddrs = new ArrayList<String>();
|
||||
String[] serverAddrsArr = this.serverAddrsStr.split(",");
|
||||
for (String serverAddr: serverAddrsArr) {
|
||||
for (String serverAddr : serverAddrsArr) {
|
||||
if (serverAddr.startsWith(HTTPS) || serverAddr.startsWith(HTTP)) {
|
||||
serverAddrs.add(serverAddr);
|
||||
} else {
|
||||
@ -161,12 +163,13 @@ public class ServerListManager implements Closeable {
|
||||
}
|
||||
this.serverUrls = serverAddrs;
|
||||
if (StringUtils.isBlank(namespace)) {
|
||||
this.name = FIXED_NAME + "-" + getFixedNameSuffix(this.serverUrls.toArray(new String[this.serverUrls.size()]));
|
||||
this.name = FIXED_NAME + "-" + getFixedNameSuffix(
|
||||
this.serverUrls.toArray(new String[this.serverUrls.size()]));
|
||||
} else {
|
||||
this.namespace = namespace;
|
||||
this.tenant = namespace;
|
||||
this.name = FIXED_NAME + "-" + getFixedNameSuffix(this.serverUrls.toArray(new String[this.serverUrls.size()])) + "-"
|
||||
+ namespace;
|
||||
this.name = FIXED_NAME + "-" + getFixedNameSuffix(
|
||||
this.serverUrls.toArray(new String[this.serverUrls.size()])) + "-" + namespace;
|
||||
}
|
||||
} else {
|
||||
if (StringUtils.isBlank(endpoint)) {
|
||||
@ -175,21 +178,23 @@ public class ServerListManager implements Closeable {
|
||||
this.isFixed = false;
|
||||
if (StringUtils.isBlank(namespace)) {
|
||||
this.name = endpoint;
|
||||
this.addressServerUrl = String.format("http://%s:%d/%s/%s", this.endpoint, this.endpointPort, this.contentPath,
|
||||
this.serverListName);
|
||||
this.addressServerUrl = String
|
||||
.format("http://%s:%d/%s/%s", this.endpoint, this.endpointPort, this.contentPath,
|
||||
this.serverListName);
|
||||
} else {
|
||||
this.namespace = namespace;
|
||||
this.tenant = namespace;
|
||||
this.name = this.endpoint + "-" + namespace;
|
||||
this.addressServerUrl = String.format("http://%s:%d/%s/%s?namespace=%s", this.endpoint, this.endpointPort,
|
||||
this.contentPath, this.serverListName, namespace);
|
||||
this.addressServerUrl = String
|
||||
.format("http://%s:%d/%s/%s?namespace=%s", this.endpoint, this.endpointPort, this.contentPath,
|
||||
this.serverListName, namespace);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void initParam(Properties properties) {
|
||||
this.endpoint = initEndpoint(properties);
|
||||
|
||||
|
||||
String contentPathTmp = properties.getProperty(PropertyKeyConst.CONTEXT_PATH);
|
||||
if (!StringUtils.isBlank(contentPathTmp)) {
|
||||
this.contentPath = contentPathTmp;
|
||||
@ -199,27 +204,28 @@ public class ServerListManager implements Closeable {
|
||||
this.serverListName = serverListNameTmp;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private String initEndpoint(final Properties properties) {
|
||||
|
||||
String endpointPortTmp = TemplateUtils.stringEmptyAndThenExecute(System.getenv(PropertyKeyConst.SystemEnv.ALIBABA_ALIWARE_ENDPOINT_PORT), new Callable<String>() {
|
||||
@Override
|
||||
public String call() {
|
||||
return properties.getProperty(PropertyKeyConst.ENDPOINT_PORT);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
String endpointPortTmp = TemplateUtils
|
||||
.stringEmptyAndThenExecute(System.getenv(PropertyKeyConst.SystemEnv.ALIBABA_ALIWARE_ENDPOINT_PORT),
|
||||
new Callable<String>() {
|
||||
@Override
|
||||
public String call() {
|
||||
return properties.getProperty(PropertyKeyConst.ENDPOINT_PORT);
|
||||
}
|
||||
});
|
||||
|
||||
if (StringUtils.isNotBlank(endpointPortTmp)) {
|
||||
this.endpointPort = Integer.parseInt(endpointPortTmp);
|
||||
}
|
||||
|
||||
|
||||
String endpointTmp = properties.getProperty(PropertyKeyConst.ENDPOINT);
|
||||
|
||||
|
||||
// Whether to enable domain name resolution rules
|
||||
String isUseEndpointRuleParsing =
|
||||
properties.getProperty(PropertyKeyConst.IS_USE_ENDPOINT_PARSING_RULE,
|
||||
String isUseEndpointRuleParsing = properties.getProperty(PropertyKeyConst.IS_USE_ENDPOINT_PARSING_RULE,
|
||||
System.getProperty(SystemPropertyKeyConst.IS_USE_ENDPOINT_PARSING_RULE,
|
||||
String.valueOf(ParamUtil.USE_ENDPOINT_PARSING_RULE_DEFAULT_VALUE)));
|
||||
String.valueOf(ParamUtil.USE_ENDPOINT_PARSING_RULE_DEFAULT_VALUE)));
|
||||
if (Boolean.parseBoolean(isUseEndpointRuleParsing)) {
|
||||
String endpointUrl = ParamUtil.parsingEndpointRule(endpointTmp);
|
||||
if (StringUtils.isNotBlank(endpointUrl)) {
|
||||
@ -227,16 +233,21 @@ public class ServerListManager implements Closeable {
|
||||
}
|
||||
return endpointUrl;
|
||||
}
|
||||
|
||||
|
||||
return StringUtils.isNotBlank(endpointTmp) ? endpointTmp : "";
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Start.
|
||||
*
|
||||
* @throws NacosException nacos exception
|
||||
*/
|
||||
public synchronized void start() throws NacosException {
|
||||
|
||||
|
||||
if (isStarted || isFixed) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
GetServerListTask getServersTask = new GetServerListTask(addressServerUrl);
|
||||
for (int i = 0; i < initServerlistRetryTimes && serverUrls.isEmpty(); ++i) {
|
||||
getServersTask.run();
|
||||
@ -246,65 +257,65 @@ public class ServerListManager implements Closeable {
|
||||
LOGGER.warn("get serverlist fail,url: {}", addressServerUrl);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (serverUrls.isEmpty()) {
|
||||
LOGGER.error("[init-serverlist] fail to get NACOS-server serverlist! env: {}, url: {}", name,
|
||||
addressServerUrl);
|
||||
addressServerUrl);
|
||||
throw new NacosException(NacosException.SERVER_ERROR,
|
||||
"fail to get NACOS-server serverlist! env:" + name + ", not connnect url:" + addressServerUrl);
|
||||
"fail to get NACOS-server serverlist! env:" + name + ", not connnect url:" + addressServerUrl);
|
||||
}
|
||||
|
||||
|
||||
// executor schedules the timer task
|
||||
this.executorService.scheduleWithFixedDelay(getServersTask,0L, 30L, TimeUnit.SECONDS);
|
||||
this.executorService.scheduleWithFixedDelay(getServersTask, 0L, 30L, TimeUnit.SECONDS);
|
||||
isStarted = true;
|
||||
}
|
||||
|
||||
|
||||
public List<String> getServerUrls() {
|
||||
return serverUrls;
|
||||
}
|
||||
|
||||
|
||||
Iterator<String> iterator() {
|
||||
if (serverUrls.isEmpty()) {
|
||||
LOGGER.error("[{}] [iterator-serverlist] No server address defined!", name);
|
||||
}
|
||||
return new ServerAddressIterator(serverUrls);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void shutdown() throws NacosException{
|
||||
public void shutdown() throws NacosException {
|
||||
String className = this.getClass().getName();
|
||||
LOGGER.info("{} do shutdown begin", className);
|
||||
ThreadUtils.shutdownThreadPool(executorService, LOGGER);
|
||||
LOGGER.info("{} do shutdown stop", className);
|
||||
}
|
||||
|
||||
|
||||
class GetServerListTask implements Runnable {
|
||||
|
||||
final String url;
|
||||
|
||||
|
||||
GetServerListTask(String url) {
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
/**
|
||||
* get serverlist from nameserver
|
||||
/*
|
||||
get serverlist from nameserver
|
||||
*/
|
||||
try {
|
||||
updateIfChanged(getApacheServerList(url, name));
|
||||
} catch (Exception e) {
|
||||
LOGGER.error("[" + name + "][update-serverlist] failed to update serverlist from address server!",
|
||||
e);
|
||||
LOGGER.error("[" + name + "][update-serverlist] failed to update serverlist from address server!", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void updateIfChanged(List<String> newList) {
|
||||
if (null == newList || newList.isEmpty()) {
|
||||
LOGGER.warn("[update-serverlist] current serverlist from address server is empty!!!");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
List<String> newServerAddrList = new ArrayList<String>();
|
||||
for (String server : newList) {
|
||||
if (server.startsWith(HTTP) || server.startsWith(HTTPS)) {
|
||||
@ -313,9 +324,9 @@ public class ServerListManager implements Closeable {
|
||||
newServerAddrList.add(HTTP + server);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* no change
|
||||
|
||||
/*
|
||||
no change
|
||||
*/
|
||||
if (newServerAddrList.equals(serverUrls)) {
|
||||
return;
|
||||
@ -323,15 +334,15 @@ public class ServerListManager implements Closeable {
|
||||
serverUrls = new ArrayList<String>(newServerAddrList);
|
||||
iterator = iterator();
|
||||
currentServerAddr = iterator.next();
|
||||
|
||||
|
||||
EventDispatcher.fireEvent(new ServerlistChangeEvent());
|
||||
LOGGER.info("[{}] [update-serverlist] serverlist updated to {}", name, serverUrls);
|
||||
}
|
||||
|
||||
|
||||
private List<String> getApacheServerList(String url, String name) {
|
||||
try {
|
||||
HttpResult httpResult = HttpSimpleClient.httpGet(url, null, null, null, 3000);
|
||||
|
||||
|
||||
if (HttpURLConnection.HTTP_OK == httpResult.code) {
|
||||
if (DEFAULT_NAME.equals(name)) {
|
||||
EnvUtil.setSelfEnv(httpResult.headers);
|
||||
@ -352,7 +363,7 @@ public class ServerListManager implements Closeable {
|
||||
return result;
|
||||
} else {
|
||||
LOGGER.error("[check-serverlist] error. addressServerUrl: {}, code: {}", addressServerUrl,
|
||||
httpResult.code);
|
||||
httpResult.code);
|
||||
return null;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
@ -360,11 +371,11 @@ public class ServerListManager implements Closeable {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
String getUrlString() {
|
||||
return serverUrls.toString();
|
||||
}
|
||||
|
||||
|
||||
String getFixedNameSuffix(String... serverIps) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
String split = "";
|
||||
@ -376,22 +387,22 @@ public class ServerListManager implements Closeable {
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ServerManager-" + name + "-" + getUrlString();
|
||||
}
|
||||
|
||||
|
||||
public boolean contain(String ip) {
|
||||
|
||||
|
||||
return serverUrls.contains(ip);
|
||||
}
|
||||
|
||||
|
||||
public void refreshCurrentServerAddr() {
|
||||
iterator = iterator();
|
||||
currentServerAddr = iterator.next();
|
||||
}
|
||||
|
||||
|
||||
public String getCurrentServerAddr() {
|
||||
if (StringUtils.isBlank(currentServerAddr)) {
|
||||
iterator = iterator();
|
||||
@ -399,124 +410,140 @@ public class ServerListManager implements Closeable {
|
||||
}
|
||||
return currentServerAddr;
|
||||
}
|
||||
|
||||
|
||||
public void updateCurrentServerAddr(String currentServerAddr) {
|
||||
this.currentServerAddr = currentServerAddr;
|
||||
}
|
||||
|
||||
|
||||
public Iterator<String> getIterator() {
|
||||
return iterator;
|
||||
}
|
||||
|
||||
|
||||
public String getContentPath() {
|
||||
return contentPath;
|
||||
}
|
||||
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
|
||||
public String getNamespace() {
|
||||
return namespace;
|
||||
}
|
||||
|
||||
|
||||
public String getTenant() {
|
||||
return tenant;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The name of the different environment
|
||||
* The name of the different environment.
|
||||
*/
|
||||
private String name;
|
||||
private final String name;
|
||||
|
||||
private String namespace = "";
|
||||
|
||||
private String tenant = "";
|
||||
static public final String DEFAULT_NAME = "default";
|
||||
static public final String CUSTOM_NAME = "custom";
|
||||
static public final String FIXED_NAME = "fixed";
|
||||
private int initServerlistRetryTimes = 5;
|
||||
|
||||
public static final String DEFAULT_NAME = "default";
|
||||
|
||||
public static final String CUSTOM_NAME = "custom";
|
||||
|
||||
public static final String FIXED_NAME = "fixed";
|
||||
|
||||
private final int initServerlistRetryTimes = 5;
|
||||
|
||||
/**
|
||||
* Connection timeout and socket timeout with other servers
|
||||
* Connection timeout and socket timeout with other servers.
|
||||
*/
|
||||
static final int TIMEOUT = 5000;
|
||||
|
||||
|
||||
final boolean isFixed;
|
||||
|
||||
boolean isStarted = false;
|
||||
|
||||
private String endpoint;
|
||||
|
||||
private int endpointPort = 8080;
|
||||
|
||||
private String contentPath = ParamUtil.getDefaultContextPath();
|
||||
|
||||
private String serverListName = ParamUtil.getDefaultNodesPath();
|
||||
|
||||
volatile List<String> serverUrls = new ArrayList<String>();
|
||||
|
||||
|
||||
private volatile String currentServerAddr;
|
||||
|
||||
|
||||
private Iterator<String> iterator;
|
||||
|
||||
public String serverPort = ParamUtil.getDefaultServerPort();
|
||||
|
||||
|
||||
public String addressServerUrl;
|
||||
|
||||
|
||||
private String serverAddrsStr;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort the address list, with the same room priority.
|
||||
*/
|
||||
class ServerAddressIterator implements Iterator<String> {
|
||||
|
||||
static class RandomizedServerAddress implements Comparable<RandomizedServerAddress> {
|
||||
static Random random = new Random();
|
||||
|
||||
String serverIp;
|
||||
int priority = 0;
|
||||
int seed;
|
||||
|
||||
public RandomizedServerAddress(String ip) {
|
||||
try {
|
||||
this.serverIp = ip;
|
||||
/**
|
||||
* change random scope from 32 to Integer.MAX_VALUE to fix load balance issue
|
||||
*/
|
||||
this.seed = random.nextInt(Integer.MAX_VALUE);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
|
||||
/**
|
||||
* Sort the address list, with the same room priority.
|
||||
*/
|
||||
private static class ServerAddressIterator implements Iterator<String> {
|
||||
|
||||
static class RandomizedServerAddress implements Comparable<RandomizedServerAddress> {
|
||||
|
||||
static Random random = new Random();
|
||||
|
||||
String serverIp;
|
||||
|
||||
int priority = 0;
|
||||
|
||||
int seed;
|
||||
|
||||
public RandomizedServerAddress(String ip) {
|
||||
try {
|
||||
this.serverIp = ip;
|
||||
/*
|
||||
change random scope from 32 to Integer.MAX_VALUE to fix load balance issue
|
||||
*/
|
||||
this.seed = random.nextInt(Integer.MAX_VALUE);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(RandomizedServerAddress other) {
|
||||
if (this.priority != other.priority) {
|
||||
return other.priority - this.priority;
|
||||
} else {
|
||||
return other.seed - this.seed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public ServerAddressIterator(List<String> source) {
|
||||
sorted = new ArrayList<RandomizedServerAddress>();
|
||||
for (String address : source) {
|
||||
sorted.add(new RandomizedServerAddress(address));
|
||||
}
|
||||
Collections.sort(sorted);
|
||||
iter = sorted.iterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(RandomizedServerAddress other) {
|
||||
if (this.priority != other.priority) {
|
||||
return other.priority - this.priority;
|
||||
} else {
|
||||
return other.seed - this.seed;
|
||||
}
|
||||
public boolean hasNext() {
|
||||
return iter.hasNext();
|
||||
}
|
||||
}
|
||||
|
||||
public ServerAddressIterator(List<String> source) {
|
||||
sorted = new ArrayList<RandomizedServerAddress>();
|
||||
for (String address : source) {
|
||||
sorted.add(new RandomizedServerAddress(address));
|
||||
|
||||
@Override
|
||||
public String next() {
|
||||
return iter.next().serverIp;
|
||||
}
|
||||
Collections.sort(sorted);
|
||||
iter = sorted.iterator();
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
final List<RandomizedServerAddress> sorted;
|
||||
|
||||
final Iterator<RandomizedServerAddress> iter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return iter.hasNext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String next() {
|
||||
return iter.next().serverIp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
final List<RandomizedServerAddress> sorted;
|
||||
final Iterator<RandomizedServerAddress> iter;
|
||||
}
|
||||
|
||||
|
@ -13,6 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.client.config.impl;
|
||||
|
||||
import com.alibaba.nacos.api.common.Constants;
|
||||
@ -23,15 +24,20 @@ import com.alibaba.nacos.common.utils.StringUtils;
|
||||
import javax.crypto.Mac;
|
||||
import javax.crypto.SecretKey;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
import java.util.*;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 适配spas接口
|
||||
* 适配spas接口.
|
||||
*
|
||||
* @author Nacos
|
||||
*/
|
||||
public class SpasAdapter {
|
||||
|
||||
|
||||
public static List<String> getSignHeaders(String resource, String secretKey) {
|
||||
List<String> header = new ArrayList<String>();
|
||||
String timeStamp = String.valueOf(System.currentTimeMillis());
|
||||
@ -41,15 +47,15 @@ public class SpasAdapter {
|
||||
header.add("Spas-Signature");
|
||||
String signature = "";
|
||||
if (StringUtils.isBlank(resource)) {
|
||||
signature = signWithhmacSHA1Encrypt(timeStamp, secretKey);
|
||||
signature = signWithHmacSha1Encrypt(timeStamp, secretKey);
|
||||
} else {
|
||||
signature = signWithhmacSHA1Encrypt(resource + "+" + timeStamp, secretKey);
|
||||
signature = signWithHmacSha1Encrypt(resource + "+" + timeStamp, secretKey);
|
||||
}
|
||||
header.add(signature);
|
||||
}
|
||||
return header;
|
||||
}
|
||||
|
||||
|
||||
public static List<String> getSignHeaders(List<String> paramValues, String secretKey) {
|
||||
if (null == paramValues) {
|
||||
return null;
|
||||
@ -73,25 +79,32 @@ public class SpasAdapter {
|
||||
}
|
||||
return getSignHeaders(resource, secretKey);
|
||||
}
|
||||
|
||||
|
||||
public static String getSk() {
|
||||
return CredentialService.getInstance().getCredential().getSecretKey();
|
||||
}
|
||||
|
||||
|
||||
public static String getAk() {
|
||||
return CredentialService.getInstance().getCredential().getAccessKey();
|
||||
}
|
||||
|
||||
public static String signWithhmacSHA1Encrypt(String encryptText, String encryptKey) {
|
||||
|
||||
/**
|
||||
* Sign with hmac SHA1 encrtpt.
|
||||
*
|
||||
* @param encryptText encrypt text
|
||||
* @param encryptKey encrypt key
|
||||
* @return base64 string
|
||||
*/
|
||||
public static String signWithHmacSha1Encrypt(String encryptText, String encryptKey) {
|
||||
try {
|
||||
byte[] data = encryptKey.getBytes("UTF-8");
|
||||
byte[] data = encryptKey.getBytes(StandardCharsets.UTF_8);
|
||||
// 根据给定的字节数组构造一个密钥,第二参数指定一个密钥算法的名称
|
||||
SecretKey secretKey = new SecretKeySpec(data, "HmacSHA1");
|
||||
// 生成一个指定 Mac 算法 的 Mac 对象
|
||||
Mac mac = Mac.getInstance("HmacSHA1");
|
||||
// 用给定密钥初始化 Mac 对象
|
||||
mac.init(secretKey);
|
||||
byte[] text = encryptText.getBytes("UTF-8");
|
||||
byte[] text = encryptText.getBytes(StandardCharsets.UTF_8);
|
||||
byte[] textFinal = mac.doFinal(text);
|
||||
// 完成 Mac 操作, base64编码,将byte数组转换为字符串
|
||||
return new String(Base64.encodeBase64(textFinal), Constants.ENCODE);
|
||||
@ -99,7 +112,8 @@ public class SpasAdapter {
|
||||
throw new RuntimeException("signWithhmacSHA1Encrypt fail", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static final String GROUP_KEY = "group";
|
||||
|
||||
public static final String TENANT_KEY = "tenant";
|
||||
}
|
||||
|
@ -13,28 +13,35 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.client.config.impl;
|
||||
|
||||
import com.alibaba.nacos.api.config.ConfigChangeItem;
|
||||
import com.alibaba.nacos.common.utils.StringUtils;
|
||||
import org.yaml.snakeyaml.Yaml;
|
||||
import java.util.*;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* YmlChangeParser
|
||||
* YmlChangeParser.
|
||||
*
|
||||
* @author rushsky518
|
||||
*/
|
||||
public class YmlChangeParser extends AbstractConfigChangeParser {
|
||||
|
||||
public YmlChangeParser() {
|
||||
super("yaml");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Map<String, ConfigChangeItem> doParse(String oldContent, String newContent, String type) {
|
||||
Map<String, Object> oldMap = Collections.emptyMap();
|
||||
Map<String, Object> newMap = Collections.emptyMap();
|
||||
|
||||
|
||||
if (StringUtils.isNotBlank(oldContent)) {
|
||||
oldMap = (new Yaml()).load(oldContent);
|
||||
oldMap = getFlattenedMap(oldMap);
|
||||
@ -43,16 +50,16 @@ public class YmlChangeParser extends AbstractConfigChangeParser {
|
||||
newMap = (new Yaml()).load(newContent);
|
||||
newMap = getFlattenedMap(newMap);
|
||||
}
|
||||
|
||||
|
||||
return filterChangeData(oldMap, newMap);
|
||||
}
|
||||
|
||||
|
||||
private final Map<String, Object> getFlattenedMap(Map<String, Object> source) {
|
||||
Map<String, Object> result = new LinkedHashMap<String, Object>(128);
|
||||
buildFlattenedMap(result, source, null);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
private void buildFlattenedMap(Map<String, Object> result, Map<String, Object> source, String path) {
|
||||
for (Iterator<Map.Entry<String, Object>> itr = source.entrySet().iterator(); itr.hasNext(); ) {
|
||||
Map.Entry<String, Object> e = itr.next();
|
||||
@ -67,12 +74,10 @@ public class YmlChangeParser extends AbstractConfigChangeParser {
|
||||
if (e.getValue() instanceof String) {
|
||||
result.put(key, e.getValue());
|
||||
} else if (e.getValue() instanceof Map) {
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, Object> map = (Map<String, Object>) e.getValue();
|
||||
@SuppressWarnings("unchecked") Map<String, Object> map = (Map<String, Object>) e.getValue();
|
||||
buildFlattenedMap(result, map, key);
|
||||
} else if (e.getValue() instanceof Collection) {
|
||||
@SuppressWarnings("unchecked")
|
||||
Collection<Object> collection = (Collection<Object>) e.getValue();
|
||||
@SuppressWarnings("unchecked") Collection<Object> collection = (Collection<Object>) e.getValue();
|
||||
if (collection.isEmpty()) {
|
||||
result.put(key, "");
|
||||
} else {
|
||||
@ -86,5 +91,5 @@ public class YmlChangeParser extends AbstractConfigChangeParser {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -13,24 +13,28 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.client.config.listener.impl;
|
||||
|
||||
import com.alibaba.nacos.api.config.listener.AbstractListener;
|
||||
import com.alibaba.nacos.api.config.ConfigChangeEvent;
|
||||
import com.alibaba.nacos.api.config.listener.AbstractListener;
|
||||
|
||||
/**
|
||||
* AbstractConfigChangeListener
|
||||
* AbstractConfigChangeListener.
|
||||
*
|
||||
* @author rushsky518
|
||||
*/
|
||||
public abstract class AbstractConfigChangeListener extends AbstractListener {
|
||||
|
||||
/**
|
||||
* handle config change
|
||||
* @param event
|
||||
* handle config change.
|
||||
*
|
||||
* @param event config change event
|
||||
*/
|
||||
public abstract void receiveConfigChange(final ConfigChangeEvent event);
|
||||
|
||||
|
||||
@Override
|
||||
public void receiveConfigInfo(final String configInfo) {}
|
||||
public void receiveConfigInfo(final String configInfo) {
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -13,6 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.client.config.listener.impl;
|
||||
|
||||
import com.alibaba.nacos.api.config.listener.AbstractListener;
|
||||
@ -25,21 +26,21 @@ import java.io.StringReader;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* Properties Listener
|
||||
* Properties Listener.
|
||||
*
|
||||
* @author Nacos
|
||||
*/
|
||||
@SuppressWarnings("PMD.AbstractClassShouldStartWithAbstractNamingRule")
|
||||
public abstract class PropertiesListener extends AbstractListener {
|
||||
|
||||
|
||||
private static final Logger LOGGER = LogUtils.logger(PropertiesListener.class);
|
||||
|
||||
|
||||
@Override
|
||||
public void receiveConfigInfo(String configInfo) {
|
||||
if (StringUtils.isEmpty(configInfo)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
Properties properties = new Properties();
|
||||
try {
|
||||
properties.load(new StringReader(configInfo));
|
||||
@ -47,14 +48,14 @@ public abstract class PropertiesListener extends AbstractListener {
|
||||
} catch (IOException e) {
|
||||
LOGGER.error("load properties error:" + configInfo, e);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* properties type for receiver
|
||||
* properties type for receiver.
|
||||
*
|
||||
* @param properties properties
|
||||
*/
|
||||
public abstract void innerReceive(Properties properties);
|
||||
|
||||
|
||||
}
|
||||
|
@ -13,6 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.client.config.utils;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
@ -30,36 +31,34 @@ import java.nio.charset.Charset;
|
||||
import java.nio.charset.CharsetDecoder;
|
||||
|
||||
/**
|
||||
* concurrent disk util;op file with file lock
|
||||
* concurrent disk util;op file with file lock.
|
||||
*
|
||||
* @author configCenter
|
||||
*/
|
||||
public class ConcurrentDiskUtil {
|
||||
|
||||
|
||||
/**
|
||||
* get file content
|
||||
* get file content.
|
||||
*
|
||||
* @param path file path
|
||||
* @param charsetName charsetName
|
||||
* @return content
|
||||
* @throws IOException IOException
|
||||
*/
|
||||
public static String getFileContent(String path, String charsetName)
|
||||
throws IOException {
|
||||
public static String getFileContent(String path, String charsetName) throws IOException {
|
||||
File file = new File(path);
|
||||
return getFileContent(file, charsetName);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* get file content
|
||||
* get file content.
|
||||
*
|
||||
* @param file file
|
||||
* @param charsetName charsetName
|
||||
* @return content
|
||||
* @throws IOException IOException
|
||||
*/
|
||||
public static String getFileContent(File file, String charsetName)
|
||||
throws IOException {
|
||||
public static String getFileContent(File file, String charsetName) throws IOException {
|
||||
RandomAccessFile fis = null;
|
||||
FileLock rlock = null;
|
||||
try {
|
||||
@ -72,17 +71,14 @@ public class ConcurrentDiskUtil {
|
||||
} catch (Exception e) {
|
||||
++i;
|
||||
if (i > RETRY_COUNT) {
|
||||
LOGGER.error("read {} fail;retryed time:{}",
|
||||
file.getName(), i);
|
||||
throw new IOException("read " + file.getAbsolutePath()
|
||||
+ " conflict");
|
||||
LOGGER.error("read {} fail;retryed time:{}", file.getName(), i);
|
||||
throw new IOException("read " + file.getAbsolutePath() + " conflict");
|
||||
}
|
||||
sleep(SLEEP_BASETIME * i);
|
||||
LOGGER.warn("read {} conflict;retry time:{}", file.getName(),
|
||||
i);
|
||||
LOGGER.warn("read {} conflict;retry time:{}", file.getName(), i);
|
||||
}
|
||||
} while (null == rlock);
|
||||
int fileSize = (int)fcin.size();
|
||||
int fileSize = (int) fcin.size();
|
||||
ByteBuffer byteBuffer = ByteBuffer.allocate(fileSize);
|
||||
fcin.read(byteBuffer);
|
||||
byteBuffer.flip();
|
||||
@ -98,9 +94,9 @@ public class ConcurrentDiskUtil {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* write file content
|
||||
* write file content.
|
||||
*
|
||||
* @param path file path
|
||||
* @param content content
|
||||
@ -108,14 +104,13 @@ public class ConcurrentDiskUtil {
|
||||
* @return whether write ok
|
||||
* @throws IOException IOException
|
||||
*/
|
||||
public static Boolean writeFileContent(String path, String content,
|
||||
String charsetName) throws IOException {
|
||||
public static Boolean writeFileContent(String path, String content, String charsetName) throws IOException {
|
||||
File file = new File(path);
|
||||
return writeFileContent(file, content, charsetName);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* write file content
|
||||
* write file content.
|
||||
*
|
||||
* @param file file
|
||||
* @param content content
|
||||
@ -123,8 +118,7 @@ public class ConcurrentDiskUtil {
|
||||
* @return whether write ok
|
||||
* @throws IOException IOException
|
||||
*/
|
||||
public static Boolean writeFileContent(File file, String content,
|
||||
String charsetName) throws IOException {
|
||||
public static Boolean writeFileContent(File file, String content, String charsetName) throws IOException {
|
||||
if (!file.exists()) {
|
||||
boolean isCreateOk = file.createNewFile();
|
||||
if (!isCreateOk) {
|
||||
@ -144,19 +138,15 @@ public class ConcurrentDiskUtil {
|
||||
} catch (Exception e) {
|
||||
++i;
|
||||
if (i > RETRY_COUNT) {
|
||||
LOGGER.error("write {} fail;retryed time:{}",
|
||||
file.getName(), i);
|
||||
throw new IOException("write " + file.getAbsolutePath()
|
||||
+ " conflict");
|
||||
LOGGER.error("write {} fail;retryed time:{}", file.getName(), i);
|
||||
throw new IOException("write " + file.getAbsolutePath() + " conflict");
|
||||
}
|
||||
sleep(SLEEP_BASETIME * i);
|
||||
LOGGER.warn("write {} conflict;retry time:{}", file.getName(),
|
||||
i);
|
||||
LOGGER.warn("write {} conflict;retry time:{}", file.getName(), i);
|
||||
}
|
||||
} while (null == lock);
|
||||
|
||||
ByteBuffer sendBuffer = ByteBuffer.wrap(content
|
||||
.getBytes(charsetName));
|
||||
|
||||
ByteBuffer sendBuffer = ByteBuffer.wrap(content.getBytes(charsetName));
|
||||
while (sendBuffer.hasRemaining()) {
|
||||
channel.write(sendBuffer);
|
||||
}
|
||||
@ -188,21 +178,20 @@ public class ConcurrentDiskUtil {
|
||||
LOGGER.warn("close wrong", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* transfer ByteBuffer to String
|
||||
* transfer ByteBuffer to String.
|
||||
*
|
||||
* @param buffer buffer
|
||||
* @param charsetName charsetName
|
||||
* @return String
|
||||
* @throws IOException IOException
|
||||
*/
|
||||
public static String byteBufferToString(ByteBuffer buffer,
|
||||
String charsetName) throws IOException {
|
||||
public static String byteBufferToString(ByteBuffer buffer, String charsetName) throws IOException {
|
||||
Charset charset = null;
|
||||
CharsetDecoder decoder = null;
|
||||
CharBuffer charBuffer = null;
|
||||
@ -211,7 +200,7 @@ public class ConcurrentDiskUtil {
|
||||
charBuffer = decoder.decode(buffer.asReadOnlyBuffer());
|
||||
return charBuffer.toString();
|
||||
}
|
||||
|
||||
|
||||
private static void sleep(int time) {
|
||||
try {
|
||||
Thread.sleep(time);
|
||||
@ -219,11 +208,13 @@ public class ConcurrentDiskUtil {
|
||||
LOGGER.warn("sleep wrong", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(ConcurrentDiskUtil.class);
|
||||
|
||||
static final int RETRY_COUNT = 10;
|
||||
|
||||
/**
|
||||
* ms
|
||||
* ms.
|
||||
*/
|
||||
static final int SLEEP_BASETIME = 10;
|
||||
}
|
||||
|
@ -13,6 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.client.config.utils;
|
||||
|
||||
import com.alibaba.nacos.api.common.Constants;
|
||||
@ -20,14 +21,20 @@ import com.alibaba.nacos.api.common.Constants;
|
||||
import static com.alibaba.nacos.api.common.Constants.WORD_SEPARATOR;
|
||||
|
||||
/**
|
||||
* Content Util
|
||||
* Content Util.
|
||||
*
|
||||
* @author Nacos
|
||||
*/
|
||||
public class ContentUtils {
|
||||
|
||||
|
||||
/**
|
||||
* Verify increment pub content.
|
||||
*
|
||||
* @param content content
|
||||
* @throws IllegalArgumentException if content is not valid
|
||||
*/
|
||||
public static void verifyIncrementPubContent(String content) {
|
||||
|
||||
|
||||
if (content == null || content.length() == 0) {
|
||||
throw new IllegalArgumentException("发布/删除内容不能为空");
|
||||
}
|
||||
@ -41,7 +48,7 @@ public class ContentUtils {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static String getContentIdentity(String content) {
|
||||
int index = content.indexOf(WORD_SEPARATOR);
|
||||
if (index == -1) {
|
||||
@ -49,7 +56,7 @@ public class ContentUtils {
|
||||
}
|
||||
return content.substring(0, index);
|
||||
}
|
||||
|
||||
|
||||
public static String getContent(String content) {
|
||||
int index = content.indexOf(WORD_SEPARATOR);
|
||||
if (index == -1) {
|
||||
@ -57,7 +64,13 @@ public class ContentUtils {
|
||||
}
|
||||
return content.substring(index + 1);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Truncate content.
|
||||
*
|
||||
* @param content content
|
||||
* @return truncated content
|
||||
*/
|
||||
public static String truncateContent(String content) {
|
||||
if (content == null) {
|
||||
return "";
|
||||
@ -67,6 +80,6 @@ public class ContentUtils {
|
||||
return content.substring(0, SHOW_CONTENT_SIZE) + "...";
|
||||
}
|
||||
}
|
||||
|
||||
private static int SHOW_CONTENT_SIZE = 100;
|
||||
|
||||
private static final int SHOW_CONTENT_SIZE = 100;
|
||||
}
|
||||
|
@ -13,32 +13,34 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.client.config.utils;
|
||||
|
||||
import com.alibaba.nacos.client.utils.LogUtils;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
/**
|
||||
* Get jvm config
|
||||
* Get jvm config.
|
||||
*
|
||||
* @author Nacos
|
||||
*/
|
||||
@SuppressWarnings("PMD.ClassNamingShouldBeCamelRule")
|
||||
public class JVMUtil {
|
||||
|
||||
public class JvmUtil {
|
||||
|
||||
/**
|
||||
* whether is multi instance
|
||||
* whether is multi instance.
|
||||
*
|
||||
* @return whether multi
|
||||
*/
|
||||
public static Boolean isMultiInstance() {
|
||||
return isMultiInstance;
|
||||
}
|
||||
|
||||
|
||||
private static Boolean isMultiInstance = false;
|
||||
|
||||
private static final String TRUE = "true";
|
||||
private static final Logger LOGGER = LogUtils.logger(JVMUtil.class);
|
||||
|
||||
|
||||
private static final Logger LOGGER = LogUtils.logger(JvmUtil.class);
|
||||
|
||||
static {
|
||||
String multiDeploy = System.getProperty("isMultiInstance", "false");
|
||||
if (TRUE.equals(multiDeploy)) {
|
@ -13,28 +13,29 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.client.config.utils;
|
||||
|
||||
import com.alibaba.nacos.api.exception.NacosException;
|
||||
import com.alibaba.nacos.client.utils.IPUtil;
|
||||
import com.alibaba.nacos.client.utils.IpUtil;
|
||||
import com.alibaba.nacos.common.utils.StringUtils;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Param check util
|
||||
* Param check util.
|
||||
*
|
||||
* @author Nacos
|
||||
*/
|
||||
public class ParamUtils {
|
||||
|
||||
private static char[] validChars = new char[] {'_', '-', '.', ':'};
|
||||
|
||||
|
||||
private static final char[] VALID_CHARS = new char[] {'_', '-', '.', ':'};
|
||||
|
||||
/**
|
||||
* 白名单的方式检查, 合法的参数只能包含字母、数字、以及validChars中的字符, 并且不能为空
|
||||
* 白名单的方式检查, 合法的参数只能包含字母、数字、以及validChars中的字符, 并且不能为空.
|
||||
*
|
||||
* @param param
|
||||
* @return
|
||||
* @param param parameter
|
||||
* @return true if valid
|
||||
*/
|
||||
public static boolean isValid(String param) {
|
||||
if (param == null) {
|
||||
@ -49,26 +50,25 @@ public class ParamUtils {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
private static boolean isValidChar(char ch) {
|
||||
for (char c : validChars) {
|
||||
for (char c : VALID_CHARS) {
|
||||
if (c == ch) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void checkKeyParam(String dataId, String group) throws NacosException {
|
||||
if (StringUtils.isBlank(dataId) || !ParamUtils.isValid(dataId)) {
|
||||
throw new NacosException(NacosException.CLIENT_INVALID_PARAM, "dataId invalid");
|
||||
}
|
||||
if (StringUtils.isBlank(group) || !ParamUtils.isValid(group)) {
|
||||
throw new NacosException(NacosException.CLIENT_INVALID_PARAM, "group invalid");
|
||||
}
|
||||
}
|
||||
|
||||
public static void checkTDG(String tenant, String dataId, String group) throws NacosException {
|
||||
|
||||
/**
|
||||
* Check Tenant, dataId and group.
|
||||
*
|
||||
* @param tenant tenant
|
||||
* @param dataId dataId
|
||||
* @param group group
|
||||
* @throws NacosException nacos exception
|
||||
*/
|
||||
public static void checkTdg(String tenant, String dataId, String group) throws NacosException {
|
||||
checkTenant(tenant);
|
||||
if (StringUtils.isBlank(dataId) || !ParamUtils.isValid(dataId)) {
|
||||
throw new NacosException(NacosException.CLIENT_INVALID_PARAM, "dataId invalid");
|
||||
@ -77,9 +77,32 @@ public class ParamUtils {
|
||||
throw new NacosException(NacosException.CLIENT_INVALID_PARAM, "group invalid");
|
||||
}
|
||||
}
|
||||
|
||||
public static void checkKeyParam(String dataId, String group, String datumId)
|
||||
throws NacosException {
|
||||
|
||||
/**
|
||||
* Check key param.
|
||||
*
|
||||
* @param dataId dataId
|
||||
* @param group group
|
||||
* @throws NacosException nacos exception
|
||||
*/
|
||||
public static void checkKeyParam(String dataId, String group) throws NacosException {
|
||||
if (StringUtils.isBlank(dataId) || !ParamUtils.isValid(dataId)) {
|
||||
throw new NacosException(NacosException.CLIENT_INVALID_PARAM, "dataId invalid");
|
||||
}
|
||||
if (StringUtils.isBlank(group) || !ParamUtils.isValid(group)) {
|
||||
throw new NacosException(NacosException.CLIENT_INVALID_PARAM, "group invalid");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check key param.
|
||||
*
|
||||
* @param dataId dataId
|
||||
* @param group group
|
||||
* @param datumId datumId
|
||||
* @throws NacosException nacos exception
|
||||
*/
|
||||
public static void checkKeyParam(String dataId, String group, String datumId) throws NacosException {
|
||||
if (StringUtils.isBlank(dataId) || !ParamUtils.isValid(dataId)) {
|
||||
throw new NacosException(NacosException.CLIENT_INVALID_PARAM, "dataId invalid");
|
||||
}
|
||||
@ -90,7 +113,14 @@ public class ParamUtils {
|
||||
throw new NacosException(NacosException.CLIENT_INVALID_PARAM, "datumId invalid");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check key param.
|
||||
*
|
||||
* @param dataIds dataIds
|
||||
* @param group group
|
||||
* @throws NacosException nacos exception
|
||||
*/
|
||||
public static void checkKeyParam(List<String> dataIds, String group) throws NacosException {
|
||||
if (dataIds == null || dataIds.size() == 0) {
|
||||
throw new NacosException(NacosException.CLIENT_INVALID_PARAM, "dataIds invalid");
|
||||
@ -104,39 +134,74 @@ public class ParamUtils {
|
||||
throw new NacosException(NacosException.CLIENT_INVALID_PARAM, "group invalid");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check parameter.
|
||||
*
|
||||
* @param dataId dataId
|
||||
* @param group group
|
||||
* @param content content
|
||||
* @throws NacosException nacos exception
|
||||
*/
|
||||
public static void checkParam(String dataId, String group, String content) throws NacosException {
|
||||
checkKeyParam(dataId, group);
|
||||
if (StringUtils.isBlank(content)) {
|
||||
throw new NacosException(NacosException.CLIENT_INVALID_PARAM, "content invalid");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check parameter.
|
||||
*
|
||||
* @param dataId dataId
|
||||
* @param group group
|
||||
* @param datumId datumId
|
||||
* @param content content
|
||||
* @throws NacosException nacos exception
|
||||
*/
|
||||
public static void checkParam(String dataId, String group, String datumId, String content) throws NacosException {
|
||||
checkKeyParam(dataId, group, datumId);
|
||||
if (StringUtils.isBlank(content)) {
|
||||
throw new NacosException(NacosException.CLIENT_INVALID_PARAM, "content invalid");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check Tenant.
|
||||
*
|
||||
* @param tenant tenant
|
||||
* @throws NacosException nacos exception
|
||||
*/
|
||||
public static void checkTenant(String tenant) throws NacosException {
|
||||
if (StringUtils.isBlank(tenant) || !ParamUtils.isValid(tenant)) {
|
||||
throw new NacosException(NacosException.CLIENT_INVALID_PARAM, "tenant invalid");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check beta ips.
|
||||
*
|
||||
* @param betaIps beta ips
|
||||
* @throws NacosException nacos exception
|
||||
*/
|
||||
public static void checkBetaIps(String betaIps) throws NacosException {
|
||||
if (StringUtils.isBlank(betaIps)) {
|
||||
throw new NacosException(NacosException.CLIENT_INVALID_PARAM, "betaIps invalid");
|
||||
}
|
||||
String[] ipsArr = betaIps.split(",");
|
||||
for (String ip : ipsArr) {
|
||||
if (!IPUtil.isIPV4(ip)) {
|
||||
if (!IpUtil.isIpv4(ip)) {
|
||||
throw new NacosException(NacosException.CLIENT_INVALID_PARAM, "betaIps invalid");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check content.
|
||||
*
|
||||
* @param content content
|
||||
* @throws NacosException nacos exception
|
||||
*/
|
||||
public static void checkContent(String content) throws NacosException {
|
||||
if (StringUtils.isBlank(content)) {
|
||||
throw new NacosException(NacosException.CLIENT_INVALID_PARAM, "content invalid");
|
||||
|
@ -13,29 +13,30 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.client.config.utils;
|
||||
|
||||
import com.alibaba.nacos.client.config.impl.LocalConfigInfoProcessor;
|
||||
|
||||
/**
|
||||
* Snapshot switch
|
||||
* Snapshot switch.
|
||||
*
|
||||
* @author Nacos
|
||||
*/
|
||||
public class SnapShotSwitch {
|
||||
|
||||
|
||||
/**
|
||||
* whether use local cache
|
||||
* whether use local cache.
|
||||
*/
|
||||
private static Boolean isSnapShot = true;
|
||||
|
||||
|
||||
public static Boolean getIsSnapShot() {
|
||||
return isSnapShot;
|
||||
}
|
||||
|
||||
|
||||
public static void setIsSnapShot(Boolean isSnapShot) {
|
||||
SnapShotSwitch.isSnapShot = isSnapShot;
|
||||
LocalConfigInfoProcessor.cleanAllSnapshot();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -13,14 +13,17 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.client.identify;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
/**
|
||||
* Provides Base64 encoding and decoding as defined by <a href="http://www.ietf.org/rfc/rfc2045.txt">RFC 2045</a>.
|
||||
* <p>
|
||||
* <p> This class implements section <cite>6.8. Base64 Content-Transfer-Encoding</cite> from RFC 2045 <cite>Multipurpose
|
||||
*
|
||||
* <p>This class implements section <cite>6.8. Base64 Content-Transfer-Encoding</cite> from RFC 2045
|
||||
*
|
||||
* <cite>Multipurpose
|
||||
* Internet Mail Extensions (MIME) Part One: Format of Internet Message Bodies</cite> by Freed and Borenstein. </p> <p>
|
||||
* The class can be parameterized in the following manner with various constructors: <ul> <li>URL-safe mode: Default
|
||||
* off.</li> <li>Line length: Default 76. Line length that aren't multiples of 4 will still essentially end up being
|
||||
@ -35,129 +38,120 @@ import java.io.UnsupportedEncodingException;
|
||||
* @since 1.0
|
||||
*/
|
||||
public class Base64 {
|
||||
|
||||
|
||||
/**
|
||||
* BASE32 characters are 6 bits in length. They are formed by taking a block of 3 octets to form a 24-bit string,
|
||||
* which is converted into 4 BASE64 characters.
|
||||
*/
|
||||
private static final int BITS_PER_ENCODED_BYTE = 6;
|
||||
|
||||
private static final int BYTES_PER_UNENCODED_BLOCK = 3;
|
||||
|
||||
private static final int BYTES_PER_ENCODED_BLOCK = 4;
|
||||
|
||||
|
||||
/**
|
||||
* Chunk separator per RFC 2045 section 2.1.
|
||||
* <p>
|
||||
* <p> N.B. The next major release may break compatibility and make this field private. </p>
|
||||
*
|
||||
* <p>N.B. The next major release may break compatibility and make this field private. </p>
|
||||
*
|
||||
* @see <a href="http://www.ietf.org/rfc/rfc2045.txt">RFC 2045 section 2.1</a>
|
||||
*/
|
||||
static final byte[] CHUNK_SEPARATOR = {'\r', '\n'};
|
||||
|
||||
|
||||
/**
|
||||
* This array is a lookup table that translates 6-bit positive integer index values into their "Base64 Alphabet"
|
||||
* equivalents as specified in Table 1 of RFC 2045.
|
||||
* <p>
|
||||
* Thanks to "commons" project in ws.apache.org for this code. http://svn.apache
|
||||
* .org/repos/asf/webservices/commons/trunk/modules/util/
|
||||
*
|
||||
* <p>Thanks to "commons" project in ws.apache.org for this code.
|
||||
*
|
||||
* <p>http://svn.apache.org/repos/asf/webservices/commons/trunk/modules/util/
|
||||
*/
|
||||
private static final byte[] STANDARD_ENCODE_TABLE = {
|
||||
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
|
||||
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
|
||||
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
|
||||
'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
|
||||
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
|
||||
};
|
||||
|
||||
private static final byte[] STANDARD_ENCODE_TABLE = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L',
|
||||
'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
|
||||
'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1',
|
||||
'2', '3', '4', '5', '6', '7', '8', '9', '+', '/'};
|
||||
|
||||
/**
|
||||
* This is a copy of the STANDARD_ENCODE_TABLE above, but with + and / changed to - and _ to make the encoded Base64
|
||||
* results more URL-SAFE. This table is only used when the Base64's mode is set to URL-SAFE.
|
||||
*/
|
||||
private static final byte[] URL_SAFE_ENCODE_TABLE = {
|
||||
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
|
||||
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
|
||||
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
|
||||
'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
|
||||
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-', '_'
|
||||
};
|
||||
|
||||
private static final byte[] URL_SAFE_ENCODE_TABLE = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L',
|
||||
'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
|
||||
'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1',
|
||||
'2', '3', '4', '5', '6', '7', '8', '9', '-', '_'};
|
||||
|
||||
/**
|
||||
* This array is a lookup table that translates Unicode characters drawn from the "Base64 Alphabet" (as specified in
|
||||
* Table 1 of RFC 2045) into their 6-bit positive integer equivalents. Characters that are not in the Base64
|
||||
* alphabet but fall within the bounds of the array are translated to -1.
|
||||
* <p>
|
||||
* Note: '+' and '-' both decode to 62. '/' and '_' both decode to 63. This means decoder seamlessly handles both
|
||||
* URL_SAFE and STANDARD base64. (The encoder, on the other hand, needs to know ahead of time what to emit).
|
||||
* <p>
|
||||
* Thanks to "commons" project in ws.apache.org for this code. http://svn.apache
|
||||
* .org/repos/asf/webservices/commons/trunk/modules/util/
|
||||
*
|
||||
* <p>Note: '+' and '-' both decode to 62. '/' and '_' both decode to 63. This means decoder seamlessly handles
|
||||
* both URL_SAFE and STANDARD base64. (The encoder, on the other hand, needs to know ahead of time what to emit).
|
||||
*
|
||||
* <p>Thanks to "commons" project in ws.apache.org for this code.
|
||||
*
|
||||
* <p>http://svn.apache.org/repos/asf/webservices/commons/trunk/modules/util/
|
||||
*/
|
||||
private static final byte[] DECODE_TABLE = {
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, 62, -1, 63, 52, 53, 54,
|
||||
55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4,
|
||||
5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
|
||||
24, 25, -1, -1, -1, -1, 63, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34,
|
||||
35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
|
||||
};
|
||||
|
||||
private static final byte[] DECODE_TABLE = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1,
|
||||
62, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8,
|
||||
9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, 63, -1, 26, 27, 28, 29,
|
||||
30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51};
|
||||
|
||||
/**
|
||||
* Base64 uses 6-bit fields.
|
||||
*/
|
||||
/**
|
||||
* Mask used to extract 6 bits, used when encoding
|
||||
* Base64 uses 6-bit fields. Mask used to extract 6 bits, used when encoding
|
||||
*/
|
||||
private static final int MASK_6BITS = 0x3f;
|
||||
|
||||
|
||||
// The static final fields above are used for the original static byte[] methods on Base64.
|
||||
// The private member fields below are used with the new streaming approach, which requires
|
||||
// some state be preserved between calls of encode() and decode().
|
||||
|
||||
|
||||
/**
|
||||
* Encode table to use: either STANDARD or URL_SAFE. Note: the DECODE_TABLE above remains static because it is able
|
||||
* to decode both STANDARD and URL_SAFE streams, but the encodeTable must be a member variable so we can switch
|
||||
* between the two modes.
|
||||
*/
|
||||
private final byte[] encodeTable;
|
||||
|
||||
|
||||
/**
|
||||
* Only one decode table currently; keep for consistency with Base32 code
|
||||
* Only one decode table currently; keep for consistency with Base32 code.
|
||||
*/
|
||||
private final byte[] decodeTable = DECODE_TABLE;
|
||||
|
||||
|
||||
/**
|
||||
* Line separator for encoding. Not used when decoding. Only used if lineLength > 0.
|
||||
*/
|
||||
private final byte[] lineSeparator;
|
||||
|
||||
|
||||
/**
|
||||
* Convenience variable to help us determine when our buffer is going to run out of room and needs resizing.
|
||||
* <code>decodeSize = 3 + lineSeparator.length;</code>
|
||||
*/
|
||||
private final int decodeSize;
|
||||
|
||||
|
||||
/**
|
||||
* Convenience variable to help us determine when our buffer is going to run out of room and needs resizing.
|
||||
* <code>encodeSize = 4 + lineSeparator.length;</code>
|
||||
*/
|
||||
private final int encodeSize;
|
||||
|
||||
|
||||
/**
|
||||
* Place holder for the bytes we're dealing with for our based logic. Bitwise operations store and extract the
|
||||
* encoding or decoding from this variable.
|
||||
*/
|
||||
private int bitWorkArea;
|
||||
|
||||
|
||||
/**
|
||||
* Creates a Base64 codec used for decoding (all modes) and encoding in URL-unsafe mode. <p> When encoding the line
|
||||
* length is 0 (no chunking), and the encoding table is STANDARD_ENCODE_TABLE. </p>
|
||||
* <p>
|
||||
* <p> When decoding all variants are supported. </p>
|
||||
*
|
||||
* <p>When decoding all variants are supported. </p>
|
||||
*/
|
||||
public Base64() {
|
||||
this(0, CHUNK_SEPARATOR, false);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a Base64 codec used for decoding (all modes) and encoding in URL-unsafe mode. <p> When encoding the line
|
||||
* length and line separator are given in the constructor, and the encoding table is STANDARD_ENCODE_TABLE. </p> <p>
|
||||
@ -178,17 +172,14 @@ public class Base64 {
|
||||
chunkSeparatorLength = lineSeparator == null ? 0 : lineSeparator.length;
|
||||
unencodedBlockSize = BYTES_PER_UNENCODED_BLOCK;
|
||||
encodedBlockSize = BYTES_PER_ENCODED_BLOCK;
|
||||
this.lineLength = (lineLength > 0 && chunkSeparatorLength > 0) ? (lineLength / encodedBlockSize)
|
||||
* encodedBlockSize : 0;
|
||||
this.lineLength =
|
||||
(lineLength > 0 && chunkSeparatorLength > 0) ? (lineLength / encodedBlockSize) * encodedBlockSize : 0;
|
||||
// TODO could be simplified if there is no requirement to reject invalid line sep when length <=0
|
||||
// @see test case Base64Test.testConstructors()
|
||||
if (lineSeparator != null) {
|
||||
if (containsAlphabetOrPad(lineSeparator)) {
|
||||
String sep = null;
|
||||
try {
|
||||
sep = new String(lineSeparator, "UTF-8");
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
}
|
||||
sep = new String(lineSeparator, StandardCharsets.UTF_8);
|
||||
throw new IllegalArgumentException("lineSeparator must not contain base64 characters: [" + sep + "]");
|
||||
}
|
||||
if (lineLength > 0) {
|
||||
@ -206,7 +197,25 @@ public class Base64 {
|
||||
this.decodeSize = this.encodeSize - 1;
|
||||
this.encodeTable = urlSafe ? URL_SAFE_ENCODE_TABLE : STANDARD_ENCODE_TABLE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Encodes a byte[] containing binary data, into a byte[] containing characters in the alphabet.
|
||||
*
|
||||
* @param pArray a byte array containing binary data
|
||||
* @return A byte array containing only the basen alphabetic character data
|
||||
*/
|
||||
private byte[] encode(byte[] pArray) {
|
||||
reset();
|
||||
if (pArray == null || pArray.length == 0) {
|
||||
return pArray;
|
||||
}
|
||||
encode(pArray, 0, pArray.length);
|
||||
encode(pArray, 0, -1);
|
||||
byte[] buf = new byte[pos - readPos];
|
||||
readResults(buf, 0, buf.length);
|
||||
return buf;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p> Encodes all of the provided data, starting at inPos, for inAvail bytes. Must be called at least twice: once
|
||||
* with the data to encode, and once with inAvail set to "-1" to alert encoder that EOF has been reached, so flush
|
||||
@ -233,18 +242,18 @@ public class Base64 {
|
||||
case 1:
|
||||
buffer[pos++] = encodeTable[(bitWorkArea >> 2) & MASK_6BITS];
|
||||
buffer[pos++] = encodeTable[(bitWorkArea << 4) & MASK_6BITS];
|
||||
|
||||
|
||||
if (encodeTable == STANDARD_ENCODE_TABLE) {
|
||||
buffer[pos++] = PAD;
|
||||
buffer[pos++] = PAD;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case 2:
|
||||
buffer[pos++] = encodeTable[(bitWorkArea >> 10) & MASK_6BITS];
|
||||
buffer[pos++] = encodeTable[(bitWorkArea >> 4) & MASK_6BITS];
|
||||
buffer[pos++] = encodeTable[(bitWorkArea << 2) & MASK_6BITS];
|
||||
|
||||
|
||||
if (encodeTable == STANDARD_ENCODE_TABLE) {
|
||||
buffer[pos++] = PAD;
|
||||
}
|
||||
@ -253,8 +262,8 @@ public class Base64 {
|
||||
break;
|
||||
}
|
||||
currentLinePos += pos - savedPos;
|
||||
/**
|
||||
* if currentPos == 0 we are at the start of a line, so don't add CRLF
|
||||
/*
|
||||
if currentPos == 0 we are at the start of a line, so don't add CRLF
|
||||
*/
|
||||
if (lineLength > 0 && currentLinePos > 0) {
|
||||
System.arraycopy(lineSeparator, 0, buffer, pos, lineSeparator.length);
|
||||
@ -284,14 +293,32 @@ public class Base64 {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* <p> Decodes all of the provided data, starting at inPos, for inAvail bytes. Should be called at least twice: once
|
||||
* with the data to decode, and once with inAvail set to "-1" to alert decoder that EOF has been reached. The "-1"
|
||||
* call is not necessary when decoding, but it doesn't hurt, either. </p> <p> Ignores all non-base64 characters.
|
||||
* This is how chunked (e.g. 76 character) data is handled, since CR and LF are silently ignored, but has
|
||||
* implications for other bytes, too. This method subscribes to the garbage-in, garbage-out philosophy: it will not
|
||||
* check the provided data for validity. </p> <p> Thanks to "commons" project in ws.apache.org for the bitwise
|
||||
* Decodes a byte[] containing characters in the Base-N alphabet.
|
||||
*
|
||||
* @param pArray A byte array containing Base-N character data
|
||||
* @return a byte array containing binary data
|
||||
*/
|
||||
private byte[] decode(byte[] pArray) {
|
||||
reset();
|
||||
if (pArray == null || pArray.length == 0) {
|
||||
return pArray;
|
||||
}
|
||||
decode(pArray, 0, pArray.length);
|
||||
decode(pArray, 0, -1);
|
||||
byte[] result = new byte[pos];
|
||||
readResults(result, 0, result.length);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p> Decodes all of the provided data, starting at inPos, for inAvail bytes. Should be called at least twice:
|
||||
* once with the data to decode, and once with inAvail set to "-1" to alert decoder that EOF has been reached. The
|
||||
* "-1" call is not necessary when decoding, but it doesn't hurt, either. </p> <p> Ignores all non-base64
|
||||
* characters. This is how chunked (e.g. 76 character) data is handled, since CR and LF are silently ignored, but
|
||||
* has implications for other bytes, too. This method subscribes to the garbage-in, garbage-out philosophy: it will
|
||||
* not check the provided data for validity. </p> <p> Thanks to "commons" project in ws.apache.org for the bitwise
|
||||
* operations, and general approach. http://svn.apache.org/repos/asf/webservices/commons/trunk/modules/util/ </p>
|
||||
*
|
||||
* @param in byte[] array of ascii data to base64 decode.
|
||||
@ -319,21 +346,21 @@ public class Base64 {
|
||||
modulus = (modulus + 1) % BYTES_PER_ENCODED_BLOCK;
|
||||
bitWorkArea = (bitWorkArea << BITS_PER_ENCODED_BYTE) + result;
|
||||
if (modulus == 0) {
|
||||
buffer[pos++] = (byte)((bitWorkArea >> 16) & MASK_8BITS);
|
||||
buffer[pos++] = (byte)((bitWorkArea >> 8) & MASK_8BITS);
|
||||
buffer[pos++] = (byte)(bitWorkArea & MASK_8BITS);
|
||||
buffer[pos++] = (byte) ((bitWorkArea >> 16) & MASK_8BITS);
|
||||
buffer[pos++] = (byte) ((bitWorkArea >> 8) & MASK_8BITS);
|
||||
buffer[pos++] = (byte) (bitWorkArea & MASK_8BITS);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Two forms of EOF as far as base64 decoder is concerned: actual
|
||||
// EOF (-1) and first time '=' character is encountered in stream.
|
||||
// This approach makes the '=' padding characters completely optional.
|
||||
if (eof && modulus != 0) {
|
||||
ensureBufferSize(decodeSize);
|
||||
|
||||
|
||||
// We have some spare bits remaining
|
||||
// Output all whole multiples of 8 bits and ignore the rest
|
||||
switch (modulus) {
|
||||
@ -341,19 +368,19 @@ public class Base64 {
|
||||
// break;
|
||||
case 2:
|
||||
bitWorkArea = bitWorkArea >> 4;
|
||||
buffer[pos++] = (byte)((bitWorkArea) & MASK_8BITS);
|
||||
buffer[pos++] = (byte) ((bitWorkArea) & MASK_8BITS);
|
||||
break;
|
||||
case 3:
|
||||
bitWorkArea = bitWorkArea >> 2;
|
||||
buffer[pos++] = (byte)((bitWorkArea >> 8) & MASK_8BITS);
|
||||
buffer[pos++] = (byte)((bitWorkArea) & MASK_8BITS);
|
||||
buffer[pos++] = (byte) ((bitWorkArea >> 8) & MASK_8BITS);
|
||||
buffer[pos++] = (byte) ((bitWorkArea) & MASK_8BITS);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Encodes binary data using the base64 algorithm but does not chunk the output.
|
||||
*
|
||||
@ -363,7 +390,7 @@ public class Base64 {
|
||||
public static byte[] encodeBase64(byte[] binaryData) {
|
||||
return encodeBase64(binaryData, false, false, Integer.MAX_VALUE);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Encodes binary data using the base64 algorithm, optionally chunking the output into 76 character blocks.
|
||||
*
|
||||
@ -380,24 +407,22 @@ public class Base64 {
|
||||
if (binaryData == null || binaryData.length == 0) {
|
||||
return binaryData;
|
||||
}
|
||||
|
||||
|
||||
// Create this so can use the super-class method
|
||||
// Also ensures that the same roundings are performed by the ctor and the code
|
||||
Base64 b64 = isChunked ? new Base64(MIME_CHUNK_SIZE, CHUNK_SEPARATOR, urlSafe) : new Base64(0, CHUNK_SEPARATOR,
|
||||
urlSafe);
|
||||
Base64 b64 = isChunked ? new Base64(MIME_CHUNK_SIZE, CHUNK_SEPARATOR, urlSafe)
|
||||
: new Base64(0, CHUNK_SEPARATOR, urlSafe);
|
||||
long len = b64.getEncodedLength(binaryData);
|
||||
if (len > maxResultSize) {
|
||||
throw new IllegalArgumentException("Input array too big, the output array would be bigger (" +
|
||||
len +
|
||||
") than the specified maximum size of " +
|
||||
maxResultSize);
|
||||
throw new IllegalArgumentException("Input array too big, the output array would be bigger (" + len
|
||||
+ ") than the specified maximum size of " + maxResultSize);
|
||||
}
|
||||
|
||||
|
||||
return b64.encode(binaryData);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Decodes Base64 data into octets
|
||||
* Decodes Base64 data into octets.
|
||||
*
|
||||
* @param base64Data Byte array containing Base64 data
|
||||
* @return Array containing decoded data.
|
||||
@ -405,7 +430,7 @@ public class Base64 {
|
||||
public static byte[] decodeBase64(byte[] base64Data) {
|
||||
return new Base64().decode(base64Data);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns whether or not the <code>octet</code> is in the Base32 alphabet.
|
||||
*
|
||||
@ -415,97 +440,93 @@ public class Base64 {
|
||||
protected boolean isInAlphabet(byte octet) {
|
||||
return octet >= 0 && octet < decodeTable.length && decodeTable[octet] != -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Below from base class
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* MIME chunk size per RFC 2045 section 6.8.
|
||||
* <p>
|
||||
* <p> The {@value} character limit does not count the trailing CRLF, but counts all other characters, including any
|
||||
* equal signs. </p>
|
||||
*
|
||||
* <p> The {@value} character limit does not count the trailing CRLF, but counts all other characters, including
|
||||
* any equal signs. </p>
|
||||
*
|
||||
* @see <a href="http://www.ietf.org/rfc/rfc2045.txt">RFC 2045 section 6.8</a>
|
||||
*/
|
||||
private static final int MIME_CHUNK_SIZE = 76;
|
||||
|
||||
|
||||
private static final int DEFAULT_BUFFER_RESIZE_FACTOR = 2;
|
||||
|
||||
|
||||
/**
|
||||
* Defines the default buffer size - currently {@value} - must be large enough for at least one encoded
|
||||
* block+separator
|
||||
* block+separator.
|
||||
*/
|
||||
private static final int DEFAULT_BUFFER_SIZE = 8192;
|
||||
|
||||
|
||||
/**
|
||||
* Mask used to extract 8 bits, used in decoding bytes
|
||||
* Mask used to extract 8 bits, used in decoding bytes.
|
||||
*/
|
||||
private static final int MASK_8BITS = 0xff;
|
||||
|
||||
|
||||
/**
|
||||
* Byte used to pad output.
|
||||
*/
|
||||
private static final byte PAD_DEFAULT = '=';
|
||||
|
||||
|
||||
private static final byte PAD = PAD_DEFAULT;
|
||||
|
||||
|
||||
/**
|
||||
* Number of bytes in each full block of unencoded data, e.g. 4 for Base64 and 5 for Base32
|
||||
*/
|
||||
private final int unencodedBlockSize;
|
||||
|
||||
|
||||
/**
|
||||
* Number of bytes in each full block of encoded data, e.g. 3 for Base64 and 8 for Base32
|
||||
*/
|
||||
private final int encodedBlockSize;
|
||||
|
||||
|
||||
/**
|
||||
* Chunksize for encoding. Not used when decoding. A value of zero or less implies no chunking of the encoded data.
|
||||
* Rounded down to nearest multiple of encodedBlockSize.
|
||||
*/
|
||||
private final int lineLength;
|
||||
|
||||
|
||||
/**
|
||||
* Size of chunk separator. Not used unless {@link #lineLength} > 0.
|
||||
*/
|
||||
private final int chunkSeparatorLength;
|
||||
|
||||
|
||||
/**
|
||||
* Buffer for streaming.
|
||||
*/
|
||||
private byte[] buffer;
|
||||
|
||||
|
||||
/**
|
||||
* Position where next character should be written in the buffer.
|
||||
*/
|
||||
private int pos;
|
||||
|
||||
|
||||
/**
|
||||
* Position where next character should be read from the buffer.
|
||||
*/
|
||||
private int readPos;
|
||||
|
||||
|
||||
/**
|
||||
* Boolean flag to indicate the EOF has been reached. Once EOF has been reached, this object becomes useless, and
|
||||
* must be thrown away.
|
||||
*/
|
||||
private boolean eof;
|
||||
|
||||
|
||||
/**
|
||||
* Variable tracks how many characters have been written to the current line. Only used when encoding. We use it to
|
||||
* make sure each encoded line never goes beyond lineLength (if lineLength > 0).
|
||||
*/
|
||||
private int currentLinePos;
|
||||
|
||||
|
||||
/**
|
||||
* Writes to the buffer only occur after every 3/5 reads when encoding, and every 4/8 reads when decoding. This
|
||||
* variable helps track that.
|
||||
*/
|
||||
private int modulus;
|
||||
|
||||
|
||||
/**
|
||||
* Ensure that the buffer has room for <code>size</code> bytes
|
||||
* Ensure that the buffer has room for <code>size</code> bytes.
|
||||
*
|
||||
* @param size minimum spare space required
|
||||
*/
|
||||
@ -522,7 +543,7 @@ public class Base64 {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Extracts buffered data into the provided byte[] array, starting at position bPos, up to a maximum of bAvail
|
||||
* bytes. Returns how many bytes were actually extracted.
|
||||
@ -544,7 +565,7 @@ public class Base64 {
|
||||
}
|
||||
return eof ? -1 : 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Resets this object to its initial newly constructed state.
|
||||
*/
|
||||
@ -556,47 +577,11 @@ public class Base64 {
|
||||
modulus = 0;
|
||||
eof = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes a byte[] containing characters in the Base-N alphabet.
|
||||
*
|
||||
* @param pArray A byte array containing Base-N character data
|
||||
* @return a byte array containing binary data
|
||||
*/
|
||||
private byte[] decode(byte[] pArray) {
|
||||
reset();
|
||||
if (pArray == null || pArray.length == 0) {
|
||||
return pArray;
|
||||
}
|
||||
decode(pArray, 0, pArray.length);
|
||||
decode(pArray, 0, -1);
|
||||
byte[] result = new byte[pos];
|
||||
readResults(result, 0, result.length);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes a byte[] containing binary data, into a byte[] containing characters in the alphabet.
|
||||
*
|
||||
* @param pArray a byte array containing binary data
|
||||
* @return A byte array containing only the basen alphabetic character data
|
||||
*/
|
||||
private byte[] encode(byte[] pArray) {
|
||||
reset();
|
||||
if (pArray == null || pArray.length == 0) {
|
||||
return pArray;
|
||||
}
|
||||
encode(pArray, 0, pArray.length);
|
||||
encode(pArray, 0, -1);
|
||||
byte[] buf = new byte[pos - readPos];
|
||||
readResults(buf, 0, buf.length);
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Tests a given byte array to see if it contains any characters within the alphabet or PAD.
|
||||
* <p>
|
||||
* Intended for use in checking line-ending arrays
|
||||
*
|
||||
* <p>Intended for use in checking line-ending arrays
|
||||
*
|
||||
* @param arrayOctet byte array to test
|
||||
* @return <code>true</code> if any byte is a valid character in the alphabet or PAD; <code>false</code> otherwise
|
||||
@ -612,7 +597,7 @@ public class Base64 {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Calculates the amount of space needed to encode the supplied array.
|
||||
*
|
||||
@ -623,10 +608,10 @@ public class Base64 {
|
||||
private long getEncodedLength(byte[] pArray) {
|
||||
// Calculate non-chunked size - rounded up to allow for padding
|
||||
// cast to long is needed to avoid possibility of overflow
|
||||
long len = ((pArray.length + unencodedBlockSize - 1) / unencodedBlockSize) * (long)encodedBlockSize;
|
||||
long len = ((pArray.length + unencodedBlockSize - 1) / unencodedBlockSize) * (long) encodedBlockSize;
|
||||
if (lineLength > 0) {
|
||||
/**
|
||||
* Round up to nearest multiple
|
||||
/*
|
||||
Round up to nearest multiple
|
||||
*/
|
||||
len += ((len + lineLength - 1) / lineLength) * chunkSeparatorLength;
|
||||
}
|
||||
|
@ -13,16 +13,18 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.client.identify;
|
||||
|
||||
/**
|
||||
* Credential Listener
|
||||
* Credential Listener.
|
||||
*
|
||||
* @author Nacos
|
||||
*/
|
||||
public interface CredentialListener {
|
||||
|
||||
/**
|
||||
* update Credential
|
||||
* update Credential.
|
||||
*/
|
||||
void onUpdateCredential();
|
||||
}
|
||||
|
@ -13,6 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.client.identify;
|
||||
|
||||
import com.alibaba.nacos.client.utils.LogUtils;
|
||||
@ -22,21 +23,24 @@ import org.slf4j.Logger;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* Credential Service
|
||||
* Credential Service.
|
||||
*
|
||||
* @author Nacos
|
||||
*/
|
||||
public final class CredentialService implements SpasCredentialLoader {
|
||||
|
||||
private static final Logger LOGGER = LogUtils.logger(CredentialService.class);
|
||||
|
||||
private static ConcurrentHashMap<String, CredentialService> instances
|
||||
= new ConcurrentHashMap<String, CredentialService>();
|
||||
|
||||
private String appName;
|
||||
|
||||
private static final ConcurrentHashMap<String, CredentialService> INSTANCES = new ConcurrentHashMap<String, CredentialService>();
|
||||
|
||||
private final String appName;
|
||||
|
||||
private Credentials credentials = new Credentials();
|
||||
private CredentialWatcher watcher;
|
||||
|
||||
private final CredentialWatcher watcher;
|
||||
|
||||
private CredentialListener listener;
|
||||
|
||||
|
||||
private CredentialService(String appName) {
|
||||
if (appName == null) {
|
||||
String value = System.getProperty("project.name");
|
||||
@ -47,44 +51,53 @@ public final class CredentialService implements SpasCredentialLoader {
|
||||
this.appName = appName;
|
||||
watcher = new CredentialWatcher(appName, this);
|
||||
}
|
||||
|
||||
|
||||
public static CredentialService getInstance() {
|
||||
return getInstance(null);
|
||||
}
|
||||
|
||||
|
||||
public static CredentialService getInstance(String appName) {
|
||||
String key = appName != null ? appName : IdentifyConstants.NO_APP_NAME;
|
||||
CredentialService instance = instances.get(key);
|
||||
CredentialService instance = INSTANCES.get(key);
|
||||
if (instance == null) {
|
||||
instance = new CredentialService(appName);
|
||||
CredentialService previous = instances.putIfAbsent(key, instance);
|
||||
CredentialService previous = INSTANCES.putIfAbsent(key, instance);
|
||||
if (previous != null) {
|
||||
instance = previous;
|
||||
}
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
|
||||
public static CredentialService freeInstance() {
|
||||
return freeInstance(null);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Free instance.
|
||||
*
|
||||
* @param appName app name
|
||||
* @return {@link CredentialService}
|
||||
*/
|
||||
public static CredentialService freeInstance(String appName) {
|
||||
String key = appName != null ? appName : IdentifyConstants.NO_APP_NAME;
|
||||
CredentialService instance = instances.remove(key);
|
||||
CredentialService instance = INSTANCES.remove(key);
|
||||
if (instance != null) {
|
||||
instance.free();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Free service.
|
||||
*/
|
||||
public void free() {
|
||||
if (watcher != null) {
|
||||
watcher.stop();
|
||||
}
|
||||
LOGGER.info("[{}] {} is freed", appName, this.getClass().getSimpleName());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Credentials getCredential() {
|
||||
Credentials localCredential = credentials;
|
||||
@ -93,7 +106,7 @@ public final class CredentialService implements SpasCredentialLoader {
|
||||
}
|
||||
return credentials;
|
||||
}
|
||||
|
||||
|
||||
public void setCredential(Credentials credential) {
|
||||
boolean changed = !(credentials == credential || (credentials != null && credentials.identical(credential)));
|
||||
credentials = credential;
|
||||
@ -101,36 +114,36 @@ public final class CredentialService implements SpasCredentialLoader {
|
||||
listener.onUpdateCredential();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void setStaticCredential(Credentials credential) {
|
||||
if (watcher != null) {
|
||||
watcher.stop();
|
||||
}
|
||||
setCredential(credential);
|
||||
}
|
||||
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -13,46 +13,58 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.client.identify;
|
||||
|
||||
import com.alibaba.nacos.client.utils.LogUtils;
|
||||
import com.alibaba.nacos.common.utils.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import java.io.*;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
import java.util.Properties;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
|
||||
/**
|
||||
* Credential Watcher
|
||||
* Credential Watcher.
|
||||
*
|
||||
* @author Nacos
|
||||
*/
|
||||
public class CredentialWatcher {
|
||||
private static final Logger SpasLogger = LogUtils.logger(CredentialWatcher.class);
|
||||
|
||||
private static final Logger SPAS_LOGGER = LogUtils.logger(CredentialWatcher.class);
|
||||
|
||||
private static final long REFRESH_INTERVAL = 10 * 1000;
|
||||
|
||||
private CredentialService serviceInstance;
|
||||
private String appName;
|
||||
|
||||
private final CredentialService serviceInstance;
|
||||
|
||||
private final String appName;
|
||||
|
||||
private String propertyPath;
|
||||
private TimerTask watcher;
|
||||
|
||||
private final TimerTask watcher;
|
||||
|
||||
private boolean stopped;
|
||||
|
||||
|
||||
@SuppressWarnings("PMD.AvoidUseTimerRule")
|
||||
public CredentialWatcher(String appName, CredentialService serviceInstance) {
|
||||
this.appName = appName;
|
||||
this.serviceInstance = serviceInstance;
|
||||
loadCredential(true);
|
||||
watcher = new TimerTask() {
|
||||
private Timer timer = new Timer(true);
|
||||
private final Timer timer = new Timer(true);
|
||||
|
||||
private long modified = 0;
|
||||
|
||||
|
||||
{
|
||||
timer.schedule(this, REFRESH_INTERVAL, REFRESH_INTERVAL);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
synchronized (this) {
|
||||
@ -77,7 +89,10 @@ public class CredentialWatcher {
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Stop watcher.
|
||||
*/
|
||||
public void stop() {
|
||||
if (stopped) {
|
||||
return;
|
||||
@ -88,9 +103,9 @@ public class CredentialWatcher {
|
||||
stopped = true;
|
||||
}
|
||||
}
|
||||
SpasLogger.info("[{}] {} is stopped", appName, this.getClass().getSimpleName());
|
||||
SPAS_LOGGER.info("[{}] {} is stopped", appName, this.getClass().getSimpleName());
|
||||
}
|
||||
|
||||
|
||||
private void loadCredential(boolean init) {
|
||||
boolean logWarn = init;
|
||||
if (propertyPath == null) {
|
||||
@ -99,34 +114,35 @@ public class CredentialWatcher {
|
||||
propertyPath = url.getPath();
|
||||
}
|
||||
if (propertyPath == null || propertyPath.isEmpty()) {
|
||||
|
||||
|
||||
String value = System.getProperty("spas.identity");
|
||||
if (StringUtils.isNotEmpty(value)) {
|
||||
propertyPath = value;
|
||||
}
|
||||
if (propertyPath == null || propertyPath.isEmpty()) {
|
||||
propertyPath = IdentifyConstants.CREDENTIAL_PATH + (appName == null ? IdentifyConstants.CREDENTIAL_DEFAULT
|
||||
: appName);
|
||||
propertyPath =
|
||||
IdentifyConstants.CREDENTIAL_PATH + (appName == null ? IdentifyConstants.CREDENTIAL_DEFAULT
|
||||
: appName);
|
||||
} else {
|
||||
if (logWarn) {
|
||||
SpasLogger.info("[{}] Defined credential file: -Dspas.identity={}", appName, propertyPath);
|
||||
SPAS_LOGGER.info("[{}] Defined credential file: -Dspas.identity={}", appName, propertyPath);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (logWarn) {
|
||||
SpasLogger.info("[{}] Load credential file from classpath: {}", appName,
|
||||
IdentifyConstants.PROPERTIES_FILENAME);
|
||||
SPAS_LOGGER.info("[{}] Load credential file from classpath: {}", appName,
|
||||
IdentifyConstants.PROPERTIES_FILENAME);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
InputStream propertiesIS = null;
|
||||
do {
|
||||
try {
|
||||
propertiesIS = new FileInputStream(propertyPath);
|
||||
} catch (FileNotFoundException e) {
|
||||
if (appName != null && !appName.equals(IdentifyConstants.CREDENTIAL_DEFAULT) && propertyPath.equals(
|
||||
IdentifyConstants.CREDENTIAL_PATH + appName)) {
|
||||
if (appName != null && !appName.equals(IdentifyConstants.CREDENTIAL_DEFAULT) && propertyPath
|
||||
.equals(IdentifyConstants.CREDENTIAL_PATH + appName)) {
|
||||
propertyPath = IdentifyConstants.CREDENTIAL_PATH + IdentifyConstants.CREDENTIAL_DEFAULT;
|
||||
continue;
|
||||
}
|
||||
@ -137,7 +153,7 @@ public class CredentialWatcher {
|
||||
}
|
||||
break;
|
||||
} while (true);
|
||||
|
||||
|
||||
String accessKey = null;
|
||||
String secretKey = null;
|
||||
String tenantId = null;
|
||||
@ -147,7 +163,7 @@ public class CredentialWatcher {
|
||||
secretKey = System.getenv(IdentifyConstants.ENV_SECRET_KEY);
|
||||
if (accessKey == null && secretKey == null) {
|
||||
if (logWarn) {
|
||||
SpasLogger.info("{} No credential found", appName);
|
||||
SPAS_LOGGER.info("{} No credential found", appName);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@ -156,23 +172,23 @@ public class CredentialWatcher {
|
||||
try {
|
||||
properties.load(propertiesIS);
|
||||
} catch (IOException e) {
|
||||
SpasLogger.error("[26] Unable to load credential file, appName:" + appName
|
||||
+ "Unable to load credential file " + propertyPath, e);
|
||||
SPAS_LOGGER.error("[26] Unable to load credential file, appName:" + appName
|
||||
+ "Unable to load credential file " + propertyPath, e);
|
||||
propertyPath = null;
|
||||
return;
|
||||
} finally {
|
||||
try {
|
||||
propertiesIS.close();
|
||||
} catch (IOException e) {
|
||||
SpasLogger.error("[27] Unable to close credential file, appName:" + appName
|
||||
+ "Unable to close credential file " + propertyPath, e);
|
||||
SPAS_LOGGER.error("[27] Unable to close credential file, appName:" + appName
|
||||
+ "Unable to close credential file " + propertyPath, e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (logWarn) {
|
||||
SpasLogger.info("[{}] Load credential file {}", appName, propertyPath);
|
||||
SPAS_LOGGER.info("[{}] Load credential file {}", appName, propertyPath);
|
||||
}
|
||||
|
||||
|
||||
if (!IdentifyConstants.DOCKER_CREDENTIAL_PATH.equals(propertyPath)) {
|
||||
if (properties.containsKey(IdentifyConstants.ACCESS_KEY)) {
|
||||
accessKey = properties.getProperty(IdentifyConstants.ACCESS_KEY);
|
||||
@ -190,32 +206,33 @@ public class CredentialWatcher {
|
||||
if (properties.containsKey(IdentifyConstants.DOCKER_SECRET_KEY)) {
|
||||
secretKey = properties.getProperty(IdentifyConstants.DOCKER_SECRET_KEY);
|
||||
}
|
||||
|
||||
|
||||
if (properties.containsKey(IdentifyConstants.DOCKER_TENANT_ID)) {
|
||||
tenantId = properties.getProperty(IdentifyConstants.DOCKER_TENANT_ID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (accessKey != null) {
|
||||
accessKey = accessKey.trim();
|
||||
}
|
||||
if (secretKey != null) {
|
||||
secretKey = secretKey.trim();
|
||||
}
|
||||
|
||||
|
||||
if (tenantId != null) {
|
||||
tenantId = tenantId.trim();
|
||||
}
|
||||
|
||||
|
||||
Credentials credential = new Credentials(accessKey, secretKey, tenantId);
|
||||
if (!credential.valid()) {
|
||||
SpasLogger.warn("[1] Credential file missing required property {} Credential file missing {} or {}",
|
||||
appName, IdentifyConstants.ACCESS_KEY, IdentifyConstants.SECRET_KEY);
|
||||
SPAS_LOGGER
|
||||
.warn("[1] Credential file missing required property {} Credential file missing {} or {}", appName,
|
||||
IdentifyConstants.ACCESS_KEY, IdentifyConstants.SECRET_KEY);
|
||||
propertyPath = null;
|
||||
// return;
|
||||
}
|
||||
|
||||
|
||||
serviceInstance.setCredential(credential);
|
||||
}
|
||||
}
|
||||
|
@ -13,67 +13,72 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.client.identify;
|
||||
|
||||
/**
|
||||
* Credentials
|
||||
* Credentials.
|
||||
*
|
||||
* @author Nacos
|
||||
*/
|
||||
public class Credentials implements SpasCredential {
|
||||
|
||||
|
||||
private volatile String accessKey;
|
||||
|
||||
|
||||
private volatile String secretKey;
|
||||
|
||||
|
||||
private volatile String tenantId;
|
||||
|
||||
|
||||
public Credentials(String accessKey, String secretKey, String tenantId) {
|
||||
this.accessKey = accessKey;
|
||||
this.secretKey = secretKey;
|
||||
this.tenantId = tenantId;
|
||||
}
|
||||
|
||||
|
||||
public Credentials() {
|
||||
this(null, null, null);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getAccessKey() {
|
||||
return accessKey;
|
||||
}
|
||||
|
||||
|
||||
public void setAccessKey(String accessKey) {
|
||||
this.accessKey = accessKey;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getSecretKey() {
|
||||
return secretKey;
|
||||
}
|
||||
|
||||
|
||||
public void setSecretKey(String secretKey) {
|
||||
this.secretKey = secretKey;
|
||||
}
|
||||
|
||||
|
||||
public String getTenantId() {
|
||||
return tenantId;
|
||||
}
|
||||
|
||||
|
||||
public void setTenantId(String tenantId) {
|
||||
this.tenantId = tenantId;
|
||||
}
|
||||
|
||||
|
||||
public boolean valid() {
|
||||
return accessKey != null && !accessKey.isEmpty() && secretKey != null
|
||||
&& !secretKey.isEmpty();
|
||||
return accessKey != null && !accessKey.isEmpty() && secretKey != null && !secretKey.isEmpty();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Identical.
|
||||
*
|
||||
* @param other other
|
||||
* @return true if identical
|
||||
*/
|
||||
public boolean identical(Credentials other) {
|
||||
return this == other || (other != null
|
||||
&& (accessKey == null && other.accessKey == null
|
||||
|| accessKey != null && accessKey.equals(other.accessKey))
|
||||
&& (secretKey == null && other.secretKey == null
|
||||
|| secretKey != null && secretKey.equals(other.secretKey)));
|
||||
return this == other || (other != null && (accessKey == null && other.accessKey == null
|
||||
|| accessKey != null && accessKey.equals(other.accessKey)) && (
|
||||
secretKey == null && other.secretKey == null || secretKey != null && secretKey
|
||||
.equals(other.secretKey)));
|
||||
}
|
||||
}
|
||||
|
@ -13,40 +13,42 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.client.identify;
|
||||
|
||||
/**
|
||||
* Identify Constants
|
||||
* Identify Constants.
|
||||
*
|
||||
* @author Nacos
|
||||
*/
|
||||
public class IdentifyConstants {
|
||||
|
||||
public static final String ACCESS_KEY = "accessKey";
|
||||
|
||||
|
||||
public static final String SECRET_KEY = "secretKey";
|
||||
|
||||
|
||||
public static final String TENANT_ID = "tenantId";
|
||||
|
||||
|
||||
public static final String PROPERTIES_FILENAME = "spas.properties";
|
||||
|
||||
|
||||
public static final String CREDENTIAL_PATH = "/home/admin/.spas_key/";
|
||||
|
||||
|
||||
public static final String CREDENTIAL_DEFAULT = "default";
|
||||
|
||||
|
||||
public static final String DOCKER_CREDENTIAL_PATH = "/etc/instanceInfo";
|
||||
|
||||
|
||||
public static final String DOCKER_ACCESS_KEY = "env_spas_accessKey";
|
||||
|
||||
|
||||
public static final String DOCKER_SECRET_KEY = "env_spas_secretKey";
|
||||
|
||||
|
||||
public static final String DOCKER_TENANT_ID = "ebv_spas_tenantId";
|
||||
|
||||
|
||||
public static final String ENV_ACCESS_KEY = "spas_accessKey";
|
||||
|
||||
|
||||
public static final String ENV_SECRET_KEY = "spas_secretKey";
|
||||
|
||||
|
||||
public static final String ENV_TENANT_ID = "tenant.id";
|
||||
|
||||
|
||||
public static final String NO_APP_NAME = "";
|
||||
|
||||
|
||||
}
|
||||
|
@ -13,23 +13,25 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.client.identify;
|
||||
|
||||
/**
|
||||
* Spas Credential Interface
|
||||
* Spas Credential Interface.
|
||||
*
|
||||
* @author Nacos
|
||||
*/
|
||||
public interface SpasCredential {
|
||||
|
||||
/**
|
||||
* get AccessKey
|
||||
* get AccessKey.
|
||||
*
|
||||
* @return AccessKey
|
||||
*/
|
||||
String getAccessKey();
|
||||
|
||||
|
||||
/**
|
||||
* get SecretKey
|
||||
* get SecretKey.
|
||||
*
|
||||
* @return SecretKey
|
||||
*/
|
||||
|
@ -13,16 +13,18 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.client.identify;
|
||||
|
||||
/**
|
||||
* Spas Credential Loader
|
||||
* Spas Credential Loader.
|
||||
*
|
||||
* @author Nacos
|
||||
*/
|
||||
public interface SpasCredentialLoader {
|
||||
|
||||
/**
|
||||
* get Credential
|
||||
* get Credential.
|
||||
*
|
||||
* @return Credential
|
||||
*/
|
||||
|
@ -13,116 +13,121 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.alibaba.nacos.client.identify;
|
||||
|
||||
package com.alibaba.nacos.client.identify;
|
||||
|
||||
import com.alibaba.nacos.common.utils.StringUtils;
|
||||
|
||||
/**
|
||||
* Sts config
|
||||
* Sts config.
|
||||
*
|
||||
* @author Nacos
|
||||
*/
|
||||
@SuppressWarnings("PMD.ClassNamingShouldBeCamelRule")
|
||||
public class STSConfig {
|
||||
private static final String RAM_SECURITY_CREDENTIALS_URL
|
||||
= "http://100.100.100.200/latest/meta-data/ram/security-credentials/";
|
||||
public class StsConfig {
|
||||
|
||||
private static final String RAM_SECURITY_CREDENTIALS_URL = "http://100.100.100.200/latest/meta-data/ram/security-credentials/";
|
||||
|
||||
private String ramRoleName;
|
||||
|
||||
/**
|
||||
* STS 临时凭证有效期剩余多少时开始刷新(允许本地时间比 STS 服务时间最多慢多久)
|
||||
* STS 临时凭证有效期剩余多少时开始刷新(允许本地时间比 STS 服务时间最多慢多久).
|
||||
*/
|
||||
private int timeToRefreshInMillisecond = 3 * 60 * 1000;
|
||||
|
||||
/**
|
||||
* 获取 STS 临时凭证的元数据接口(包含角色名称)
|
||||
* 获取 STS 临时凭证的元数据接口(包含角色名称).
|
||||
*/
|
||||
private String securityCredentialsUrl;
|
||||
|
||||
/**
|
||||
* 设定 STS 临时凭证,不再通过元数据接口获取
|
||||
* 设定 STS 临时凭证,不再通过元数据接口获取.
|
||||
*/
|
||||
private String securityCredentials;
|
||||
|
||||
/**
|
||||
* 是否缓存
|
||||
* 是否缓存.
|
||||
*/
|
||||
private boolean cacheSecurityCredentials = true;
|
||||
|
||||
|
||||
private static class Singleton {
|
||||
private static final STSConfig INSTANCE = new STSConfig();
|
||||
|
||||
private static final StsConfig INSTANCE = new StsConfig();
|
||||
}
|
||||
|
||||
private STSConfig() {
|
||||
|
||||
private StsConfig() {
|
||||
String ramRoleName = System.getProperty("ram.role.name");
|
||||
if (!StringUtils.isBlank(ramRoleName)) {
|
||||
setRamRoleName(ramRoleName);
|
||||
}
|
||||
|
||||
|
||||
String timeToRefreshInMillisecond = System.getProperty("time.to.refresh.in.millisecond");
|
||||
if (!StringUtils.isBlank(timeToRefreshInMillisecond)) {
|
||||
setTimeToRefreshInMillisecond(Integer.parseInt(timeToRefreshInMillisecond));
|
||||
}
|
||||
|
||||
|
||||
String securityCredentials = System.getProperty("security.credentials");
|
||||
if (!StringUtils.isBlank(securityCredentials)) {
|
||||
setSecurityCredentials(securityCredentials);
|
||||
}
|
||||
|
||||
|
||||
String securityCredentialsUrl = System.getProperty("security.credentials.url");
|
||||
if (!StringUtils.isBlank(securityCredentialsUrl)) {
|
||||
setSecurityCredentialsUrl(securityCredentialsUrl);
|
||||
}
|
||||
|
||||
|
||||
String cacheSecurityCredentials = System.getProperty("cache.security.credentials");
|
||||
if (!StringUtils.isBlank(cacheSecurityCredentials)) {
|
||||
setCacheSecurityCredentials(Boolean.parseBoolean(cacheSecurityCredentials));
|
||||
}
|
||||
}
|
||||
|
||||
public static STSConfig getInstance() {
|
||||
|
||||
public static StsConfig getInstance() {
|
||||
return Singleton.INSTANCE;
|
||||
}
|
||||
|
||||
|
||||
public String getRamRoleName() {
|
||||
return ramRoleName;
|
||||
}
|
||||
|
||||
|
||||
public void setRamRoleName(String ramRoleName) {
|
||||
this.ramRoleName = ramRoleName;
|
||||
}
|
||||
|
||||
|
||||
public int getTimeToRefreshInMillisecond() {
|
||||
return timeToRefreshInMillisecond;
|
||||
}
|
||||
|
||||
|
||||
public void setTimeToRefreshInMillisecond(int timeToRefreshInMillisecond) {
|
||||
this.timeToRefreshInMillisecond = timeToRefreshInMillisecond;
|
||||
}
|
||||
|
||||
|
||||
public String getSecurityCredentialsUrl() {
|
||||
if (securityCredentialsUrl == null && ramRoleName != null) {
|
||||
return RAM_SECURITY_CREDENTIALS_URL + ramRoleName;
|
||||
}
|
||||
return securityCredentialsUrl;
|
||||
}
|
||||
|
||||
|
||||
public void setSecurityCredentialsUrl(String securityCredentialsUrl) {
|
||||
this.securityCredentialsUrl = securityCredentialsUrl;
|
||||
}
|
||||
|
||||
|
||||
public String getSecurityCredentials() {
|
||||
return securityCredentials;
|
||||
}
|
||||
|
||||
|
||||
public void setSecurityCredentials(String securityCredentials) {
|
||||
this.securityCredentials = securityCredentials;
|
||||
}
|
||||
|
||||
public boolean isSTSOn() {
|
||||
|
||||
public boolean isStsOn() {
|
||||
return StringUtils.isNotEmpty(getSecurityCredentials()) || StringUtils.isNotEmpty(getSecurityCredentialsUrl());
|
||||
}
|
||||
|
||||
|
||||
public boolean isCacheSecurityCredentials() {
|
||||
return cacheSecurityCredentials;
|
||||
}
|
||||
|
||||
|
||||
public void setCacheSecurityCredentials(boolean cacheSecurityCredentials) {
|
||||
this.cacheSecurityCredentials = cacheSecurityCredentials;
|
||||
}
|
@ -13,24 +13,26 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.alibaba.nacos.client.logging;
|
||||
|
||||
package com.alibaba.nacos.client.logging;
|
||||
|
||||
import com.alibaba.nacos.common.utils.ConvertUtils;
|
||||
import com.alibaba.nacos.common.utils.StringUtils;
|
||||
|
||||
/**
|
||||
* Abstract nacos logging.
|
||||
*
|
||||
* @author <a href="mailto:huangxiaoyu1018@gmail.com">hxy1991</a>
|
||||
* @since 0.9.0
|
||||
*/
|
||||
public abstract class AbstractNacosLogging {
|
||||
|
||||
|
||||
private static final String NACOS_LOGGING_CONFIG_PROPERTY = "nacos.logging.config";
|
||||
|
||||
|
||||
private static final String NACOS_LOGGING_DEFAULT_CONFIG_ENABLED_PROPERTY = "nacos.logging.default.config.enabled";
|
||||
|
||||
|
||||
private static final String NACOS_LOGGING_PATH_PROPERTY = "nacos.logging.path";
|
||||
|
||||
|
||||
static {
|
||||
String loggingPath = System.getProperty(NACOS_LOGGING_PATH_PROPERTY);
|
||||
if (StringUtils.isBlank(loggingPath)) {
|
||||
@ -38,7 +40,7 @@ public abstract class AbstractNacosLogging {
|
||||
System.setProperty(NACOS_LOGGING_PATH_PROPERTY, userHome + "/logs/nacos");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected String getLocation(String defaultLocation) {
|
||||
String location = System.getProperty(NACOS_LOGGING_CONFIG_PROPERTY);
|
||||
if (StringUtils.isBlank(location)) {
|
||||
@ -49,15 +51,15 @@ public abstract class AbstractNacosLogging {
|
||||
}
|
||||
return location;
|
||||
}
|
||||
|
||||
|
||||
private boolean isDefaultConfigEnabled() {
|
||||
String property = System.getProperty(NACOS_LOGGING_DEFAULT_CONFIG_ENABLED_PROPERTY);
|
||||
// The default value is true.
|
||||
return property == null || ConvertUtils.toBoolean(property);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Load logging configuration
|
||||
* Load logging configuration.
|
||||
*/
|
||||
public abstract void loadConfiguration();
|
||||
}
|
||||
|
@ -13,6 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.client.logging.log4j2;
|
||||
|
||||
import com.alibaba.nacos.client.logging.AbstractNacosLogging;
|
||||
@ -37,27 +38,27 @@ import java.util.Map;
|
||||
* @since 0.9.0
|
||||
*/
|
||||
public class Log4J2NacosLogging extends AbstractNacosLogging {
|
||||
|
||||
|
||||
private static final String NACOS_LOG4J2_LOCATION = "classpath:nacos-log4j2.xml";
|
||||
|
||||
|
||||
private static final String FILE_PROTOCOL = "file";
|
||||
|
||||
|
||||
private static final String NACOS_LOGGER_PREFIX = "com.alibaba.nacos";
|
||||
|
||||
private String location = getLocation(NACOS_LOG4J2_LOCATION);
|
||||
|
||||
|
||||
private final String location = getLocation(NACOS_LOG4J2_LOCATION);
|
||||
|
||||
@Override
|
||||
public void loadConfiguration() {
|
||||
final LoggerContext loggerContext = (LoggerContext)LogManager.getContext(false);
|
||||
final LoggerContext loggerContext = (LoggerContext) LogManager.getContext(false);
|
||||
final Configuration contextConfiguration = loggerContext.getConfiguration();
|
||||
|
||||
|
||||
// load and start nacos configuration
|
||||
Configuration configuration = loadConfiguration(loggerContext, location);
|
||||
configuration.start();
|
||||
|
||||
|
||||
// append loggers and appenders to contextConfiguration
|
||||
Map<String, Appender> appenders = configuration.getAppenders();
|
||||
for (Appender appender: appenders.values()) {
|
||||
for (Appender appender : appenders.values()) {
|
||||
contextConfiguration.addAppender(appender);
|
||||
}
|
||||
Map<String, LoggerConfig> loggers = configuration.getLoggers();
|
||||
@ -66,10 +67,10 @@ public class Log4J2NacosLogging extends AbstractNacosLogging {
|
||||
contextConfiguration.addLogger(name, loggers.get(name));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
loggerContext.updateLoggers();
|
||||
}
|
||||
|
||||
|
||||
private Configuration loadConfiguration(LoggerContext loggerContext, String location) {
|
||||
try {
|
||||
URL url = ResourceUtils.getResourceUrl(location);
|
||||
@ -77,11 +78,10 @@ public class Log4J2NacosLogging extends AbstractNacosLogging {
|
||||
// since log4j 2.7 getConfiguration(LoggerContext loggerContext, ConfigurationSource source)
|
||||
return ConfigurationFactory.getInstance().getConfiguration(loggerContext, source);
|
||||
} catch (Exception e) {
|
||||
throw new IllegalStateException(
|
||||
"Could not initialize Log4J2 logging from " + location, e);
|
||||
throw new IllegalStateException("Could not initialize Log4J2 logging from " + location, e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private ConfigurationSource getConfigurationSource(URL url) throws IOException {
|
||||
InputStream stream = url.openStream();
|
||||
if (FILE_PROTOCOL.equals(url.getProtocol())) {
|
||||
|
@ -13,6 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.client.logging.logback;
|
||||
|
||||
import ch.qos.logback.classic.LoggerContext;
|
||||
@ -29,22 +30,22 @@ import org.slf4j.impl.StaticLoggerBinder;
|
||||
* @since 0.9.0
|
||||
*/
|
||||
public class LogbackNacosLogging extends AbstractNacosLogging {
|
||||
|
||||
|
||||
private static final String NACOS_LOGBACK_LOCATION = "classpath:nacos-logback.xml";
|
||||
|
||||
|
||||
@Override
|
||||
public void loadConfiguration() {
|
||||
String location = getLocation(NACOS_LOGBACK_LOCATION);
|
||||
if (StringUtils.isBlank(location)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
LoggerContext loggerContext = (LoggerContext)StaticLoggerBinder.getSingleton().getLoggerFactory();
|
||||
LoggerContext loggerContext = (LoggerContext) StaticLoggerBinder.getSingleton().getLoggerFactory();
|
||||
new ContextInitializer(loggerContext).configureByResource(ResourceUtils.getResourceUrl(location));
|
||||
} catch (Exception e) {
|
||||
throw new IllegalStateException("Could not initialize Logback Nacos logging from " + location, e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -13,44 +13,44 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.client.monitor;
|
||||
|
||||
import io.prometheus.client.Gauge;
|
||||
import io.prometheus.client.Histogram;
|
||||
|
||||
/**
|
||||
* Metrics Monitor
|
||||
* Metrics Monitor.
|
||||
*
|
||||
* @author Nacos
|
||||
*/
|
||||
public class MetricsMonitor {
|
||||
private static Gauge nacosMonitor = Gauge.build()
|
||||
.name("nacos_monitor").labelNames("module", "name")
|
||||
.help("nacos_monitor").register();
|
||||
|
||||
private static Histogram nacosClientRequestHistogram = Histogram.build().labelNames("module", "method", "url", "code")
|
||||
.name("nacos_client_request").help("nacos_client_request")
|
||||
.register();
|
||||
|
||||
|
||||
|
||||
private static final Gauge NACOS_MONITOR = Gauge.build().name("nacos_monitor").labelNames("module", "name")
|
||||
.help("nacos_monitor").register();
|
||||
|
||||
private static final Histogram NACOS_CLIENT_REQUEST_HISTOGRAM = Histogram.build()
|
||||
.labelNames("module", "method", "url", "code").name("nacos_client_request").help("nacos_client_request")
|
||||
.register();
|
||||
|
||||
public static Gauge.Child getServiceInfoMapSizeMonitor() {
|
||||
return nacosMonitor.labels("naming", "serviceInfoMapSize");
|
||||
return NACOS_MONITOR.labels("naming", "serviceInfoMapSize");
|
||||
}
|
||||
|
||||
|
||||
public static Gauge.Child getDom2BeatSizeMonitor() {
|
||||
return nacosMonitor.labels("naming", "dom2BeatSize");
|
||||
return NACOS_MONITOR.labels("naming", "dom2BeatSize");
|
||||
}
|
||||
|
||||
|
||||
public static Gauge.Child getListenConfigCountMonitor() {
|
||||
return nacosMonitor.labels("naming", "listenConfigCount");
|
||||
return NACOS_MONITOR.labels("naming", "listenConfigCount");
|
||||
}
|
||||
|
||||
|
||||
public static Histogram.Timer getConfigRequestMonitor(String method, String url, String code) {
|
||||
return nacosClientRequestHistogram.labels("config", method, url, code).startTimer();
|
||||
return NACOS_CLIENT_REQUEST_HISTOGRAM.labels("config", method, url, code).startTimer();
|
||||
}
|
||||
|
||||
|
||||
public static Histogram.Child getNamingRequestMonitor(String method, String url, String code) {
|
||||
return nacosClientRequestHistogram.labels("naming", method, url, code);
|
||||
return NACOS_CLIENT_REQUEST_HISTOGRAM.labels("naming", method, url, code);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -34,31 +34,33 @@ import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* Nacos naming maintain service.
|
||||
*
|
||||
* @author liaochuntao
|
||||
* @since 1.0.1
|
||||
*/
|
||||
@SuppressWarnings("PMD.ServiceOrDaoClassShouldEndWithImplRule")
|
||||
public class NacosNamingMaintainService implements NamingMaintainService {
|
||||
|
||||
|
||||
private String namespace;
|
||||
|
||||
|
||||
private String endpoint;
|
||||
|
||||
|
||||
private String serverList;
|
||||
|
||||
|
||||
private NamingProxy serverProxy;
|
||||
|
||||
public NacosNamingMaintainService(String serverList) throws NacosException {
|
||||
|
||||
public NacosNamingMaintainService(String serverList) throws NacosException {
|
||||
Properties properties = new Properties();
|
||||
properties.setProperty(PropertyKeyConst.SERVER_ADDR, serverList);
|
||||
init(properties);
|
||||
}
|
||||
|
||||
public NacosNamingMaintainService(Properties properties) throws NacosException {
|
||||
|
||||
public NacosNamingMaintainService(Properties properties) throws NacosException {
|
||||
init(properties);
|
||||
}
|
||||
|
||||
private void init(Properties properties) throws NacosException {
|
||||
|
||||
private void init(Properties properties) throws NacosException {
|
||||
ValidatorUtils.checkInitParam(properties);
|
||||
namespace = InitUtils.initNamespaceForNaming(properties);
|
||||
InitUtils.initSerialization();
|
||||
@ -66,7 +68,7 @@ public class NacosNamingMaintainService implements NamingMaintainService {
|
||||
InitUtils.initWebRootContext();
|
||||
serverProxy = new NamingProxy(namespace, endpoint, serverList, properties);
|
||||
}
|
||||
|
||||
|
||||
private void initServerAddr(Properties properties) {
|
||||
serverList = properties.getProperty(PropertyKeyConst.SERVER_ADDR);
|
||||
endpoint = InitUtils.initEndpoint(properties);
|
||||
@ -74,100 +76,101 @@ public class NacosNamingMaintainService implements NamingMaintainService {
|
||||
serverList = "";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void updateInstance(String serviceName, Instance instance) throws NacosException {
|
||||
updateInstance(serviceName, Constants.DEFAULT_GROUP, instance);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void updateInstance(String serviceName, String groupName, Instance instance) throws NacosException {
|
||||
serverProxy.updateInstance(serviceName, groupName, instance);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Service queryService(String serviceName) throws NacosException {
|
||||
return queryService(serviceName, Constants.DEFAULT_GROUP);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Service queryService(String serviceName, String groupName) throws NacosException {
|
||||
return serverProxy.queryService(serviceName, groupName);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void createService(String serviceName) throws NacosException {
|
||||
createService(serviceName, Constants.DEFAULT_GROUP);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void createService(String serviceName, String groupName) throws NacosException {
|
||||
createService(serviceName, groupName, Constants.DEFAULT_PROTECT_THRESHOLD);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void createService(String serviceName, String groupName, float protectThreshold) throws NacosException {
|
||||
NoneSelector selector = new NoneSelector();
|
||||
Service service = new Service();
|
||||
service.setName(serviceName);
|
||||
service.setGroupName(groupName);
|
||||
service.setProtectThreshold(protectThreshold);
|
||||
|
||||
createService(service, selector);
|
||||
|
||||
createService(service, new NoneSelector());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void createService(String serviceName, String groupName, float protectThreshold, String expression) throws NacosException {
|
||||
public void createService(String serviceName, String groupName, float protectThreshold, String expression)
|
||||
throws NacosException {
|
||||
Service service = new Service();
|
||||
service.setName(serviceName);
|
||||
service.setGroupName(groupName);
|
||||
service.setProtectThreshold(protectThreshold);
|
||||
|
||||
|
||||
ExpressionSelector selector = new ExpressionSelector();
|
||||
selector.setExpression(expression);
|
||||
|
||||
|
||||
createService(service, selector);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void createService(Service service, AbstractSelector selector) throws NacosException {
|
||||
serverProxy.createService(service, selector);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean deleteService(String serviceName) throws NacosException {
|
||||
return deleteService(serviceName, Constants.DEFAULT_GROUP);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean deleteService(String serviceName, String groupName) throws NacosException {
|
||||
return serverProxy.deleteService(serviceName, groupName);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void updateService(String serviceName, String groupName, float protectThreshold) throws NacosException {
|
||||
Service service = new Service();
|
||||
service.setName(serviceName);
|
||||
service.setGroupName(groupName);
|
||||
service.setProtectThreshold(protectThreshold);
|
||||
|
||||
|
||||
updateService(service, new NoneSelector());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void updateService(String serviceName, String groupName, float protectThreshold, Map<String, String> metadata) throws NacosException {
|
||||
public void updateService(String serviceName, String groupName, float protectThreshold,
|
||||
Map<String, String> metadata) throws NacosException {
|
||||
Service service = new Service();
|
||||
service.setName(serviceName);
|
||||
service.setGroupName(groupName);
|
||||
service.setProtectThreshold(protectThreshold);
|
||||
service.setMetadata(metadata);
|
||||
|
||||
|
||||
updateService(service, new NoneSelector());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void updateService(Service service, AbstractSelector selector) throws NacosException {
|
||||
serverProxy.updateService(service, selector);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -13,6 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.client.naming;
|
||||
|
||||
import com.alibaba.nacos.api.PropertyKeyConst;
|
||||
@ -44,45 +45,45 @@ import java.util.List;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* Nacos Naming Service
|
||||
* Nacos Naming Service.
|
||||
*
|
||||
* @author nkorange
|
||||
*/
|
||||
@SuppressWarnings("PMD.ServiceOrDaoClassShouldEndWithImplRule")
|
||||
public class NacosNamingService implements NamingService {
|
||||
|
||||
|
||||
/**
|
||||
* Each Naming service should have different namespace.
|
||||
*/
|
||||
private String namespace;
|
||||
|
||||
|
||||
private String endpoint;
|
||||
|
||||
|
||||
private String serverList;
|
||||
|
||||
|
||||
private String cacheDir;
|
||||
|
||||
|
||||
private String logName;
|
||||
|
||||
|
||||
private HostReactor hostReactor;
|
||||
|
||||
|
||||
private BeatReactor beatReactor;
|
||||
|
||||
|
||||
private EventDispatcher eventDispatcher;
|
||||
|
||||
|
||||
private NamingProxy serverProxy;
|
||||
|
||||
|
||||
public NacosNamingService(String serverList) throws NacosException {
|
||||
Properties properties = new Properties();
|
||||
properties.setProperty(PropertyKeyConst.SERVER_ADDR, serverList);
|
||||
init(properties);
|
||||
}
|
||||
|
||||
public NacosNamingService(Properties properties) throws NacosException {
|
||||
|
||||
public NacosNamingService(Properties properties) throws NacosException {
|
||||
init(properties);
|
||||
}
|
||||
|
||||
private void init(Properties properties) throws NacosException {
|
||||
|
||||
private void init(Properties properties) throws NacosException {
|
||||
ValidatorUtils.checkInitParam(properties);
|
||||
this.namespace = InitUtils.initNamespaceForNaming(properties);
|
||||
InitUtils.initSerialization();
|
||||
@ -90,43 +91,44 @@ public class NacosNamingService implements NamingService {
|
||||
InitUtils.initWebRootContext();
|
||||
initCacheDir();
|
||||
initLogName(properties);
|
||||
|
||||
|
||||
this.eventDispatcher = new EventDispatcher();
|
||||
this.serverProxy = new NamingProxy(this.namespace, this.endpoint, this.serverList, properties);
|
||||
this.beatReactor = new BeatReactor(this.serverProxy, initClientBeatThreadCount(properties));
|
||||
this.hostReactor = new HostReactor(this.eventDispatcher, this.serverProxy, beatReactor, this.cacheDir,
|
||||
isLoadCacheAtStart(properties), initPollingThreadCount(properties));
|
||||
isLoadCacheAtStart(properties), initPollingThreadCount(properties));
|
||||
}
|
||||
|
||||
|
||||
private int initClientBeatThreadCount(Properties properties) {
|
||||
if (properties == null) {
|
||||
return UtilAndComs.DEFAULT_CLIENT_BEAT_THREAD_COUNT;
|
||||
}
|
||||
|
||||
|
||||
return ConvertUtils.toInt(properties.getProperty(PropertyKeyConst.NAMING_CLIENT_BEAT_THREAD_COUNT),
|
||||
UtilAndComs.DEFAULT_CLIENT_BEAT_THREAD_COUNT);
|
||||
UtilAndComs.DEFAULT_CLIENT_BEAT_THREAD_COUNT);
|
||||
}
|
||||
|
||||
|
||||
private int initPollingThreadCount(Properties properties) {
|
||||
if (properties == null) {
|
||||
|
||||
|
||||
return UtilAndComs.DEFAULT_POLLING_THREAD_COUNT;
|
||||
}
|
||||
|
||||
|
||||
return ConvertUtils.toInt(properties.getProperty(PropertyKeyConst.NAMING_POLLING_THREAD_COUNT),
|
||||
UtilAndComs.DEFAULT_POLLING_THREAD_COUNT);
|
||||
UtilAndComs.DEFAULT_POLLING_THREAD_COUNT);
|
||||
}
|
||||
|
||||
|
||||
private boolean isLoadCacheAtStart(Properties properties) {
|
||||
boolean loadCacheAtStart = false;
|
||||
if (properties != null && StringUtils.isNotEmpty(properties.getProperty(PropertyKeyConst.NAMING_LOAD_CACHE_AT_START))) {
|
||||
loadCacheAtStart = ConvertUtils.toBoolean(
|
||||
properties.getProperty(PropertyKeyConst.NAMING_LOAD_CACHE_AT_START));
|
||||
if (properties != null && StringUtils
|
||||
.isNotEmpty(properties.getProperty(PropertyKeyConst.NAMING_LOAD_CACHE_AT_START))) {
|
||||
loadCacheAtStart = ConvertUtils
|
||||
.toBoolean(properties.getProperty(PropertyKeyConst.NAMING_LOAD_CACHE_AT_START));
|
||||
}
|
||||
|
||||
|
||||
return loadCacheAtStart;
|
||||
}
|
||||
|
||||
|
||||
private void initServerAddr(Properties properties) {
|
||||
serverList = properties.getProperty(PropertyKeyConst.SERVER_ADDR);
|
||||
endpoint = InitUtils.initEndpoint(properties);
|
||||
@ -134,149 +136,160 @@ public class NacosNamingService implements NamingService {
|
||||
serverList = "";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void initLogName(Properties properties) {
|
||||
logName = System.getProperty(UtilAndComs.NACOS_NAMING_LOG_NAME);
|
||||
if (StringUtils.isEmpty(logName)) {
|
||||
|
||||
if (properties != null && StringUtils.isNotEmpty(properties.getProperty(UtilAndComs.NACOS_NAMING_LOG_NAME))) {
|
||||
|
||||
if (properties != null && StringUtils
|
||||
.isNotEmpty(properties.getProperty(UtilAndComs.NACOS_NAMING_LOG_NAME))) {
|
||||
logName = properties.getProperty(UtilAndComs.NACOS_NAMING_LOG_NAME);
|
||||
} else {
|
||||
logName = "naming.log";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void initCacheDir() {
|
||||
cacheDir = System.getProperty("com.alibaba.nacos.naming.cache.dir");
|
||||
if (StringUtils.isEmpty(cacheDir)) {
|
||||
cacheDir = System.getProperty("user.home") + "/nacos/naming/" + namespace;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void registerInstance(String serviceName, String ip, int port) throws NacosException {
|
||||
registerInstance(serviceName, ip, port, Constants.DEFAULT_CLUSTER_NAME);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void registerInstance(String serviceName, String groupName, String ip, int port) throws NacosException {
|
||||
registerInstance(serviceName, groupName, ip, port, Constants.DEFAULT_CLUSTER_NAME);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void registerInstance(String serviceName, String ip, int port, String clusterName) throws NacosException {
|
||||
registerInstance(serviceName, Constants.DEFAULT_GROUP, ip, port, clusterName);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void registerInstance(String serviceName, String groupName, String ip, int port, String clusterName) throws NacosException {
|
||||
|
||||
public void registerInstance(String serviceName, String groupName, String ip, int port, String clusterName)
|
||||
throws NacosException {
|
||||
|
||||
Instance instance = new Instance();
|
||||
instance.setIp(ip);
|
||||
instance.setPort(port);
|
||||
instance.setWeight(1.0);
|
||||
instance.setClusterName(clusterName);
|
||||
|
||||
|
||||
registerInstance(serviceName, groupName, instance);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void registerInstance(String serviceName, Instance instance) throws NacosException {
|
||||
registerInstance(serviceName, Constants.DEFAULT_GROUP, instance);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void registerInstance(String serviceName, String groupName, Instance instance) throws NacosException {
|
||||
String groupedServiceName = NamingUtils.getGroupedName(serviceName, groupName);
|
||||
if (instance.isEphemeral()) {
|
||||
BeatInfo beatInfo = beatReactor.buildBeatInfo(instance);
|
||||
beatReactor.addBeatInfo(NamingUtils.getGroupedName(serviceName, groupName), beatInfo);
|
||||
BeatInfo beatInfo = beatReactor.buildBeatInfo(groupedServiceName, instance);
|
||||
beatReactor.addBeatInfo(groupedServiceName, beatInfo);
|
||||
}
|
||||
serverProxy.registerService(NamingUtils.getGroupedName(serviceName, groupName), groupName, instance);
|
||||
serverProxy.registerService(groupedServiceName, groupName, instance);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void deregisterInstance(String serviceName, String ip, int port) throws NacosException {
|
||||
deregisterInstance(serviceName, ip, port, Constants.DEFAULT_CLUSTER_NAME);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void deregisterInstance(String serviceName, String groupName, String ip, int port) throws NacosException {
|
||||
deregisterInstance(serviceName, groupName, ip, port, Constants.DEFAULT_CLUSTER_NAME);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void deregisterInstance(String serviceName, String ip, int port, String clusterName) throws NacosException {
|
||||
deregisterInstance(serviceName, Constants.DEFAULT_GROUP, ip, port, clusterName);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void deregisterInstance(String serviceName, String groupName, String ip, int port, String clusterName) throws NacosException {
|
||||
public void deregisterInstance(String serviceName, String groupName, String ip, int port, String clusterName)
|
||||
throws NacosException {
|
||||
Instance instance = new Instance();
|
||||
instance.setIp(ip);
|
||||
instance.setPort(port);
|
||||
instance.setClusterName(clusterName);
|
||||
|
||||
|
||||
deregisterInstance(serviceName, groupName, instance);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void deregisterInstance(String serviceName, Instance instance) throws NacosException {
|
||||
deregisterInstance(serviceName, Constants.DEFAULT_GROUP, instance);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void deregisterInstance(String serviceName, String groupName, Instance instance) throws NacosException {
|
||||
if (instance.isEphemeral()) {
|
||||
beatReactor.removeBeatInfo(NamingUtils.getGroupedName(serviceName, groupName), instance.getIp(), instance.getPort());
|
||||
beatReactor.removeBeatInfo(NamingUtils.getGroupedName(serviceName, groupName), instance.getIp(),
|
||||
instance.getPort());
|
||||
}
|
||||
serverProxy.deregisterService(NamingUtils.getGroupedName(serviceName, groupName), instance);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public List<Instance> getAllInstances(String serviceName) throws NacosException {
|
||||
return getAllInstances(serviceName, new ArrayList<String>());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public List<Instance> getAllInstances(String serviceName, String groupName) throws NacosException {
|
||||
return getAllInstances(serviceName, groupName, new ArrayList<String>());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public List<Instance> getAllInstances(String serviceName, boolean subscribe) throws NacosException {
|
||||
return getAllInstances(serviceName, new ArrayList<String>(), subscribe);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public List<Instance> getAllInstances(String serviceName, String groupName, boolean subscribe) throws NacosException {
|
||||
public List<Instance> getAllInstances(String serviceName, String groupName, boolean subscribe)
|
||||
throws NacosException {
|
||||
return getAllInstances(serviceName, groupName, new ArrayList<String>(), subscribe);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public List<Instance> getAllInstances(String serviceName, List<String> clusters) throws NacosException {
|
||||
return getAllInstances(serviceName, clusters, true);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public List<Instance> getAllInstances(String serviceName, String groupName, List<String> clusters) throws NacosException {
|
||||
public List<Instance> getAllInstances(String serviceName, String groupName, List<String> clusters)
|
||||
throws NacosException {
|
||||
return getAllInstances(serviceName, groupName, clusters, true);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public List<Instance> getAllInstances(String serviceName, List<String> clusters, boolean subscribe)
|
||||
throws NacosException {
|
||||
throws NacosException {
|
||||
return getAllInstances(serviceName, Constants.DEFAULT_GROUP, clusters, subscribe);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public List<Instance> getAllInstances(String serviceName, String groupName, List<String> clusters, boolean subscribe) throws NacosException {
|
||||
|
||||
public List<Instance> getAllInstances(String serviceName, String groupName, List<String> clusters,
|
||||
boolean subscribe) throws NacosException {
|
||||
|
||||
ServiceInfo serviceInfo;
|
||||
if (subscribe) {
|
||||
serviceInfo = hostReactor.getServiceInfo(NamingUtils.getGroupedName(serviceName, groupName), StringUtils.join(clusters, ","));
|
||||
serviceInfo = hostReactor.getServiceInfo(NamingUtils.getGroupedName(serviceName, groupName),
|
||||
StringUtils.join(clusters, ","));
|
||||
} else {
|
||||
serviceInfo = hostReactor.getServiceInfoDirectlyFromServer(NamingUtils.getGroupedName(serviceName, groupName), StringUtils.join(clusters, ","));
|
||||
serviceInfo = hostReactor
|
||||
.getServiceInfoDirectlyFromServer(NamingUtils.getGroupedName(serviceName, groupName),
|
||||
StringUtils.join(clusters, ","));
|
||||
}
|
||||
List<Instance> list;
|
||||
if (serviceInfo == null || CollectionUtils.isEmpty(list = serviceInfo.getHosts())) {
|
||||
@ -284,183 +297,69 @@ public class NacosNamingService implements NamingService {
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public List<Instance> selectInstances(String serviceName, boolean healthy) throws NacosException {
|
||||
return selectInstances(serviceName, new ArrayList<String>(), healthy);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public List<Instance> selectInstances(String serviceName, String groupName, boolean healthy) throws NacosException {
|
||||
return selectInstances(serviceName, groupName, healthy, true);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public List<Instance> selectInstances(String serviceName, boolean healthy, boolean subscribe)
|
||||
throws NacosException {
|
||||
throws NacosException {
|
||||
return selectInstances(serviceName, new ArrayList<String>(), healthy, subscribe);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public List<Instance> selectInstances(String serviceName, String groupName, boolean healthy, boolean subscribe) throws NacosException {
|
||||
public List<Instance> selectInstances(String serviceName, String groupName, boolean healthy, boolean subscribe)
|
||||
throws NacosException {
|
||||
return selectInstances(serviceName, groupName, new ArrayList<String>(), healthy, subscribe);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public List<Instance> selectInstances(String serviceName, List<String> clusters, boolean healthy)
|
||||
throws NacosException {
|
||||
throws NacosException {
|
||||
return selectInstances(serviceName, clusters, healthy, true);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public List<Instance> selectInstances(String serviceName, String groupName, List<String> clusters, boolean healthy) throws NacosException {
|
||||
public List<Instance> selectInstances(String serviceName, String groupName, List<String> clusters, boolean healthy)
|
||||
throws NacosException {
|
||||
return selectInstances(serviceName, groupName, clusters, healthy, true);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public List<Instance> selectInstances(String serviceName, List<String> clusters, boolean healthy,
|
||||
boolean subscribe) throws NacosException {
|
||||
public List<Instance> selectInstances(String serviceName, List<String> clusters, boolean healthy, boolean subscribe)
|
||||
throws NacosException {
|
||||
return selectInstances(serviceName, Constants.DEFAULT_GROUP, clusters, healthy, subscribe);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public List<Instance> selectInstances(String serviceName, String groupName, List<String> clusters, boolean healthy, boolean subscribe) throws NacosException {
|
||||
|
||||
public List<Instance> selectInstances(String serviceName, String groupName, List<String> clusters, boolean healthy,
|
||||
boolean subscribe) throws NacosException {
|
||||
|
||||
ServiceInfo serviceInfo;
|
||||
if (subscribe) {
|
||||
serviceInfo = hostReactor.getServiceInfo(NamingUtils.getGroupedName(serviceName, groupName), StringUtils.join(clusters, ","));
|
||||
serviceInfo = hostReactor.getServiceInfo(NamingUtils.getGroupedName(serviceName, groupName),
|
||||
StringUtils.join(clusters, ","));
|
||||
} else {
|
||||
serviceInfo = hostReactor.getServiceInfoDirectlyFromServer(NamingUtils.getGroupedName(serviceName, groupName), StringUtils.join(clusters, ","));
|
||||
serviceInfo = hostReactor
|
||||
.getServiceInfoDirectlyFromServer(NamingUtils.getGroupedName(serviceName, groupName),
|
||||
StringUtils.join(clusters, ","));
|
||||
}
|
||||
return selectInstances(serviceInfo, healthy);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Instance selectOneHealthyInstance(String serviceName) throws NacosException {
|
||||
return selectOneHealthyInstance(serviceName, new ArrayList<String>());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Instance selectOneHealthyInstance(String serviceName, String groupName) throws NacosException {
|
||||
return selectOneHealthyInstance(serviceName, groupName, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Instance selectOneHealthyInstance(String serviceName, boolean subscribe) throws NacosException {
|
||||
return selectOneHealthyInstance(serviceName, new ArrayList<String>(), subscribe);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Instance selectOneHealthyInstance(String serviceName, String groupName, boolean subscribe) throws NacosException {
|
||||
return selectOneHealthyInstance(serviceName, groupName, new ArrayList<String>(), subscribe);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Instance selectOneHealthyInstance(String serviceName, List<String> clusters) throws NacosException {
|
||||
return selectOneHealthyInstance(serviceName, clusters, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Instance selectOneHealthyInstance(String serviceName, String groupName, List<String> clusters) throws NacosException {
|
||||
return selectOneHealthyInstance(serviceName, groupName, clusters, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Instance selectOneHealthyInstance(String serviceName, List<String> clusters, boolean subscribe)
|
||||
throws NacosException {
|
||||
return selectOneHealthyInstance(serviceName, Constants.DEFAULT_GROUP, clusters, subscribe);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Instance selectOneHealthyInstance(String serviceName, String groupName, List<String> clusters, boolean subscribe) throws NacosException {
|
||||
|
||||
if (subscribe) {
|
||||
return Balancer.RandomByWeight.selectHost(
|
||||
hostReactor.getServiceInfo(NamingUtils.getGroupedName(serviceName, groupName), StringUtils.join(clusters, ",")));
|
||||
} else {
|
||||
return Balancer.RandomByWeight.selectHost(
|
||||
hostReactor.getServiceInfoDirectlyFromServer(NamingUtils.getGroupedName(serviceName, groupName), StringUtils.join(clusters, ",")));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void subscribe(String serviceName, EventListener listener) throws NacosException {
|
||||
subscribe(serviceName, new ArrayList<String>(), listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void subscribe(String serviceName, String groupName, EventListener listener) throws NacosException {
|
||||
subscribe(serviceName, groupName, new ArrayList<String>(), listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void subscribe(String serviceName, List<String> clusters, EventListener listener) throws NacosException {
|
||||
subscribe(serviceName, Constants.DEFAULT_GROUP, clusters, listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void subscribe(String serviceName, String groupName, List<String> clusters, EventListener listener) throws NacosException {
|
||||
eventDispatcher.addListener(hostReactor.getServiceInfo(NamingUtils.getGroupedName(serviceName, groupName),
|
||||
StringUtils.join(clusters, ",")), StringUtils.join(clusters, ","), listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unsubscribe(String serviceName, EventListener listener) throws NacosException {
|
||||
unsubscribe(serviceName, new ArrayList<String>(), listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unsubscribe(String serviceName, String groupName, EventListener listener) throws NacosException {
|
||||
unsubscribe(serviceName, groupName, new ArrayList<String>(), listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unsubscribe(String serviceName, List<String> clusters, EventListener listener) throws NacosException {
|
||||
unsubscribe(serviceName, Constants.DEFAULT_GROUP, clusters, listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unsubscribe(String serviceName, String groupName, List<String> clusters, EventListener listener) throws NacosException {
|
||||
eventDispatcher.removeListener(NamingUtils.getGroupedName(serviceName, groupName), StringUtils.join(clusters, ","), listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListView<String> getServicesOfServer(int pageNo, int pageSize) throws NacosException {
|
||||
return serverProxy.getServiceList(pageNo, pageSize, Constants.DEFAULT_GROUP);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListView<String> getServicesOfServer(int pageNo, int pageSize, String groupName) throws NacosException {
|
||||
return getServicesOfServer(pageNo, pageSize, groupName, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListView<String> getServicesOfServer(int pageNo, int pageSize, AbstractSelector selector)
|
||||
throws NacosException {
|
||||
return getServicesOfServer(pageNo, pageSize, Constants.DEFAULT_GROUP, selector);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListView<String> getServicesOfServer(int pageNo, int pageSize, String groupName, AbstractSelector selector) throws NacosException {
|
||||
return serverProxy.getServiceList(pageNo, pageSize, groupName, selector);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ServiceInfo> getSubscribeServices() {
|
||||
return eventDispatcher.getSubscribeServices();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getServerStatus() {
|
||||
return serverProxy.serverHealthy() ? "UP" : "DOWN";
|
||||
}
|
||||
|
||||
|
||||
private List<Instance> selectInstances(ServiceInfo serviceInfo, boolean healthy) {
|
||||
List<Instance> list;
|
||||
if (serviceInfo == null || CollectionUtils.isEmpty(list = serviceInfo.getHosts())) {
|
||||
return new ArrayList<Instance>();
|
||||
}
|
||||
|
||||
|
||||
Iterator<Instance> iterator = list.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
Instance instance = iterator.next();
|
||||
@ -468,14 +367,145 @@ public class NacosNamingService implements NamingService {
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Instance selectOneHealthyInstance(String serviceName) throws NacosException {
|
||||
return selectOneHealthyInstance(serviceName, new ArrayList<String>());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Instance selectOneHealthyInstance(String serviceName, String groupName) throws NacosException {
|
||||
return selectOneHealthyInstance(serviceName, groupName, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Instance selectOneHealthyInstance(String serviceName, boolean subscribe) throws NacosException {
|
||||
return selectOneHealthyInstance(serviceName, new ArrayList<String>(), subscribe);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Instance selectOneHealthyInstance(String serviceName, String groupName, boolean subscribe)
|
||||
throws NacosException {
|
||||
return selectOneHealthyInstance(serviceName, groupName, new ArrayList<String>(), subscribe);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Instance selectOneHealthyInstance(String serviceName, List<String> clusters) throws NacosException {
|
||||
return selectOneHealthyInstance(serviceName, clusters, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Instance selectOneHealthyInstance(String serviceName, String groupName, List<String> clusters)
|
||||
throws NacosException {
|
||||
return selectOneHealthyInstance(serviceName, groupName, clusters, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Instance selectOneHealthyInstance(String serviceName, List<String> clusters, boolean subscribe)
|
||||
throws NacosException {
|
||||
return selectOneHealthyInstance(serviceName, Constants.DEFAULT_GROUP, clusters, subscribe);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Instance selectOneHealthyInstance(String serviceName, String groupName, List<String> clusters,
|
||||
boolean subscribe) throws NacosException {
|
||||
|
||||
if (subscribe) {
|
||||
return Balancer.RandomByWeight.selectHost(hostReactor
|
||||
.getServiceInfo(NamingUtils.getGroupedName(serviceName, groupName),
|
||||
StringUtils.join(clusters, ",")));
|
||||
} else {
|
||||
return Balancer.RandomByWeight.selectHost(hostReactor
|
||||
.getServiceInfoDirectlyFromServer(NamingUtils.getGroupedName(serviceName, groupName),
|
||||
StringUtils.join(clusters, ",")));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void subscribe(String serviceName, EventListener listener) throws NacosException {
|
||||
subscribe(serviceName, new ArrayList<String>(), listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void subscribe(String serviceName, String groupName, EventListener listener) throws NacosException {
|
||||
subscribe(serviceName, groupName, new ArrayList<String>(), listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void subscribe(String serviceName, List<String> clusters, EventListener listener) throws NacosException {
|
||||
subscribe(serviceName, Constants.DEFAULT_GROUP, clusters, listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void subscribe(String serviceName, String groupName, List<String> clusters, EventListener listener)
|
||||
throws NacosException {
|
||||
eventDispatcher.addListener(hostReactor
|
||||
.getServiceInfo(NamingUtils.getGroupedName(serviceName, groupName), StringUtils.join(clusters, ",")),
|
||||
StringUtils.join(clusters, ","), listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unsubscribe(String serviceName, EventListener listener) throws NacosException {
|
||||
unsubscribe(serviceName, new ArrayList<String>(), listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unsubscribe(String serviceName, String groupName, EventListener listener) throws NacosException {
|
||||
unsubscribe(serviceName, groupName, new ArrayList<String>(), listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unsubscribe(String serviceName, List<String> clusters, EventListener listener) throws NacosException {
|
||||
unsubscribe(serviceName, Constants.DEFAULT_GROUP, clusters, listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unsubscribe(String serviceName, String groupName, List<String> clusters, EventListener listener)
|
||||
throws NacosException {
|
||||
eventDispatcher
|
||||
.removeListener(NamingUtils.getGroupedName(serviceName, groupName), StringUtils.join(clusters, ","),
|
||||
listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListView<String> getServicesOfServer(int pageNo, int pageSize) throws NacosException {
|
||||
return serverProxy.getServiceList(pageNo, pageSize, Constants.DEFAULT_GROUP);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListView<String> getServicesOfServer(int pageNo, int pageSize, String groupName) throws NacosException {
|
||||
return getServicesOfServer(pageNo, pageSize, groupName, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListView<String> getServicesOfServer(int pageNo, int pageSize, AbstractSelector selector)
|
||||
throws NacosException {
|
||||
return getServicesOfServer(pageNo, pageSize, Constants.DEFAULT_GROUP, selector);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListView<String> getServicesOfServer(int pageNo, int pageSize, String groupName, AbstractSelector selector)
|
||||
throws NacosException {
|
||||
return serverProxy.getServiceList(pageNo, pageSize, groupName, selector);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ServiceInfo> getSubscribeServices() {
|
||||
return eventDispatcher.getSubscribeServices();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getServerStatus() {
|
||||
return serverProxy.serverHealthy() ? "UP" : "DOWN";
|
||||
}
|
||||
|
||||
public BeatReactor getBeatReactor() {
|
||||
return beatReactor;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void shutDown() throws NacosException {
|
||||
beatReactor.shutdown();
|
||||
|
@ -13,6 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.client.naming.backups;
|
||||
|
||||
import com.alibaba.nacos.api.exception.NacosException;
|
||||
@ -24,7 +25,6 @@ import com.alibaba.nacos.client.naming.utils.CollectionUtils;
|
||||
import com.alibaba.nacos.client.naming.utils.UtilAndComs;
|
||||
import com.alibaba.nacos.common.lifecycle.Closeable;
|
||||
import com.alibaba.nacos.common.utils.JacksonUtils;
|
||||
|
||||
import com.alibaba.nacos.common.utils.StringUtils;
|
||||
import com.alibaba.nacos.common.utils.ThreadUtils;
|
||||
|
||||
@ -32,28 +32,32 @@ import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.StringReader;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Map;
|
||||
import java.util.Date;
|
||||
import java.util.Calendar;
|
||||
import java.util.TimerTask;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.*;
|
||||
import java.util.Map;
|
||||
import java.util.TimerTask;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ScheduledThreadPoolExecutor;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static com.alibaba.nacos.client.utils.LogUtils.NAMING_LOGGER;
|
||||
|
||||
/**
|
||||
* Failover reactor.
|
||||
*
|
||||
* @author nkorange
|
||||
*/
|
||||
public class FailoverReactor implements Closeable {
|
||||
|
||||
private String failoverDir;
|
||||
|
||||
private HostReactor hostReactor;
|
||||
|
||||
private ScheduledExecutorService executorService;
|
||||
|
||||
|
||||
private final String failoverDir;
|
||||
|
||||
private final HostReactor hostReactor;
|
||||
|
||||
private final ScheduledExecutorService executorService;
|
||||
|
||||
public FailoverReactor(HostReactor hostReactor, String cacheDir) {
|
||||
this.hostReactor = hostReactor;
|
||||
this.failoverDir = cacheDir + "/failover";
|
||||
@ -69,28 +73,33 @@ public class FailoverReactor implements Closeable {
|
||||
});
|
||||
this.init();
|
||||
}
|
||||
|
||||
|
||||
private Map<String, ServiceInfo> serviceMap = new ConcurrentHashMap<String, ServiceInfo>();
|
||||
private Map<String, String> switchParams = new ConcurrentHashMap<String, String>();
|
||||
|
||||
private final Map<String, String> switchParams = new ConcurrentHashMap<String, String>();
|
||||
|
||||
private static final long DAY_PERIOD_MINUTES = 24 * 60;
|
||||
|
||||
|
||||
/**
|
||||
* Init.
|
||||
*/
|
||||
public void init() {
|
||||
|
||||
|
||||
executorService.scheduleWithFixedDelay(new SwitchRefresher(), 0L, 5000L, TimeUnit.MILLISECONDS);
|
||||
|
||||
|
||||
executorService.scheduleWithFixedDelay(new DiskFileWriter(), 30, DAY_PERIOD_MINUTES, TimeUnit.MINUTES);
|
||||
|
||||
|
||||
// backup file on startup if failover directory is empty.
|
||||
executorService.schedule(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
File cacheDir = new File(failoverDir);
|
||||
|
||||
|
||||
if (!cacheDir.exists() && !cacheDir.mkdirs()) {
|
||||
throw new IllegalStateException("failed to create cache dir: " + failoverDir);
|
||||
}
|
||||
|
||||
|
||||
File[] files = cacheDir.listFiles();
|
||||
if (files == null || files.length <= 0) {
|
||||
new DiskFileWriter().run();
|
||||
@ -98,18 +107,25 @@ public class FailoverReactor implements Closeable {
|
||||
} catch (Throwable e) {
|
||||
NAMING_LOGGER.error("[NA] failed to backup file on startup.", e);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}, 10000L, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add day.
|
||||
*
|
||||
* @param date start time
|
||||
* @param num add day number
|
||||
* @return new date
|
||||
*/
|
||||
public Date addDay(Date date, int num) {
|
||||
Calendar startDT = Calendar.getInstance();
|
||||
startDT.setTime(date);
|
||||
startDT.add(Calendar.DAY_OF_MONTH, num);
|
||||
return startDT.getTime();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void shutdown() throws NacosException {
|
||||
String className = this.getClass().getName();
|
||||
@ -117,10 +133,11 @@ public class FailoverReactor implements Closeable {
|
||||
ThreadUtils.shutdownThreadPool(executorService, NAMING_LOGGER);
|
||||
NAMING_LOGGER.info("{} do shutdown stop", className);
|
||||
}
|
||||
|
||||
|
||||
class SwitchRefresher implements Runnable {
|
||||
|
||||
long lastModifiedMillis = 0L;
|
||||
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
@ -130,16 +147,16 @@ public class FailoverReactor implements Closeable {
|
||||
NAMING_LOGGER.debug("failover switch is not found, " + switchFile.getName());
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
long modified = switchFile.lastModified();
|
||||
|
||||
|
||||
if (lastModifiedMillis < modified) {
|
||||
lastModifiedMillis = modified;
|
||||
String failover = ConcurrentDiskUtil.getFileContent(failoverDir + UtilAndComs.FAILOVER_SWITCH,
|
||||
Charset.defaultCharset().toString());
|
||||
Charset.defaultCharset().toString());
|
||||
if (!StringUtils.isEmpty(failover)) {
|
||||
List<String> lines = Arrays.asList(failover.split(DiskCache.getLineSeparator()));
|
||||
|
||||
String[] lines = failover.split(DiskCache.getLineSeparator());
|
||||
|
||||
for (String line : lines) {
|
||||
String line1 = line.trim();
|
||||
if ("1".equals(line1)) {
|
||||
@ -155,48 +172,48 @@ public class FailoverReactor implements Closeable {
|
||||
switchParams.put("failover-mode", "false");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} catch (Throwable e) {
|
||||
NAMING_LOGGER.error("[NA] failed to read failover switch.", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class FailoverFileReader implements Runnable {
|
||||
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
Map<String, ServiceInfo> domMap = new HashMap<String, ServiceInfo>(16);
|
||||
|
||||
|
||||
BufferedReader reader = null;
|
||||
try {
|
||||
|
||||
|
||||
File cacheDir = new File(failoverDir);
|
||||
if (!cacheDir.exists() && !cacheDir.mkdirs()) {
|
||||
throw new IllegalStateException("failed to create cache dir: " + failoverDir);
|
||||
}
|
||||
|
||||
|
||||
File[] files = cacheDir.listFiles();
|
||||
if (files == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
for (File file : files) {
|
||||
if (!file.isFile()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
if (file.getName().equals(UtilAndComs.FAILOVER_SWITCH)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
ServiceInfo dom = new ServiceInfo(file.getName());
|
||||
|
||||
|
||||
try {
|
||||
String dataString = ConcurrentDiskUtil.getFileContent(file,
|
||||
Charset.defaultCharset().toString());
|
||||
String dataString = ConcurrentDiskUtil
|
||||
.getFileContent(file, Charset.defaultCharset().toString());
|
||||
reader = new BufferedReader(new StringReader(dataString));
|
||||
|
||||
|
||||
String json;
|
||||
if ((json = reader.readLine()) != null) {
|
||||
try {
|
||||
@ -205,7 +222,7 @@ public class FailoverReactor implements Closeable {
|
||||
NAMING_LOGGER.error("[NA] error while parsing cached dom : " + json, e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} catch (Exception e) {
|
||||
NAMING_LOGGER.error("[NA] failed to read cache for dom: " + file.getName(), e);
|
||||
} finally {
|
||||
@ -224,44 +241,45 @@ public class FailoverReactor implements Closeable {
|
||||
} catch (Exception e) {
|
||||
NAMING_LOGGER.error("[NA] failed to read cache file", e);
|
||||
}
|
||||
|
||||
|
||||
if (domMap.size() > 0) {
|
||||
serviceMap = domMap;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class DiskFileWriter extends TimerTask {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
Map<String, ServiceInfo> map = hostReactor.getServiceInfoMap();
|
||||
for (Map.Entry<String, ServiceInfo> entry : map.entrySet()) {
|
||||
ServiceInfo serviceInfo = entry.getValue();
|
||||
if (StringUtils.equals(serviceInfo.getKey(), UtilAndComs.ALL_IPS) || StringUtils.equals(
|
||||
serviceInfo.getName(), UtilAndComs.ENV_LIST_KEY)
|
||||
|| StringUtils.equals(serviceInfo.getName(), "00-00---000-ENV_CONFIGS-000---00-00")
|
||||
|| StringUtils.equals(serviceInfo.getName(), "vipclient.properties")
|
||||
|| StringUtils.equals(serviceInfo.getName(), "00-00---000-ALL_HOSTS-000---00-00")) {
|
||||
if (StringUtils.equals(serviceInfo.getKey(), UtilAndComs.ALL_IPS) || StringUtils
|
||||
.equals(serviceInfo.getName(), UtilAndComs.ENV_LIST_KEY) || StringUtils
|
||||
.equals(serviceInfo.getName(), "00-00---000-ENV_CONFIGS-000---00-00") || StringUtils
|
||||
.equals(serviceInfo.getName(), "vipclient.properties") || StringUtils
|
||||
.equals(serviceInfo.getName(), "00-00---000-ALL_HOSTS-000---00-00")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
DiskCache.write(serviceInfo, failoverDir);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public boolean isFailoverSwitch() {
|
||||
return Boolean.parseBoolean(switchParams.get("failover-mode"));
|
||||
}
|
||||
|
||||
|
||||
public ServiceInfo getService(String key) {
|
||||
ServiceInfo serviceInfo = serviceMap.get(key);
|
||||
|
||||
|
||||
if (serviceInfo == null) {
|
||||
serviceInfo = new ServiceInfo();
|
||||
serviceInfo.setName(key);
|
||||
}
|
||||
|
||||
|
||||
return serviceInfo;
|
||||
}
|
||||
}
|
||||
|
@ -13,108 +13,111 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.client.naming.beat;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Beat information.
|
||||
*
|
||||
* @author nkorange
|
||||
*/
|
||||
public class BeatInfo {
|
||||
|
||||
|
||||
private int port;
|
||||
|
||||
private String ip;
|
||||
|
||||
private double weight;
|
||||
|
||||
private String serviceName;
|
||||
|
||||
private String cluster;
|
||||
|
||||
private Map<String, String> metadata;
|
||||
|
||||
private volatile boolean scheduled;
|
||||
|
||||
private volatile long period;
|
||||
|
||||
private volatile boolean stopped;
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "BeatInfo{" +
|
||||
"port=" + port +
|
||||
", ip='" + ip + '\'' +
|
||||
", weight=" + weight +
|
||||
", serviceName='" + serviceName + '\'' +
|
||||
", cluster='" + cluster + '\'' +
|
||||
", metadata=" + metadata +
|
||||
", scheduled=" + scheduled +
|
||||
", period=" + period +
|
||||
", stopped=" + stopped +
|
||||
'}';
|
||||
return "BeatInfo{" + "port=" + port + ", ip='" + ip + '\'' + ", weight=" + weight + ", serviceName='"
|
||||
+ serviceName + '\'' + ", cluster='" + cluster + '\'' + ", metadata=" + metadata + ", scheduled="
|
||||
+ scheduled + ", period=" + period + ", stopped=" + stopped + '}';
|
||||
}
|
||||
|
||||
|
||||
public String getServiceName() {
|
||||
return serviceName;
|
||||
}
|
||||
|
||||
|
||||
public void setServiceName(String serviceName) {
|
||||
this.serviceName = serviceName;
|
||||
}
|
||||
|
||||
|
||||
public String getCluster() {
|
||||
return cluster;
|
||||
}
|
||||
|
||||
|
||||
public void setCluster(String cluster) {
|
||||
this.cluster = cluster;
|
||||
}
|
||||
|
||||
|
||||
public String getIp() {
|
||||
return ip;
|
||||
}
|
||||
|
||||
|
||||
public void setIp(String ip) {
|
||||
this.ip = ip;
|
||||
}
|
||||
|
||||
|
||||
public int getPort() {
|
||||
return port;
|
||||
}
|
||||
|
||||
|
||||
public void setPort(int port) {
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
|
||||
public Map<String, String> getMetadata() {
|
||||
return metadata;
|
||||
}
|
||||
|
||||
|
||||
public void setMetadata(Map<String, String> metadata) {
|
||||
this.metadata = metadata;
|
||||
}
|
||||
|
||||
|
||||
public double getWeight() {
|
||||
return weight;
|
||||
}
|
||||
|
||||
|
||||
public void setWeight(double weight) {
|
||||
this.weight = weight;
|
||||
}
|
||||
|
||||
|
||||
public boolean isScheduled() {
|
||||
return scheduled;
|
||||
}
|
||||
|
||||
|
||||
public void setScheduled(boolean scheduled) {
|
||||
this.scheduled = scheduled;
|
||||
}
|
||||
|
||||
|
||||
public long getPeriod() {
|
||||
return period;
|
||||
}
|
||||
|
||||
|
||||
public void setPeriod(long period) {
|
||||
this.period = period;
|
||||
}
|
||||
|
||||
|
||||
public boolean isStopped() {
|
||||
return stopped;
|
||||
}
|
||||
|
||||
|
||||
public void setStopped(boolean stopped) {
|
||||
this.stopped = stopped;
|
||||
}
|
||||
|
@ -13,6 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.client.naming.beat;
|
||||
|
||||
import com.alibaba.nacos.api.common.Constants;
|
||||
@ -30,27 +31,33 @@ import com.alibaba.nacos.common.utils.ThreadUtils;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ScheduledThreadPoolExecutor;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static com.alibaba.nacos.client.utils.LogUtils.NAMING_LOGGER;
|
||||
|
||||
/**
|
||||
* Beat reactor.
|
||||
*
|
||||
* @author harold
|
||||
*/
|
||||
public class BeatReactor implements Closeable {
|
||||
|
||||
private ScheduledExecutorService executorService;
|
||||
|
||||
private NamingProxy serverProxy;
|
||||
|
||||
|
||||
private final ScheduledExecutorService executorService;
|
||||
|
||||
private final NamingProxy serverProxy;
|
||||
|
||||
private boolean lightBeatEnabled = false;
|
||||
|
||||
public final Map<String, BeatInfo> dom2Beat = new ConcurrentHashMap<>();
|
||||
|
||||
|
||||
public final Map<String, BeatInfo> dom2Beat = new ConcurrentHashMap<String, BeatInfo>();
|
||||
|
||||
public BeatReactor(NamingProxy serverProxy) {
|
||||
this(serverProxy, UtilAndComs.DEFAULT_CLIENT_BEAT_THREAD_COUNT);
|
||||
}
|
||||
|
||||
|
||||
public BeatReactor(NamingProxy serverProxy, int threadCount) {
|
||||
this.serverProxy = serverProxy;
|
||||
this.executorService = new ScheduledThreadPoolExecutor(threadCount, new ThreadFactory() {
|
||||
@ -63,7 +70,13 @@ public class BeatReactor implements Closeable {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add beat information.
|
||||
*
|
||||
* @param serviceName service name
|
||||
* @param beatInfo beat information
|
||||
*/
|
||||
public void addBeatInfo(String serviceName, BeatInfo beatInfo) {
|
||||
NAMING_LOGGER.info("[BEAT] adding beat: {} to beat map.", beatInfo);
|
||||
String key = buildKey(serviceName, beatInfo.getIp(), beatInfo.getPort());
|
||||
@ -76,7 +89,14 @@ public class BeatReactor implements Closeable {
|
||||
executorService.schedule(new BeatTask(beatInfo), beatInfo.getPeriod(), TimeUnit.MILLISECONDS);
|
||||
MetricsMonitor.getDom2BeatSizeMonitor().set(dom2Beat.size());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Remove beat information.
|
||||
*
|
||||
* @param serviceName service name
|
||||
* @param ip ip of beat information
|
||||
* @param port port of beat information
|
||||
*/
|
||||
public void removeBeatInfo(String serviceName, String ip, int port) {
|
||||
NAMING_LOGGER.info("[BEAT] removing beat: {}:{}:{} from beat map.", serviceName, ip, port);
|
||||
BeatInfo beatInfo = dom2Beat.remove(buildKey(serviceName, ip, port));
|
||||
@ -86,10 +106,27 @@ public class BeatReactor implements Closeable {
|
||||
beatInfo.setStopped(true);
|
||||
MetricsMonitor.getDom2BeatSizeMonitor().set(dom2Beat.size());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Build new beat information.
|
||||
*
|
||||
* @param instance instance
|
||||
* @return new beat information
|
||||
*/
|
||||
public BeatInfo buildBeatInfo(Instance instance) {
|
||||
return buildBeatInfo(instance.getServiceName(), instance);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build new beat information.
|
||||
*
|
||||
* @param groupedServiceName service name with group name, format: ${groupName}@@${serviceName}
|
||||
* @param instance instance
|
||||
* @return new beat information
|
||||
*/
|
||||
public BeatInfo buildBeatInfo(String groupedServiceName, Instance instance) {
|
||||
BeatInfo beatInfo = new BeatInfo();
|
||||
beatInfo.setServiceName(instance.getServiceName());
|
||||
beatInfo.setServiceName(groupedServiceName);
|
||||
beatInfo.setIp(instance.getIp());
|
||||
beatInfo.setPort(instance.getPort());
|
||||
beatInfo.setCluster(instance.getClusterName());
|
||||
@ -99,28 +136,27 @@ public class BeatReactor implements Closeable {
|
||||
beatInfo.setPeriod(instance.getInstanceHeartBeatInterval());
|
||||
return beatInfo;
|
||||
}
|
||||
|
||||
|
||||
public String buildKey(String serviceName, String ip, int port) {
|
||||
return serviceName + Constants.NAMING_INSTANCE_ID_SPLITTER
|
||||
+ ip + Constants.NAMING_INSTANCE_ID_SPLITTER + port;
|
||||
return serviceName + Constants.NAMING_INSTANCE_ID_SPLITTER + ip + Constants.NAMING_INSTANCE_ID_SPLITTER + port;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void shutdown() throws NacosException{
|
||||
public void shutdown() throws NacosException {
|
||||
String className = this.getClass().getName();
|
||||
NAMING_LOGGER.info("{} do shutdown begin", className);
|
||||
ThreadUtils.shutdownThreadPool(executorService, NAMING_LOGGER);
|
||||
NAMING_LOGGER.info("{} do shutdown stop", className);
|
||||
}
|
||||
|
||||
|
||||
class BeatTask implements Runnable {
|
||||
|
||||
|
||||
BeatInfo beatInfo;
|
||||
|
||||
|
||||
public BeatTask(BeatInfo beatInfo) {
|
||||
this.beatInfo = beatInfo;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (beatInfo.isStopped()) {
|
||||
@ -129,7 +165,7 @@ public class BeatReactor implements Closeable {
|
||||
long nextTime = beatInfo.getPeriod();
|
||||
try {
|
||||
JsonNode result = serverProxy.sendBeat(beatInfo, BeatReactor.this.lightBeatEnabled);
|
||||
long interval = result.get("clientBeatInterval").asInt();
|
||||
long interval = result.get("clientBeatInterval").asLong();
|
||||
boolean lightBeatEnabled = false;
|
||||
if (result.has(CommonParams.LIGHT_BEAT_ENABLED)) {
|
||||
lightBeatEnabled = result.get(CommonParams.LIGHT_BEAT_ENABLED).asBoolean();
|
||||
@ -154,14 +190,14 @@ public class BeatReactor implements Closeable {
|
||||
instance.setEphemeral(true);
|
||||
try {
|
||||
serverProxy.registerService(beatInfo.getServiceName(),
|
||||
NamingUtils.getGroupName(beatInfo.getServiceName()), instance);
|
||||
NamingUtils.getGroupName(beatInfo.getServiceName()), instance);
|
||||
} catch (Exception ignore) {
|
||||
}
|
||||
}
|
||||
} catch (NacosException ne) {
|
||||
} catch (NacosException ex) {
|
||||
NAMING_LOGGER.error("[CLIENT-BEAT] failed to send beat: {}, code: {}, msg: {}",
|
||||
JacksonUtils.toJson(beatInfo), ne.getErrCode(), ne.getErrMsg());
|
||||
|
||||
JacksonUtils.toJson(beatInfo), ex.getErrCode(), ex.getErrMsg());
|
||||
|
||||
}
|
||||
executorService.schedule(new BeatTask(beatInfo), nextTime, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
@ -13,6 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.client.naming.cache;
|
||||
|
||||
import java.io.File;
|
||||
@ -29,34 +30,34 @@ import java.nio.charset.CharsetDecoder;
|
||||
import static com.alibaba.nacos.client.utils.LogUtils.NAMING_LOGGER;
|
||||
|
||||
/**
|
||||
* Concurrent Disk util.
|
||||
*
|
||||
* @author nkorange
|
||||
*/
|
||||
public class ConcurrentDiskUtil {
|
||||
|
||||
|
||||
/**
|
||||
* get file content
|
||||
* get file content.
|
||||
*
|
||||
* @param path file path
|
||||
* @param charsetName charsetName
|
||||
* @return content
|
||||
* @throws IOException IOException
|
||||
*/
|
||||
public static String getFileContent(String path, String charsetName)
|
||||
throws IOException {
|
||||
public static String getFileContent(String path, String charsetName) throws IOException {
|
||||
File file = new File(path);
|
||||
return getFileContent(file, charsetName);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* get file content
|
||||
* get file content.
|
||||
*
|
||||
* @param file file
|
||||
* @param charsetName charsetName
|
||||
* @return content
|
||||
* @throws IOException IOException
|
||||
*/
|
||||
public static String getFileContent(File file, String charsetName)
|
||||
throws IOException {
|
||||
public static String getFileContent(File file, String charsetName) throws IOException {
|
||||
RandomAccessFile fis = null;
|
||||
FileLock rlock = null;
|
||||
try {
|
||||
@ -70,14 +71,13 @@ public class ConcurrentDiskUtil {
|
||||
++i;
|
||||
if (i > RETRY_COUNT) {
|
||||
NAMING_LOGGER.error("[NA] read " + file.getName() + " fail;retryed time: " + i, e);
|
||||
throw new IOException("read " + file.getAbsolutePath()
|
||||
+ " conflict");
|
||||
throw new IOException("read " + file.getAbsolutePath() + " conflict");
|
||||
}
|
||||
sleep(SLEEP_BASETIME * i);
|
||||
NAMING_LOGGER.warn("read " + file.getName() + " conflict;retry time: " + i);
|
||||
}
|
||||
} while (null == rlock);
|
||||
int fileSize = (int)fcin.size();
|
||||
int fileSize = (int) fcin.size();
|
||||
ByteBuffer byteBuffer = ByteBuffer.allocate(fileSize);
|
||||
fcin.read(byteBuffer);
|
||||
byteBuffer.flip();
|
||||
@ -93,9 +93,9 @@ public class ConcurrentDiskUtil {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* write file content
|
||||
* write file content.
|
||||
*
|
||||
* @param path file path
|
||||
* @param content content
|
||||
@ -103,14 +103,13 @@ public class ConcurrentDiskUtil {
|
||||
* @return whether write ok
|
||||
* @throws IOException IOException
|
||||
*/
|
||||
public static Boolean writeFileContent(String path, String content,
|
||||
String charsetName) throws IOException {
|
||||
public static Boolean writeFileContent(String path, String content, String charsetName) throws IOException {
|
||||
File file = new File(path);
|
||||
return writeFileContent(file, content, charsetName);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* write file content
|
||||
* write file content.
|
||||
*
|
||||
* @param file file
|
||||
* @param content content
|
||||
@ -118,9 +117,8 @@ public class ConcurrentDiskUtil {
|
||||
* @return whether write ok
|
||||
* @throws IOException IOException
|
||||
*/
|
||||
public static Boolean writeFileContent(File file, String content,
|
||||
String charsetName) throws IOException {
|
||||
|
||||
public static Boolean writeFileContent(File file, String content, String charsetName) throws IOException {
|
||||
|
||||
if (!file.exists() && !file.createNewFile()) {
|
||||
return false;
|
||||
}
|
||||
@ -138,16 +136,14 @@ public class ConcurrentDiskUtil {
|
||||
++i;
|
||||
if (i > RETRY_COUNT) {
|
||||
NAMING_LOGGER.error("[NA] write {} fail;retryed time:{}", file.getName(), i);
|
||||
throw new IOException("write " + file.getAbsolutePath()
|
||||
+ " conflict", e);
|
||||
throw new IOException("write " + file.getAbsolutePath() + " conflict", e);
|
||||
}
|
||||
sleep(SLEEP_BASETIME * i);
|
||||
NAMING_LOGGER.warn("write " + file.getName() + " conflict;retry time: " + i);
|
||||
}
|
||||
} while (null == lock);
|
||||
|
||||
ByteBuffer sendBuffer = ByteBuffer.wrap(content
|
||||
.getBytes(charsetName));
|
||||
|
||||
ByteBuffer sendBuffer = ByteBuffer.wrap(content.getBytes(charsetName));
|
||||
while (sendBuffer.hasRemaining()) {
|
||||
channel.write(sendBuffer);
|
||||
}
|
||||
@ -179,21 +175,20 @@ public class ConcurrentDiskUtil {
|
||||
NAMING_LOGGER.warn("close wrong", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* transfer ByteBuffer to String
|
||||
* transfer ByteBuffer to String.
|
||||
*
|
||||
* @param buffer buffer
|
||||
* @param charsetName charsetName
|
||||
* @return String
|
||||
* @throws IOException IOException
|
||||
*/
|
||||
public static String byteBufferToString(ByteBuffer buffer,
|
||||
String charsetName) throws IOException {
|
||||
public static String byteBufferToString(ByteBuffer buffer, String charsetName) throws IOException {
|
||||
Charset charset = null;
|
||||
CharsetDecoder decoder = null;
|
||||
CharBuffer charBuffer = null;
|
||||
@ -202,7 +197,7 @@ public class ConcurrentDiskUtil {
|
||||
charBuffer = decoder.decode(buffer.asReadOnlyBuffer());
|
||||
return charBuffer.toString();
|
||||
}
|
||||
|
||||
|
||||
private static void sleep(int time) {
|
||||
try {
|
||||
Thread.sleep(time);
|
||||
@ -210,7 +205,8 @@ public class ConcurrentDiskUtil {
|
||||
NAMING_LOGGER.warn("sleep wrong", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static final int RETRY_COUNT = 10;
|
||||
|
||||
private static final int SLEEP_BASETIME = 10;
|
||||
}
|
||||
|
@ -13,6 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.client.naming.cache;
|
||||
|
||||
import com.alibaba.nacos.api.common.Constants;
|
||||
@ -35,16 +36,23 @@ import java.util.Map;
|
||||
import static com.alibaba.nacos.client.utils.LogUtils.NAMING_LOGGER;
|
||||
|
||||
/**
|
||||
* Disk cache.
|
||||
*
|
||||
* @author xuanyin
|
||||
*/
|
||||
public class DiskCache {
|
||||
|
||||
|
||||
/**
|
||||
* Write service info to dir.
|
||||
*
|
||||
* @param dom service info
|
||||
* @param dir directory
|
||||
*/
|
||||
public static void write(ServiceInfo dom, String dir) {
|
||||
|
||||
|
||||
try {
|
||||
makeSureCacheDirExists(dir);
|
||||
|
||||
|
||||
|
||||
File file = new File(dir, dom.getKeyEncoded());
|
||||
if (!file.exists()) {
|
||||
// add another !file.exists() to avoid conflicted creating-new-file from multi-instances
|
||||
@ -52,68 +60,74 @@ public class DiskCache {
|
||||
throw new IllegalStateException("failed to create cache file");
|
||||
}
|
||||
}
|
||||
|
||||
StringBuilder keyContentBuffer = new StringBuilder("");
|
||||
|
||||
|
||||
StringBuilder keyContentBuffer = new StringBuilder();
|
||||
|
||||
String json = dom.getJsonFromServer();
|
||||
|
||||
|
||||
if (StringUtils.isEmpty(json)) {
|
||||
json = JacksonUtils.toJson(dom);
|
||||
}
|
||||
|
||||
|
||||
keyContentBuffer.append(json);
|
||||
|
||||
|
||||
//Use the concurrent API to ensure the consistency.
|
||||
ConcurrentDiskUtil.writeFileContent(file, keyContentBuffer.toString(), Charset.defaultCharset().toString());
|
||||
|
||||
|
||||
} catch (Throwable e) {
|
||||
NAMING_LOGGER.error("[NA] failed to write cache for dom:" + dom.getName(), e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static String getLineSeparator() {
|
||||
return System.getProperty("line.separator");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Read service info from disk.
|
||||
*
|
||||
* @param cacheDir cache file dir
|
||||
* @return service infos
|
||||
*/
|
||||
public static Map<String, ServiceInfo> read(String cacheDir) {
|
||||
Map<String, ServiceInfo> domMap = new HashMap<String, ServiceInfo>(16);
|
||||
|
||||
|
||||
BufferedReader reader = null;
|
||||
try {
|
||||
File[] files = makeSureCacheDirExists(cacheDir).listFiles();
|
||||
if (files == null || files.length == 0) {
|
||||
return domMap;
|
||||
}
|
||||
|
||||
|
||||
for (File file : files) {
|
||||
if (!file.isFile()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
String fileName = URLDecoder.decode(file.getName(), "UTF-8");
|
||||
|
||||
if (!(fileName.endsWith(Constants.SERVICE_INFO_SPLITER + "meta") || fileName.endsWith(
|
||||
Constants.SERVICE_INFO_SPLITER + "special-url"))) {
|
||||
|
||||
if (!(fileName.endsWith(Constants.SERVICE_INFO_SPLITER + "meta") || fileName
|
||||
.endsWith(Constants.SERVICE_INFO_SPLITER + "special-url"))) {
|
||||
ServiceInfo dom = new ServiceInfo(fileName);
|
||||
List<Instance> ips = new ArrayList<Instance>();
|
||||
dom.setHosts(ips);
|
||||
|
||||
|
||||
ServiceInfo newFormat = null;
|
||||
|
||||
|
||||
try {
|
||||
String dataString = ConcurrentDiskUtil.getFileContent(file,
|
||||
Charset.defaultCharset().toString());
|
||||
String dataString = ConcurrentDiskUtil
|
||||
.getFileContent(file, Charset.defaultCharset().toString());
|
||||
reader = new BufferedReader(new StringReader(dataString));
|
||||
|
||||
|
||||
String json;
|
||||
while ((json = reader.readLine()) != null) {
|
||||
try {
|
||||
if (!json.startsWith("{")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
newFormat = JacksonUtils.toObj(json, ServiceInfo.class);
|
||||
|
||||
|
||||
if (StringUtils.isEmpty(newFormat.getName())) {
|
||||
ips.add(JacksonUtils.toObj(json, Instance.class));
|
||||
}
|
||||
@ -132,25 +146,25 @@ public class DiskCache {
|
||||
//ignore
|
||||
}
|
||||
}
|
||||
if (newFormat != null && !StringUtils.isEmpty(newFormat.getName()) && !CollectionUtils.isEmpty(
|
||||
newFormat.getHosts())) {
|
||||
if (newFormat != null && !StringUtils.isEmpty(newFormat.getName()) && !CollectionUtils
|
||||
.isEmpty(newFormat.getHosts())) {
|
||||
domMap.put(dom.getKey(), newFormat);
|
||||
} else if (!CollectionUtils.isEmpty(dom.getHosts())) {
|
||||
domMap.put(dom.getKey(), dom);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
NAMING_LOGGER.error("[NA] failed to read cache file", e);
|
||||
}
|
||||
|
||||
|
||||
return domMap;
|
||||
}
|
||||
|
||||
|
||||
private static File makeSureCacheDirExists(String dir) {
|
||||
File cacheDir = new File(dir);
|
||||
|
||||
|
||||
if (!cacheDir.exists()) {
|
||||
if (!cacheDir.mkdirs() && !cacheDir.exists()) {
|
||||
throw new IllegalStateException("failed to create cache dir: " + dir);
|
||||
|
@ -13,6 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.client.naming.core;
|
||||
|
||||
import com.alibaba.nacos.api.naming.pojo.Instance;
|
||||
@ -27,34 +28,48 @@ import java.util.List;
|
||||
import static com.alibaba.nacos.client.utils.LogUtils.NAMING_LOGGER;
|
||||
|
||||
/**
|
||||
* Balancer.
|
||||
*
|
||||
* @author xuanyin
|
||||
*/
|
||||
public class Balancer {
|
||||
|
||||
|
||||
public static class RandomByWeight {
|
||||
|
||||
|
||||
/**
|
||||
* Select all instance.
|
||||
*
|
||||
* @param serviceInfo service information
|
||||
* @return all instance of services
|
||||
*/
|
||||
public static List<Instance> selectAll(ServiceInfo serviceInfo) {
|
||||
List<Instance> hosts = serviceInfo.getHosts();
|
||||
|
||||
|
||||
if (CollectionUtils.isEmpty(hosts)) {
|
||||
throw new IllegalStateException("no host to srv for serviceInfo: " + serviceInfo.getName());
|
||||
}
|
||||
|
||||
|
||||
return hosts;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Random select one instance from service.
|
||||
*
|
||||
* @param dom service
|
||||
* @return random instance
|
||||
*/
|
||||
public static Instance selectHost(ServiceInfo dom) {
|
||||
|
||||
|
||||
List<Instance> hosts = selectAll(dom);
|
||||
|
||||
|
||||
if (CollectionUtils.isEmpty(hosts)) {
|
||||
throw new IllegalStateException("no host to srv for service: " + dom.getName());
|
||||
}
|
||||
|
||||
|
||||
return getHostByRandomWeight(hosts);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return one host from the host list by random-weight.
|
||||
*
|
||||
@ -67,11 +82,7 @@ public class Balancer {
|
||||
NAMING_LOGGER.debug("hosts == null || hosts.size() == 0");
|
||||
return null;
|
||||
}
|
||||
|
||||
Chooser<String, Instance> vipChooser = new Chooser<String, Instance>("www.taobao.com");
|
||||
|
||||
NAMING_LOGGER.debug("new Chooser");
|
||||
|
||||
List<Pair<Instance>> hostsWithWeight = new ArrayList<Pair<Instance>>();
|
||||
for (Instance host : hosts) {
|
||||
if (host.isHealthy()) {
|
||||
@ -79,6 +90,7 @@ public class Balancer {
|
||||
}
|
||||
}
|
||||
NAMING_LOGGER.debug("for (Host host : hosts)");
|
||||
Chooser<String, Instance> vipChooser = new Chooser<String, Instance>("www.taobao.com");
|
||||
vipChooser.refresh(hostsWithWeight);
|
||||
NAMING_LOGGER.debug("vipChooser.refresh");
|
||||
return vipChooser.randomWithWeight();
|
||||
|
@ -13,6 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.client.naming.core;
|
||||
|
||||
import com.alibaba.nacos.api.exception.NacosException;
|
||||
@ -28,55 +29,80 @@ import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.*;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static com.alibaba.nacos.client.utils.LogUtils.NAMING_LOGGER;
|
||||
|
||||
/**
|
||||
* Event dispatcher.
|
||||
*
|
||||
* @author xuanyin
|
||||
*/
|
||||
@SuppressWarnings("PMD.ThreadPoolCreationRule")
|
||||
public class EventDispatcher implements Closeable {
|
||||
|
||||
|
||||
private ExecutorService executor = null;
|
||||
|
||||
private BlockingQueue<ServiceInfo> changedServices = new LinkedBlockingQueue<ServiceInfo>();
|
||||
|
||||
private ConcurrentMap<String, List<EventListener>> observerMap
|
||||
= new ConcurrentHashMap<String, List<EventListener>>();
|
||||
|
||||
|
||||
private final BlockingQueue<ServiceInfo> changedServices = new LinkedBlockingQueue<ServiceInfo>();
|
||||
|
||||
private final ConcurrentMap<String, List<EventListener>> observerMap = new ConcurrentHashMap<String, List<EventListener>>();
|
||||
|
||||
private volatile boolean closed = false;
|
||||
|
||||
public EventDispatcher() {
|
||||
|
||||
|
||||
this.executor = Executors.newSingleThreadExecutor(new ThreadFactory() {
|
||||
@Override
|
||||
public Thread newThread(Runnable r) {
|
||||
Thread thread = new Thread(r, "com.alibaba.nacos.naming.client.listener");
|
||||
thread.setDaemon(true);
|
||||
|
||||
|
||||
return thread;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
this.executor.execute(new Notifier());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add listener.
|
||||
*
|
||||
* @param serviceInfo service info
|
||||
* @param clusters clusters
|
||||
* @param listener listener
|
||||
*/
|
||||
public void addListener(ServiceInfo serviceInfo, String clusters, EventListener listener) {
|
||||
|
||||
|
||||
NAMING_LOGGER.info("[LISTENER] adding " + serviceInfo.getName() + " with " + clusters + " to listener map");
|
||||
List<EventListener> observers = Collections.synchronizedList(new ArrayList<EventListener>());
|
||||
observers.add(listener);
|
||||
|
||||
|
||||
observers = observerMap.putIfAbsent(ServiceInfo.getKey(serviceInfo.getName(), clusters), observers);
|
||||
if (observers != null) {
|
||||
observers.add(listener);
|
||||
}
|
||||
|
||||
|
||||
serviceChanged(serviceInfo);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Remove listener.
|
||||
*
|
||||
* @param serviceName service name
|
||||
* @param clusters clusters
|
||||
* @param listener listener
|
||||
*/
|
||||
public void removeListener(String serviceName, String clusters, EventListener listener) {
|
||||
|
||||
|
||||
NAMING_LOGGER.info("[LISTENER] removing " + serviceName + " with " + clusters + " from listener map");
|
||||
|
||||
|
||||
List<EventListener> observers = observerMap.get(ServiceInfo.getKey(serviceName, clusters));
|
||||
if (observers != null) {
|
||||
Iterator<EventListener> iter = observers.iterator();
|
||||
@ -91,11 +117,11 @@ public class EventDispatcher implements Closeable {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public boolean isSubscribed(String serviceName, String clusters) {
|
||||
return observerMap.containsKey(ServiceInfo.getKey(serviceName, clusters));
|
||||
}
|
||||
|
||||
|
||||
public List<ServiceInfo> getSubscribeServices() {
|
||||
List<ServiceInfo> serviceInfos = new ArrayList<ServiceInfo>();
|
||||
for (String key : observerMap.keySet()) {
|
||||
@ -103,50 +129,59 @@ public class EventDispatcher implements Closeable {
|
||||
}
|
||||
return serviceInfos;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Service changed.
|
||||
*
|
||||
* @param serviceInfo service info
|
||||
*/
|
||||
public void serviceChanged(ServiceInfo serviceInfo) {
|
||||
if (serviceInfo == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
changedServices.add(serviceInfo);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void shutdown() throws NacosException {
|
||||
String className = this.getClass().getName();
|
||||
NAMING_LOGGER.info("{} do shutdown begin", className);
|
||||
ThreadUtils.shutdownThreadPool(executor, NAMING_LOGGER);
|
||||
closed = true;
|
||||
NAMING_LOGGER.info("{} do shutdown stop", className);
|
||||
}
|
||||
|
||||
|
||||
private class Notifier implements Runnable {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
while (true) {
|
||||
while (!closed) {
|
||||
|
||||
ServiceInfo serviceInfo = null;
|
||||
try {
|
||||
serviceInfo = changedServices.poll(5, TimeUnit.MINUTES);
|
||||
} catch (Exception ignore) {
|
||||
}
|
||||
|
||||
|
||||
if (serviceInfo == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
List<EventListener> listeners = observerMap.get(serviceInfo.getKey());
|
||||
|
||||
|
||||
if (!CollectionUtils.isEmpty(listeners)) {
|
||||
for (EventListener listener : listeners) {
|
||||
List<Instance> hosts = Collections.unmodifiableList(serviceInfo.getHosts());
|
||||
listener.onEvent(new NamingEvent(serviceInfo.getName(), serviceInfo.getGroupName(), serviceInfo.getClusters(), hosts));
|
||||
listener.onEvent(new NamingEvent(serviceInfo.getName(), serviceInfo.getGroupName(),
|
||||
serviceInfo.getClusters(), hosts));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} catch (Exception e) {
|
||||
NAMING_LOGGER.error("[NA] notify error for service: "
|
||||
+ serviceInfo.getName() + ", clusters: " + serviceInfo.getClusters(), e);
|
||||
NAMING_LOGGER.error("[NA] notify error for service: " + serviceInfo.getName() + ", clusters: "
|
||||
+ serviceInfo.getClusters(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -13,6 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.client.naming.core;
|
||||
|
||||
import com.alibaba.nacos.api.exception.NacosException;
|
||||
@ -30,57 +31,59 @@ import com.alibaba.nacos.common.utils.JacksonUtils;
|
||||
import com.alibaba.nacos.common.utils.StringUtils;
|
||||
import com.alibaba.nacos.common.utils.ThreadUtils;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.HashMap;
|
||||
import java.util.Set;
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.ScheduledThreadPoolExecutor;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
|
||||
import static com.alibaba.nacos.client.utils.LogUtils.NAMING_LOGGER;
|
||||
|
||||
/**
|
||||
* Host reactor.
|
||||
*
|
||||
* @author xuanyin
|
||||
*/
|
||||
public class HostReactor implements Closeable {
|
||||
|
||||
|
||||
private static final long DEFAULT_DELAY = 1000L;
|
||||
|
||||
|
||||
private static final long UPDATE_HOLD_INTERVAL = 5000L;
|
||||
|
||||
|
||||
private final Map<String, ScheduledFuture<?>> futureMap = new HashMap<String, ScheduledFuture<?>>();
|
||||
|
||||
private Map<String, ServiceInfo> serviceInfoMap;
|
||||
|
||||
private Map<String, Object> updatingMap;
|
||||
|
||||
private PushReceiver pushReceiver;
|
||||
|
||||
private EventDispatcher eventDispatcher;
|
||||
|
||||
private BeatReactor beatReactor;
|
||||
|
||||
private NamingProxy serverProxy;
|
||||
|
||||
private FailoverReactor failoverReactor;
|
||||
|
||||
private String cacheDir;
|
||||
|
||||
private ScheduledExecutorService executor;
|
||||
|
||||
public HostReactor(EventDispatcher eventDispatcher, NamingProxy serverProxy, BeatReactor beatReactor, String cacheDir) {
|
||||
|
||||
private final Map<String, ServiceInfo> serviceInfoMap;
|
||||
|
||||
private final Map<String, Object> updatingMap;
|
||||
|
||||
private final PushReceiver pushReceiver;
|
||||
|
||||
private final EventDispatcher eventDispatcher;
|
||||
|
||||
private final BeatReactor beatReactor;
|
||||
|
||||
private final NamingProxy serverProxy;
|
||||
|
||||
private final FailoverReactor failoverReactor;
|
||||
|
||||
private final String cacheDir;
|
||||
|
||||
private final ScheduledExecutorService executor;
|
||||
|
||||
public HostReactor(EventDispatcher eventDispatcher, NamingProxy serverProxy, BeatReactor beatReactor,
|
||||
String cacheDir) {
|
||||
this(eventDispatcher, serverProxy, beatReactor, cacheDir, false, UtilAndComs.DEFAULT_POLLING_THREAD_COUNT);
|
||||
}
|
||||
|
||||
public HostReactor(EventDispatcher eventDispatcher, NamingProxy serverProxy, BeatReactor beatReactor, String cacheDir,
|
||||
boolean loadCacheAtStart, int pollingThreadCount) {
|
||||
|
||||
public HostReactor(EventDispatcher eventDispatcher, NamingProxy serverProxy, BeatReactor beatReactor,
|
||||
String cacheDir, boolean loadCacheAtStart, int pollingThreadCount) {
|
||||
// init executorService
|
||||
this.executor = new ScheduledThreadPoolExecutor(pollingThreadCount, new ThreadFactory() {
|
||||
@Override
|
||||
@ -100,128 +103,134 @@ public class HostReactor implements Closeable {
|
||||
} else {
|
||||
this.serviceInfoMap = new ConcurrentHashMap<String, ServiceInfo>(16);
|
||||
}
|
||||
|
||||
|
||||
this.updatingMap = new ConcurrentHashMap<String, Object>();
|
||||
this.failoverReactor = new FailoverReactor(this, cacheDir);
|
||||
this.pushReceiver = new PushReceiver(this);
|
||||
}
|
||||
|
||||
|
||||
public Map<String, ServiceInfo> getServiceInfoMap() {
|
||||
return serviceInfoMap;
|
||||
}
|
||||
|
||||
|
||||
public synchronized ScheduledFuture<?> addTask(UpdateTask task) {
|
||||
return executor.schedule(task, DEFAULT_DELAY, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
public ServiceInfo processServiceJSON(String json) {
|
||||
|
||||
/**
|
||||
* Process service json.
|
||||
*
|
||||
* @param json service json
|
||||
* @return service info
|
||||
*/
|
||||
public ServiceInfo processServiceJson(String json) {
|
||||
ServiceInfo serviceInfo = JacksonUtils.toObj(json, ServiceInfo.class);
|
||||
ServiceInfo oldService = serviceInfoMap.get(serviceInfo.getKey());
|
||||
if (serviceInfo.getHosts() == null || !serviceInfo.validate()) {
|
||||
//empty or error push, just ignore
|
||||
return oldService;
|
||||
}
|
||||
|
||||
|
||||
boolean changed = false;
|
||||
|
||||
|
||||
if (oldService != null) {
|
||||
|
||||
|
||||
if (oldService.getLastRefTime() > serviceInfo.getLastRefTime()) {
|
||||
NAMING_LOGGER.warn("out of date data received, old-t: " + oldService.getLastRefTime()
|
||||
+ ", new-t: " + serviceInfo.getLastRefTime());
|
||||
NAMING_LOGGER.warn("out of date data received, old-t: " + oldService.getLastRefTime() + ", new-t: "
|
||||
+ serviceInfo.getLastRefTime());
|
||||
}
|
||||
|
||||
|
||||
serviceInfoMap.put(serviceInfo.getKey(), serviceInfo);
|
||||
|
||||
|
||||
Map<String, Instance> oldHostMap = new HashMap<String, Instance>(oldService.getHosts().size());
|
||||
for (Instance host : oldService.getHosts()) {
|
||||
oldHostMap.put(host.toInetAddr(), host);
|
||||
}
|
||||
|
||||
|
||||
Map<String, Instance> newHostMap = new HashMap<String, Instance>(serviceInfo.getHosts().size());
|
||||
for (Instance host : serviceInfo.getHosts()) {
|
||||
newHostMap.put(host.toInetAddr(), host);
|
||||
}
|
||||
|
||||
|
||||
Set<Instance> modHosts = new HashSet<Instance>();
|
||||
Set<Instance> newHosts = new HashSet<Instance>();
|
||||
Set<Instance> remvHosts = new HashSet<Instance>();
|
||||
|
||||
|
||||
List<Map.Entry<String, Instance>> newServiceHosts = new ArrayList<Map.Entry<String, Instance>>(
|
||||
newHostMap.entrySet());
|
||||
newHostMap.entrySet());
|
||||
for (Map.Entry<String, Instance> entry : newServiceHosts) {
|
||||
Instance host = entry.getValue();
|
||||
String key = entry.getKey();
|
||||
if (oldHostMap.containsKey(key) && !StringUtils.equals(host.toString(),
|
||||
oldHostMap.get(key).toString())) {
|
||||
if (oldHostMap.containsKey(key) && !StringUtils
|
||||
.equals(host.toString(), oldHostMap.get(key).toString())) {
|
||||
modHosts.add(host);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
if (!oldHostMap.containsKey(key)) {
|
||||
newHosts.add(host);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (Map.Entry<String, Instance> entry : oldHostMap.entrySet()) {
|
||||
Instance host = entry.getValue();
|
||||
String key = entry.getKey();
|
||||
if (newHostMap.containsKey(key)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
if (!newHostMap.containsKey(key)) {
|
||||
remvHosts.add(host);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
if (newHosts.size() > 0) {
|
||||
changed = true;
|
||||
NAMING_LOGGER.info("new ips(" + newHosts.size() + ") service: "
|
||||
+ serviceInfo.getKey() + " -> " + JacksonUtils.toJson(newHosts));
|
||||
NAMING_LOGGER.info("new ips(" + newHosts.size() + ") service: " + serviceInfo.getKey() + " -> "
|
||||
+ JacksonUtils.toJson(newHosts));
|
||||
}
|
||||
|
||||
|
||||
if (remvHosts.size() > 0) {
|
||||
changed = true;
|
||||
NAMING_LOGGER.info("removed ips(" + remvHosts.size() + ") service: "
|
||||
+ serviceInfo.getKey() + " -> " + JacksonUtils.toJson(remvHosts));
|
||||
NAMING_LOGGER.info("removed ips(" + remvHosts.size() + ") service: " + serviceInfo.getKey() + " -> "
|
||||
+ JacksonUtils.toJson(remvHosts));
|
||||
}
|
||||
|
||||
|
||||
if (modHosts.size() > 0) {
|
||||
changed = true;
|
||||
updateBeatInfo(modHosts);
|
||||
NAMING_LOGGER.info("modified ips(" + modHosts.size() + ") service: "
|
||||
+ serviceInfo.getKey() + " -> " + JacksonUtils.toJson(modHosts));
|
||||
NAMING_LOGGER.info("modified ips(" + modHosts.size() + ") service: " + serviceInfo.getKey() + " -> "
|
||||
+ JacksonUtils.toJson(modHosts));
|
||||
}
|
||||
|
||||
|
||||
serviceInfo.setJsonFromServer(json);
|
||||
|
||||
|
||||
if (newHosts.size() > 0 || remvHosts.size() > 0 || modHosts.size() > 0) {
|
||||
eventDispatcher.serviceChanged(serviceInfo);
|
||||
DiskCache.write(serviceInfo, cacheDir);
|
||||
}
|
||||
|
||||
|
||||
} else {
|
||||
changed = true;
|
||||
NAMING_LOGGER.info("init new ips(" + serviceInfo.ipCount() + ") service: " + serviceInfo.getKey() + " -> " +
|
||||
JacksonUtils.toJson(serviceInfo.getHosts()));
|
||||
NAMING_LOGGER.info("init new ips(" + serviceInfo.ipCount() + ") service: " + serviceInfo.getKey() + " -> "
|
||||
+ JacksonUtils.toJson(serviceInfo.getHosts()));
|
||||
serviceInfoMap.put(serviceInfo.getKey(), serviceInfo);
|
||||
eventDispatcher.serviceChanged(serviceInfo);
|
||||
serviceInfo.setJsonFromServer(json);
|
||||
DiskCache.write(serviceInfo, cacheDir);
|
||||
}
|
||||
|
||||
|
||||
MetricsMonitor.getServiceInfoMapSizeMonitor().set(serviceInfoMap.size());
|
||||
|
||||
|
||||
if (changed) {
|
||||
NAMING_LOGGER.info("current ips:(" + serviceInfo.ipCount() + ") service: " + serviceInfo.getKey() +
|
||||
" -> " + JacksonUtils.toJson(serviceInfo.getHosts()));
|
||||
NAMING_LOGGER.info("current ips:(" + serviceInfo.ipCount() + ") service: " + serviceInfo.getKey() + " -> "
|
||||
+ JacksonUtils.toJson(serviceInfo.getHosts()));
|
||||
}
|
||||
|
||||
|
||||
return serviceInfo;
|
||||
}
|
||||
|
||||
|
||||
private void updateBeatInfo(Set<Instance> modHosts) {
|
||||
for (Instance instance : modHosts) {
|
||||
String key = beatReactor.buildKey(instance.getServiceName(), instance.getIp(), instance.getPort());
|
||||
@ -231,84 +240,97 @@ public class HostReactor implements Closeable {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private ServiceInfo getServiceInfo0(String serviceName, String clusters) {
|
||||
|
||||
|
||||
String key = ServiceInfo.getKey(serviceName, clusters);
|
||||
|
||||
|
||||
return serviceInfoMap.get(key);
|
||||
}
|
||||
|
||||
public ServiceInfo getServiceInfoDirectlyFromServer(final String serviceName, final String clusters) throws NacosException {
|
||||
|
||||
public ServiceInfo getServiceInfoDirectlyFromServer(final String serviceName, final String clusters)
|
||||
throws NacosException {
|
||||
String result = serverProxy.queryList(serviceName, clusters, 0, false);
|
||||
if (StringUtils.isNotEmpty(result)) {
|
||||
return JacksonUtils.toObj(result, ServiceInfo.class);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public ServiceInfo getServiceInfo(final String serviceName, final String clusters) {
|
||||
|
||||
|
||||
NAMING_LOGGER.debug("failover-mode: " + failoverReactor.isFailoverSwitch());
|
||||
String key = ServiceInfo.getKey(serviceName, clusters);
|
||||
if (failoverReactor.isFailoverSwitch()) {
|
||||
return failoverReactor.getService(key);
|
||||
}
|
||||
|
||||
|
||||
ServiceInfo serviceObj = getServiceInfo0(serviceName, clusters);
|
||||
|
||||
|
||||
if (null == serviceObj) {
|
||||
serviceObj = new ServiceInfo(serviceName, clusters);
|
||||
|
||||
|
||||
serviceInfoMap.put(serviceObj.getKey(), serviceObj);
|
||||
|
||||
|
||||
updatingMap.put(serviceName, new Object());
|
||||
updateServiceNow(serviceName, clusters);
|
||||
updatingMap.remove(serviceName);
|
||||
|
||||
|
||||
} else if (updatingMap.containsKey(serviceName)) {
|
||||
|
||||
|
||||
if (UPDATE_HOLD_INTERVAL > 0) {
|
||||
// hold a moment waiting for update finish
|
||||
synchronized (serviceObj) {
|
||||
try {
|
||||
serviceObj.wait(UPDATE_HOLD_INTERVAL);
|
||||
} catch (InterruptedException e) {
|
||||
NAMING_LOGGER.error("[getServiceInfo] serviceName:" + serviceName + ", clusters:" + clusters, e);
|
||||
NAMING_LOGGER
|
||||
.error("[getServiceInfo] serviceName:" + serviceName + ", clusters:" + clusters, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
scheduleUpdateIfAbsent(serviceName, clusters);
|
||||
|
||||
|
||||
return serviceInfoMap.get(serviceObj.getKey());
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Schedule update if absent.
|
||||
*
|
||||
* @param serviceName service name
|
||||
* @param clusters clusters
|
||||
*/
|
||||
public void scheduleUpdateIfAbsent(String serviceName, String clusters) {
|
||||
if (futureMap.get(ServiceInfo.getKey(serviceName, clusters)) != null) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
synchronized (futureMap) {
|
||||
if (futureMap.get(ServiceInfo.getKey(serviceName, clusters)) != null) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
ScheduledFuture<?> future = addTask(new UpdateTask(serviceName, clusters));
|
||||
futureMap.put(ServiceInfo.getKey(serviceName, clusters), future);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Update service now.
|
||||
*
|
||||
* @param serviceName service name
|
||||
* @param clusters clusters
|
||||
*/
|
||||
public void updateServiceNow(String serviceName, String clusters) {
|
||||
ServiceInfo oldService = getServiceInfo0(serviceName, clusters);
|
||||
try {
|
||||
|
||||
String result = serverProxy.queryList(serviceName, clusters, pushReceiver.getUDPPort(), false);
|
||||
|
||||
|
||||
String result = serverProxy.queryList(serviceName, clusters, pushReceiver.getUdpPort(), false);
|
||||
|
||||
if (StringUtils.isNotEmpty(result)) {
|
||||
processServiceJSON(result);
|
||||
processServiceJson(result);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
NAMING_LOGGER.error("[NA] failed to update serviceName: " + serviceName, e);
|
||||
@ -320,46 +342,57 @@ public class HostReactor implements Closeable {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Refresh only.
|
||||
*
|
||||
* @param serviceName service name
|
||||
* @param clusters cluster
|
||||
*/
|
||||
public void refreshOnly(String serviceName, String clusters) {
|
||||
try {
|
||||
serverProxy.queryList(serviceName, clusters, pushReceiver.getUDPPort(), false);
|
||||
serverProxy.queryList(serviceName, clusters, pushReceiver.getUdpPort(), false);
|
||||
} catch (Exception e) {
|
||||
NAMING_LOGGER.error("[NA] failed to update serviceName: " + serviceName, e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void shutdown() throws NacosException {
|
||||
String className = this.getClass().getName();
|
||||
NAMING_LOGGER.info("{} do shutdown begin", className);
|
||||
ThreadUtils.shutdownThreadPool(executor, NAMING_LOGGER);
|
||||
pushReceiver.shutdown();
|
||||
failoverReactor.shutdown();
|
||||
NAMING_LOGGER.info("{} do shutdown stop", className);
|
||||
}
|
||||
|
||||
|
||||
public class UpdateTask implements Runnable {
|
||||
|
||||
long lastRefTime = Long.MAX_VALUE;
|
||||
private String clusters;
|
||||
private String serviceName;
|
||||
|
||||
|
||||
private final String clusters;
|
||||
|
||||
private final String serviceName;
|
||||
|
||||
public UpdateTask(String serviceName, String clusters) {
|
||||
this.serviceName = serviceName;
|
||||
this.clusters = clusters;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
long delayTime = -1;
|
||||
|
||||
|
||||
try {
|
||||
ServiceInfo serviceObj = serviceInfoMap.get(ServiceInfo.getKey(serviceName, clusters));
|
||||
|
||||
|
||||
if (serviceObj == null) {
|
||||
updateServiceNow(serviceName, clusters);
|
||||
delayTime = DEFAULT_DELAY;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (serviceObj.getLastRefTime() <= lastRefTime) {
|
||||
updateServiceNow(serviceName, clusters);
|
||||
serviceObj = serviceInfoMap.get(ServiceInfo.getKey(serviceName, clusters));
|
||||
@ -368,19 +401,18 @@ public class HostReactor implements Closeable {
|
||||
// since the push data may be different from pull through force push
|
||||
refreshOnly(serviceName, clusters);
|
||||
}
|
||||
|
||||
|
||||
lastRefTime = serviceObj.getLastRefTime();
|
||||
|
||||
if (!eventDispatcher.isSubscribed(serviceName, clusters) &&
|
||||
!futureMap.containsKey(ServiceInfo.getKey(serviceName, clusters))) {
|
||||
// abort the update task:
|
||||
|
||||
if (!eventDispatcher.isSubscribed(serviceName, clusters) && !futureMap
|
||||
.containsKey(ServiceInfo.getKey(serviceName, clusters))) {
|
||||
// abort the update task
|
||||
NAMING_LOGGER.info("update task is stopped, service:" + serviceName + ", clusters:" + clusters);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
delayTime = serviceObj.getCacheMillis();
|
||||
|
||||
|
||||
|
||||
} catch (Throwable e) {
|
||||
NAMING_LOGGER.warn("[NA] failed to update serviceName: " + serviceName, e);
|
||||
} finally {
|
||||
@ -388,7 +420,7 @@ public class HostReactor implements Closeable {
|
||||
executor.schedule(this, delayTime, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -13,23 +13,26 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.client.naming.core;
|
||||
|
||||
/**
|
||||
* Protect mode.
|
||||
*
|
||||
* @author nkorange
|
||||
*/
|
||||
public class ProtectMode {
|
||||
|
||||
|
||||
private float protectThreshold;
|
||||
|
||||
|
||||
public ProtectMode() {
|
||||
this.protectThreshold = 0.8F;
|
||||
}
|
||||
|
||||
|
||||
public float getProtectThreshold() {
|
||||
return protectThreshold;
|
||||
}
|
||||
|
||||
|
||||
public void setProtectThreshold(float protectThreshold) {
|
||||
this.protectThreshold = protectThreshold;
|
||||
}
|
||||
|
@ -13,18 +13,19 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.client.naming.core;
|
||||
|
||||
import com.alibaba.nacos.api.exception.NacosException;
|
||||
import com.alibaba.nacos.common.lifecycle.Closeable;
|
||||
import com.alibaba.nacos.common.utils.IoUtils;
|
||||
import com.alibaba.nacos.common.utils.JacksonUtils;
|
||||
import com.alibaba.nacos.common.utils.StringUtils;
|
||||
import com.alibaba.nacos.common.utils.IoUtils;
|
||||
import com.alibaba.nacos.common.utils.ThreadUtils;
|
||||
|
||||
import java.net.DatagramPacket;
|
||||
import java.net.DatagramSocket;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ScheduledThreadPoolExecutor;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
@ -32,23 +33,26 @@ import java.util.concurrent.ThreadFactory;
|
||||
import static com.alibaba.nacos.client.utils.LogUtils.NAMING_LOGGER;
|
||||
|
||||
/**
|
||||
* Push receiver.
|
||||
*
|
||||
* @author xuanyin
|
||||
*/
|
||||
public class PushReceiver implements Runnable, Closeable {
|
||||
|
||||
|
||||
private ScheduledExecutorService executorService;
|
||||
|
||||
|
||||
private static final int UDP_MSS = 64 * 1024;
|
||||
|
||||
|
||||
private DatagramSocket udpSocket;
|
||||
|
||||
|
||||
private HostReactor hostReactor;
|
||||
|
||||
|
||||
private volatile boolean closed = false;
|
||||
|
||||
public PushReceiver(HostReactor hostReactor) {
|
||||
try {
|
||||
this.hostReactor = hostReactor;
|
||||
this.udpSocket = new DatagramSocket();
|
||||
|
||||
this.executorService = new ScheduledThreadPoolExecutor(1, new ThreadFactory() {
|
||||
@Override
|
||||
public Thread newThread(Runnable r) {
|
||||
@ -58,72 +62,74 @@ public class PushReceiver implements Runnable, Closeable {
|
||||
return thread;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
this.executorService.execute(this);
|
||||
} catch (Exception e) {
|
||||
NAMING_LOGGER.error("[NA] init udp socket failed", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
while (true) {
|
||||
while (!closed) {
|
||||
try {
|
||||
|
||||
// byte[] is initialized with 0 full filled by default
|
||||
byte[] buffer = new byte[UDP_MSS];
|
||||
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
|
||||
|
||||
|
||||
udpSocket.receive(packet);
|
||||
|
||||
String json = new String(IoUtils.tryDecompress(packet.getData()), "UTF-8").trim();
|
||||
|
||||
String json = new String(IoUtils.tryDecompress(packet.getData()), StandardCharsets.UTF_8).trim();
|
||||
NAMING_LOGGER.info("received push data: " + json + " from " + packet.getAddress().toString());
|
||||
|
||||
|
||||
PushPacket pushPacket = JacksonUtils.toObj(json, PushPacket.class);
|
||||
String ack;
|
||||
if ("dom".equals(pushPacket.type) || "service".equals(pushPacket.type)) {
|
||||
hostReactor.processServiceJSON(pushPacket.data);
|
||||
|
||||
hostReactor.processServiceJson(pushPacket.data);
|
||||
|
||||
// send ack to server
|
||||
ack = "{\"type\": \"push-ack\""
|
||||
+ ", \"lastRefTime\":\"" + pushPacket.lastRefTime
|
||||
+ "\", \"data\":" + "\"\"}";
|
||||
ack = "{\"type\": \"push-ack\"" + ", \"lastRefTime\":\"" + pushPacket.lastRefTime + "\", \"data\":"
|
||||
+ "\"\"}";
|
||||
} else if ("dump".equals(pushPacket.type)) {
|
||||
// dump data to server
|
||||
ack = "{\"type\": \"dump-ack\""
|
||||
+ ", \"lastRefTime\": \"" + pushPacket.lastRefTime
|
||||
+ "\", \"data\":" + "\""
|
||||
+ StringUtils.escapeJavaScript(JacksonUtils.toJson(hostReactor.getServiceInfoMap()))
|
||||
+ "\"}";
|
||||
ack = "{\"type\": \"dump-ack\"" + ", \"lastRefTime\": \"" + pushPacket.lastRefTime + "\", \"data\":"
|
||||
+ "\"" + StringUtils.escapeJavaScript(JacksonUtils.toJson(hostReactor.getServiceInfoMap()))
|
||||
+ "\"}";
|
||||
} else {
|
||||
// do nothing send ack only
|
||||
ack = "{\"type\": \"unknown-ack\""
|
||||
+ ", \"lastRefTime\":\"" + pushPacket.lastRefTime
|
||||
+ "\", \"data\":" + "\"\"}";
|
||||
ack = "{\"type\": \"unknown-ack\"" + ", \"lastRefTime\":\"" + pushPacket.lastRefTime
|
||||
+ "\", \"data\":" + "\"\"}";
|
||||
}
|
||||
|
||||
udpSocket.send(new DatagramPacket(ack.getBytes(Charset.forName("UTF-8")),
|
||||
ack.getBytes(Charset.forName("UTF-8")).length, packet.getSocketAddress()));
|
||||
|
||||
udpSocket.send(new DatagramPacket(ack.getBytes(StandardCharsets.UTF_8),
|
||||
ack.getBytes(StandardCharsets.UTF_8).length, packet.getSocketAddress()));
|
||||
} catch (Exception e) {
|
||||
NAMING_LOGGER.error("[NA] error while receiving push data", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void shutdown() throws NacosException {
|
||||
String className = this.getClass().getName();
|
||||
NAMING_LOGGER.info("{} do shutdown begin", className);
|
||||
ThreadUtils.shutdownThreadPool(executorService, NAMING_LOGGER);
|
||||
closed = true;
|
||||
udpSocket.close();
|
||||
NAMING_LOGGER.info("{} do shutdown stop", className);
|
||||
}
|
||||
|
||||
|
||||
public static class PushPacket {
|
||||
|
||||
public String type;
|
||||
|
||||
public long lastRefTime;
|
||||
|
||||
public String data;
|
||||
}
|
||||
|
||||
public int getUDPPort() {
|
||||
|
||||
public int getUdpPort() {
|
||||
return this.udpSocket.getLocalPort();
|
||||
}
|
||||
}
|
||||
|
@ -13,6 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.client.naming.net;
|
||||
|
||||
import com.alibaba.nacos.api.common.Constants;
|
||||
@ -29,51 +30,70 @@ import java.net.HttpURLConnection;
|
||||
import java.net.InetAddress;
|
||||
import java.net.URL;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.*;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
|
||||
import static com.alibaba.nacos.client.utils.LogUtils.NAMING_LOGGER;
|
||||
|
||||
/**
|
||||
* Http client.
|
||||
*
|
||||
* @author nkorange
|
||||
* @deprecated Use NacosRestTemplate{@link NacosRestTemplate} unified http client
|
||||
*/
|
||||
@Deprecated
|
||||
public class HttpClient {
|
||||
|
||||
|
||||
public static final int READ_TIME_OUT_MILLIS = Integer
|
||||
.getInteger("com.alibaba.nacos.client.naming.rtimeout", 50000);
|
||||
public static final int CON_TIME_OUT_MILLIS = Integer
|
||||
.getInteger("com.alibaba.nacos.client.naming.ctimeout", 3000);
|
||||
private static final boolean ENABLE_HTTPS = Boolean
|
||||
.getBoolean("com.alibaba.nacos.client.naming.tls.enable");
|
||||
|
||||
.getInteger("com.alibaba.nacos.client.naming.rtimeout", 50000);
|
||||
|
||||
public static final int CON_TIME_OUT_MILLIS = Integer.getInteger("com.alibaba.nacos.client.naming.ctimeout", 3000);
|
||||
|
||||
private static final boolean ENABLE_HTTPS = Boolean.getBoolean("com.alibaba.nacos.client.naming.tls.enable");
|
||||
|
||||
static {
|
||||
// limit max redirection
|
||||
System.setProperty("http.maxRedirects", "5");
|
||||
}
|
||||
|
||||
|
||||
public static String getPrefix() {
|
||||
if (ENABLE_HTTPS) {
|
||||
return "https://";
|
||||
}
|
||||
|
||||
|
||||
return "http://";
|
||||
|
||||
|
||||
}
|
||||
|
||||
public static HttpResult httpGet(String url, List<String> headers, Map<String, String> paramValues, String encoding) {
|
||||
|
||||
public static HttpResult httpGet(String url, List<String> headers, Map<String, String> paramValues,
|
||||
String encoding) {
|
||||
return request(url, headers, paramValues, StringUtils.EMPTY, encoding, HttpMethod.GET);
|
||||
}
|
||||
|
||||
public static HttpResult request(String url, List<String> headers, Map<String, String> paramValues, String body, String encoding, String method) {
|
||||
|
||||
/**
|
||||
* request.
|
||||
*
|
||||
* @param url url
|
||||
* @param headers headers
|
||||
* @param paramValues paramValues
|
||||
* @param body body
|
||||
* @param encoding encoding
|
||||
* @param method method
|
||||
* @return result
|
||||
*/
|
||||
public static HttpResult request(String url, List<String> headers, Map<String, String> paramValues, String body,
|
||||
String encoding, String method) {
|
||||
HttpURLConnection conn = null;
|
||||
try {
|
||||
String encodedContent = encodingParams(paramValues, encoding);
|
||||
url += (StringUtils.isEmpty(encodedContent)) ? "" : ("?" + encodedContent);
|
||||
|
||||
|
||||
conn = (HttpURLConnection) new URL(url).openConnection();
|
||||
|
||||
|
||||
setHeaders(conn, headers, encoding);
|
||||
conn.setConnectTimeout(CON_TIME_OUT_MILLIS);
|
||||
conn.setReadTimeout(READ_TIME_OUT_MILLIS);
|
||||
@ -94,46 +114,45 @@ public class HttpClient {
|
||||
} catch (Exception e) {
|
||||
try {
|
||||
if (conn != null) {
|
||||
NAMING_LOGGER.warn("failed to request " + conn.getURL() + " from "
|
||||
+ InetAddress.getByName(conn.getURL().getHost()).getHostAddress());
|
||||
NAMING_LOGGER.warn("failed to request " + conn.getURL() + " from " + InetAddress
|
||||
.getByName(conn.getURL().getHost()).getHostAddress());
|
||||
}
|
||||
} catch (Exception e1) {
|
||||
NAMING_LOGGER.error("[NA] failed to request ", e1);
|
||||
} catch (Exception ex) {
|
||||
NAMING_LOGGER.error("[NA] failed to request ", ex);
|
||||
//ignore
|
||||
}
|
||||
|
||||
|
||||
NAMING_LOGGER.error("[NA] failed to request ", e);
|
||||
|
||||
|
||||
return new HttpResult(500, e.toString(), Collections.<String, String>emptyMap());
|
||||
} finally {
|
||||
IoUtils.closeQuietly(conn);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static HttpResult getResult(HttpURLConnection conn) throws IOException {
|
||||
int respCode = conn.getResponseCode();
|
||||
|
||||
|
||||
InputStream inputStream;
|
||||
if (HttpURLConnection.HTTP_OK == respCode
|
||||
|| HttpURLConnection.HTTP_NOT_MODIFIED == respCode
|
||||
|| Constants.WRITE_REDIRECT_CODE == respCode) {
|
||||
if (HttpURLConnection.HTTP_OK == respCode || HttpURLConnection.HTTP_NOT_MODIFIED == respCode
|
||||
|| Constants.WRITE_REDIRECT_CODE == respCode) {
|
||||
inputStream = conn.getInputStream();
|
||||
} else {
|
||||
inputStream = conn.getErrorStream();
|
||||
}
|
||||
|
||||
|
||||
Map<String, String> respHeaders = new HashMap<String, String>(conn.getHeaderFields().size());
|
||||
for (Map.Entry<String, List<String>> entry : conn.getHeaderFields().entrySet()) {
|
||||
respHeaders.put(entry.getKey(), entry.getValue().get(0));
|
||||
}
|
||||
|
||||
|
||||
String encodingGzip = "gzip";
|
||||
|
||||
|
||||
if (encodingGzip.equals(respHeaders.get(HttpHeaders.CONTENT_ENCODING))) {
|
||||
inputStream = new GZIPInputStream(inputStream);
|
||||
}
|
||||
HttpResult httpResult = new HttpResult(respCode, IoUtils.toString(inputStream, getCharset(conn)), respHeaders);
|
||||
|
||||
|
||||
//InputStream from HttpURLConnection can be closed automatically,but new GZIPInputStream can't be closed automatically
|
||||
//so needs to close it manually
|
||||
if (inputStream instanceof GZIPInputStream) {
|
||||
@ -141,86 +160,88 @@ public class HttpClient {
|
||||
}
|
||||
return httpResult;
|
||||
}
|
||||
|
||||
|
||||
private static String getCharset(HttpURLConnection conn) {
|
||||
String contentType = conn.getContentType();
|
||||
if (StringUtils.isEmpty(contentType)) {
|
||||
return "UTF-8";
|
||||
}
|
||||
|
||||
|
||||
String[] values = contentType.split(";");
|
||||
if (values.length == 0) {
|
||||
return "UTF-8";
|
||||
}
|
||||
|
||||
|
||||
String charset = "UTF-8";
|
||||
for (String value : values) {
|
||||
value = value.trim();
|
||||
|
||||
|
||||
if (value.toLowerCase().startsWith("charset=")) {
|
||||
charset = value.substring("charset=".length());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return charset;
|
||||
}
|
||||
|
||||
|
||||
private static void setHeaders(HttpURLConnection conn, List<String> headers, String encoding) {
|
||||
if (null != headers) {
|
||||
for (Iterator<String> iter = headers.iterator(); iter.hasNext(); ) {
|
||||
conn.addRequestProperty(iter.next(), iter.next());
|
||||
}
|
||||
}
|
||||
|
||||
conn.addRequestProperty("Content-Type", "application/x-www-form-urlencoded;charset="
|
||||
+ encoding);
|
||||
|
||||
conn.addRequestProperty("Content-Type", "application/x-www-form-urlencoded;charset=" + encoding);
|
||||
conn.addRequestProperty("Accept-Charset", encoding);
|
||||
}
|
||||
|
||||
|
||||
private static String encodingParams(Map<String, String> params, String encoding)
|
||||
throws UnsupportedEncodingException {
|
||||
throws UnsupportedEncodingException {
|
||||
if (null == params || params.isEmpty()) {
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
params.put("encoding", encoding);
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
|
||||
for (Map.Entry<String, String> entry : params.entrySet()) {
|
||||
if (StringUtils.isEmpty(entry.getValue())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
sb.append(entry.getKey()).append("=");
|
||||
sb.append(URLEncoder.encode(entry.getValue(), encoding));
|
||||
sb.append("&");
|
||||
}
|
||||
|
||||
|
||||
if (sb.length() > 0) {
|
||||
sb = sb.deleteCharAt(sb.length() - 1);
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
|
||||
public static class HttpResult {
|
||||
final public int code;
|
||||
final public String content;
|
||||
final private Map<String, String> respHeaders;
|
||||
|
||||
|
||||
public final int code;
|
||||
|
||||
public final String content;
|
||||
|
||||
private final Map<String, String> respHeaders;
|
||||
|
||||
public HttpResult(int code, String content, Map<String, String> respHeaders) {
|
||||
this.code = code;
|
||||
this.content = content;
|
||||
this.respHeaders = respHeaders;
|
||||
}
|
||||
|
||||
|
||||
public String getHeader(String name) {
|
||||
return respHeaders.get(name);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "HttpResult{" + "code=" + code + ", content='" + content + '\''
|
||||
+ ", respHeaders=" + respHeaders + '}';
|
||||
return "HttpResult{" + "code=" + code + ", content='" + content + '\'' + ", respHeaders=" + respHeaders
|
||||
+ '}';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -16,48 +16,79 @@
|
||||
|
||||
package com.alibaba.nacos.client.naming.net;
|
||||
|
||||
import com.alibaba.nacos.api.exception.NacosException;
|
||||
import com.alibaba.nacos.common.http.AbstractHttpClientFactory;
|
||||
import com.alibaba.nacos.common.http.HttpClientBeanHolder;
|
||||
import com.alibaba.nacos.common.http.HttpClientConfig;
|
||||
import com.alibaba.nacos.common.http.HttpClientFactory;
|
||||
import com.alibaba.nacos.common.http.client.NacosRestTemplate;
|
||||
import com.alibaba.nacos.common.lifecycle.Closeable;
|
||||
import com.alibaba.nacos.common.utils.ExceptionUtil;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import static com.alibaba.nacos.client.utils.LogUtils.NAMING_LOGGER;
|
||||
|
||||
/**
|
||||
* http Manager
|
||||
* http Manager.
|
||||
*
|
||||
* @author mai.jh
|
||||
*/
|
||||
public class NamingHttpClientManager {
|
||||
public class NamingHttpClientManager implements Closeable {
|
||||
|
||||
private static final int READ_TIME_OUT_MILLIS = Integer
|
||||
.getInteger("com.alibaba.nacos.client.naming.rtimeout", 50000);
|
||||
private static final int CON_TIME_OUT_MILLIS = Integer
|
||||
.getInteger("com.alibaba.nacos.client.naming.ctimeout", 3000);
|
||||
private static final boolean ENABLE_HTTPS = Boolean
|
||||
.getBoolean("com.alibaba.nacos.client.naming.tls.enable");
|
||||
.getInteger("com.alibaba.nacos.client.naming.rtimeout", 50000);
|
||||
|
||||
private static final int CON_TIME_OUT_MILLIS = Integer.getInteger("com.alibaba.nacos.client.naming.ctimeout", 3000);
|
||||
|
||||
private static final boolean ENABLE_HTTPS = Boolean.getBoolean("com.alibaba.nacos.client.naming.tls.enable");
|
||||
|
||||
private static final int MAX_REDIRECTS = 5;
|
||||
|
||||
private static final HttpClientFactory HTTP_CLIENT_FACTORY = new NamingHttpClientFactory();
|
||||
|
||||
public static String getPrefix() {
|
||||
private static class NamingHttpClientManagerInstance {
|
||||
|
||||
private static final NamingHttpClientManager INSTANCE = new NamingHttpClientManager();
|
||||
}
|
||||
|
||||
public static NamingHttpClientManager getInstance() {
|
||||
return NamingHttpClientManagerInstance.INSTANCE;
|
||||
}
|
||||
|
||||
public String getPrefix() {
|
||||
if (ENABLE_HTTPS) {
|
||||
return "https://";
|
||||
}
|
||||
return "http://";
|
||||
}
|
||||
|
||||
public static NacosRestTemplate getNacosRestTemplate() {
|
||||
public NacosRestTemplate getNacosRestTemplate() {
|
||||
return HttpClientBeanHolder.getNacosRestTemplate(HTTP_CLIENT_FACTORY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shutdown() throws NacosException {
|
||||
NAMING_LOGGER.warn("[NamingHttpClientManager] Start destroying NacosRestTemplate");
|
||||
try {
|
||||
HttpClientBeanHolder.shutdownNacostSyncRest(HTTP_CLIENT_FACTORY.getClass().getName());
|
||||
} catch (Exception ex) {
|
||||
NAMING_LOGGER.error("[NamingHttpClientManager] An exception occurred when the HTTP client was closed : {}",
|
||||
ExceptionUtil.getStackTrace(ex));
|
||||
}
|
||||
NAMING_LOGGER.warn("[NamingHttpClientManager] Destruction of the end");
|
||||
}
|
||||
|
||||
private static class NamingHttpClientFactory extends AbstractHttpClientFactory {
|
||||
|
||||
@Override
|
||||
protected HttpClientConfig buildHttpClientConfig() {
|
||||
return HttpClientConfig.builder()
|
||||
.setConTimeOutMillis(CON_TIME_OUT_MILLIS)
|
||||
.setReadTimeOutMillis(READ_TIME_OUT_MILLIS)
|
||||
.setMaxRedirects(MAX_REDIRECTS).build();
|
||||
return HttpClientConfig.builder().setConTimeOutMillis(CON_TIME_OUT_MILLIS)
|
||||
.setReadTimeOutMillis(READ_TIME_OUT_MILLIS).setMaxRedirects(MAX_REDIRECTS).build();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Logger assignLogger() {
|
||||
return NAMING_LOGGER;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -13,6 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.client.naming.net;
|
||||
|
||||
import com.alibaba.nacos.api.PropertyKeyConst;
|
||||
@ -42,66 +43,72 @@ import com.alibaba.nacos.common.http.client.NacosRestTemplate;
|
||||
import com.alibaba.nacos.common.http.param.Header;
|
||||
import com.alibaba.nacos.common.http.param.Query;
|
||||
import com.alibaba.nacos.common.lifecycle.Closeable;
|
||||
import com.alibaba.nacos.common.utils.*;
|
||||
import com.alibaba.nacos.common.utils.HttpMethod;
|
||||
import com.alibaba.nacos.common.utils.IoUtils;
|
||||
import com.alibaba.nacos.common.utils.JacksonUtils;
|
||||
import com.alibaba.nacos.common.utils.StringUtils;
|
||||
import com.alibaba.nacos.common.utils.ThreadUtils;
|
||||
import com.alibaba.nacos.common.utils.UuidUtils;
|
||||
import com.alibaba.nacos.common.utils.VersionUtils;
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import org.apache.http.HttpStatus;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.StringReader;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
import java.util.Map;
|
||||
import java.util.HashMap;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ScheduledThreadPoolExecutor;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
import static com.alibaba.nacos.client.utils.LogUtils.NAMING_LOGGER;
|
||||
|
||||
/**
|
||||
* Naming proxy.
|
||||
*
|
||||
* @author nkorange
|
||||
*/
|
||||
public class NamingProxy implements Closeable {
|
||||
|
||||
private NacosRestTemplate nacosRestTemplate = NamingHttpClientManager.getNacosRestTemplate();
|
||||
|
||||
|
||||
private final NacosRestTemplate nacosRestTemplate = NamingHttpClientManager.getInstance().getNacosRestTemplate();
|
||||
|
||||
private static final int DEFAULT_SERVER_PORT = 8848;
|
||||
|
||||
|
||||
private int serverPort = DEFAULT_SERVER_PORT;
|
||||
|
||||
private String namespaceId;
|
||||
|
||||
private String endpoint;
|
||||
|
||||
|
||||
private final String namespaceId;
|
||||
|
||||
private final String endpoint;
|
||||
|
||||
private String nacosDomain;
|
||||
|
||||
|
||||
private List<String> serverList;
|
||||
|
||||
|
||||
private List<String> serversFromEndpoint = new ArrayList<String>();
|
||||
|
||||
private SecurityProxy securityProxy;
|
||||
|
||||
|
||||
private final SecurityProxy securityProxy;
|
||||
|
||||
private long lastSrvRefTime = 0L;
|
||||
|
||||
private long vipSrvRefInterMillis = TimeUnit.SECONDS.toMillis(30);
|
||||
|
||||
private long securityInfoRefreshIntervalMills = TimeUnit.SECONDS.toMillis(5);
|
||||
|
||||
|
||||
private final long vipSrvRefInterMillis = TimeUnit.SECONDS.toMillis(30);
|
||||
|
||||
private final long securityInfoRefreshIntervalMills = TimeUnit.SECONDS.toMillis(5);
|
||||
|
||||
private Properties properties;
|
||||
|
||||
|
||||
private ScheduledExecutorService executorService;
|
||||
|
||||
|
||||
public NamingProxy(String namespaceId, String endpoint, String serverList, Properties properties) {
|
||||
|
||||
|
||||
this.securityProxy = new SecurityProxy(properties);
|
||||
this.properties = properties;
|
||||
this.setServerPort(DEFAULT_SERVER_PORT);
|
||||
@ -115,9 +122,9 @@ public class NamingProxy implements Closeable {
|
||||
}
|
||||
this.initRefreshTask();
|
||||
}
|
||||
|
||||
|
||||
private void initRefreshTask() {
|
||||
|
||||
|
||||
this.executorService = new ScheduledThreadPoolExecutor(2, new ThreadFactory() {
|
||||
@Override
|
||||
public Thread newThread(Runnable r) {
|
||||
@ -127,37 +134,36 @@ public class NamingProxy implements Closeable {
|
||||
return t;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
this.executorService.scheduleWithFixedDelay(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
refreshSrvIfNeed();
|
||||
}
|
||||
}, 0, vipSrvRefInterMillis, TimeUnit.MILLISECONDS);
|
||||
|
||||
|
||||
|
||||
this.executorService.scheduleWithFixedDelay(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
securityProxy.login(getServerList());
|
||||
}
|
||||
}, 0, securityInfoRefreshIntervalMills, TimeUnit.MILLISECONDS);
|
||||
|
||||
|
||||
refreshSrvIfNeed();
|
||||
this.securityProxy.login(getServerList());
|
||||
}
|
||||
|
||||
|
||||
public List<String> getServerListFromEndpoint() {
|
||||
|
||||
|
||||
try {
|
||||
String urlString = "http://" + endpoint + "/nacos/serverlist";
|
||||
Header header = builderHeader();
|
||||
HttpRestResult<String> restResult = nacosRestTemplate.get(urlString, header, Query.EMPTY, String.class);
|
||||
if (!restResult.ok()) {
|
||||
throw new IOException("Error while requesting: " + urlString + "'. Server returned: "
|
||||
+ restResult.getCode());
|
||||
throw new IOException(
|
||||
"Error while requesting: " + urlString + "'. Server returned: " + restResult.getCode());
|
||||
}
|
||||
|
||||
|
||||
String content = restResult.getData();
|
||||
List<String> list = new ArrayList<String>();
|
||||
for (String line : IoUtils.readLines(new StringReader(content))) {
|
||||
@ -165,50 +171,58 @@ public class NamingProxy implements Closeable {
|
||||
list.add(line.trim());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return list;
|
||||
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
private void refreshSrvIfNeed() {
|
||||
try {
|
||||
|
||||
|
||||
if (!CollectionUtils.isEmpty(serverList)) {
|
||||
NAMING_LOGGER.debug("server list provided by user: " + serverList);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (System.currentTimeMillis() - lastSrvRefTime < vipSrvRefInterMillis) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
List<String> list = getServerListFromEndpoint();
|
||||
|
||||
|
||||
if (CollectionUtils.isEmpty(list)) {
|
||||
throw new Exception("Can not acquire Nacos list");
|
||||
}
|
||||
|
||||
|
||||
if (!CollectionUtils.isEqualCollection(list, serversFromEndpoint)) {
|
||||
NAMING_LOGGER.info("[SERVER-LIST] server list is updated: " + list);
|
||||
}
|
||||
|
||||
|
||||
serversFromEndpoint = list;
|
||||
lastSrvRefTime = System.currentTimeMillis();
|
||||
} catch (Throwable e) {
|
||||
NAMING_LOGGER.warn("failed to update server list", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* register a instance to service with specified instance properties.
|
||||
*
|
||||
* @param serviceName name of service
|
||||
* @param groupName group of service
|
||||
* @param instance instance to register
|
||||
* @throws NacosException nacos exception
|
||||
*/
|
||||
public void registerService(String serviceName, String groupName, Instance instance) throws NacosException {
|
||||
|
||||
NAMING_LOGGER.info("[REGISTER-SERVICE] {} registering service {} with instance: {}",
|
||||
namespaceId, serviceName, instance);
|
||||
|
||||
|
||||
NAMING_LOGGER.info("[REGISTER-SERVICE] {} registering service {} with instance: {}", namespaceId, serviceName,
|
||||
instance);
|
||||
|
||||
final Map<String, String> params = new HashMap<String, String>(16);
|
||||
params.put(CommonParams.NAMESPACE_ID, namespaceId);
|
||||
params.put(CommonParams.SERVICE_NAME, serviceName);
|
||||
@ -221,16 +235,24 @@ public class NamingProxy implements Closeable {
|
||||
params.put("healthy", String.valueOf(instance.isHealthy()));
|
||||
params.put("ephemeral", String.valueOf(instance.isEphemeral()));
|
||||
params.put("metadata", JacksonUtils.toJson(instance.getMetadata()));
|
||||
|
||||
reqAPI(UtilAndComs.NACOS_URL_INSTANCE, params, HttpMethod.POST);
|
||||
|
||||
|
||||
reqApi(UtilAndComs.nacosUrlInstance, params, HttpMethod.POST);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* deregister instance from a service.
|
||||
*
|
||||
* @param serviceName name of service
|
||||
* @param instance instance
|
||||
* @throws NacosException nacos exception
|
||||
*/
|
||||
public void deregisterService(String serviceName, Instance instance) throws NacosException {
|
||||
|
||||
NAMING_LOGGER.info("[DEREGISTER-SERVICE] {} deregistering service {} with instance: {}",
|
||||
namespaceId, serviceName, instance);
|
||||
|
||||
|
||||
NAMING_LOGGER
|
||||
.info("[DEREGISTER-SERVICE] {} deregistering service {} with instance: {}", namespaceId, serviceName,
|
||||
instance);
|
||||
|
||||
final Map<String, String> params = new HashMap<String, String>(8);
|
||||
params.put(CommonParams.NAMESPACE_ID, namespaceId);
|
||||
params.put(CommonParams.SERVICE_NAME, serviceName);
|
||||
@ -238,14 +260,22 @@ public class NamingProxy implements Closeable {
|
||||
params.put("ip", instance.getIp());
|
||||
params.put("port", String.valueOf(instance.getPort()));
|
||||
params.put("ephemeral", String.valueOf(instance.isEphemeral()));
|
||||
|
||||
reqAPI(UtilAndComs.NACOS_URL_INSTANCE, params, HttpMethod.DELETE);
|
||||
|
||||
reqApi(UtilAndComs.nacosUrlInstance, params, HttpMethod.DELETE);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Update instance to service.
|
||||
*
|
||||
* @param serviceName service name
|
||||
* @param groupName group name
|
||||
* @param instance instance
|
||||
* @throws NacosException nacos exception
|
||||
*/
|
||||
public void updateInstance(String serviceName, String groupName, Instance instance) throws NacosException {
|
||||
NAMING_LOGGER.info("[UPDATE-SERVICE] {} update service {} with instance: {}",
|
||||
namespaceId, serviceName, instance);
|
||||
|
||||
NAMING_LOGGER
|
||||
.info("[UPDATE-SERVICE] {} update service {} with instance: {}", namespaceId, serviceName, instance);
|
||||
|
||||
final Map<String, String> params = new HashMap<String, String>(8);
|
||||
params.put(CommonParams.NAMESPACE_ID, namespaceId);
|
||||
params.put(CommonParams.SERVICE_NAME, serviceName);
|
||||
@ -257,28 +287,41 @@ public class NamingProxy implements Closeable {
|
||||
params.put("enabled", String.valueOf(instance.isEnabled()));
|
||||
params.put("ephemeral", String.valueOf(instance.isEphemeral()));
|
||||
params.put("metadata", JacksonUtils.toJson(instance.getMetadata()));
|
||||
|
||||
reqAPI(UtilAndComs.NACOS_URL_INSTANCE, params, HttpMethod.PUT);
|
||||
|
||||
reqApi(UtilAndComs.nacosUrlInstance, params, HttpMethod.PUT);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Query Service.
|
||||
*
|
||||
* @param serviceName service name
|
||||
* @param groupName group name
|
||||
* @return service
|
||||
* @throws NacosException nacos exception
|
||||
*/
|
||||
public Service queryService(String serviceName, String groupName) throws NacosException {
|
||||
NAMING_LOGGER.info("[QUERY-SERVICE] {} query service : {}, {}",
|
||||
namespaceId, serviceName, groupName);
|
||||
|
||||
NAMING_LOGGER.info("[QUERY-SERVICE] {} query service : {}, {}", namespaceId, serviceName, groupName);
|
||||
|
||||
final Map<String, String> params = new HashMap<String, String>(3);
|
||||
params.put(CommonParams.NAMESPACE_ID, namespaceId);
|
||||
params.put(CommonParams.SERVICE_NAME, serviceName);
|
||||
params.put(CommonParams.GROUP_NAME, groupName);
|
||||
|
||||
String result = reqAPI(UtilAndComs.NACOS_URL_SERVICE, params, HttpMethod.GET);
|
||||
|
||||
String result = reqApi(UtilAndComs.nacosUrlService, params, HttpMethod.GET);
|
||||
return JacksonUtils.toObj(result, Service.class);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create service.
|
||||
*
|
||||
* @param service service
|
||||
* @param selector selector
|
||||
* @throws NacosException nacos exception
|
||||
*/
|
||||
public void createService(Service service, AbstractSelector selector) throws NacosException {
|
||||
|
||||
NAMING_LOGGER.info("[CREATE-SERVICE] {} creating service : {}",
|
||||
namespaceId, service);
|
||||
|
||||
|
||||
NAMING_LOGGER.info("[CREATE-SERVICE] {} creating service : {}", namespaceId, service);
|
||||
|
||||
final Map<String, String> params = new HashMap<String, String>(6);
|
||||
params.put(CommonParams.NAMESPACE_ID, namespaceId);
|
||||
params.put(CommonParams.SERVICE_NAME, service.getName());
|
||||
@ -286,28 +329,42 @@ public class NamingProxy implements Closeable {
|
||||
params.put("protectThreshold", String.valueOf(service.getProtectThreshold()));
|
||||
params.put("metadata", JacksonUtils.toJson(service.getMetadata()));
|
||||
params.put("selector", JacksonUtils.toJson(selector));
|
||||
|
||||
reqAPI(UtilAndComs.NACOS_URL_SERVICE, params, HttpMethod.POST);
|
||||
|
||||
|
||||
reqApi(UtilAndComs.nacosUrlService, params, HttpMethod.POST);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Delete service.
|
||||
*
|
||||
* @param serviceName service name
|
||||
* @param groupName group name
|
||||
* @return true if delete ok
|
||||
* @throws NacosException nacos exception
|
||||
*/
|
||||
public boolean deleteService(String serviceName, String groupName) throws NacosException {
|
||||
NAMING_LOGGER.info("[DELETE-SERVICE] {} deleting service : {} with groupName : {}",
|
||||
namespaceId, serviceName, groupName);
|
||||
|
||||
NAMING_LOGGER.info("[DELETE-SERVICE] {} deleting service : {} with groupName : {}", namespaceId, serviceName,
|
||||
groupName);
|
||||
|
||||
final Map<String, String> params = new HashMap<String, String>(6);
|
||||
params.put(CommonParams.NAMESPACE_ID, namespaceId);
|
||||
params.put(CommonParams.SERVICE_NAME, serviceName);
|
||||
params.put(CommonParams.GROUP_NAME, groupName);
|
||||
|
||||
String result = reqAPI(UtilAndComs.NACOS_URL_SERVICE, params, HttpMethod.DELETE);
|
||||
|
||||
String result = reqApi(UtilAndComs.nacosUrlService, params, HttpMethod.DELETE);
|
||||
return "ok".equals(result);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Update service.
|
||||
*
|
||||
* @param service service
|
||||
* @param selector selector
|
||||
* @throws NacosException nacos exception
|
||||
*/
|
||||
public void updateService(Service service, AbstractSelector selector) throws NacosException {
|
||||
NAMING_LOGGER.info("[UPDATE-SERVICE] {} updating service : {}",
|
||||
namespaceId, service);
|
||||
|
||||
NAMING_LOGGER.info("[UPDATE-SERVICE] {} updating service : {}", namespaceId, service);
|
||||
|
||||
final Map<String, String> params = new HashMap<String, String>(6);
|
||||
params.put(CommonParams.NAMESPACE_ID, namespaceId);
|
||||
params.put(CommonParams.SERVICE_NAME, service.getName());
|
||||
@ -315,13 +372,23 @@ public class NamingProxy implements Closeable {
|
||||
params.put("protectThreshold", String.valueOf(service.getProtectThreshold()));
|
||||
params.put("metadata", JacksonUtils.toJson(service.getMetadata()));
|
||||
params.put("selector", JacksonUtils.toJson(selector));
|
||||
|
||||
reqAPI(UtilAndComs.NACOS_URL_SERVICE, params, HttpMethod.PUT);
|
||||
|
||||
reqApi(UtilAndComs.nacosUrlService, params, HttpMethod.PUT);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Query instance list.
|
||||
*
|
||||
* @param serviceName service name
|
||||
* @param clusters clusters
|
||||
* @param udpPort udp port
|
||||
* @param healthyOnly healthy only
|
||||
* @return instance list
|
||||
* @throws NacosException nacos exception
|
||||
*/
|
||||
public String queryList(String serviceName, String clusters, int udpPort, boolean healthyOnly)
|
||||
throws NacosException {
|
||||
|
||||
throws NacosException {
|
||||
|
||||
final Map<String, String> params = new HashMap<String, String>(8);
|
||||
params.put(CommonParams.NAMESPACE_ID, namespaceId);
|
||||
params.put(CommonParams.SERVICE_NAME, serviceName);
|
||||
@ -329,38 +396,47 @@ public class NamingProxy implements Closeable {
|
||||
params.put("udpPort", String.valueOf(udpPort));
|
||||
params.put("clientIP", NetUtils.localIP());
|
||||
params.put("healthyOnly", String.valueOf(healthyOnly));
|
||||
|
||||
return reqAPI(UtilAndComs.NACOS_URL_BASE + "/instance/list", params, HttpMethod.GET);
|
||||
|
||||
return reqApi(UtilAndComs.nacosUrlBase + "/instance/list", params, HttpMethod.GET);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Send beat.
|
||||
*
|
||||
* @param beatInfo beat info
|
||||
* @param lightBeatEnabled light beat
|
||||
* @return beat result
|
||||
* @throws NacosException nacos exception
|
||||
*/
|
||||
public JsonNode sendBeat(BeatInfo beatInfo, boolean lightBeatEnabled) throws NacosException {
|
||||
|
||||
|
||||
if (NAMING_LOGGER.isDebugEnabled()) {
|
||||
NAMING_LOGGER.debug("[BEAT] {} sending beat to server: {}", namespaceId, beatInfo.toString());
|
||||
}
|
||||
Map<String, String> params = new HashMap<String, String>(8);
|
||||
Map<String, String> bodyMap = new HashMap<String, String>(2);
|
||||
if (!lightBeatEnabled) {
|
||||
try {
|
||||
bodyMap.put("beat", URLEncoder.encode(JacksonUtils.toJson(beatInfo), "UTF-8"));
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new NacosException(NacosException.SERVER_ERROR, "encode beatInfo error", e);
|
||||
}
|
||||
bodyMap.put("beat", JacksonUtils.toJson(beatInfo));
|
||||
}
|
||||
params.put(CommonParams.NAMESPACE_ID, namespaceId);
|
||||
params.put(CommonParams.SERVICE_NAME, beatInfo.getServiceName());
|
||||
params.put(CommonParams.CLUSTER_NAME, beatInfo.getCluster());
|
||||
params.put("ip", beatInfo.getIp());
|
||||
params.put("port", String.valueOf(beatInfo.getPort()));
|
||||
String result = reqAPI(UtilAndComs.NACOS_URL_BASE + "/instance/beat", params, bodyMap, HttpMethod.PUT);
|
||||
String result = reqApi(UtilAndComs.nacosUrlBase + "/instance/beat", params, bodyMap, HttpMethod.PUT);
|
||||
return JacksonUtils.toObj(result);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check Server healthy.
|
||||
*
|
||||
* @return true if server is healthy
|
||||
*/
|
||||
public boolean serverHealthy() {
|
||||
|
||||
|
||||
try {
|
||||
String result = reqAPI(UtilAndComs.NACOS_URL_BASE + "/operator/metrics",
|
||||
new HashMap<String, String>(2), HttpMethod.GET);
|
||||
String result = reqApi(UtilAndComs.nacosUrlBase + "/operator/metrics", new HashMap<String, String>(2),
|
||||
HttpMethod.GET);
|
||||
JsonNode json = JacksonUtils.toObj(result);
|
||||
String serverStatus = json.get("status").asText();
|
||||
return "UP".equals(serverStatus);
|
||||
@ -368,19 +444,20 @@ public class NamingProxy implements Closeable {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public ListView<String> getServiceList(int pageNo, int pageSize, String groupName) throws NacosException {
|
||||
return getServiceList(pageNo, pageSize, groupName, null);
|
||||
}
|
||||
|
||||
public ListView<String> getServiceList(int pageNo, int pageSize, String groupName, AbstractSelector selector) throws NacosException {
|
||||
|
||||
|
||||
public ListView<String> getServiceList(int pageNo, int pageSize, String groupName, AbstractSelector selector)
|
||||
throws NacosException {
|
||||
|
||||
Map<String, String> params = new HashMap<String, String>(4);
|
||||
params.put("pageNo", String.valueOf(pageNo));
|
||||
params.put("pageSize", String.valueOf(pageSize));
|
||||
params.put(CommonParams.NAMESPACE_ID, namespaceId);
|
||||
params.put(CommonParams.GROUP_NAME, groupName);
|
||||
|
||||
|
||||
if (selector != null) {
|
||||
switch (SelectorType.valueOf(selector.getType())) {
|
||||
case none:
|
||||
@ -393,89 +470,54 @@ public class NamingProxy implements Closeable {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
String result = reqAPI(UtilAndComs.NACOS_URL_BASE + "/service/list", params, HttpMethod.GET);
|
||||
|
||||
|
||||
String result = reqApi(UtilAndComs.nacosUrlBase + "/service/list", params, HttpMethod.GET);
|
||||
|
||||
JsonNode json = JacksonUtils.toObj(result);
|
||||
ListView<String> listView = new ListView<>();
|
||||
ListView<String> listView = new ListView<String>();
|
||||
listView.setCount(json.get("count").asInt());
|
||||
listView.setData(JacksonUtils.toObj(json.get("doms").toString(), new TypeReference<List<String>>() {}));
|
||||
|
||||
listView.setData(JacksonUtils.toObj(json.get("doms").toString(), new TypeReference<List<String>>() {
|
||||
}));
|
||||
|
||||
return listView;
|
||||
}
|
||||
|
||||
public String reqAPI(String api, Map<String, String> params, String method) throws NacosException {
|
||||
return reqAPI(api, params, Collections.EMPTY_MAP, method);
|
||||
|
||||
public String reqApi(String api, Map<String, String> params, String method) throws NacosException {
|
||||
return reqApi(api, params, Collections.EMPTY_MAP, method);
|
||||
}
|
||||
|
||||
public String reqAPI(String api, Map<String, String> params, Map<String, String> body, String method) throws NacosException {
|
||||
return reqAPI(api, params, body, getServerList(), method);
|
||||
|
||||
public String reqApi(String api, Map<String, String> params, Map<String, String> body, String method)
|
||||
throws NacosException {
|
||||
return reqApi(api, params, body, getServerList(), method);
|
||||
}
|
||||
|
||||
private List<String> getServerList() {
|
||||
List<String> snapshot = serversFromEndpoint;
|
||||
if (!CollectionUtils.isEmpty(serverList)) {
|
||||
snapshot = serverList;
|
||||
}
|
||||
return snapshot;
|
||||
}
|
||||
|
||||
public String callServer(String api, Map<String, String> params, Map<String, String> body, String curServer) throws NacosException {
|
||||
return callServer(api, params, body, curServer, HttpMethod.GET);
|
||||
}
|
||||
|
||||
public String callServer(String api, Map<String, String> params, Map<String, String> body, String curServer, String method)
|
||||
throws NacosException {
|
||||
long start = System.currentTimeMillis();
|
||||
long end = 0;
|
||||
injectSecurityInfo(params);
|
||||
Header header = builderHeader();
|
||||
|
||||
String url;
|
||||
if (curServer.startsWith(UtilAndComs.HTTPS) || curServer.startsWith(UtilAndComs.HTTP)) {
|
||||
url = curServer + api;
|
||||
} else {
|
||||
if (!curServer.contains(UtilAndComs.SERVER_ADDR_IP_SPLITER)) {
|
||||
curServer = curServer + UtilAndComs.SERVER_ADDR_IP_SPLITER + serverPort;
|
||||
}
|
||||
url = NamingHttpClientManager.getPrefix() + curServer + api;
|
||||
}
|
||||
|
||||
try {
|
||||
HttpRestResult<String> restResult = nacosRestTemplate.exchangeForm(url, header, params, body, method, String.class);
|
||||
end = System.currentTimeMillis();
|
||||
|
||||
MetricsMonitor.getNamingRequestMonitor(method, url, String.valueOf(restResult.getCode()))
|
||||
.observe(end - start);
|
||||
|
||||
if (restResult.ok()) {
|
||||
return restResult.getData();
|
||||
}
|
||||
if (HttpStatus.SC_NOT_MODIFIED == restResult.getCode()) {
|
||||
return StringUtils.EMPTY;
|
||||
}
|
||||
throw new NacosException(restResult.getCode(), restResult.getData());
|
||||
} catch (Exception e) {
|
||||
NAMING_LOGGER.error("[NA] failed to request", e);
|
||||
throw new NacosException(NacosException.SERVER_ERROR, e);
|
||||
}
|
||||
}
|
||||
|
||||
public String reqAPI(String api, Map<String, String> params, Map<String, String> body, List<String> servers, String method) throws NacosException {
|
||||
|
||||
|
||||
/**
|
||||
* Request api.
|
||||
*
|
||||
* @param api api
|
||||
* @param params parameters
|
||||
* @param body body
|
||||
* @param servers servers
|
||||
* @param method http method
|
||||
* @return result
|
||||
* @throws NacosException nacos exception
|
||||
*/
|
||||
public String reqApi(String api, Map<String, String> params, Map<String, String> body, List<String> servers,
|
||||
String method) throws NacosException {
|
||||
|
||||
params.put(CommonParams.NAMESPACE_ID, getNamespaceId());
|
||||
|
||||
|
||||
if (CollectionUtils.isEmpty(servers) && StringUtils.isEmpty(nacosDomain)) {
|
||||
throw new NacosException(NacosException.INVALID_PARAM, "no server available");
|
||||
}
|
||||
|
||||
|
||||
NacosException exception = new NacosException();
|
||||
|
||||
|
||||
if (servers != null && !servers.isEmpty()) {
|
||||
|
||||
|
||||
Random random = new Random(System.currentTimeMillis());
|
||||
int index = random.nextInt(servers.size());
|
||||
|
||||
|
||||
for (int i = 0; i < servers.size(); i++) {
|
||||
String server = servers.get(index);
|
||||
try {
|
||||
@ -489,7 +531,7 @@ public class NamingProxy implements Closeable {
|
||||
index = (index + 1) % servers.size();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (StringUtils.isNotBlank(nacosDomain)) {
|
||||
for (int i = 0; i < UtilAndComs.REQUEST_DOMAIN_RETRY_COUNT; i++) {
|
||||
try {
|
||||
@ -502,22 +544,84 @@ public class NamingProxy implements Closeable {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NAMING_LOGGER.error("request: {} failed, servers: {}, code: {}, msg: {}",
|
||||
api, servers, exception.getErrCode(), exception.getErrMsg());
|
||||
|
||||
throw new NacosException(exception.getErrCode(), "failed to req API:" + api + " after all servers(" + servers + ") tried: "
|
||||
+ exception.getMessage());
|
||||
|
||||
|
||||
NAMING_LOGGER.error("request: {} failed, servers: {}, code: {}, msg: {}", api, servers, exception.getErrCode(),
|
||||
exception.getErrMsg());
|
||||
|
||||
throw new NacosException(exception.getErrCode(),
|
||||
"failed to req API:" + api + " after all servers(" + servers + ") tried: " + exception.getMessage());
|
||||
|
||||
}
|
||||
|
||||
|
||||
private List<String> getServerList() {
|
||||
List<String> snapshot = serversFromEndpoint;
|
||||
if (!CollectionUtils.isEmpty(serverList)) {
|
||||
snapshot = serverList;
|
||||
}
|
||||
return snapshot;
|
||||
}
|
||||
|
||||
public String callServer(String api, Map<String, String> params, Map<String, String> body, String curServer)
|
||||
throws NacosException {
|
||||
return callServer(api, params, body, curServer, HttpMethod.GET);
|
||||
}
|
||||
|
||||
/**
|
||||
* Call server.
|
||||
*
|
||||
* @param api api
|
||||
* @param params parameters
|
||||
* @param body body
|
||||
* @param curServer ?
|
||||
* @param method http method
|
||||
* @return result
|
||||
* @throws NacosException nacos exception
|
||||
*/
|
||||
public String callServer(String api, Map<String, String> params, Map<String, String> body, String curServer,
|
||||
String method) throws NacosException {
|
||||
long start = System.currentTimeMillis();
|
||||
long end = 0;
|
||||
injectSecurityInfo(params);
|
||||
Header header = builderHeader();
|
||||
|
||||
String url;
|
||||
if (curServer.startsWith(UtilAndComs.HTTPS) || curServer.startsWith(UtilAndComs.HTTP)) {
|
||||
url = curServer + api;
|
||||
} else {
|
||||
if (!curServer.contains(UtilAndComs.SERVER_ADDR_IP_SPLITER)) {
|
||||
curServer = curServer + UtilAndComs.SERVER_ADDR_IP_SPLITER + serverPort;
|
||||
}
|
||||
url = NamingHttpClientManager.getInstance().getPrefix() + curServer + api;
|
||||
}
|
||||
|
||||
try {
|
||||
HttpRestResult<String> restResult = nacosRestTemplate
|
||||
.exchangeForm(url, header, params, body, method, String.class);
|
||||
end = System.currentTimeMillis();
|
||||
|
||||
MetricsMonitor.getNamingRequestMonitor(method, url, String.valueOf(restResult.getCode()))
|
||||
.observe(end - start);
|
||||
|
||||
if (restResult.ok()) {
|
||||
return restResult.getData();
|
||||
}
|
||||
if (HttpStatus.SC_NOT_MODIFIED == restResult.getCode()) {
|
||||
return StringUtils.EMPTY;
|
||||
}
|
||||
throw new NacosException(restResult.getCode(), restResult.getData());
|
||||
} catch (Exception e) {
|
||||
NAMING_LOGGER.error("[NA] failed to request", e);
|
||||
throw new NacosException(NacosException.SERVER_ERROR, e);
|
||||
}
|
||||
}
|
||||
|
||||
private void injectSecurityInfo(Map<String, String> params) {
|
||||
|
||||
|
||||
// Inject token if exist:
|
||||
if (StringUtils.isNotBlank(securityProxy.getAccessToken())) {
|
||||
params.put(Constants.ACCESS_TOKEN, securityProxy.getAccessToken());
|
||||
}
|
||||
|
||||
|
||||
// Inject ak/sk if exist:
|
||||
String ak = getAccessKey();
|
||||
String sk = getSecretKey();
|
||||
@ -534,7 +638,12 @@ public class NamingProxy implements Closeable {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Build header.
|
||||
*
|
||||
* @return header
|
||||
*/
|
||||
public Header builderHeader() {
|
||||
Header header = Header.newInstance();
|
||||
header.addParam(HttpHeaderConsts.CLIENT_VERSION_HEADER, VersionUtils.version);
|
||||
@ -545,65 +654,67 @@ public class NamingProxy implements Closeable {
|
||||
header.addParam(HttpHeaderConsts.REQUEST_MODULE, "Naming");
|
||||
return header;
|
||||
}
|
||||
|
||||
|
||||
private static String getSignData(String serviceName) {
|
||||
return StringUtils.isNotEmpty(serviceName)
|
||||
? System.currentTimeMillis() + "@@" + serviceName
|
||||
: String.valueOf(System.currentTimeMillis());
|
||||
return StringUtils.isNotEmpty(serviceName) ? System.currentTimeMillis() + "@@" + serviceName
|
||||
: String.valueOf(System.currentTimeMillis());
|
||||
}
|
||||
|
||||
|
||||
public String getAccessKey() {
|
||||
if (properties == null) {
|
||||
|
||||
|
||||
return SpasAdapter.getAk();
|
||||
}
|
||||
|
||||
return TemplateUtils.stringEmptyAndThenExecute(properties.getProperty(PropertyKeyConst.ACCESS_KEY), new Callable<String>() {
|
||||
|
||||
@Override
|
||||
public String call() {
|
||||
return SpasAdapter.getAk();
|
||||
}
|
||||
});
|
||||
|
||||
return TemplateUtils
|
||||
.stringEmptyAndThenExecute(properties.getProperty(PropertyKeyConst.ACCESS_KEY), new Callable<String>() {
|
||||
|
||||
@Override
|
||||
public String call() {
|
||||
return SpasAdapter.getAk();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
public String getSecretKey() {
|
||||
if (properties == null) {
|
||||
|
||||
|
||||
return SpasAdapter.getSk();
|
||||
}
|
||||
|
||||
return TemplateUtils.stringEmptyAndThenExecute(properties.getProperty(PropertyKeyConst.SECRET_KEY), new Callable<String>() {
|
||||
@Override
|
||||
public String call() throws Exception {
|
||||
return SpasAdapter.getSk();
|
||||
}
|
||||
});
|
||||
|
||||
return TemplateUtils
|
||||
.stringEmptyAndThenExecute(properties.getProperty(PropertyKeyConst.SECRET_KEY), new Callable<String>() {
|
||||
@Override
|
||||
public String call() throws Exception {
|
||||
return SpasAdapter.getSk();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
public void setProperties(Properties properties) {
|
||||
this.properties = properties;
|
||||
setServerPort(DEFAULT_SERVER_PORT);
|
||||
}
|
||||
|
||||
|
||||
public String getNamespaceId() {
|
||||
return namespaceId;
|
||||
}
|
||||
|
||||
|
||||
public void setServerPort(int serverPort) {
|
||||
this.serverPort = serverPort;
|
||||
|
||||
|
||||
String sp = System.getProperty(SystemPropertyKeyConst.NAMING_SERVER_PORT);
|
||||
if (StringUtils.isNotBlank(sp)) {
|
||||
this.serverPort = Integer.parseInt(sp);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void shutdown() throws NacosException{
|
||||
public void shutdown() throws NacosException {
|
||||
String className = this.getClass().getName();
|
||||
NAMING_LOGGER.info("{} do shutdown begin", className);
|
||||
ThreadUtils.shutdownThreadPool(executorService, NAMING_LOGGER);
|
||||
NamingHttpClientManager.getInstance().shutdown();
|
||||
NAMING_LOGGER.info("{} do shutdown stop", className);
|
||||
}
|
||||
}
|
||||
|
@ -13,6 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.client.naming.utils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@ -20,14 +21,21 @@ import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Chooser.
|
||||
*
|
||||
* @author alibaba
|
||||
*/
|
||||
public class Chooser<K, T> {
|
||||
|
||||
private K uniqueKey;
|
||||
|
||||
|
||||
private final K uniqueKey;
|
||||
|
||||
private volatile Ref<T> ref;
|
||||
|
||||
|
||||
/**
|
||||
* Random get one item.
|
||||
*
|
||||
* @return item
|
||||
*/
|
||||
public T random() {
|
||||
List<T> items = ref.items;
|
||||
if (items.size() == 0) {
|
||||
@ -38,7 +46,12 @@ public class Chooser<K, T> {
|
||||
}
|
||||
return items.get(ThreadLocalRandom.current().nextInt(items.size()));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Random get one item with weight.
|
||||
*
|
||||
* @return item
|
||||
*/
|
||||
public T randomWithWeight() {
|
||||
Ref<T> ref = this.ref;
|
||||
double random = ThreadLocalRandom.current().nextDouble(0, 1);
|
||||
@ -48,67 +61,78 @@ public class Chooser<K, T> {
|
||||
} else {
|
||||
return ref.items.get(index);
|
||||
}
|
||||
|
||||
|
||||
if (index >= 0 && index < ref.weights.length) {
|
||||
if (random < ref.weights[index]) {
|
||||
return ref.items.get(index);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* This should never happen, but it ensures we will return a correct
|
||||
* object in case there is some floating point inequality problem
|
||||
* wrt the cumulative probabilities. */
|
||||
return ref.items.get(ref.items.size() - 1);
|
||||
}
|
||||
|
||||
|
||||
public Chooser(K uniqueKey) {
|
||||
this(uniqueKey, new ArrayList<Pair<T>>());
|
||||
}
|
||||
|
||||
|
||||
public Chooser(K uniqueKey, List<Pair<T>> pairs) {
|
||||
Ref<T> ref = new Ref<T>(pairs);
|
||||
ref.refresh();
|
||||
this.uniqueKey = uniqueKey;
|
||||
this.ref = ref;
|
||||
}
|
||||
|
||||
|
||||
public K getUniqueKey() {
|
||||
return uniqueKey;
|
||||
}
|
||||
|
||||
|
||||
public Ref<T> getRef() {
|
||||
return ref;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* refresh items.
|
||||
*
|
||||
* @param itemsWithWeight items with weight
|
||||
*/
|
||||
public void refresh(List<Pair<T>> itemsWithWeight) {
|
||||
Ref<T> newRef = new Ref<T>(itemsWithWeight);
|
||||
newRef.refresh();
|
||||
newRef.poller = this.ref.poller.refresh(newRef.items);
|
||||
this.ref = newRef;
|
||||
}
|
||||
|
||||
|
||||
public class Ref<T> {
|
||||
|
||||
private List<Pair<T>> itemsWithWeight = new ArrayList<Pair<T>>();
|
||||
private List<T> items = new ArrayList<T>();
|
||||
|
||||
private final List<T> items = new ArrayList<T>();
|
||||
|
||||
private Poller<T> poller = new GenericPoller<T>(items);
|
||||
|
||||
private double[] weights;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
|
||||
public Ref(List<Pair<T>> itemsWithWeight) {
|
||||
this.itemsWithWeight = itemsWithWeight;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Refresh.
|
||||
*/
|
||||
public void refresh() {
|
||||
Double originWeightSum = (double) 0;
|
||||
|
||||
|
||||
for (Pair<T> item : itemsWithWeight) {
|
||||
|
||||
|
||||
double weight = item.weight();
|
||||
//ignore item which weight is zero.see test_randomWithWeight_weight0 in ChooserTest
|
||||
if (weight <= 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
items.add(item.item());
|
||||
if (Double.isInfinite(weight)) {
|
||||
weight = 10000.0D;
|
||||
@ -118,7 +142,7 @@ public class Chooser<K, T> {
|
||||
}
|
||||
originWeightSum += weight;
|
||||
}
|
||||
|
||||
|
||||
double[] exactWeights = new double[items.size()];
|
||||
int index = 0;
|
||||
for (Pair<T> item : itemsWithWeight) {
|
||||
@ -129,27 +153,28 @@ public class Chooser<K, T> {
|
||||
}
|
||||
exactWeights[index++] = singleWeight / originWeightSum;
|
||||
}
|
||||
|
||||
|
||||
weights = new double[items.size()];
|
||||
double randomRange = 0D;
|
||||
for (int i = 0; i < index; i++) {
|
||||
weights[i] = randomRange + exactWeights[i];
|
||||
randomRange += exactWeights[i];
|
||||
}
|
||||
|
||||
|
||||
double doublePrecisionDelta = 0.0001;
|
||||
|
||||
|
||||
if (index == 0 || (Math.abs(weights[index - 1] - 1) < doublePrecisionDelta)) {
|
||||
return;
|
||||
}
|
||||
throw new IllegalStateException("Cumulative Weight caculate wrong , the sum of probabilities does not equals 1.");
|
||||
throw new IllegalStateException(
|
||||
"Cumulative Weight caculate wrong , the sum of probabilities does not equals 1.");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return itemsWithWeight.hashCode();
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
@ -167,9 +192,7 @@ public class Chooser<K, T> {
|
||||
}
|
||||
Ref<T> otherRef = (Ref<T>) other;
|
||||
if (itemsWithWeight == null) {
|
||||
if (otherRef.itemsWithWeight != null) {
|
||||
return false;
|
||||
}
|
||||
return otherRef.itemsWithWeight == null;
|
||||
} else {
|
||||
if (otherRef.itemsWithWeight == null) {
|
||||
return false;
|
||||
@ -177,15 +200,14 @@ public class Chooser<K, T> {
|
||||
return this.itemsWithWeight.equals(otherRef.itemsWithWeight);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return uniqueKey.hashCode();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
if (this == other) {
|
||||
@ -197,7 +219,7 @@ public class Chooser<K, T> {
|
||||
if (getClass() != other.getClass()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
Chooser otherChooser = (Chooser) other;
|
||||
if (this.uniqueKey == null) {
|
||||
if (otherChooser.getUniqueKey() != null) {
|
||||
@ -209,22 +231,17 @@ public class Chooser<K, T> {
|
||||
} else if (!this.uniqueKey.equals(otherChooser.getUniqueKey())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
if (this.ref == null) {
|
||||
if (otherChooser.getRef() != null) {
|
||||
return false;
|
||||
}
|
||||
return otherChooser.getRef() == null;
|
||||
} else {
|
||||
if (otherChooser.getRef() == null) {
|
||||
return false;
|
||||
} else if (!this.ref.equals(otherChooser.getRef())) {
|
||||
return false;
|
||||
} else {
|
||||
return this.ref.equals(otherChooser.getRef());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -13,13 +13,14 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.client.naming.utils;
|
||||
|
||||
/**
|
||||
* Created by harold on 2015/12/7.
|
||||
*/
|
||||
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Provides utility methods and decorators for {@link Collection} instances.
|
||||
@ -41,22 +42,22 @@ import java.util.*;
|
||||
* @since Commons Collections 1.0
|
||||
*/
|
||||
public class CollectionUtils {
|
||||
|
||||
|
||||
/**
|
||||
* Constant to avoid repeated object creation
|
||||
* Constant to avoid repeated object creation.
|
||||
*/
|
||||
private static final Integer INTEGER_ONE = 1;
|
||||
|
||||
|
||||
/**
|
||||
* <code>CollectionUtils</code> should not normally be instantiated.
|
||||
*/
|
||||
public CollectionUtils() {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a new {@link Collection} containing <tt><i>a</i> - <i>b</i></tt>. The cardinality of each element
|
||||
* <i>e</i> in the returned {@link Collection} will be the cardinality of <i>e</i> in <i>a</i> minus the cardinality
|
||||
* of <i>e</i> in <i>b</i>, or zero, whichever is greater.
|
||||
* <i>e</i> in the returned {@link Collection} will be the cardinality of <i>e</i> in <i>a</i> minus the
|
||||
* cardinality of <i>e</i> in <i>b</i>, or zero, whichever is greater.
|
||||
*
|
||||
* @param a the collection to subtract from, must not be null
|
||||
* @param b the collection to subtract, must not be null
|
||||
@ -70,12 +71,12 @@ public class CollectionUtils {
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a {@link Map} mapping each unique element in the given {@link Collection} to an {@link Integer}
|
||||
* representing the number of occurrences of that element in the {@link Collection}.
|
||||
* <p>
|
||||
* Only those elements present in the collection will appear as keys in the map.
|
||||
*
|
||||
* <p>Only those elements present in the collection will appear as keys in the map.
|
||||
*
|
||||
* @param coll the collection to get the cardinality map for, must not be null
|
||||
* @return the populated cardinality map
|
||||
@ -84,7 +85,7 @@ public class CollectionUtils {
|
||||
Map count = new HashMap(coll.size());
|
||||
for (Iterator it = coll.iterator(); it.hasNext(); ) {
|
||||
Object obj = it.next();
|
||||
Integer c = (Integer)(count.get(obj));
|
||||
Integer c = (Integer) (count.get(obj));
|
||||
if (c == null) {
|
||||
count.put(obj, INTEGER_ONE);
|
||||
} else {
|
||||
@ -93,12 +94,12 @@ public class CollectionUtils {
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns <tt>true</tt> iff the given {@link Collection}s contain exactly the same elements with exactly the same
|
||||
* cardinalities.
|
||||
* <p>
|
||||
* That is, iff the cardinality of <i>e</i> in <i>a</i> is equal to the cardinality of <i>e</i> in <i>b</i>, for
|
||||
*
|
||||
* <p>That is, iff the cardinality of <i>e</i> in <i>a</i> is equal to the cardinality of <i>e</i> in <i>b</i>, for
|
||||
* each element <i>e</i> in <i>a</i> or <i>b</i>.
|
||||
*
|
||||
* @param a the first collection, must not be null
|
||||
@ -125,13 +126,13 @@ public class CollectionUtils {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
|
||||
/**
|
||||
* Null-safe check if the specified collection is empty.
|
||||
* <p>
|
||||
* Null returns true.
|
||||
*
|
||||
* <p>Null returns true.
|
||||
*
|
||||
* @param coll the collection to check, may be null
|
||||
* @return true if empty or null
|
||||
@ -140,9 +141,9 @@ public class CollectionUtils {
|
||||
public static boolean isEmpty(Collection coll) {
|
||||
return (coll == null || coll.isEmpty());
|
||||
}
|
||||
|
||||
|
||||
private static int getFreq(final Object obj, final Map freqMap) {
|
||||
Integer count = (Integer)freqMap.get(obj);
|
||||
Integer count = (Integer) freqMap.get(obj);
|
||||
if (count != null) {
|
||||
return count.intValue();
|
||||
}
|
||||
|
@ -13,6 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.client.naming.utils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@ -20,22 +21,25 @@ import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
/**
|
||||
* Generic Poller.
|
||||
*
|
||||
* @author nkorange
|
||||
*/
|
||||
public class GenericPoller<T> implements Poller<T> {
|
||||
|
||||
private AtomicInteger index = new AtomicInteger(0);
|
||||
|
||||
private final AtomicInteger index = new AtomicInteger(0);
|
||||
|
||||
private List<T> items = new ArrayList<T>();
|
||||
|
||||
|
||||
public GenericPoller(List<T> items) {
|
||||
this.items = items;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public T next() {
|
||||
return items.get(Math.abs(index.getAndIncrement() % items.size()));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Poller<T> refresh(List<T> items) {
|
||||
return new GenericPoller<T>(items);
|
||||
|
@ -22,7 +22,10 @@ import com.alibaba.nacos.api.common.Constants;
|
||||
import com.alibaba.nacos.api.selector.ExpressionSelector;
|
||||
import com.alibaba.nacos.api.selector.NoneSelector;
|
||||
import com.alibaba.nacos.api.selector.SelectorType;
|
||||
import com.alibaba.nacos.client.utils.*;
|
||||
import com.alibaba.nacos.client.utils.LogUtils;
|
||||
import com.alibaba.nacos.client.utils.ParamUtil;
|
||||
import com.alibaba.nacos.client.utils.TemplateUtils;
|
||||
import com.alibaba.nacos.client.utils.TenantUtil;
|
||||
import com.alibaba.nacos.common.utils.JacksonUtils;
|
||||
import com.alibaba.nacos.common.utils.StringUtils;
|
||||
|
||||
@ -30,29 +33,29 @@ import java.util.Properties;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
/**
|
||||
* Init utils.
|
||||
*
|
||||
* @author liaochuntao
|
||||
* @author deshao
|
||||
*/
|
||||
public class InitUtils {
|
||||
|
||||
|
||||
/**
|
||||
* Add a difference to the name naming. This method simply initializes the namespace for Naming.
|
||||
* Config initialization is not the same, so it cannot be reused directly.
|
||||
* Add a difference to the name naming. This method simply initializes the namespace for Naming. Config
|
||||
* initialization is not the same, so it cannot be reused directly.
|
||||
*
|
||||
* @param properties
|
||||
* @return
|
||||
* @param properties properties
|
||||
* @return namespace
|
||||
*/
|
||||
public static String initNamespaceForNaming(Properties properties) {
|
||||
String tmpNamespace = null;
|
||||
|
||||
|
||||
String isUseCloudNamespaceParsing =
|
||||
properties.getProperty(PropertyKeyConst.IS_USE_CLOUD_NAMESPACE_PARSING,
|
||||
|
||||
String isUseCloudNamespaceParsing = properties.getProperty(PropertyKeyConst.IS_USE_CLOUD_NAMESPACE_PARSING,
|
||||
System.getProperty(SystemPropertyKeyConst.IS_USE_CLOUD_NAMESPACE_PARSING,
|
||||
String.valueOf(Constants.DEFAULT_USE_CLOUD_NAMESPACE_PARSING)));
|
||||
|
||||
String.valueOf(Constants.DEFAULT_USE_CLOUD_NAMESPACE_PARSING)));
|
||||
|
||||
if (Boolean.parseBoolean(isUseCloudNamespaceParsing)) {
|
||||
|
||||
|
||||
tmpNamespace = TenantUtil.getUserTenantForAns();
|
||||
tmpNamespace = TemplateUtils.stringEmptyAndThenExecute(tmpNamespace, new Callable<String>() {
|
||||
@Override
|
||||
@ -62,7 +65,7 @@ public class InitUtils {
|
||||
return namespace;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
tmpNamespace = TemplateUtils.stringEmptyAndThenExecute(tmpNamespace, new Callable<String>() {
|
||||
@Override
|
||||
public String call() {
|
||||
@ -72,7 +75,7 @@ public class InitUtils {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
tmpNamespace = TemplateUtils.stringEmptyAndThenExecute(tmpNamespace, new Callable<String>() {
|
||||
@Override
|
||||
public String call() {
|
||||
@ -81,11 +84,11 @@ public class InitUtils {
|
||||
return namespace;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
if (StringUtils.isEmpty(tmpNamespace) && properties != null) {
|
||||
tmpNamespace = properties.getProperty(PropertyKeyConst.NAMESPACE);
|
||||
}
|
||||
|
||||
|
||||
tmpNamespace = TemplateUtils.stringEmptyAndThenExecute(tmpNamespace, new Callable<String>() {
|
||||
@Override
|
||||
public String call() {
|
||||
@ -94,33 +97,40 @@ public class InitUtils {
|
||||
});
|
||||
return tmpNamespace;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Init web root context.
|
||||
*/
|
||||
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, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
UtilAndComs.WEB_CONTEXT = webContext.indexOf("/") > -1 ? webContext
|
||||
: "/" + webContext;
|
||||
|
||||
UtilAndComs.NACOS_URL_BASE = UtilAndComs.WEB_CONTEXT + "/v1/ns";
|
||||
UtilAndComs.NACOS_URL_INSTANCE = UtilAndComs.NACOS_URL_BASE + "/instance";
|
||||
UtilAndComs.webContext = webContext.indexOf("/") > -1 ? webContext : "/" + webContext;
|
||||
|
||||
UtilAndComs.nacosUrlBase = UtilAndComs.webContext + "/v1/ns";
|
||||
UtilAndComs.nacosUrlInstance = UtilAndComs.nacosUrlBase + "/instance";
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Init end point.
|
||||
*
|
||||
* @param properties properties
|
||||
* @return end point
|
||||
*/
|
||||
public static String initEndpoint(final Properties properties) {
|
||||
if (properties == null) {
|
||||
|
||||
|
||||
return "";
|
||||
}
|
||||
// Whether to enable domain name resolution rules
|
||||
String isUseEndpointRuleParsing =
|
||||
properties.getProperty(PropertyKeyConst.IS_USE_ENDPOINT_PARSING_RULE,
|
||||
String isUseEndpointRuleParsing = properties.getProperty(PropertyKeyConst.IS_USE_ENDPOINT_PARSING_RULE,
|
||||
System.getProperty(SystemPropertyKeyConst.IS_USE_ENDPOINT_PARSING_RULE,
|
||||
String.valueOf(ParamUtil.USE_ENDPOINT_PARSING_RULE_DEFAULT_VALUE)));
|
||||
|
||||
String.valueOf(ParamUtil.USE_ENDPOINT_PARSING_RULE_DEFAULT_VALUE)));
|
||||
|
||||
boolean isUseEndpointParsingRule = Boolean.parseBoolean(isUseEndpointRuleParsing);
|
||||
String endpointUrl;
|
||||
if (isUseEndpointParsingRule) {
|
||||
@ -132,40 +142,42 @@ public class InitUtils {
|
||||
} else {
|
||||
endpointUrl = properties.getProperty(PropertyKeyConst.ENDPOINT);
|
||||
}
|
||||
|
||||
|
||||
if (StringUtils.isBlank(endpointUrl)) {
|
||||
return "";
|
||||
}
|
||||
|
||||
String endpointPort = TemplateUtils.stringEmptyAndThenExecute(System.getenv(PropertyKeyConst.SystemEnv.ALIBABA_ALIWARE_ENDPOINT_PORT), new Callable<String>() {
|
||||
@Override
|
||||
public String call() {
|
||||
|
||||
return properties.getProperty(PropertyKeyConst.ENDPOINT_PORT);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
String endpointPort = TemplateUtils
|
||||
.stringEmptyAndThenExecute(System.getenv(PropertyKeyConst.SystemEnv.ALIBABA_ALIWARE_ENDPOINT_PORT),
|
||||
new Callable<String>() {
|
||||
@Override
|
||||
public String call() {
|
||||
|
||||
return properties.getProperty(PropertyKeyConst.ENDPOINT_PORT);
|
||||
}
|
||||
});
|
||||
|
||||
endpointPort = TemplateUtils.stringEmptyAndThenExecute(endpointPort, new Callable<String>() {
|
||||
@Override
|
||||
public String call() {
|
||||
return "8080";
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
return endpointUrl + ":" + endpointPort;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Register subType for serialization
|
||||
* Register subType for serialization.
|
||||
*
|
||||
* Now these subType implementation class has registered in static code.
|
||||
* But there are some problem for classloader. The implementation class
|
||||
* will be loaded when they are used, which will make deserialize
|
||||
* before register.
|
||||
* <p>
|
||||
* Now these subType implementation class has registered in static code. But there are some problem for classloader.
|
||||
* The implementation class will be loaded when they are used, which will make deserialize before register.
|
||||
* </p>
|
||||
*
|
||||
* 子类实现类中的静态代码串中已经向Jackson进行了注册,但是由于classloader的原因,只有当
|
||||
* 该子类被使用的时候,才会加载该类。这可能会导致Jackson先进性反序列化,再注册子类,从而导致
|
||||
* 反序列化失败。
|
||||
* <p>
|
||||
* 子类实现类中的静态代码串中已经向Jackson进行了注册,但是由于classloader的原因,只有当 该子类被使用的时候,才会加载该类。这可能会导致Jackson先进性反序列化,再注册子类,从而导致 反序列化失败。
|
||||
* </p>
|
||||
*/
|
||||
public static void initSerialization() {
|
||||
// TODO register in implementation class or remove subType
|
||||
|
@ -13,6 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.client.naming.utils;
|
||||
|
||||
import java.util.Random;
|
||||
@ -22,43 +23,43 @@ import java.util.Random;
|
||||
* java.lang.Math#random()} method and its system-wide {@link Random} object.</p>
|
||||
* <p>
|
||||
* It does this to allow for a Random class in which the seed is shared between all members of the class - a better name
|
||||
* would have been SharedSeedRandom.
|
||||
* would have been SharedSeedRandom.</p>
|
||||
* <p>
|
||||
* <b>N.B.</b> the current implementation overrides the methods {@link Random#nextInt(int)} and {@link
|
||||
* Random#nextLong()} to produce positive numbers ranging from 0 (inclusive) to MAX_VALUE (exclusive).
|
||||
*
|
||||
* </p>
|
||||
* @author unknown
|
||||
* @version $Id: JVMRandom.java 911986 2010-02-19 21:19:05Z niallp $
|
||||
* @since 2.0
|
||||
*/
|
||||
public final class JvmRandom extends Random {
|
||||
|
||||
|
||||
/**
|
||||
* Required for serialization support.
|
||||
*
|
||||
* @see java.io.Serializable
|
||||
*/
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
|
||||
private static final Random SHARED_RANDOM = new Random();
|
||||
|
||||
|
||||
/**
|
||||
* Ensures that only the parent constructor can call reseed.
|
||||
*/
|
||||
private boolean constructed = false;
|
||||
|
||||
|
||||
/**
|
||||
* Constructs a new instance.
|
||||
*/
|
||||
public JvmRandom() {
|
||||
this.constructed = true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Unsupported in 2.0.
|
||||
*
|
||||
* @param seed ignored
|
||||
* @throws UnsupportedOperationException
|
||||
* @throws UnsupportedOperationException unsupported operation exception
|
||||
*/
|
||||
@Override
|
||||
public synchronized void setSeed(long seed) {
|
||||
@ -66,32 +67,32 @@ public final class JvmRandom extends Random {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Unsupported in 2.0.
|
||||
*
|
||||
* @return Nothing, this method always throws an UnsupportedOperationException.
|
||||
* @throws UnsupportedOperationException
|
||||
* @throws UnsupportedOperationException unsupported operation exception
|
||||
*/
|
||||
@Override
|
||||
public synchronized double nextGaussian() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Unsupported in 2.0.
|
||||
*
|
||||
* @param byteArray ignored
|
||||
* @throws UnsupportedOperationException
|
||||
* @throws UnsupportedOperationException unsupported operation exception
|
||||
*/
|
||||
@Override
|
||||
public void nextBytes(byte[] byteArray) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* <p>Returns the next pseudorandom, uniformly distributed int value from the Math.random() sequence.</p> Identical
|
||||
* to <code>nextInt(Integer.MAX_VALUE)</code> <p> <b>N.B. All values are >= 0.<b> </p>
|
||||
* to <code>nextInt(Integer.MAX_VALUE)</code> <p> <b>N.B. All values are >= 0.</b> </p>
|
||||
*
|
||||
* @return the random int
|
||||
*/
|
||||
@ -99,7 +100,7 @@ public final class JvmRandom extends Random {
|
||||
public int nextInt() {
|
||||
return nextInt(Integer.MAX_VALUE);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* <p>Returns a pseudorandom, uniformly distributed int value between <code>0</code> (inclusive) and the specified
|
||||
* value (exclusive), from the Math.random() sequence.</p>
|
||||
@ -112,10 +113,11 @@ public final class JvmRandom extends Random {
|
||||
public int nextInt(int n) {
|
||||
return SHARED_RANDOM.nextInt(n);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* <p>Returns the next pseudorandom, uniformly distributed long value from the Math.random() sequence.</p> Identical
|
||||
* to <code>nextLong(Long.MAX_VALUE)</code> <p> <b>N.B. All values are >= 0.<b> </p>
|
||||
* <p>Returns the next pseudorandom, uniformly distributed long value from the Math.random() sequence.</p>
|
||||
* Identical
|
||||
* to <code>nextLong(Long.MAX_VALUE)</code> <p> <b>N.B. All values are >= 0.</b> </p>
|
||||
*
|
||||
* @return the random long
|
||||
*/
|
||||
@ -123,7 +125,7 @@ public final class JvmRandom extends Random {
|
||||
public long nextLong() {
|
||||
return nextLong(Long.MAX_VALUE);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* <p>Returns a pseudorandom, uniformly distributed long value between <code>0</code> (inclusive) and the specified
|
||||
* value (exclusive), from the Math.random() sequence.</p>
|
||||
@ -134,16 +136,13 @@ public final class JvmRandom extends Random {
|
||||
*/
|
||||
public static long nextLong(long n) {
|
||||
if (n <= 0) {
|
||||
throw new IllegalArgumentException(
|
||||
"Upper bound for nextInt must be positive"
|
||||
);
|
||||
throw new IllegalArgumentException("Upper bound for nextInt must be positive");
|
||||
}
|
||||
// Code adapted from Harmony Random#nextInt(int)
|
||||
// n is power of 2
|
||||
if ((n & -n) == n) {
|
||||
// dropping lower order bits improves behaviour for low values of n
|
||||
return next63bits() >> 63
|
||||
- bitsRequired(n - 1);
|
||||
return next63bits() >> 63 - bitsRequired(n - 1);
|
||||
}
|
||||
// Not a power of two
|
||||
long val;
|
||||
@ -155,7 +154,7 @@ public final class JvmRandom extends Random {
|
||||
} while (bits - val + (n - 1) < 0);
|
||||
return val;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* <p>Returns the next pseudorandom, uniformly distributed boolean value from the Math.random() sequence.</p>
|
||||
*
|
||||
@ -165,9 +164,10 @@ public final class JvmRandom extends Random {
|
||||
public boolean nextBoolean() {
|
||||
return SHARED_RANDOM.nextBoolean();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* <p>Returns the next pseudorandom, uniformly distributed float value between <code>0.0</code> and <code>1.0</code>
|
||||
* <p>Returns the next pseudorandom, uniformly distributed float value between <code>0.0</code> and
|
||||
* <code>1.0</code>
|
||||
* from the Math.random() sequence.</p>
|
||||
*
|
||||
* @return the random float
|
||||
@ -176,7 +176,7 @@ public final class JvmRandom extends Random {
|
||||
public float nextFloat() {
|
||||
return SHARED_RANDOM.nextFloat();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* <p>Synonymous to the Math.random() call.</p>
|
||||
*
|
||||
@ -186,9 +186,9 @@ public final class JvmRandom extends Random {
|
||||
public double nextDouble() {
|
||||
return SHARED_RANDOM.nextDouble();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the next unsigned random long
|
||||
* Get the next unsigned random long.
|
||||
*
|
||||
* @return unsigned random long
|
||||
*/
|
||||
@ -196,7 +196,7 @@ public final class JvmRandom extends Random {
|
||||
// drop the sign bit to leave 63 random bits
|
||||
return SHARED_RANDOM.nextLong() & 0x7fffffffffffffffL;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Count the number of bits required to represent a long number.
|
||||
*
|
||||
|
@ -13,6 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.client.naming.utils;
|
||||
|
||||
import com.alibaba.nacos.common.utils.StringUtils;
|
||||
@ -21,20 +22,29 @@ import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
|
||||
/**
|
||||
* Net utils.
|
||||
*
|
||||
* @author xuanyin.zy
|
||||
*/
|
||||
public class NetUtils {
|
||||
private static String LOCAL_IP;
|
||||
|
||||
|
||||
private static String localIp;
|
||||
|
||||
/**
|
||||
* Get local ip.
|
||||
*
|
||||
* @return local ip
|
||||
*/
|
||||
public static String localIP() {
|
||||
try {
|
||||
if (!StringUtils.isEmpty(LOCAL_IP)) {
|
||||
return LOCAL_IP;
|
||||
if (!StringUtils.isEmpty(localIp)) {
|
||||
return localIp;
|
||||
}
|
||||
|
||||
String ip = System.getProperty("com.alibaba.nacos.client.naming.local.ip", InetAddress.getLocalHost().getHostAddress());
|
||||
|
||||
return LOCAL_IP = ip;
|
||||
|
||||
String ip = System.getProperty("com.alibaba.nacos.client.naming.local.ip",
|
||||
InetAddress.getLocalHost().getHostAddress());
|
||||
|
||||
return localIp = ip;
|
||||
} catch (UnknownHostException e) {
|
||||
return "resolve_failed";
|
||||
}
|
||||
|
@ -13,25 +13,29 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.client.naming.utils;
|
||||
|
||||
/**
|
||||
* Pair.
|
||||
*
|
||||
* @author nkorange
|
||||
*/
|
||||
public class Pair<T> {
|
||||
|
||||
private T item;
|
||||
private double weight;
|
||||
|
||||
|
||||
private final T item;
|
||||
|
||||
private final double weight;
|
||||
|
||||
public Pair(T item, double weight) {
|
||||
this.item = item;
|
||||
this.weight = weight;
|
||||
}
|
||||
|
||||
|
||||
public T item() {
|
||||
return item;
|
||||
}
|
||||
|
||||
|
||||
public double weight() {
|
||||
return weight;
|
||||
}
|
||||
|
@ -13,23 +13,27 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.client.naming.utils;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Poller.
|
||||
*
|
||||
* @author nkorange
|
||||
*/
|
||||
public interface Poller<T> {
|
||||
|
||||
/**
|
||||
* Get next element selected by poller
|
||||
* Get next element selected by poller.
|
||||
*
|
||||
* @return next element
|
||||
*/
|
||||
T next();
|
||||
|
||||
|
||||
/**
|
||||
* Update items stored in poller
|
||||
* Update items stored in poller.
|
||||
*
|
||||
* @param items new item list
|
||||
* @return new poller instance
|
||||
|
@ -13,12 +13,13 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.client.naming.utils;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* <p><code>RandomUtils</code> is a wrapper that supports all possible {@link java.util.Random} methods via the {@link
|
||||
* <code>RandomUtils</code> is a wrapper that supports all possible {@link java.util.Random} methods via the {@link
|
||||
* java.lang.Math#random()} method and its system-wide <code>Random</code> object.
|
||||
*
|
||||
* @author Gary D. Gregory
|
||||
@ -26,27 +27,27 @@ import java.util.Random;
|
||||
* @since 2.0
|
||||
*/
|
||||
public class RandomUtils {
|
||||
|
||||
|
||||
/**
|
||||
* An instance of {@link JvmRandom}.
|
||||
*/
|
||||
private static final Random JVM_RANDOM = new JvmRandom();
|
||||
|
||||
|
||||
// should be possible for JVM_RANDOM?
|
||||
// public static void nextBytes(byte[]) {
|
||||
// public synchronized double nextGaussian();
|
||||
// }
|
||||
|
||||
|
||||
/**
|
||||
* <p>Returns the next pseudorandom, uniformly distributed int value from the Math.random() sequence.</p> <b>N.B.
|
||||
* All values are >= 0.<b>
|
||||
* All values are >= 0.</b>
|
||||
*
|
||||
* @return the random int
|
||||
*/
|
||||
public static int nextInt() {
|
||||
return nextInt(JVM_RANDOM);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* <p>Returns the next pseudorandom, uniformly distributed int value from the given <code>random</code>
|
||||
* sequence.</p>
|
||||
@ -57,7 +58,7 @@ public class RandomUtils {
|
||||
public static int nextInt(Random random) {
|
||||
return random.nextInt();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* <p>Returns a pseudorandom, uniformly distributed int value between <code>0</code> (inclusive) and the specified
|
||||
* value (exclusive), from the Math.random() sequence.</p>
|
||||
@ -68,7 +69,7 @@ public class RandomUtils {
|
||||
public static int nextInt(int n) {
|
||||
return nextInt(JVM_RANDOM, n);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* <p>Returns a pseudorandom, uniformly distributed int value between <code>0</code> (inclusive) and the specified
|
||||
* value (exclusive), from the given Random sequence.</p>
|
||||
@ -81,17 +82,17 @@ public class RandomUtils {
|
||||
// check this cannot return 'n'
|
||||
return random.nextInt(n);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* <p>Returns the next pseudorandom, uniformly distributed long value from the Math.random() sequence.</p> <b>N.B.
|
||||
* All values are >= 0.<b>
|
||||
* All values are >= 0.</b>
|
||||
*
|
||||
* @return the random long
|
||||
*/
|
||||
public static long nextLong() {
|
||||
return nextLong(JVM_RANDOM);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* <p>Returns the next pseudorandom, uniformly distributed long value from the given Random sequence.</p>
|
||||
*
|
||||
@ -101,7 +102,7 @@ public class RandomUtils {
|
||||
public static long nextLong(Random random) {
|
||||
return random.nextLong();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* <p>Returns the next pseudorandom, uniformly distributed boolean value from the Math.random() sequence.</p>
|
||||
*
|
||||
@ -110,7 +111,7 @@ public class RandomUtils {
|
||||
public static boolean nextBoolean() {
|
||||
return nextBoolean(JVM_RANDOM);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* <p>Returns the next pseudorandom, uniformly distributed boolean value from the given random sequence.</p>
|
||||
*
|
||||
@ -120,9 +121,10 @@ public class RandomUtils {
|
||||
public static boolean nextBoolean(Random random) {
|
||||
return random.nextBoolean();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* <p>Returns the next pseudorandom, uniformly distributed float value between <code>0.0</code> and <code>1.0</code>
|
||||
* <p>Returns the next pseudorandom, uniformly distributed float value between <code>0.0</code> and
|
||||
* <code>1.0</code>
|
||||
* from the Math.random() sequence.</p>
|
||||
*
|
||||
* @return the random float
|
||||
@ -130,9 +132,10 @@ public class RandomUtils {
|
||||
public static float nextFloat() {
|
||||
return nextFloat(JVM_RANDOM);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* <p>Returns the next pseudorandom, uniformly distributed float value between <code>0.0</code> and <code>1.0</code>
|
||||
* <p>Returns the next pseudorandom, uniformly distributed float value between <code>0.0</code> and
|
||||
* <code>1.0</code>
|
||||
* from the given Random sequence.</p>
|
||||
*
|
||||
* @param random the Random sequence generator.
|
||||
@ -141,9 +144,10 @@ public class RandomUtils {
|
||||
public static float nextFloat(Random random) {
|
||||
return random.nextFloat();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* <p>Returns the next pseudorandom, uniformly distributed float value between <code>0.0</code> and <code>1.0</code>
|
||||
* <p>Returns the next pseudorandom, uniformly distributed float value between <code>0.0</code> and
|
||||
* <code>1.0</code>
|
||||
* from the Math.random() sequence.</p>
|
||||
*
|
||||
* @return the random double
|
||||
@ -151,9 +155,10 @@ public class RandomUtils {
|
||||
public static double nextDouble() {
|
||||
return nextDouble(JVM_RANDOM);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* <p>Returns the next pseudorandom, uniformly distributed float value between <code>0.0</code> and <code>1.0</code>
|
||||
* <p>Returns the next pseudorandom, uniformly distributed float value between <code>0.0</code> and
|
||||
* <code>1.0</code>
|
||||
* from the given Random sequence.</p>
|
||||
*
|
||||
* @param random the Random sequence generator.
|
||||
@ -162,5 +167,5 @@ public class RandomUtils {
|
||||
public static double nextDouble(Random random) {
|
||||
return random.nextDouble();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -13,6 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.client.naming.utils;
|
||||
|
||||
import com.alibaba.nacos.client.identify.Base64;
|
||||
@ -20,46 +21,52 @@ import com.alibaba.nacos.client.identify.Base64;
|
||||
import javax.crypto.Mac;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
/**
|
||||
* Sign util.
|
||||
*
|
||||
* @author pbting
|
||||
* @date 2019-01-22 10:20 PM
|
||||
*/
|
||||
public class SignUtil {
|
||||
public static final Charset UTF8 = Charset.forName("UTF-8");
|
||||
|
||||
|
||||
public static final Charset UTF8 = StandardCharsets.UTF_8;
|
||||
|
||||
public SignUtil() {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sign.
|
||||
*
|
||||
* @param data data
|
||||
* @param key key
|
||||
* @return signature
|
||||
* @throws Exception exception
|
||||
*/
|
||||
public static String sign(String data, String key) throws Exception {
|
||||
try {
|
||||
byte[] signature = sign(data.getBytes(UTF8), key.getBytes(UTF8),
|
||||
SignUtil.SigningAlgorithm.HmacSHA1);
|
||||
byte[] signature = sign(data.getBytes(UTF8), key.getBytes(UTF8), SignUtil.SigningAlgorithm.HmacSHA1);
|
||||
return new String(Base64.encodeBase64(signature));
|
||||
} catch (Exception var3) {
|
||||
throw new Exception(
|
||||
"Unable to calculate a request signature: " + var3.getMessage(),
|
||||
var3);
|
||||
} catch (Exception ex) {
|
||||
throw new Exception("Unable to calculate a request signature: " + ex.getMessage(), ex);
|
||||
}
|
||||
}
|
||||
|
||||
private static byte[] sign(byte[] data, byte[] key,
|
||||
SignUtil.SigningAlgorithm algorithm) throws Exception {
|
||||
|
||||
private static byte[] sign(byte[] data, byte[] key, SignUtil.SigningAlgorithm algorithm) throws Exception {
|
||||
try {
|
||||
Mac mac = Mac.getInstance(algorithm.toString());
|
||||
mac.init(new SecretKeySpec(key, algorithm.toString()));
|
||||
return mac.doFinal(data);
|
||||
} catch (Exception var4) {
|
||||
throw new Exception(
|
||||
"Unable to calculate a request signature: " + var4.getMessage(),
|
||||
var4);
|
||||
} catch (Exception ex) {
|
||||
throw new Exception("Unable to calculate a request signature: " + ex.getMessage(), ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public enum SigningAlgorithm {
|
||||
// Hmac SHA1 algorithm
|
||||
HmacSHA1;
|
||||
|
||||
|
||||
SigningAlgorithm() {
|
||||
}
|
||||
}
|
||||
|
@ -13,6 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.client.naming.utils;
|
||||
|
||||
import java.security.SecureRandom;
|
||||
@ -30,27 +31,26 @@ import java.util.concurrent.atomic.AtomicLong;
|
||||
* ThreadLocalRandom} is particularly appropriate when multiple tasks (for example, each a {@link
|
||||
* io.netty.util.internal.chmv8.ForkJoinTask}) use random numbers in parallel in thread pools.
|
||||
* <p>
|
||||
* <p>
|
||||
* Usages of this class should typically be of the form: {@code ThreadLocalRandom.current().nextX(...)} (where {@code X}
|
||||
* is {@code Int}, {@code Long}, etc). When all usages are of this form, it is never possible to accidently share a
|
||||
* {@code ThreadLocalRandom} across multiple threads.
|
||||
* <p>
|
||||
* </p>
|
||||
* <p>
|
||||
* This class also provides additional commonly used bounded random generation methods.
|
||||
* <p>
|
||||
* </p>
|
||||
* //since 1.7 //author Doug Lea
|
||||
*/
|
||||
@SuppressWarnings("all")
|
||||
public class ThreadLocalRandom extends Random {
|
||||
|
||||
|
||||
private static final AtomicLong seedUniquifier = new AtomicLong();
|
||||
|
||||
|
||||
private static volatile long initialSeedUniquifier;
|
||||
|
||||
|
||||
public static void setInitialSeedUniquifier(long initialSeedUniquifier) {
|
||||
ThreadLocalRandom.initialSeedUniquifier = initialSeedUniquifier;
|
||||
}
|
||||
|
||||
|
||||
public static synchronized long getInitialSeedUniquifier() {
|
||||
// Use the value set via the setter.
|
||||
long initialSeedUniquifier = ThreadLocalRandom.initialSeedUniquifier;
|
||||
@ -67,7 +67,7 @@ public class ThreadLocalRandom extends Random {
|
||||
}
|
||||
};
|
||||
generatorThread.start();
|
||||
|
||||
|
||||
// Get the random seed from the thread with timeout.
|
||||
final long timeoutSeconds = 3;
|
||||
final long deadLine = System.nanoTime() + TimeUnit.SECONDS.toNanos(timeoutSeconds);
|
||||
@ -76,7 +76,7 @@ public class ThreadLocalRandom extends Random {
|
||||
if (waitTime <= 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
Long result = queue.poll(waitTime, TimeUnit.NANOSECONDS);
|
||||
if (result != null) {
|
||||
@ -87,53 +87,55 @@ public class ThreadLocalRandom extends Random {
|
||||
// Ignore
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Just in case the initialSeedUniquifier is zero or some other constant
|
||||
initialSeedUniquifier ^= 0x3255ecdc33bae119L; // just a meaningless random number
|
||||
initialSeedUniquifier ^= Long.reverse(System.nanoTime());
|
||||
|
||||
|
||||
ThreadLocalRandom.initialSeedUniquifier = initialSeedUniquifier;
|
||||
}
|
||||
|
||||
|
||||
return initialSeedUniquifier;
|
||||
}
|
||||
|
||||
|
||||
private static long newSeed() {
|
||||
for (; ; ) {
|
||||
final long current = seedUniquifier.get();
|
||||
final long actualCurrent = current != 0 ? current : getInitialSeedUniquifier();
|
||||
|
||||
|
||||
// L'Ecuyer, "Tables of Linear Congruential Generators of Different Sizes and Good Lattice Structure", 1999
|
||||
final long next = actualCurrent * 181783497276652981L;
|
||||
|
||||
|
||||
if (seedUniquifier.compareAndSet(current, next)) {
|
||||
return next ^ System.nanoTime();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// same constants as Random, but must be redeclared because private
|
||||
private static final long multiplier = 0x5DEECE66DL;
|
||||
|
||||
private static final long addend = 0xBL;
|
||||
|
||||
private static final long mask = (1L << 48) - 1;
|
||||
|
||||
|
||||
/**
|
||||
* The random seed. We can't use super.seed.
|
||||
*/
|
||||
private long rnd;
|
||||
|
||||
|
||||
/**
|
||||
* Initialization flag to permit calls to setSeed to succeed only while executing the Random constructor. We can't
|
||||
* allow others since it would cause setting seed in one part of a program to unintentionally impact other usages by
|
||||
* the thread.
|
||||
*/
|
||||
boolean initialized = false;
|
||||
|
||||
|
||||
// Padding to help avoid memory contention among seed updates in
|
||||
// different TLRs in the common case that they are located near
|
||||
// each other.
|
||||
private long pad0, pad1, pad2, pad3, pad4, pad5, pad6, pad7;
|
||||
|
||||
|
||||
/**
|
||||
* Constructor called only by localRandom.initialValue.
|
||||
*/
|
||||
@ -141,7 +143,7 @@ public class ThreadLocalRandom extends Random {
|
||||
super(newSeed());
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The actual ThreadLocal
|
||||
*/
|
||||
@ -151,7 +153,7 @@ public class ThreadLocalRandom extends Random {
|
||||
return new ThreadLocalRandom();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the current thread's {@code ThreadLocalRandom}.
|
||||
*
|
||||
@ -160,7 +162,7 @@ public class ThreadLocalRandom extends Random {
|
||||
public static ThreadLocalRandom current() {
|
||||
return localRandom.get();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Throws {@code UnsupportedOperationException}. Setting seeds in this generator is not supported.
|
||||
*
|
||||
@ -173,13 +175,13 @@ public class ThreadLocalRandom extends Random {
|
||||
}
|
||||
rnd = (seed ^ multiplier) & mask;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected int next(int bits) {
|
||||
rnd = (rnd * multiplier + addend) & mask;
|
||||
return (int)(rnd >>> (48 - bits));
|
||||
return (int) (rnd >>> (48 - bits));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a pseudorandom, uniformly distributed value between the given least value (inclusive) and bound
|
||||
* (exclusive).
|
||||
@ -195,7 +197,7 @@ public class ThreadLocalRandom extends Random {
|
||||
}
|
||||
return nextInt(bound - least) + least;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a pseudorandom, uniformly distributed value between 0 (inclusive) and the specified value (exclusive).
|
||||
*
|
||||
@ -207,7 +209,7 @@ public class ThreadLocalRandom extends Random {
|
||||
if (n <= 0) {
|
||||
throw new IllegalArgumentException("n must be positive");
|
||||
}
|
||||
|
||||
|
||||
// Divide n by two until small enough for nextInt. On each
|
||||
// iteration (at most 31 of them but usually much less),
|
||||
// randomly choose both whether to include high bit in result
|
||||
@ -223,9 +225,9 @@ public class ThreadLocalRandom extends Random {
|
||||
}
|
||||
n = nextn;
|
||||
}
|
||||
return offset + nextInt((int)n);
|
||||
return offset + nextInt((int) n);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a pseudorandom, uniformly distributed value between the given least value (inclusive) and bound
|
||||
* (exclusive).
|
||||
@ -241,7 +243,7 @@ public class ThreadLocalRandom extends Random {
|
||||
}
|
||||
return nextLong(bound - least) + least;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a pseudorandom, uniformly distributed {@code double} value between 0 (inclusive) and the specified value
|
||||
* (exclusive).
|
||||
@ -256,7 +258,7 @@ public class ThreadLocalRandom extends Random {
|
||||
}
|
||||
return nextDouble() * n;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a pseudorandom, uniformly distributed value between the given least value (inclusive) and bound
|
||||
* (exclusive).
|
||||
@ -272,6 +274,6 @@ public class ThreadLocalRandom extends Random {
|
||||
}
|
||||
return nextDouble() * (bound - least) + least;
|
||||
}
|
||||
|
||||
|
||||
private static final long serialVersionUID = -5851777807851030925L;
|
||||
}
|
||||
|
@ -13,53 +13,54 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.client.naming.utils;
|
||||
|
||||
import com.alibaba.nacos.common.utils.VersionUtils;
|
||||
|
||||
/**
|
||||
* Util and constants.
|
||||
*
|
||||
* @author xuanyin.zy
|
||||
*/
|
||||
public class UtilAndComs {
|
||||
|
||||
|
||||
public static final String VERSION = "Nacos-Java-Client:v" + VersionUtils.version;
|
||||
|
||||
public static String WEB_CONTEXT = "/nacos";
|
||||
|
||||
public static String NACOS_URL_BASE = WEB_CONTEXT + "/v1/ns";
|
||||
|
||||
public static String NACOS_URL_INSTANCE = NACOS_URL_BASE + "/instance";
|
||||
|
||||
public static String NACOS_URL_SERVICE = NACOS_URL_BASE + "/service";
|
||||
|
||||
|
||||
public static String webContext = "/nacos";
|
||||
|
||||
public static String nacosUrlBase = webContext + "/v1/ns";
|
||||
|
||||
public static String nacosUrlInstance = nacosUrlBase + "/instance";
|
||||
|
||||
public static String nacosUrlService = nacosUrlBase + "/service";
|
||||
|
||||
public static final String ENCODING = "UTF-8";
|
||||
|
||||
|
||||
public static final String ENV_LIST_KEY = "envList";
|
||||
|
||||
|
||||
public static final String ALL_IPS = "000--00-ALL_IPS--00--000";
|
||||
|
||||
|
||||
public static final String FAILOVER_SWITCH = "00-00---000-VIPSRV_FAILOVER_SWITCH-000---00-00";
|
||||
|
||||
|
||||
public static final String DEFAULT_NAMESPACE_ID = "public";
|
||||
|
||||
|
||||
public static final int REQUEST_DOMAIN_RETRY_COUNT = 3;
|
||||
|
||||
|
||||
public static final String NACOS_NAMING_LOG_NAME = "com.alibaba.nacos.naming.log.filename";
|
||||
|
||||
|
||||
public static final String NACOS_NAMING_LOG_LEVEL = "com.alibaba.nacos.naming.log.level";
|
||||
|
||||
|
||||
public static final String SERVER_ADDR_IP_SPLITER = ":";
|
||||
|
||||
public static final int DEFAULT_CLIENT_BEAT_THREAD_COUNT = Runtime.getRuntime()
|
||||
.availableProcessors() > 1 ? Runtime.getRuntime().availableProcessors() / 2
|
||||
: 1;
|
||||
|
||||
public static final int DEFAULT_POLLING_THREAD_COUNT = Runtime.getRuntime()
|
||||
.availableProcessors() > 1 ? Runtime.getRuntime().availableProcessors() / 2
|
||||
: 1;
|
||||
|
||||
|
||||
public static final int DEFAULT_CLIENT_BEAT_THREAD_COUNT =
|
||||
Runtime.getRuntime().availableProcessors() > 1 ? Runtime.getRuntime().availableProcessors() / 2 : 1;
|
||||
|
||||
public static final int DEFAULT_POLLING_THREAD_COUNT =
|
||||
Runtime.getRuntime().availableProcessors() > 1 ? Runtime.getRuntime().availableProcessors() / 2 : 1;
|
||||
|
||||
public static final String HTTP = "http://";
|
||||
|
||||
|
||||
public static final String HTTPS = "https://";
|
||||
|
||||
|
||||
}
|
||||
|
@ -13,6 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.client.security;
|
||||
|
||||
import com.alibaba.nacos.api.PropertyKeyConst;
|
||||
@ -24,7 +25,6 @@ import com.alibaba.nacos.common.http.param.Header;
|
||||
import com.alibaba.nacos.common.utils.JacksonUtils;
|
||||
import com.alibaba.nacos.common.utils.StringUtils;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@ -35,53 +35,53 @@ import java.util.Properties;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* Security proxy to update security information
|
||||
* Security proxy to update security information.
|
||||
*
|
||||
* @author nkorange
|
||||
* @since 1.2.0
|
||||
*/
|
||||
public class SecurityProxy {
|
||||
|
||||
|
||||
private static final Logger SECURITY_LOGGER = LoggerFactory.getLogger(SecurityProxy.class);
|
||||
|
||||
|
||||
private static final String LOGIN_URL = "/v1/auth/users/login";
|
||||
|
||||
private NacosRestTemplate nacosRestTemplate = NamingHttpClientManager.getNacosRestTemplate();
|
||||
|
||||
|
||||
private final NacosRestTemplate nacosRestTemplate = NamingHttpClientManager.getInstance().getNacosRestTemplate();
|
||||
|
||||
private String contextPath;
|
||||
|
||||
|
||||
/**
|
||||
* User's name
|
||||
* User's name.
|
||||
*/
|
||||
private String username;
|
||||
|
||||
private final String username;
|
||||
|
||||
/**
|
||||
* User's password
|
||||
* User's password.
|
||||
*/
|
||||
private String password;
|
||||
|
||||
private final String password;
|
||||
|
||||
/**
|
||||
* A token to take with when sending request to Nacos server
|
||||
* A token to take with when sending request to Nacos server.
|
||||
*/
|
||||
private String accessToken;
|
||||
|
||||
|
||||
/**
|
||||
* TTL of token in seconds
|
||||
* TTL of token in seconds.
|
||||
*/
|
||||
private long tokenTtl;
|
||||
|
||||
|
||||
/**
|
||||
* Last timestamp refresh security info from server
|
||||
* Last timestamp refresh security info from server.
|
||||
*/
|
||||
private long lastRefreshTime;
|
||||
|
||||
|
||||
/**
|
||||
* time window to refresh security info in seconds
|
||||
* time window to refresh security info in seconds.
|
||||
*/
|
||||
private long tokenRefreshWindow;
|
||||
|
||||
|
||||
/**
|
||||
* Construct from properties, keeping flexibility
|
||||
* Construct from properties, keeping flexibility.
|
||||
*
|
||||
* @param properties a bunch of properties to read
|
||||
*/
|
||||
@ -91,14 +91,21 @@ public class SecurityProxy {
|
||||
contextPath = properties.getProperty(PropertyKeyConst.CONTEXT_PATH, "/nacos");
|
||||
contextPath = contextPath.startsWith("/") ? contextPath : "/" + contextPath;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Login to servers.
|
||||
*
|
||||
* @param servers server list
|
||||
* @return true if login successfully
|
||||
*/
|
||||
public boolean login(List<String> servers) {
|
||||
|
||||
|
||||
try {
|
||||
if ((System.currentTimeMillis() - lastRefreshTime) < TimeUnit.SECONDS.toMillis(tokenTtl - tokenRefreshWindow)) {
|
||||
if ((System.currentTimeMillis() - lastRefreshTime) < TimeUnit.SECONDS
|
||||
.toMillis(tokenTtl - tokenRefreshWindow)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
for (String server : servers) {
|
||||
if (login(server)) {
|
||||
lastRefreshTime = System.currentTimeMillis();
|
||||
@ -107,24 +114,31 @@ public class SecurityProxy {
|
||||
}
|
||||
} catch (Throwable ignore) {
|
||||
}
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Login to server.
|
||||
*
|
||||
* @param server server address
|
||||
* @return true if login successfully
|
||||
*/
|
||||
public boolean login(String server) {
|
||||
|
||||
|
||||
if (StringUtils.isNotBlank(username)) {
|
||||
Map<String, String> params = new HashMap<String, String>(2);
|
||||
Map<String, String> bodyMap = new HashMap<>(2);
|
||||
Map<String, String> bodyMap = new HashMap<String, String>(2);
|
||||
params.put("username", username);
|
||||
bodyMap.put("password", password);
|
||||
String url = "http://" + server + contextPath + LOGIN_URL;
|
||||
|
||||
|
||||
if (server.contains(Constants.HTTP_PREFIX)) {
|
||||
url = server + contextPath + LOGIN_URL;
|
||||
}
|
||||
try {
|
||||
HttpRestResult<String> restResult = nacosRestTemplate.postForm(url, Header.EMPTY, params, bodyMap, String.class);
|
||||
HttpRestResult<String> restResult = nacosRestTemplate
|
||||
.postForm(url, Header.EMPTY, params, bodyMap, String.class);
|
||||
if (!restResult.ok()) {
|
||||
SECURITY_LOGGER.error("login failed: {}", JacksonUtils.toJson(restResult));
|
||||
return false;
|
||||
@ -136,14 +150,14 @@ public class SecurityProxy {
|
||||
tokenRefreshWindow = tokenTtl / 10;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
SECURITY_LOGGER.error("[SecurityProxy] login http request failed" +
|
||||
" url: {}, params: {}, bodyMap: {}, errorMsg: {}", url, params, bodyMap, e.getMessage());
|
||||
SECURITY_LOGGER.error("[SecurityProxy] login http request failed"
|
||||
+ " url: {}, params: {}, bodyMap: {}, errorMsg: {}", url, params, bodyMap, e.getMessage());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public String getAccessToken() {
|
||||
return accessToken;
|
||||
}
|
||||
|
@ -13,6 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.client.utils;
|
||||
|
||||
import com.alibaba.nacos.common.utils.StringUtils;
|
||||
@ -20,43 +21,50 @@ import com.alibaba.nacos.common.utils.StringUtils;
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* appName util
|
||||
* appName util.
|
||||
*
|
||||
* @author Nacos
|
||||
*/
|
||||
public class AppNameUtils {
|
||||
|
||||
|
||||
private static final String PARAM_MARKING_PROJECT = "project.name";
|
||||
|
||||
private static final String PARAM_MARKING_JBOSS = "jboss.server.home.dir";
|
||||
|
||||
private static final String PARAM_MARKING_JETTY = "jetty.home";
|
||||
|
||||
private static final String PARAM_MARKING_TOMCAT = "catalina.base";
|
||||
|
||||
|
||||
private static final String LINUX_ADMIN_HOME = "/home/admin/";
|
||||
|
||||
private static final String SERVER_JBOSS = "jboss";
|
||||
|
||||
private static final String SERVER_JETTY = "jetty";
|
||||
|
||||
private static final String SERVER_TOMCAT = "tomcat";
|
||||
|
||||
private static final String SERVER_UNKNOWN = "unknown server";
|
||||
|
||||
|
||||
public static String getAppName() {
|
||||
String appName = null;
|
||||
|
||||
|
||||
appName = getAppNameByProjectName();
|
||||
if (appName != null) {
|
||||
return appName;
|
||||
}
|
||||
|
||||
|
||||
appName = getAppNameByServerHome();
|
||||
if (appName != null) {
|
||||
return appName;
|
||||
}
|
||||
|
||||
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
|
||||
private static String getAppNameByProjectName() {
|
||||
return System.getProperty(PARAM_MARKING_PROJECT);
|
||||
}
|
||||
|
||||
|
||||
private static String getAppNameByServerHome() {
|
||||
String serverHome = null;
|
||||
if (SERVER_JBOSS.equals(getServerType())) {
|
||||
@ -66,14 +74,14 @@ public class AppNameUtils {
|
||||
} else if (SERVER_TOMCAT.equals(getServerType())) {
|
||||
serverHome = System.getProperty(PARAM_MARKING_TOMCAT);
|
||||
}
|
||||
|
||||
|
||||
if (serverHome != null && serverHome.startsWith(LINUX_ADMIN_HOME)) {
|
||||
return StringUtils.substringBetween(serverHome, LINUX_ADMIN_HOME, File.separator);
|
||||
}
|
||||
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
private static String getServerType() {
|
||||
String serverType = null;
|
||||
if (System.getProperty(PARAM_MARKING_JBOSS) != null) {
|
||||
@ -87,5 +95,5 @@ public class AppNameUtils {
|
||||
}
|
||||
return serverType;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -13,6 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.client.utils;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
@ -26,9 +27,9 @@ import java.util.Map;
|
||||
* @author Nacos
|
||||
*/
|
||||
public class EnvUtil {
|
||||
|
||||
final static public Logger LOGGER = LogUtils.logger(EnvUtil.class);
|
||||
|
||||
|
||||
public static final Logger LOGGER = LogUtils.logger(EnvUtil.class);
|
||||
|
||||
public static void setSelfEnv(Map<String, List<String>> headers) {
|
||||
if (headers != null) {
|
||||
List<String> amorayTagTmp = headers.get(AMORY_TAG);
|
||||
@ -44,7 +45,7 @@ public class EnvUtil {
|
||||
LOGGER.warn("selfAmoryTag:{}", selfAmorayTag);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
List<String> vipserverTagTmp = headers.get(VIPSERVER_TAG);
|
||||
if (vipserverTagTmp == null) {
|
||||
if (selfVipserverTag != null) {
|
||||
@ -73,19 +74,19 @@ public class EnvUtil {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static String getSelfAmorayTag() {
|
||||
return selfAmorayTag;
|
||||
}
|
||||
|
||||
|
||||
public static String getSelfVipserverTag() {
|
||||
return selfVipserverTag;
|
||||
}
|
||||
|
||||
|
||||
public static String getSelfLocationTag() {
|
||||
return selfLocationTag;
|
||||
}
|
||||
|
||||
|
||||
private static String listToString(List<String> list) {
|
||||
if (list == null || list.isEmpty()) {
|
||||
return null;
|
||||
@ -97,11 +98,16 @@ public class EnvUtil {
|
||||
}
|
||||
return result.toString().substring(0, result.length() - 1);
|
||||
}
|
||||
|
||||
|
||||
private static String selfAmorayTag;
|
||||
|
||||
private static String selfVipserverTag;
|
||||
|
||||
private static String selfLocationTag;
|
||||
private final static String AMORY_TAG = "Amory-Tag";
|
||||
private final static String VIPSERVER_TAG = "Vipserver-Tag";
|
||||
private final static String LOCATION_TAG = "Location-Tag";
|
||||
|
||||
private static final String AMORY_TAG = "Amory-Tag";
|
||||
|
||||
private static final String VIPSERVER_TAG = "Vipserver-Tag";
|
||||
|
||||
private static final String LOCATION_TAG = "Location-Tag";
|
||||
}
|
||||
|
@ -13,6 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.client.utils;
|
||||
|
||||
import com.alibaba.nacos.common.utils.StringUtils;
|
||||
@ -21,24 +22,25 @@ import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* ip tool
|
||||
* ip tool.
|
||||
*
|
||||
* @author Nacos
|
||||
*/
|
||||
@SuppressWarnings("PMD.ClassNamingShouldBeCamelRule")
|
||||
public class IPUtil {
|
||||
|
||||
private static final Pattern IPV4_PATTERN = Pattern.compile("^((25[0-5]|2[0-4]\\d|[01]?\\d\\d?)\\.){3}(25[0-5]|2[0-4]\\d|[01]?\\d\\d?)$");
|
||||
public class IpUtil {
|
||||
|
||||
private static final Pattern IPV4_PATTERN = Pattern
|
||||
.compile("^((25[0-5]|2[0-4]\\d|[01]?\\d\\d?)\\.){3}(25[0-5]|2[0-4]\\d|[01]?\\d\\d?)$");
|
||||
|
||||
private static final Pattern IPV6_PATTERN = Pattern.compile("^([\\da-fA-F]{1,4}:){7}[\\da-fA-F]{1,4}$");
|
||||
|
||||
public static boolean isIPV4(String addr) {
|
||||
|
||||
public static boolean isIpv4(String addr) {
|
||||
return isMatch(addr, IPV4_PATTERN);
|
||||
}
|
||||
|
||||
public static boolean isIPV6(String addr) {
|
||||
|
||||
public static boolean isIpv6(String addr) {
|
||||
return isMatch(addr, IPV6_PATTERN);
|
||||
}
|
||||
|
||||
|
||||
private static boolean isMatch(String data, Pattern pattern) {
|
||||
if (StringUtils.isBlank(data)) {
|
||||
return false;
|
@ -13,6 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.client.utils;
|
||||
|
||||
import com.alibaba.nacos.client.logging.AbstractNacosLogging;
|
||||
@ -23,18 +24,20 @@ import org.slf4j.Logger;
|
||||
import static org.slf4j.LoggerFactory.getLogger;
|
||||
|
||||
/**
|
||||
* Log utils.
|
||||
*
|
||||
* @author <a href="mailto:huangxiaoyu1018@gmail.com">hxy1991</a>
|
||||
* @since 0.9.0
|
||||
*/
|
||||
public class LogUtils {
|
||||
|
||||
|
||||
public static final Logger NAMING_LOGGER;
|
||||
|
||||
|
||||
static {
|
||||
try {
|
||||
boolean isLogback = false;
|
||||
AbstractNacosLogging nacosLogging;
|
||||
|
||||
|
||||
try {
|
||||
Class.forName("ch.qos.logback.classic.Logger");
|
||||
nacosLogging = new LogbackNacosLogging();
|
||||
@ -42,27 +45,27 @@ public class LogUtils {
|
||||
} catch (ClassNotFoundException e) {
|
||||
nacosLogging = new Log4J2NacosLogging();
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
nacosLogging.loadConfiguration();
|
||||
} catch (Throwable t) {
|
||||
if (isLogback) {
|
||||
getLogger(LogUtils.class).warn("Load Logback Configuration of Nacos fail, message: {}",
|
||||
t.getMessage());
|
||||
getLogger(LogUtils.class)
|
||||
.warn("Load Logback Configuration of Nacos fail, message: {}", t.getMessage());
|
||||
} else {
|
||||
getLogger(LogUtils.class).warn("Load Log4j Configuration of Nacos fail, message: {}",
|
||||
t.getMessage());
|
||||
getLogger(LogUtils.class)
|
||||
.warn("Load Log4j Configuration of Nacos fail, message: {}", t.getMessage());
|
||||
}
|
||||
}
|
||||
} catch (Throwable t1) {
|
||||
getLogger(LogUtils.class).warn("Init Nacos Logging fail, message: {}", t1.getMessage());
|
||||
} catch (Throwable ex) {
|
||||
getLogger(LogUtils.class).warn("Init Nacos Logging fail, message: {}", ex.getMessage());
|
||||
}
|
||||
|
||||
|
||||
NAMING_LOGGER = getLogger("com.alibaba.nacos.client.naming");
|
||||
}
|
||||
|
||||
|
||||
public static Logger logger(Class<?> clazz) {
|
||||
return getLogger(clazz);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -13,6 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.client.utils;
|
||||
|
||||
import com.alibaba.nacos.api.PropertyKeyConst;
|
||||
@ -28,39 +29,47 @@ import java.util.concurrent.Callable;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* manage param tool
|
||||
* manage param tool.
|
||||
*
|
||||
* @author nacos
|
||||
*/
|
||||
public class ParamUtil {
|
||||
|
||||
private final static Logger LOGGER = LogUtils.logger(ParamUtil.class);
|
||||
|
||||
public final static boolean USE_ENDPOINT_PARSING_RULE_DEFAULT_VALUE = true;
|
||||
|
||||
|
||||
private static final Logger LOGGER = LogUtils.logger(ParamUtil.class);
|
||||
|
||||
public static final boolean USE_ENDPOINT_PARSING_RULE_DEFAULT_VALUE = true;
|
||||
|
||||
private static final Pattern PATTERN = Pattern.compile("\\$\\{[^}]+\\}");
|
||||
|
||||
private static String defaultContextPath;
|
||||
|
||||
private static String defaultNodesPath = "serverlist";
|
||||
|
||||
private static String appKey;
|
||||
|
||||
private static String appName;
|
||||
private static String defaultServerPort;
|
||||
|
||||
private static final String DEFAULT_SERVER_PORT;
|
||||
|
||||
private static String clientVersion = "unknown";
|
||||
|
||||
private static int connectTimeout;
|
||||
|
||||
private static double perTaskConfigSize = 3000;
|
||||
|
||||
|
||||
static {
|
||||
// 客户端身份信息
|
||||
appKey = System.getProperty("nacos.client.appKey", "");
|
||||
|
||||
|
||||
defaultContextPath = System.getProperty("nacos.client.contextPath", "nacos");
|
||||
|
||||
|
||||
appName = AppNameUtils.getAppName();
|
||||
|
||||
|
||||
String defaultServerPortTmp = "8848";
|
||||
|
||||
defaultServerPort = System.getProperty("nacos.server.port", defaultServerPortTmp);
|
||||
LOGGER.info("[settings] [req-serv] nacos-server port:{}", defaultServerPort);
|
||||
|
||||
|
||||
DEFAULT_SERVER_PORT = System.getProperty("nacos.server.port", defaultServerPortTmp);
|
||||
LOGGER.info("[settings] [req-serv] nacos-server port:{}", DEFAULT_SERVER_PORT);
|
||||
|
||||
String tmp = "1000";
|
||||
try {
|
||||
tmp = System.getProperty("NACOS.CONNECT.TIMEOUT", "1000");
|
||||
@ -71,10 +80,9 @@ public class ParamUtil {
|
||||
throw new IllegalArgumentException(msg, e);
|
||||
}
|
||||
LOGGER.info("[settings] [http-client] connect timeout:{}", connectTimeout);
|
||||
|
||||
|
||||
try {
|
||||
InputStream in = HttpSimpleClient.class.getClassLoader()
|
||||
.getResourceAsStream("application.properties");
|
||||
InputStream in = HttpSimpleClient.class.getClassLoader().getResourceAsStream("application.properties");
|
||||
Properties props = new Properties();
|
||||
props.load(in);
|
||||
String val = null;
|
||||
@ -86,7 +94,7 @@ public class ParamUtil {
|
||||
} catch (Exception e) {
|
||||
LOGGER.error("[500] read application.properties", e);
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
perTaskConfigSize = Double.valueOf(System.getProperty("PER_TASK_CONFIG_SIZE", "3000"));
|
||||
LOGGER.info("PER_TASK_CONFIG_SIZE: {}", perTaskConfigSize);
|
||||
@ -94,75 +102,80 @@ public class ParamUtil {
|
||||
LOGGER.error("[PER_TASK_CONFIG_SIZE] PER_TASK_CONFIG_SIZE invalid", t);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static String getAppKey() {
|
||||
return appKey;
|
||||
}
|
||||
|
||||
|
||||
public static void setAppKey(String appKey) {
|
||||
ParamUtil.appKey = appKey;
|
||||
}
|
||||
|
||||
|
||||
public static String getAppName() {
|
||||
return appName;
|
||||
}
|
||||
|
||||
|
||||
public static void setAppName(String appName) {
|
||||
ParamUtil.appName = appName;
|
||||
}
|
||||
|
||||
|
||||
public static String getDefaultContextPath() {
|
||||
return defaultContextPath;
|
||||
}
|
||||
|
||||
|
||||
public static void setDefaultContextPath(String defaultContextPath) {
|
||||
ParamUtil.defaultContextPath = defaultContextPath;
|
||||
}
|
||||
|
||||
|
||||
public static String getClientVersion() {
|
||||
return clientVersion;
|
||||
}
|
||||
|
||||
|
||||
public static void setClientVersion(String clientVersion) {
|
||||
ParamUtil.clientVersion = clientVersion;
|
||||
}
|
||||
|
||||
|
||||
public static int getConnectTimeout() {
|
||||
return connectTimeout;
|
||||
}
|
||||
|
||||
|
||||
public static void setConnectTimeout(int connectTimeout) {
|
||||
ParamUtil.connectTimeout = connectTimeout;
|
||||
}
|
||||
|
||||
|
||||
public static double getPerTaskConfigSize() {
|
||||
return perTaskConfigSize;
|
||||
}
|
||||
|
||||
|
||||
public static void setPerTaskConfigSize(double perTaskConfigSize) {
|
||||
ParamUtil.perTaskConfigSize = perTaskConfigSize;
|
||||
}
|
||||
|
||||
|
||||
public static String getDefaultServerPort() {
|
||||
return defaultServerPort;
|
||||
return DEFAULT_SERVER_PORT;
|
||||
}
|
||||
|
||||
|
||||
public static String getDefaultNodesPath() {
|
||||
return defaultNodesPath;
|
||||
}
|
||||
|
||||
|
||||
public static void setDefaultNodesPath(String defaultNodesPath) {
|
||||
ParamUtil.defaultNodesPath = defaultNodesPath;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Parse namespace from properties and environment.
|
||||
*
|
||||
* @param properties properties
|
||||
* @return namespace
|
||||
*/
|
||||
public static String parseNamespace(Properties properties) {
|
||||
String namespaceTmp = null;
|
||||
|
||||
String isUseCloudNamespaceParsing =
|
||||
properties.getProperty(PropertyKeyConst.IS_USE_CLOUD_NAMESPACE_PARSING,
|
||||
|
||||
String isUseCloudNamespaceParsing = properties.getProperty(PropertyKeyConst.IS_USE_CLOUD_NAMESPACE_PARSING,
|
||||
System.getProperty(SystemPropertyKeyConst.IS_USE_CLOUD_NAMESPACE_PARSING,
|
||||
String.valueOf(Constants.DEFAULT_USE_CLOUD_NAMESPACE_PARSING)));
|
||||
|
||||
String.valueOf(Constants.DEFAULT_USE_CLOUD_NAMESPACE_PARSING)));
|
||||
|
||||
if (Boolean.parseBoolean(isUseCloudNamespaceParsing)) {
|
||||
namespaceTmp = TemplateUtils.stringBlankAndThenExecute(namespaceTmp, new Callable<String>() {
|
||||
@Override
|
||||
@ -170,7 +183,7 @@ public class ParamUtil {
|
||||
return TenantUtil.getUserTenantForAcm();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
namespaceTmp = TemplateUtils.stringBlankAndThenExecute(namespaceTmp, new Callable<String>() {
|
||||
@Override
|
||||
public String call() {
|
||||
@ -179,44 +192,48 @@ public class ParamUtil {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
if (StringUtils.isBlank(namespaceTmp)) {
|
||||
namespaceTmp = properties.getProperty(PropertyKeyConst.NAMESPACE);
|
||||
}
|
||||
return StringUtils.isNotBlank(namespaceTmp) ? namespaceTmp.trim() : StringUtils.EMPTY;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Parse end point rule.
|
||||
*
|
||||
* @param endpointUrl endpoint url
|
||||
* @return end point rule
|
||||
*/
|
||||
public static String parsingEndpointRule(String endpointUrl) {
|
||||
// 配置文件中输入的话,以 ENV 中的优先,
|
||||
if (endpointUrl == null
|
||||
|| !PATTERN.matcher(endpointUrl).find()) {
|
||||
if (endpointUrl == null || !PATTERN.matcher(endpointUrl).find()) {
|
||||
// skip retrieve from system property and retrieve directly from system env
|
||||
String endpointUrlSource = System.getenv(PropertyKeyConst.SystemEnv.ALIBABA_ALIWARE_ENDPOINT_URL);
|
||||
if (StringUtils.isNotBlank(endpointUrlSource)) {
|
||||
endpointUrl = endpointUrlSource;
|
||||
}
|
||||
|
||||
|
||||
return StringUtils.isNotBlank(endpointUrl) ? endpointUrl : "";
|
||||
}
|
||||
|
||||
endpointUrl = endpointUrl.substring(endpointUrl.indexOf("${") + 2,
|
||||
endpointUrl.lastIndexOf("}"));
|
||||
|
||||
endpointUrl = endpointUrl.substring(endpointUrl.indexOf("${") + 2, endpointUrl.lastIndexOf("}"));
|
||||
int defStartOf = endpointUrl.indexOf(":");
|
||||
String defaultEndpointUrl = null;
|
||||
if (defStartOf != -1) {
|
||||
defaultEndpointUrl = endpointUrl.substring(defStartOf + 1);
|
||||
endpointUrl = endpointUrl.substring(0, defStartOf);
|
||||
}
|
||||
|
||||
String endpointUrlSource = TemplateUtils.stringBlankAndThenExecute(System.getProperty(endpointUrl,
|
||||
System.getenv(endpointUrl)), new Callable<String>() {
|
||||
@Override
|
||||
public String call() {
|
||||
return System.getenv(PropertyKeyConst.SystemEnv.ALIBABA_ALIWARE_ENDPOINT_URL);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
|
||||
String endpointUrlSource = TemplateUtils
|
||||
.stringBlankAndThenExecute(System.getProperty(endpointUrl, System.getenv(endpointUrl)),
|
||||
new Callable<String>() {
|
||||
@Override
|
||||
public String call() {
|
||||
return System.getenv(PropertyKeyConst.SystemEnv.ALIBABA_ALIWARE_ENDPOINT_URL);
|
||||
}
|
||||
});
|
||||
|
||||
if (StringUtils.isBlank(endpointUrlSource)) {
|
||||
if (StringUtils.isNotBlank(defaultEndpointUrl)) {
|
||||
endpointUrl = defaultEndpointUrl;
|
||||
@ -224,7 +241,7 @@ public class ParamUtil {
|
||||
} else {
|
||||
endpointUrl = endpointUrlSource;
|
||||
}
|
||||
|
||||
|
||||
return StringUtils.isNotBlank(endpointUrl) ? endpointUrl : "";
|
||||
}
|
||||
}
|
||||
|
@ -13,6 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.client.utils;
|
||||
|
||||
import com.alibaba.nacos.common.utils.StringUtils;
|
||||
@ -20,15 +21,23 @@ import com.alibaba.nacos.common.utils.StringUtils;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
/**
|
||||
* Template Utils.
|
||||
*
|
||||
* @author pbting
|
||||
* @date 2019-03-04 1:31 PM
|
||||
*/
|
||||
public class TemplateUtils {
|
||||
|
||||
|
||||
/**
|
||||
* Execute if string not empty.
|
||||
*
|
||||
* @param source source
|
||||
* @param runnable execute runnable
|
||||
*/
|
||||
public static void stringNotEmptyAndThenExecute(String source, Runnable runnable) {
|
||||
|
||||
|
||||
if (StringUtils.isNotEmpty(source)) {
|
||||
|
||||
|
||||
try {
|
||||
runnable.run();
|
||||
} catch (Exception e) {
|
||||
@ -36,32 +45,46 @@ public class TemplateUtils {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Execute if string empty.
|
||||
*
|
||||
* @param source empty source
|
||||
* @param callable execute callable
|
||||
* @return result
|
||||
*/
|
||||
public static String stringEmptyAndThenExecute(String source, Callable<String> callable) {
|
||||
|
||||
|
||||
if (StringUtils.isEmpty(source)) {
|
||||
|
||||
|
||||
try {
|
||||
return callable.call();
|
||||
} catch (Exception e) {
|
||||
LogUtils.NAMING_LOGGER.error("string empty and then execute cause an exception.", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return source.trim();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Execute if string blank.
|
||||
*
|
||||
* @param source empty source
|
||||
* @param callable execute callable
|
||||
* @return result
|
||||
*/
|
||||
public static String stringBlankAndThenExecute(String source, Callable<String> callable) {
|
||||
|
||||
|
||||
if (StringUtils.isBlank(source)) {
|
||||
|
||||
|
||||
try {
|
||||
return callable.call();
|
||||
} catch (Exception e) {
|
||||
LogUtils.NAMING_LOGGER.error("string empty and then execute cause an exception.", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return source.trim();
|
||||
}
|
||||
}
|
||||
|
@ -13,51 +13,52 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.client.utils;
|
||||
|
||||
import com.alibaba.nacos.common.utils.StringUtils;
|
||||
|
||||
/**
|
||||
* Tenant Util
|
||||
* Tenant Util.
|
||||
*
|
||||
* @author Nacos
|
||||
*/
|
||||
public class TenantUtil {
|
||||
|
||||
private static String userTenant;
|
||||
|
||||
|
||||
private static final String USER_TENANT;
|
||||
|
||||
static {
|
||||
userTenant = System.getProperty("tenant.id", "");
|
||||
USER_TENANT = System.getProperty("tenant.id", "");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Adapt the way ACM gets tenant on the cloud.
|
||||
* <p>
|
||||
* Note the difference between getting and getting ANS.
|
||||
* Since the processing logic on the server side is different, the default value returns differently.
|
||||
* Note the difference between getting and getting ANS. Since the processing logic on the server side is different,
|
||||
* the default value returns differently.
|
||||
* </p>
|
||||
*
|
||||
* @return
|
||||
* @return user tenant for acm
|
||||
*/
|
||||
public static String getUserTenantForAcm() {
|
||||
String tmp = userTenant;
|
||||
|
||||
if (StringUtils.isBlank(userTenant)) {
|
||||
String tmp = USER_TENANT;
|
||||
|
||||
if (StringUtils.isBlank(USER_TENANT)) {
|
||||
tmp = System.getProperty("acm.namespace", "");
|
||||
}
|
||||
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Adapt the way ANS gets tenant on the cloud.
|
||||
*
|
||||
* @return
|
||||
* @return user tenant for ans
|
||||
*/
|
||||
public static String getUserTenantForAns() {
|
||||
String tmp = userTenant;
|
||||
|
||||
if (StringUtils.isBlank(userTenant)) {
|
||||
String tmp = USER_TENANT;
|
||||
|
||||
if (StringUtils.isBlank(USER_TENANT)) {
|
||||
tmp = System.getProperty("ans.namespace");
|
||||
}
|
||||
return tmp;
|
||||
|
@ -18,34 +18,37 @@ package com.alibaba.nacos.client.utils;
|
||||
|
||||
import com.alibaba.nacos.api.PropertyKeyConst;
|
||||
import com.alibaba.nacos.api.exception.NacosException;
|
||||
import com.alibaba.nacos.common.utils.StringUtils;
|
||||
|
||||
import java.util.Properties;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* All parameter validation tools
|
||||
* All parameter validation tools.
|
||||
*
|
||||
* @author <a href="mailto:liaochuntao@live.com">liaochuntao</a>
|
||||
*/
|
||||
@SuppressWarnings("all")
|
||||
public final class ValidatorUtils {
|
||||
|
||||
private static final Pattern CONTEXT_PATH_MATCH = Pattern.compile("(\\/)\\1+");
|
||||
|
||||
public static void checkInitParam(Properties properties) throws NacosException {
|
||||
checkContextPath(properties.getProperty(PropertyKeyConst.CONTEXT_PATH));
|
||||
}
|
||||
|
||||
public static void checkContextPath(String contextPath) {
|
||||
if (contextPath == null) {
|
||||
return;
|
||||
}
|
||||
Matcher matcher = CONTEXT_PATH_MATCH.matcher(contextPath);
|
||||
if (matcher.find()) {
|
||||
throw new IllegalArgumentException("Illegal url path expression");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static final Pattern CONTEXT_PATH_MATCH = Pattern.compile("(\\/)\\1+");
|
||||
|
||||
public static void checkInitParam(Properties properties) throws NacosException {
|
||||
checkContextPath(properties.getProperty(PropertyKeyConst.CONTEXT_PATH));
|
||||
}
|
||||
|
||||
/**
|
||||
* Check context path.
|
||||
*
|
||||
* @param contextPath context path
|
||||
*/
|
||||
public static void checkContextPath(String contextPath) {
|
||||
if (contextPath == null) {
|
||||
return;
|
||||
}
|
||||
Matcher matcher = CONTEXT_PATH_MATCH.matcher(contextPath);
|
||||
if (matcher.find()) {
|
||||
throw new IllegalArgumentException("Illegal url path expression");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -13,5 +13,4 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
version=${project.version}
|
||||
|
@ -18,47 +18,47 @@
|
||||
<Configuration status="WARN">
|
||||
<Appenders>
|
||||
<RollingFile name="CONFIG_LOG_FILE" fileName="${sys:nacos.logging.path}/config.log"
|
||||
filePattern="${sys:nacos.logging.path}/config.log.%d{yyyy-MM-dd}.%i">
|
||||
filePattern="${sys:nacos.logging.path}/config.log.%d{yyyy-MM-dd}.%i">
|
||||
<PatternLayout>
|
||||
<Pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %p [%-5t:%c{2}] %m%n</Pattern>
|
||||
</PatternLayout>
|
||||
|
||||
|
||||
<Policies>
|
||||
<TimeBasedTriggeringPolicy/>
|
||||
<SizeBasedTriggeringPolicy size="${sys:JM.LOG.FILE.SIZE:-10MB}"/>
|
||||
</Policies>
|
||||
|
||||
|
||||
<DefaultRolloverStrategy max="${sys:JM.LOG.RETAIN.COUNT:-7}"/>
|
||||
</RollingFile>
|
||||
|
||||
|
||||
<RollingFile name="NAMING_LOG_FILE" fileName="${sys:nacos.logging.path}/naming.log"
|
||||
filePattern="${sys:nacos.logging.path}/naming.log.%d{yyyy-MM-dd}.%i">
|
||||
filePattern="${sys:nacos.logging.path}/naming.log.%d{yyyy-MM-dd}.%i">
|
||||
<PatternLayout>
|
||||
<Pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %p [%-5t:%c{2}] %m%n</Pattern>
|
||||
</PatternLayout>
|
||||
|
||||
|
||||
<Policies>
|
||||
<TimeBasedTriggeringPolicy/>
|
||||
<SizeBasedTriggeringPolicy size="${sys:JM.LOG.FILE.SIZE:-10MB}"/>
|
||||
</Policies>
|
||||
|
||||
|
||||
<DefaultRolloverStrategy max="${sys:JM.LOG.RETAIN.COUNT:-7}"/>
|
||||
</RollingFile>
|
||||
</Appenders>
|
||||
|
||||
|
||||
<Loggers>
|
||||
<Logger name="com.alibaba.nacos.client" level="${sys:com.alibaba.nacos.config.log.level:-info}"
|
||||
additivity="false">
|
||||
additivity="false">
|
||||
<AppenderRef ref="CONFIG_LOG_FILE"/>
|
||||
</Logger>
|
||||
|
||||
|
||||
<Logger name="com.alibaba.nacos.client.config" level="${sys:com.alibaba.nacos.config.log.level:-info}"
|
||||
additivity="false">
|
||||
additivity="false">
|
||||
<AppenderRef ref="CONFIG_LOG_FILE"/>
|
||||
</Logger>
|
||||
|
||||
|
||||
<Logger name="com.alibaba.nacos.client.naming" level="${sys:com.alibaba.nacos.naming.log.level:-info}"
|
||||
additivity="false">
|
||||
additivity="false">
|
||||
<AppenderRef ref="NAMING_LOG_FILE"/>
|
||||
</Logger>
|
||||
<Root level="INFO">
|
||||
|
@ -17,54 +17,54 @@
|
||||
|
||||
<configuration debug="false" scan="true" scanPeriod="30 seconds" packagingData="true">
|
||||
<contextName>nacos</contextName>
|
||||
|
||||
|
||||
<appender name="CONFIG_LOG_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<file>${nacos.logging.path}/config.log</file>
|
||||
|
||||
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
|
||||
<fileNamePattern>${nacos.logging.path}/config.log.%i</fileNamePattern>
|
||||
<maxIndex>${JM.LOG.RETAIN.COUNT:-7}</maxIndex>
|
||||
</rollingPolicy>
|
||||
|
||||
|
||||
<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
|
||||
<maxFileSize>${JM.LOG.FILE.SIZE:-10MB}</maxFileSize>
|
||||
</triggeringPolicy>
|
||||
|
||||
|
||||
<encoder>
|
||||
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %p [%-5t:%c{2}] %m%n</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
|
||||
<appender name="NAMING_LOG_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<file>${nacos.logging.path}/naming.log</file>
|
||||
|
||||
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
|
||||
<fileNamePattern>${nacos.logging.path}/naming.log.%i</fileNamePattern>
|
||||
<maxIndex>${JM.LOG.RETAIN.COUNT:-7}</maxIndex>
|
||||
</rollingPolicy>
|
||||
|
||||
|
||||
<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
|
||||
<maxFileSize>${JM.LOG.FILE.SIZE:-10MB}</maxFileSize>
|
||||
</triggeringPolicy>
|
||||
|
||||
|
||||
<encoder>
|
||||
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %p [%-5t:%c{2}] %m%n</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
|
||||
|
||||
|
||||
<logger name="com.alibaba.nacos.client" level="${com.alibaba.nacos.config.log.level:-info}"
|
||||
additivity="false">
|
||||
additivity="false">
|
||||
<appender-ref ref="CONFIG_LOG_FILE"/>
|
||||
</logger>
|
||||
|
||||
|
||||
<logger name="com.alibaba.nacos.client.config" level="${com.alibaba.nacos.config.log.level:-info}"
|
||||
additivity="false">
|
||||
additivity="false">
|
||||
<appender-ref ref="CONFIG_LOG_FILE"/>
|
||||
</logger>
|
||||
|
||||
|
||||
<logger name="com.alibaba.nacos.client.naming" level="${com.alibaba.nacos.naming.log.level:-info}"
|
||||
additivity="false">
|
||||
additivity="false">
|
||||
<appender-ref ref="NAMING_LOG_FILE"/>
|
||||
</logger>
|
||||
|
||||
|
@ -13,36 +13,23 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.client;
|
||||
|
||||
import junit.framework.Test;
|
||||
import junit.framework.TestCase;
|
||||
import junit.framework.TestSuite;
|
||||
|
||||
/**
|
||||
* Unit test for simple App.
|
||||
*/
|
||||
public class AppTest
|
||||
extends TestCase {
|
||||
/**
|
||||
* Create the test case
|
||||
*
|
||||
* @param testName name of the test case
|
||||
*/
|
||||
public class AppTest extends TestCase {
|
||||
|
||||
public AppTest(String testName) {
|
||||
super(testName);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the suite of tests being tested
|
||||
*/
|
||||
|
||||
public static Test suite() {
|
||||
return new TestSuite(AppTest.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Rigourous Test :-)
|
||||
*/
|
||||
|
||||
public void testApp() {
|
||||
assertTrue(true);
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user