前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Ribbon的RandomRule和RoundRobinRule 原

Ribbon的RandomRule和RoundRobinRule 原

作者头像
克虏伯
发布2019-10-06 20:58:20
1.4K0
发布2019-10-06 20:58:20
举报

    Ribbon的版本是2.3.0.release.

1.RandomRule

                                                                                     图1

    图1所示,RandomRule继承AbstractLoadBalancerRule,调用choose(Object)时,调用内部方法choose(ILoadBalancer lb, Object key),如下List-1

List-1

代码语言:javascript
复制
public Server choose(ILoadBalancer lb, Object key) {
    if (lb == null) {
        return null;
    } else {
        Server server = null;

        while(server == null) {
            if (Thread.interrupted()) {
                return null;
            }

            List<Server> upList = lb.getReachableServers();
            List<Server> allList = lb.getAllServers();
            int serverCount = allList.size();
            if (serverCount == 0) {
                return null;
            }

            int index = this.chooseRandomInt(serverCount);
            server = (Server)upList.get(index);
            if (server == null) {
                Thread.yield();
            } else {
                if (server.isAlive()) {
                    return server;
                }

                server = null;
                Thread.yield();
            }
        }

        return server;
    }
}

protected int chooseRandomInt(int serverCount) {
    return ThreadLocalRandom.current().nextInt(serverCount);
}
  1. 通过ILoadBalancer获取所有的服务,如果服务个数是0则直返回null
  2. 调用chooseRandomInt方法,参数是服务个数,这样返回的随机值是在0与服务数之间,有趣的是出于多线程安全的考虑,使用了java.util.concurrent.ThreadLocalRandom#current来获取随机值
  3. 如果服务是alive,则返回改服务

2.RoundRobinRule

                                                                                  图2

    RoundRobinRule是轮循算法实现,choose(Object)方法会调用choose(ILoadBalancer lb, Object key),如下List-2所示

List-2

代码语言:javascript
复制
private AtomicInteger nextServerCyclicCounter;

public RoundRobinRule() {
    this.nextServerCyclicCounter = new AtomicInteger(0);
}

public RoundRobinRule(ILoadBalancer lb) {
    this();
    this.setLoadBalancer(lb);
}

public Server choose(ILoadBalancer lb, Object key) {
    if (lb == null) {
        log.warn("no load balancer");
        return null;
    } else {
        Server server = null;
        int count = 0;

        while(true) {
            if (server == null && count++ < 10) {
                List<Server> reachableServers = lb.getReachableServers();
                List<Server> allServers = lb.getAllServers();
                int upCount = reachableServers.size();
                int serverCount = allServers.size();
                if (upCount != 0 && serverCount != 0) {
                    int nextServerIndex = this.incrementAndGetModulo(serverCount);
                    server = (Server)allServers.get(nextServerIndex);
                    if (server == null) {
                        Thread.yield();
                    } else {
                        if (server.isAlive() && server.isReadyToServe()) {
                            return server;
                        }

                        server = null;
                    }
                    continue;
                }

                log.warn("No up servers available from load balancer: " + lb);
                return null;
            }

            if (count >= 10) {
                log.warn("No available alive servers after 10 tries from load balancer: " + lb);
            }

            return server;
        }
    }
}

private int incrementAndGetModulo(int modulo) {
    int current;
    int next;
    do {
        current = this.nextServerCyclicCounter.get();
        next = (current + 1) % modulo;
    } while(!this.nextServerCyclicCounter.compareAndSet(current, next));

    return next;
}

    很重要的一个类属性是AtomicInteger nextServerCyclicCounter,通过它来实现轮循。

  1. ILoadBalancer获取所有的服务列表
  2. 之后调用incrementAndGetModulo方法,参数是服务个数,incrementAndGetModulo方法中用CAS来实现线程安全,获得服务的下标
  3. 得到服务Server后,判断是否是alive和ReadyToServe,则返回;如果循坏了10次还没有找到,则log打印warn日志提示

    这个实现是简单的轮循,没有实现有权重的RoundRibbon。

Reference

  1. https://github.com/Netflix/ribbon/tree/v2.3.0

(adsbygoogle = window.adsbygoogle || []).push({});

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1.RandomRule
  • 2.RoundRobinRule
  • Reference
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档