Ribbon是客户端负载均衡算法。
1. 顶层接口
IRule是负载均衡算法的顶层接口,定义了三个方法。
public interface IRule{
/*
* 根据key选择一个存活的服务器
*/
Server choose(Object key);
/**
* 设置lb
*/
void setLoadBalancer(ILoadBalancer lb);
/**
* 获取lb
*/
ILoadBalancer getLoadBalancer();
}
其所有的实现类都是抽象类AbstractLoadBalancerRule的子类。AbstractLoadBalancerRule定义了lb字段。
public abstract class AbstractLoadBalancerRule implements IRule, IClientConfigAware {
/**
* 核心属性
*/
private ILoadBalancer lb;
@Override
public void setLoadBalancer(ILoadBalancer lb){
this.lb = lb;
}
@Override
public ILoadBalancer getLoadBalancer(){
return lb;
}
}
2. 轮询策略
策略实现类RoundRobinRule。
就是用个自增计数器,然后对所有server进行取模。但是这里对计数器有个较好的处理,可以防止计数器的溢出。
private int incrementAndGetModulo(int modulo) {
for (;;) {
int current = nextServerCyclicCounter.get();
//下一次要访问的服务index
int next = (current + 1) % modulo;
//***可这操作既可以让计数器自增,还可防止溢出***
if (nextServerCyclicCounter.compareAndSet(current, next)){
return next;
}
}
}
3. 重试策略
策略实现类RetryRule。
规定了重试时间为500ms,子策略使用轮询策略。
public Server choose(ILoadBalancer lb, Object key) {
//默认只能重试500ms,因此计算出截至时间戳
long requestTime = System.currentTimeMillis();
long deadline = requestTime + maxRetryMillis;
Server answer = null;
answer = subRule.choose(key);
//如果从subRule中没有选择到server,或者server不是aclive,但还未到达截至时间,则进行重试
if (((answer == null) || (!answer.isAlive())) && (System.currentTimeMillis() < deadline)) {
//到达超时时间后,对发送中断信号,结束下面的while循环
InterruptTask task = new InterruptTask(deadline - System.currentTimeMillis());
while (!Thread.interrupted()) {
answer = subRule.choose(key);
//如果从subRule中没有选择到server,或者server不是aclive,但还未到达截至时间,则进行重试
if (((answer == null) || (!answer.isAlive())) && (System.currentTimeMillis() < deadline)) {
/* pause and retry hoping it's transient */
//放弃一次cpu机会
Thread.yield();
} else {
//选择到了server,或者超时了,则退出循环
break;
}
}
//如果逻辑到达这里的时候,还没有超时,则取消task
task.cancel();
}
if ((answer == null) || (!answer.isAlive())) {
return null;
} else {
return answer;
}
}
4. 随机策略
策略实现类RandomRule。
获取随机值,然后用该随机值返回服务。
ThreadLocalRandom.current().nextInt(serverCount)
5. 响应时间权重策略
策略实现类WeightedResponseTimeRule。
假设有3个server,分别为A, B, C,平均响应时间是5,20,50.
那么算法如下:
(1)计算所有server的平均响应时间之和:sum = 5+20+50 = 75;
(2)计算每个server的累计权重:
1)A:sum - 5 = 70
2)B:70 + sum - 20 = 125
3)C:125 + sum - 50 = 150
(3)取一个随机值[0 - 150),根据这个随机值,查看哪个server的累计权重大于该值,且最接近该值,则这个server被选中。
这里面蕴含的逻辑是,谁的响应时间最小,则它的跨度越大,就越容易被随机值选中。
6. 客户端可配置策略
策略实现类ClientConfigEnabledRoundRobinRule。文章来源:https://www.toymoban.com/news/detail-533630.html
内部就是RoundRobinRule。文章来源地址https://www.toymoban.com/news/detail-533630.html
到了这里,关于[源码分析]-Ribbon(1): 7种负载均衡算法的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!