Ribbon-04丨Ribbon负载均衡源码

Posted by jiefang on December 10, 2020

ribbon负载均衡源码

RibbonClientConfiguration自动装配使用的负载均衡器是ZoneAwareLoadBalancer,默认的负载均衡策略是ZoneAvoidanceRule

ZoneAwareLoadBalancer

ZoneAwareLoadBalancer类图

chooseServer()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
ZoneAwareLoadBalancer#chooseServer(Object key) {
    //判断机房数量
    if (!ENABLED.get() || getLoadBalancerStats().getAvailableZones().size() <= 1) {
        logger.debug("Zone aware logic disabled or there is only one zone");
        //调用父类chooseServer
        return super.chooseServer(key);
    }
    ...
}
//父类chooseServer方法
BaseLoadBalancer#chooseServer(Object key) {
    if (counter == null) {
        counter = createCounter();
    }
    counter.increment();
    if (rule == null) {
        return null;
    } else {
        try {
            //通过策略选择
            return rule.choose(key);
        } catch (Exception e) {
            logger.warn("LoadBalancer [{}]:  Error choosing server for key {}", name, key, e);
            return null;
        }
    }
}

ZoneAvoidanceRule

choose()

1
2
3
4
5
6
7
8
9
10
11
12
//父类choose方法
@Override
PredicateBasedRule#choose(Object key) {
    ILoadBalancer lb = getLoadBalancer();
    //过滤后轮询选择一个服务实例
    Optional<Server> server = getPredicate().chooseRoundRobinAfterFiltering(lb.getAllServers(), key);
    if (server.isPresent()) {
        return server.get();
    } else {
        return null;
    }
}

chooseRoundRobinAfterFiltering

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
AbstractServerPredicate#chooseRoundRobinAfterFiltering(List<Server> servers, Object loadBalancerKey) {
    //过滤服务实例
    List<Server> eligible = getEligibleServers(servers, loadBalancerKey);
    if (eligible.size() == 0) {
        return Optional.absent();
    }
    //服务实例队列获取一个服务实例
    return Optional.of(eligible.get(incrementAndGetModulo(eligible.size())));
}
//轮询核心算法
AbstractServerPredicate#incrementAndGetModulo(int modulo) {
    for (;;) {
        //当前计数
        int current = nextIndex.get();
        //下一计数=当前计数+1对队列size取模
        int next = (current + 1) % modulo;
        //设置下一计数并返回当前计数
        if (nextIndex.compareAndSet(current, next) && current < modulo)
            return current;
    }
}