本篇内容介绍了“NacosNamingService中selectOneHealthyInstance的原理及作用是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

创新互联建站主要从事成都网站设计、做网站、网页设计、企业做网站、公司建网站等业务。立足成都服务怒江州,十余年网站建设经验,价格优惠、服务专业,欢迎来电咨询建站服务:18980820575
序
本文主要研究一下NacosNamingService的selectOneHealthyInstance
NacosNamingService
nacos-1.1.3/client/src/main/java/com/alibaba/nacos/client/naming/NacosNamingService.java
public class NacosNamingService implements NamingService {
    private static final String DEFAULT_PORT = "8080";
    private static final long DEFAULT_HEART_BEAT_INTERVAL = TimeUnit.SECONDS.toMillis(5);
    /**
     * Each Naming instance 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;
    //......
    @Override
    public Instance selectOneHealthyInstance(String serviceName) throws NacosException {
        return selectOneHealthyInstance(serviceName, new ArrayList());
    }
    @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(), subscribe);
    }
    @Override
    public Instance selectOneHealthyInstance(String serviceName, String groupName, boolean subscribe) throws NacosException {
        return selectOneHealthyInstance(serviceName, groupName, new ArrayList(), subscribe);
    }
    @Override
    public Instance selectOneHealthyInstance(String serviceName, List clusters) throws NacosException {
        return selectOneHealthyInstance(serviceName, clusters, true);
    }
    @Override
    public Instance selectOneHealthyInstance(String serviceName, String groupName, List clusters) throws NacosException {
        return selectOneHealthyInstance(serviceName, groupName, clusters, true);
    }
    @Override
    public Instance selectOneHealthyInstance(String serviceName, List clusters, boolean subscribe)
        throws NacosException {
        return selectOneHealthyInstance(serviceName, Constants.DEFAULT_GROUP, clusters, subscribe);
    }
    @Override
    public Instance selectOneHealthyInstance(String serviceName, String groupName, List 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, ",")));
        }
    }
    //......
}       - selectOneHealthyInstance跟selectInstances类似,只不过它返回的是单个instance;selectOneHealthyInstance也是先从hostReactor获取serviceInfo 
- 如果subscribe为true,则执行hostReactor.getServiceInfo获取serviceInfo,否则执行hostReactor.getServiceInfoDirectlyFromServer获取serviceInfo 
- 获取到serviceInfo之后,selectOneHealthyInstance通过Balancer.RandomByWeight.selectHost方法来选取单个healthy的instance 
Balancer
nacos-1.1.3/client/src/main/java/com/alibaba/nacos/client/naming/core/Balancer.java
public class Balancer {
    /**
     * report status to server
     */
    public final static List UNCONSISTENT_SERVICE_WITH_ADDRESS_SERVER = new CopyOnWriteArrayList();
    public static class RandomByWeight {
        public static List selectAll(ServiceInfo serviceInfo) {
            List hosts = serviceInfo.getHosts();
            if (CollectionUtils.isEmpty(hosts)) {
                throw new IllegalStateException("no host to srv for serviceInfo: " + serviceInfo.getName());
            }
            return hosts;
        }
        public static Instance selectHost(ServiceInfo dom) {
            List 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.
     *
     * @param hosts The list of the host.
     * @return The random-weight result of the host
     */
    protected static Instance getHostByRandomWeight(List hosts) {
        NAMING_LOGGER.debug("entry randomWithWeight");
        if (hosts == null || hosts.size() == 0) {
            NAMING_LOGGER.debug("hosts == null || hosts.size() == 0");
            return null;
        }
        Chooser vipChooser = new Chooser("www.taobao.com");
        NAMING_LOGGER.debug("new Chooser");
        List> hostsWithWeight = new ArrayList>();
        for (Instance host : hosts) {
            if (host.isHealthy()) {
                hostsWithWeight.add(new Pair(host, host.getWeight()));
            }
        }
        NAMING_LOGGER.debug("for (Host host : hosts)");
        vipChooser.refresh(hostsWithWeight);
        NAMING_LOGGER.debug("vipChooser.refresh");
        return vipChooser.randomWithWeight();
    }
}           - Balancer的RandomByWeight提供了selectAll及selectHost方法;selectAll针对serviceInfo.getHosts()进行了空判断,空的话会抛出IllegalStateException 
- selectHost方法内部调用了selectAll方法,其最后通过getHostByRandomWeight来选取单个healthy的instance 
- getHostByRandomWeight方法首先创建一个Chooser,然后选取healthy的instance构造hostsWithWeight,再通过vipChooser.refresh(hostsWithWeight)进行refresh,最后通过vipChooser.randomWithWeight()选取单个healthy的instance 
Chooser
nacos-1.1.3/client/src/main/java/com/alibaba/nacos/client/naming/utils/Chooser.java
public class Chooser{ private K uniqueKey; private volatile Ref ref; public T random() { List items = ref.items; if (items.size() == 0) { return null; } if (items.size() == 1) { return items.get(0); } return items.get(ThreadLocalRandom.current().nextInt(items.size())); } public T randomWithWeight() { Ref ref = this.ref; double random = ThreadLocalRandom.current().nextDouble(0, 1); int index = Arrays.binarySearch(ref.weights, random); if (index < 0) { index = -index - 1; } 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 >()); } public Chooser(K uniqueKey, List > pairs) { Ref ref = new Ref (pairs); ref.refresh(); this.uniqueKey = uniqueKey; this.ref = ref; } public K getUniqueKey() { return uniqueKey; } public Ref getRef() { return ref; } public void refresh(List > itemsWithWeight) { Ref newRef = new Ref (itemsWithWeight); newRef.refresh(); newRef.poller = this.ref.poller.refresh(newRef.items); this.ref = newRef; } //...... } 
- Chooser的refresh方法会根据itemsWithWeight创建Ref,然后执行Ref的refresh方法;randomWithWeight方法通过Arrays.binarySearch(ref.weights, random)创建初始index,然后根据index从ref.items获取元素 
Ref
nacos-1.1.3/client/src/main/java/com/alibaba/nacos/client/naming/utils/Chooser.java
public class Ref{ private List > itemsWithWeight = new ArrayList >(); private List items = new ArrayList (); private Poller poller = new GenericPoller (items); private double[] weights; @SuppressWarnings("unchecked") public Ref(List > itemsWithWeight) { this.itemsWithWeight = itemsWithWeight; } public void refresh() { Double originWeightSum = (double) 0; for (Pair 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; } if (Double.isNaN(weight)) { weight = 1.0D; } originWeightSum += weight; } double[] exactWeights = new double[items.size()]; int index = 0; for (Pair item : itemsWithWeight) { double singleWeight = item.weight(); //ignore item which weight is zero.see test_randomWithWeight_weight0 in ChooserTest if (singleWeight <= 0) { continue; } 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."); } //...... } 
- Ref的refresh方法主要是初始化items及weights 
小结
- selectOneHealthyInstance跟selectInstances类似,只不过它返回的是单个instance;selectOneHealthyInstance也是先从hostReactor获取serviceInfo 
- 如果subscribe为true,则执行hostReactor.getServiceInfo获取serviceInfo,否则执行hostReactor.getServiceInfoDirectlyFromServer获取serviceInfo 
- 获取到serviceInfo之后,selectOneHealthyInstance通过Balancer.RandomByWeight.selectHost方法来选取单个healthy的instance 
“NacosNamingService中selectOneHealthyInstance的原理及作用是什么”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注创新互联网站,小编将为大家输出更多高质量的实用文章!
分享文章:NacosNamingService中selectOneHealthyInstance的原理及作用是什么
本文链接:http://www.scyingshan.cn/article/gcgicc.html

 建站
建站
 咨询
咨询 售后
售后
 建站咨询
建站咨询 
 