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..3f21a9ad --- /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 com.alibaba.nacos.api.naming.pojo.Instance; +import com.alibaba.nacos.client.naming.core.Balancer; + +import java.util.List; + +/** + * @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..b8cbda2b --- /dev/null +++ b/spring-cloud-alibaba-nacos-discovery/src/main/java/org/springframework/cloud/alibaba/nacos/ribbon/NacosRule.java @@ -0,0 +1,69 @@ +package org.springframework.cloud.alibaba.nacos.ribbon; + +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; +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 java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +/** + * 支持优先调用同集群实例的ribbon负载均衡规则. + * + * @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("{}服务当前无任何实例", name); + return null; + } + + List instancesToChoose = instances; + if (StringUtils.isNotBlank(clusterName)) { + List sameClusterInstances = instances.stream() + .filter(instance -> Objects.equals(clusterName, instance.getClusterName())) + .collect(Collectors.toList()); + if (!CollectionUtils.isEmpty(sameClusterInstances)) { + instancesToChoose = sameClusterInstances; + } else { + LOGGER.warn("发生跨集群的调用,name = {}, clusterName = {}, instance = {}", name, clusterName, instances); + } + } + + Instance instance = ExtendBalancer.getHostByRandomWeight2(instancesToChoose); + + return new NacosServer(instance); + } catch (Exception e) { + LOGGER.warn("NacosRule发生异常", e); + return null; + } + } + + @Override + public void initWithNiwsConfig(IClientConfig iClientConfig) { + } +}