聊聊DependenciesBasedLoadBalancer

扫码关注公众号:Java 技术驿站

发送:vip
将链接复制到本浏览器,永久解锁本站全部文章

【公众号:Java 技术驿站】 【加作者微信交流技术,拉技术群】
免费领取10G资料包与项目实战视频资料

本文主要研究一下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<String, IRule> 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<Server> 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<Server> 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三种

doc


来源:http://ddrv.cn/a/88268

赞(1) 打赏
版权归原创作者所有,任何形式的转载请联系博主:daming_90:Java 技术驿站 » 聊聊DependenciesBasedLoadBalancer

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏