千家信息网

Ribbon中RandomRule和RoundRobinRule的使用方法

发表于:2025-02-01 作者:千家信息网编辑
千家信息网最后更新 2025年02月01日,本篇内容介绍了"Ribbon中RandomRule和RoundRobinRule的使用方法"的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况
千家信息网最后更新 2025年02月01日Ribbon中RandomRule和RoundRobinRule的使用方法

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

Ribbon的版本是2.3.0.release.

1.RandomRule

图1

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

List-1

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 upList = lb.getReachableServers();            List 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

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 reachableServers = lb.getReachableServers();                List 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。

"Ribbon中RandomRule和RoundRobinRule的使用方法"的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注网站,小编将为大家输出更多高质量的实用文章!

0