diff --git a/spring-cloud-alibaba-nacos-discovery/src/main/java/org/springframework/cloud/alibaba/nacos/NacosDiscoveryProperties.java b/spring-cloud-alibaba-nacos-discovery/src/main/java/org/springframework/cloud/alibaba/nacos/NacosDiscoveryProperties.java
index 0dadefc4..fd35cb47 100644
--- a/spring-cloud-alibaba-nacos-discovery/src/main/java/org/springframework/cloud/alibaba/nacos/NacosDiscoveryProperties.java
+++ b/spring-cloud-alibaba-nacos-discovery/src/main/java/org/springframework/cloud/alibaba/nacos/NacosDiscoveryProperties.java
@@ -16,10 +16,27 @@
package org.springframework.cloud.alibaba.nacos;
-import com.alibaba.nacos.api.NacosFactory;
-import com.alibaba.nacos.api.naming.NamingService;
-import com.alibaba.nacos.api.naming.PreservedMetadataKeys;
-import com.alibaba.nacos.client.naming.utils.UtilAndComs;
+import static com.alibaba.nacos.api.PropertyKeyConst.ACCESS_KEY;
+import static com.alibaba.nacos.api.PropertyKeyConst.CLUSTER_NAME;
+import static com.alibaba.nacos.api.PropertyKeyConst.ENDPOINT;
+import static com.alibaba.nacos.api.PropertyKeyConst.ENDPOINT_PORT;
+import static com.alibaba.nacos.api.PropertyKeyConst.NAMESPACE;
+import static com.alibaba.nacos.api.PropertyKeyConst.NAMING_LOAD_CACHE_AT_START;
+import static com.alibaba.nacos.api.PropertyKeyConst.SECRET_KEY;
+import static com.alibaba.nacos.api.PropertyKeyConst.SERVER_ADDR;
+
+import java.net.Inet4Address;
+import java.net.InetAddress;
+import java.net.NetworkInterface;
+import java.net.SocketException;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Properties;
+
+import javax.annotation.PostConstruct;
+
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
@@ -28,14 +45,13 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cloud.commons.util.InetUtils;
import org.springframework.core.env.Environment;
import org.springframework.util.StringUtils;
-import javax.annotation.PostConstruct;
-import java.net.Inet4Address;
-import java.net.InetAddress;
-import java.net.NetworkInterface;
-import java.net.SocketException;
-import java.util.*;
-import static com.alibaba.nacos.api.PropertyKeyConst.*;
+import com.alibaba.nacos.api.NacosFactory;
+import com.alibaba.nacos.api.naming.NamingMaintainFactory;
+import com.alibaba.nacos.api.naming.NamingMaintainService;
+import com.alibaba.nacos.api.naming.NamingService;
+import com.alibaba.nacos.api.naming.PreservedMetadataKeys;
+import com.alibaba.nacos.client.naming.utils.UtilAndComs;
/**
* @author dungu.zpf
@@ -147,6 +163,8 @@ public class NacosDiscoveryProperties {
private NamingService namingService;
+ private NamingMaintainService namingMaintainService;
+
@PostConstruct
public void init() throws SocketException {
@@ -389,6 +407,34 @@ public class NacosDiscoveryProperties {
return namingService;
}
+ try {
+ namingService = NacosFactory.createNamingService(getNacosProperties());
+ }
+ catch (Exception e) {
+ log.error("create naming service error!properties={},e=,", this, e);
+ return null;
+ }
+ return namingService;
+ }
+
+ public NamingMaintainService namingMaintainServiceInstance() {
+
+ if (null != namingMaintainService) {
+ return namingMaintainService;
+ }
+
+ try {
+ namingMaintainService = NamingMaintainFactory
+ .createMaintainService(getNacosProperties());
+ }
+ catch (Exception e) {
+ log.error("create naming service error!properties={},e=,", this, e);
+ return null;
+ }
+ return namingMaintainService;
+ }
+
+ private Properties getNacosProperties() {
Properties properties = new Properties();
properties.put(SERVER_ADDR, serverAddr);
properties.put(NAMESPACE, namespace);
@@ -407,15 +453,7 @@ public class NacosDiscoveryProperties {
properties.put(SECRET_KEY, secretKey);
properties.put(CLUSTER_NAME, clusterName);
properties.put(NAMING_LOAD_CACHE_AT_START, namingLoadCacheAtStart);
-
- try {
- namingService = NacosFactory.createNamingService(properties);
- }
- catch (Exception e) {
- log.error("create naming service error!properties={},e=,", this, e);
- return null;
- }
- return namingService;
+ return properties;
}
}
diff --git a/spring-cloud-alibaba-nacos-discovery/src/main/java/org/springframework/cloud/alibaba/nacos/registry/NacosServiceRegistry.java b/spring-cloud-alibaba-nacos-discovery/src/main/java/org/springframework/cloud/alibaba/nacos/registry/NacosServiceRegistry.java
index 6c362af6..3e23fefc 100644
--- a/spring-cloud-alibaba-nacos-discovery/src/main/java/org/springframework/cloud/alibaba/nacos/registry/NacosServiceRegistry.java
+++ b/spring-cloud-alibaba-nacos-discovery/src/main/java/org/springframework/cloud/alibaba/nacos/registry/NacosServiceRegistry.java
@@ -16,8 +16,8 @@
package org.springframework.cloud.alibaba.nacos.registry;
-import com.alibaba.nacos.api.naming.NamingService;
-import com.alibaba.nacos.api.naming.pojo.Instance;
+import java.util.List;
+
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.alibaba.nacos.NacosDiscoveryProperties;
@@ -25,6 +25,9 @@ import org.springframework.cloud.client.serviceregistry.Registration;
import org.springframework.cloud.client.serviceregistry.ServiceRegistry;
import org.springframework.util.StringUtils;
+import com.alibaba.nacos.api.naming.NamingService;
+import com.alibaba.nacos.api.naming.pojo.Instance;
+
/**
* @author xiaojing
* @author Mercy
@@ -52,12 +55,7 @@ public class NacosServiceRegistry implements ServiceRegistry {
String serviceId = registration.getServiceId();
- Instance instance = new Instance();
- instance.setIp(registration.getHost());
- instance.setPort(registration.getPort());
- instance.setWeight(nacosDiscoveryProperties.getWeight());
- instance.setClusterName(nacosDiscoveryProperties.getClusterName());
- instance.setMetadata(registration.getMetadata());
+ Instance instance = getNacosInstanceFromRegistration(registration);
try {
namingService.registerInstance(serviceId, instance);
@@ -102,13 +100,60 @@ public class NacosServiceRegistry implements ServiceRegistry {
@Override
public void setStatus(Registration registration, String status) {
- // nacos doesn't support set status of a particular registration.
+
+ if (!status.equalsIgnoreCase("UP") && !status.equalsIgnoreCase("DOWN")) {
+ log.warn("can't support status {},please choose UP or DOWN", status);
+ return;
+ }
+
+ String serviceId = registration.getServiceId();
+
+ Instance instance = getNacosInstanceFromRegistration(registration);
+
+ if (status.equalsIgnoreCase("DOWN")) {
+ instance.setEnabled(false);
+ }
+ else {
+ instance.setEnabled(true);
+ }
+
+ try {
+ nacosDiscoveryProperties.namingMaintainServiceInstance()
+ .updateInstance(serviceId, instance);
+ }
+ catch (Exception e) {
+ throw new RuntimeException("update nacos instance status fail", e);
+ }
+
}
@Override
- public T getStatus(Registration registration) {
- // nacos doesn't support query status of a particular registration.
+ public Object getStatus(Registration registration) {
+
+ String serviceName = registration.getServiceId();
+ try {
+ List instances = nacosDiscoveryProperties.namingServiceInstance()
+ .getAllInstances(serviceName);
+ for (Instance instance : instances) {
+ if (instance.getIp().equalsIgnoreCase(nacosDiscoveryProperties.getIp())
+ && instance.getPort() == nacosDiscoveryProperties.getPort())
+ return instance.isEnabled() ? "UP" : "DOWN";
+ }
+ }
+ catch (Exception e) {
+ log.error("get all instance of {} error,", serviceName, e);
+ }
return null;
}
+ private Instance getNacosInstanceFromRegistration(Registration registration) {
+ Instance instance = new Instance();
+ instance.setIp(registration.getHost());
+ instance.setPort(registration.getPort());
+ instance.setWeight(nacosDiscoveryProperties.getWeight());
+ instance.setClusterName(nacosDiscoveryProperties.getClusterName());
+ instance.setMetadata(registration.getMetadata());
+ return instance;
+ }
+
}
diff --git a/spring-cloud-alibaba-nacos-discovery/src/main/java/org/springframework/cloud/alibaba/nacos/ribbon/ExtendBalancer.java b/spring-cloud-alibaba-nacos-discovery/src/main/java/org/springframework/cloud/alibaba/nacos/ribbon/ExtendBalancer.java
new file mode 100644
index 00000000..d581673c
--- /dev/null
+++ b/spring-cloud-alibaba-nacos-discovery/src/main/java/org/springframework/cloud/alibaba/nacos/ribbon/ExtendBalancer.java
@@ -0,0 +1,21 @@
+package org.springframework.cloud.alibaba.nacos.ribbon;
+
+import java.util.List;
+
+import com.alibaba.nacos.api.naming.pojo.Instance;
+import com.alibaba.nacos.client.naming.core.Balancer;
+
+/**
+ * @author itmuch.com
+ */
+public class ExtendBalancer extends Balancer {
+ /**
+ * 根据权重,随机选择实例
+ *
+ * @param instances 实例列表
+ * @return 选择的实例
+ */
+ public static Instance getHostByRandomWeight2(List instances) {
+ return getHostByRandomWeight(instances);
+ }
+}
diff --git a/spring-cloud-alibaba-nacos-discovery/src/main/java/org/springframework/cloud/alibaba/nacos/ribbon/NacosRule.java b/spring-cloud-alibaba-nacos-discovery/src/main/java/org/springframework/cloud/alibaba/nacos/ribbon/NacosRule.java
new file mode 100644
index 00000000..c388a4ff
--- /dev/null
+++ b/spring-cloud-alibaba-nacos-discovery/src/main/java/org/springframework/cloud/alibaba/nacos/ribbon/NacosRule.java
@@ -0,0 +1,80 @@
+package org.springframework.cloud.alibaba.nacos.ribbon;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+
+import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.cloud.alibaba.nacos.NacosDiscoveryProperties;
+import org.springframework.util.CollectionUtils;
+
+import com.alibaba.nacos.api.naming.NamingService;
+import com.alibaba.nacos.api.naming.pojo.Instance;
+
+import com.netflix.client.config.IClientConfig;
+import com.netflix.loadbalancer.AbstractLoadBalancerRule;
+import com.netflix.loadbalancer.DynamicServerListLoadBalancer;
+import com.netflix.loadbalancer.Server;
+
+/**
+ * Supports preferentially calling the ribbon load balancing rules of the same cluster
+ * instance.
+ *
+ * @author itmuch.com
+ */
+public class NacosRule extends AbstractLoadBalancerRule {
+ private static final Logger LOGGER = LoggerFactory.getLogger(NacosRule.class);
+
+ @Autowired
+ private NacosDiscoveryProperties nacosDiscoveryProperties;
+
+ @Override
+ public Server choose(Object key) {
+ try {
+ String clusterName = this.nacosDiscoveryProperties.getClusterName();
+ DynamicServerListLoadBalancer loadBalancer = (DynamicServerListLoadBalancer) getLoadBalancer();
+ String name = loadBalancer.getName();
+
+ NamingService namingService = this.nacosDiscoveryProperties
+ .namingServiceInstance();
+ List instances = namingService.selectInstances(name, true);
+ if (CollectionUtils.isEmpty(instances)) {
+ LOGGER.warn("no instance in service {}", name);
+ return null;
+ }
+
+ List instancesToChoose = instances;
+ if (StringUtils.isNotBlank(clusterName)) {
+ List sameClusterInstances = new ArrayList<>();
+ for (Instance instance : instances) {
+ if (Objects.equals(clusterName, instance.getClusterName())) {
+ sameClusterInstances.add(instance);
+ }
+ }
+ if (!CollectionUtils.isEmpty(sameClusterInstances)) {
+ instancesToChoose = sameClusterInstances;
+ }
+ else {
+ LOGGER.warn(
+ "A cross-cluster call occurs,name = {}, clusterName = {}, instance = {}",
+ name, clusterName, instances);
+ }
+ }
+
+ Instance instance = ExtendBalancer.getHostByRandomWeight2(instancesToChoose);
+
+ return new NacosServer(instance);
+ }
+ catch (Exception e) {
+ LOGGER.warn("NacosRule error", e);
+ return null;
+ }
+ }
+
+ @Override
+ public void initWithNiwsConfig(IClientConfig iClientConfig) {
+ }
+}