千家信息网

如何理解DependenciesBasedLoadBalancer

发表于:2024-11-19 作者:千家信息网编辑
千家信息网最后更新 2024年11月19日,这篇文章给大家介绍如何理解DependenciesBasedLoadBalancer,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。序本文主要研究一下DependenciesBas
千家信息网最后更新 2024年11月19日如何理解DependenciesBasedLoadBalancer

这篇文章给大家介绍如何理解DependenciesBasedLoadBalancer,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。

本文主要研究一下DependenciesBasedLoadBalancer

DependenciesBasedLoadBalancer

spring-cloud-zookeeper-discovery-2.1.2.RELEASE-sources.jar!/org/springframework/cloud/zookeeper/discovery/dependency/DependenciesBasedLoadBalancer.java

public class DependenciesBasedLoadBalancer extends DynamicServerListLoadBalancer {        private static final Log log = LogFactory.getLog(DependenciesBasedLoadBalancer.class);        private final Map ruleCache = new ConcurrentHashMap<>();        private final ZookeeperDependencies zookeeperDependencies;        public DependenciesBasedLoadBalancer(ZookeeperDependencies zookeeperDependencies,                        ServerList serverList, IClientConfig config, IPing iPing) {                super(config);                this.zookeeperDependencies = zookeeperDependencies;                setServersList(serverList.getInitialListOfServers());                setPing(iPing);                setServerListImpl(serverList);        }        @Override        public Server chooseServer(Object key) {                String keyAsString;                if ("default".equals(key)) { // this is the default hint, use name instead                        keyAsString = getName();                }                else {                        keyAsString = (String) key;                }                ZookeeperDependency dependency = this.zookeeperDependencies                                .getDependencyForAlias(keyAsString);                log.debug(String.format("Current dependencies are [%s]",                                this.zookeeperDependencies));                if (dependency == null) {                        log.debug(String.format(                                        "No dependency found for alias [%s] - will use the default rule which is [%s]",                                        keyAsString, this.rule));                        return this.rule.choose(key);                }                cacheEntryIfMissing(keyAsString, dependency);                log.debug(String.format(                                "Will try to retrieve dependency for key [%s]. Current cache contents [%s]",                                keyAsString, this.ruleCache));                updateListOfServers();                return this.ruleCache.get(keyAsString).choose(key);        }        private void cacheEntryIfMissing(String keyAsString, ZookeeperDependency dependency) {                if (!this.ruleCache.containsKey(keyAsString)) {                        log.debug(String.format("Cache doesn't contain entry for [%s]", keyAsString));                        this.ruleCache.put(keyAsString,                                        chooseRuleForLoadBalancerType(dependency.getLoadBalancerType()));                }        }        private IRule chooseRuleForLoadBalancerType(LoadBalancerType type) {                switch (type) {                case ROUND_ROBIN:                        return getRoundRobinRule();                case RANDOM:                        return getRandomRule();                case STICKY:                        return getStickyRule();                default:                        throw new IllegalArgumentException("Unknown load balancer type " + type);                }        }        private RoundRobinRule getRoundRobinRule() {                return new RoundRobinRule(this);        }        private IRule getRandomRule() {                RandomRule randomRule = new RandomRule();                randomRule.setLoadBalancer(this);                return randomRule;        }        private IRule getStickyRule() {                StickyRule stickyRule = new StickyRule(getRoundRobinRule());                stickyRule.setLoadBalancer(this);                return stickyRule;        }}
  • DependenciesBasedLoadBalancer继承了com.netflix.loadbalancer.DynamicServerListLoadBalancer

  • 其chooseServer方法会使用zookeeperDependencies.getDependencyForAlias来跟进key获取ZookeeperDependency,如果dependency为null则直接使用rule.choose(key),不为null则进行chahe,然后更新server列表,最后通过ruleCache.get(keyAsString).choose(key)返回

  • cacheEntryIfMissing方法会根据ZookeeperDependency.getLoadBalancerType()进行chooseRuleForLoadBalancerType,这里分为了ROUND_ROBIN、RANDOM、STICKY三种

StickyRule

spring-cloud-zookeeper-discovery-2.1.2.RELEASE-sources.jar!/org/springframework/cloud/zookeeper/discovery/dependency/StickyRule.java

public class StickyRule extends AbstractLoadBalancerRule {        private static final Log log = LogFactory.getLog(StickyRule.class);        private final IRule masterStrategy;        private final AtomicReference ourInstance = new AtomicReference<>(null);        private final AtomicInteger instanceNumber = new AtomicInteger(-1);        public StickyRule(IRule masterStrategy) {                this.masterStrategy = masterStrategy;        }        @Override        public void initWithNiwsConfig(IClientConfig iClientConfig) {        }        @Override        public Server choose(Object key) {                final List instances = getLoadBalancer().getServerList(true);                log.debug(String.format("Instances taken from load balancer [%s]", instances));                Server localOurInstance = this.ourInstance.get();                log.debug(String.format("Current saved instance [%s]", localOurInstance));                if (!instances.contains(localOurInstance)) {                        this.ourInstance.compareAndSet(localOurInstance, null);                }                if (this.ourInstance.get() == null) {                        Server instance = this.masterStrategy.choose(key);                        if (this.ourInstance.compareAndSet(null, instance)) {                                this.instanceNumber.incrementAndGet();                        }                }                return this.ourInstance.get();        }        /**         * Each time a new instance is picked, an internal counter is incremented. This way         * you can track when/if the instance changes. The instance can change when the         * selected instance is not in the current list of instances returned by the instance         * provider         * @return instance number         */        public int getInstanceNumber() {                return this.instanceNumber.get();        }}
  • StickyRule继承了com.netflix.loadbalancer.AbstractLoadBalancerRule;其choose方法首先通过getLoadBalancer().getServerList(true)获取server列表,对于该列表没有localOurInstance的,则更新本地引用为null;然后判断localOurInstance是否为null,为null的话则使用masterStrategy.choose(key)进行选择然后更新;最后返回ourInstance.get()

小结

  • DependenciesBasedLoadBalancer继承了com.netflix.loadbalancer.DynamicServerListLoadBalancer

  • 其chooseServer方法会使用zookeeperDependencies.getDependencyForAlias来跟进key获取ZookeeperDependency,如果dependency为null则直接使用rule.choose(key),不为null则进行chahe,然后更新server列表,最后通过ruleCache.get(keyAsString).choose(key)返回

  • cacheEntryIfMissing方法会根据ZookeeperDependency.getLoadBalancerType()进行chooseRuleForLoadBalancerType,这里分为了ROUND_ROBIN、RANDOM、STICKY三种

关于如何理解DependenciesBasedLoadBalancer就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。

0