dubbo源码分析1——负载均衡

dubbo中涉及到的负载均衡算法只要有四种:Random LoadBalance(随机均衡算法)、RoundRobin LoadBalance(权重轮循均衡算法)、LeastAction LoadBalance(最少活跃调用数均衡算法)、ConsistentHash LoadBalance(一致性Hash均衡算法)。
在dubbo中,首先定义了一个LoadBalance的接口。
public interface LoadBalance {
/**
* select one invoker in list.
*
* @param invokers invokers.
* @param url refer url
* @param invocation invocation.
* @return selected invoker.
*/
@Adaptive("loadbalance")
<T> Invoker<T> select(List<Invoker<T>> invokers, URL url, Invocation invocation) throws RpcException;
}
这个接口中,只定义了一个select方法,用于在候选的invokers中选择一个invoker对象出来。
首先有一个AbstractLoadBalance类来实现LoadBalance接口,重写了LoadBalance接口中唯一的select方法。
public abstract class AbstractLoadBalance implements LoadBalance {
static int calculateWarmupWeight(int uptime, int warmup, int weight) {
int ww = (int) ((float) uptime / ((float) warmup / (float) weight));
return ww < 1 ? 1 : (ww > weight ? weight : ww);
}
public <T> Invoker<T> select(List<Invoker<T>> invokers, URL url, Invocation invocation) {
if (invokers == null || invokers.size() == 0)
return null;
if (invokers.size() == 1)
return invokers.get(0);
return doSelect(invokers, url, invocation);
}
protected abstract <T> Invoker<T> doSelect(List<Invoker<T>> invokers, URL url, Invocation invocation);
protected int getWeight(Invoker<?> invoker, Invocation invocation) {
int weight = invoker.getUrl().getMethodParameter(invocation.getMethodName(), Constants.WEIGHT_KEY, Constants.DEFAULT_WEIGHT);
if (weight > 0) {
long timestamp = invoker.getUrl().getParameter(Constants.REMOTE_TIMESTAMP_KEY, 0L);
if (timestamp > 0L) {
int uptime = (int) (System.currentTimeMillis() - timestamp);
int warmup = invoker.getUrl().getParameter(Constants.WARMUP_KEY, Constants.DEFAULT_WARMUP);
if (uptime > 0 && uptime < warmup) {
weight = calculateWarmupWeight(uptime, warmup, weight);
}
}
}
return weight;
}
}
1.invoker的list中若0个则返回null,1个元素则直接返回,若多于否则调用抽象方法doSelect交给子类实现;
2.通过公式(int) ( (float) uptime / ( (float) warmup / (float) weight ) )获取invoker的权重的方法;
3.如果未设置权重或者权重值都一样,则直接调用random.nextInt()随机获得一个invoker;若设置了权重并且不一样,则在总权重中随机,分布在哪个invoker的分片上,则选择该invoker对象,实现了按照权重随机。
四种不同的负载均衡算法分别为四个类,分别进行分析。
1.Random LoadBalance(随机均衡算法)
public class RandomLoadBalance extends AbstractLoadBalance {
public static final String NAME = "random";
private final Random random = new Random();
protected <T> Invoker<T> doSelect(List<Invoker<T>> invokers, URL url, Invocation invocation) {
int length = invokers.size(); // Number of invokers
int totalWeight = 0; // The sum of weights
boolean sameWeight = true; // Every invoker has the same weight?
for (int i = 0; i < length; i++) {
int weight = getWeight(invokers.get(i), invocation);
totalWeight += weight; // Sum
if (sameWeight && i > 0
&& weight != getWeight(invokers.get(i - 1), invocation)) {
sameWeight = false;
}
}
if (totalWeight > 0 && !sameWeight) {
// If (not every invoker has the same weight & at least one invoker's weight>0), select randomly based on totalWeight.
int offset = random.nextInt(totalWeight);
// Return a invoker based on the random value.
for (int i = 0; i < length; i++) {
offset -= getWeight(invokers.get(i), invocation);
if (offset < 0) {
return invokers.get(i);
}
}
}
// If all invokers have the same weight value or totalWeight=0, return evenly.
return invokers.get(random.nextInt(length));
}
}
1.计算总共的权重totalWeight;
2.如果权重不同,则使用随机函数确认在总权重中的偏移值offset,得到调用的机器;
3.如果权重相同,则直接调用随机函数确认机器。
2.RoundRobin LoadBalance(权重轮循均衡算法)
public class RoundRobinLoadBalance extends AbstractLoadBalance {
public static final String NAME = "roundrobin";
private final ConcurrentMap<String, AtomicPositiveInteger> sequences = new ConcurrentHashMap<String, AtomicPositiveInteger>();
protected <T> Invoker<T> doSelect(List<Invoker<T>> invokers, URL url, Invocation invocation) {
String key = invokers.get(0).getUrl().getServiceKey() + "." + invocation.getMethodName();
int length = invokers.size(); // Number of invokers
int maxWeight = 0; // The maximum weight
int minWeight = Integer.MAX_VALUE; // The minimum weight
final LinkedHashMap<Invoker<T>, IntegerWrapper> invokerToWeightMap = new LinkedHashMap<Invoker<T>, IntegerWrapper>();
int weightSum = 0;
for (int i = 0; i < length; i++) {
int weight = getWeight(invokers.get(i), invocation);
maxWeight = Math.max(maxWeight, weight); // Choose the maximum weight
minWeight = Math.min(minWeight, weight); // Choose the minimum weight
if (weight > 0) {
invokerToWeightMap.put(invokers.get(i), new IntegerWrapper(weight));
weightSum += weight;
}
}
AtomicPositiveInteger sequence = sequences.get(key);
if (sequence == null) {
sequences.putIfAbsent(key, new AtomicPositiveInteger());
sequence = sequences.get(key);
}
int currentSequence = sequence.getAndIncrement();
if (maxWeight > 0 && minWeight < maxWeight) {
int mod = currentSequence % weightSum;
for (int i = 0; i < maxWeight; i++) {
for (Map.Entry<Invoker<T>, IntegerWrapper> each : invokerToWeightMap.entrySet()) {
final Invoker<T> k = each.getKey();
final IntegerWrapper v = each.getValue();
if (mod == 0 && v.getValue() > 0) {
return k;
}
if (v.getValue() > 0) {
v.decrement();
mod--;
}
}
}
}
// Round robin
return invokers.get(currentSequence % length);
}
private static final class IntegerWrapper {
private int value;
public IntegerWrapper(int value) {
this.value = value;
}
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
public void decrement() {
this.value--;
}
}
}
3.LeastAction LoadBalance(最少活跃调用数均衡算法)
4.ConsistentHash LoadBalance(一致性Hash均衡算法)

最少活跃数
dubbo源码分析1——负载均衡的更多相关文章
- Dubbo 源码解析四 —— 负载均衡LoadBalance
欢迎来我的 Star Followers 后期后继续更新Dubbo别的文章 Dubbo 源码分析系列之一环境搭建 Dubbo 入门之二 --- 项目结构解析 Dubbo 源码分析系列之三 -- 架构原 ...
- dubbo源码解析之负载均衡
在分布式系统中,负载均衡是必不可少的一个模块,dubbo 中提供了五种负载均衡的实现,在阅读这块源码之前,建议先学习负载均衡的基础知识.把看源码当做一个印证自己心中所想的过程,这样会得到事半功倍的效果 ...
- dubbo源码阅读之负载均衡
负载均衡 在之前集群的文章中,我们分析了通过监听注册中心可以获取到多个服务提供者,并创建多个Invoker,然后通过集群类如FailoverClusterInvoker将多个Invoker封装在一起, ...
- 【Dubbo源码学习】负载均衡算法(2)-轮询算法的实现
@Overrideprotected <T> Invoker<T> doSelect(List<Invoker<T>> invokers, URL ur ...
- 【Dubbo源码学习】负载均衡算法(1)-随机算法
/** * random load balance. * */public class RandomLoadBalance extends AbstractLoadBalance { public s ...
- dubbo源码分析一:整体分析
本文作为dubbo源码分析的第一章,先从总体上来分析一下dubbo的代码架构.功能及优缺点,注意,本文只分析说明开源版本提供的代码及功能. 1.dubbo的代码架构: spring适配层:常规的sp ...
- Dubbo 源码分析 - 集群容错之 LoadBalance
1.简介 LoadBalance 中文意思为负载均衡,它的职责是将网络请求,或者其他形式的负载"均摊"到不同的机器上.避免集群中部分服务器压力过大,而另一些服务器比较空闲的情况.通 ...
- Dubbo 源码分析 - 集群容错之 Cluster
1.简介 为了避免单点故障,现在的应用至少会部署在两台服务器上.对于一些负载比较高的服务,会部署更多台服务器.这样,同一环境下的服务提供者数量会大于1.对于服务消费者来说,同一环境下出现了多个服务提供 ...
- Dubbo源码分析
Dubbo源码分析1 Dubbo源码分析2 dubbo源码阅读:rpc请求处理流程(1) 架构设计:系统间通信(17)——服务治理与Dubbo 中篇(分析) 13. Dubbo原理解析-注册中心之Zo ...
随机推荐
- Kafka解惑之时间轮 (TimingWheel)
Kafka中存在大量的延迟操作,比如延迟生产.延迟拉取以及延迟删除等.Kafka并没有使用JDK自带的Timer或者DelayQueue来实现延迟的功能,而是基于时间轮自定义了一个用于实现延迟功能的定 ...
- (数据科学学习手札53)Python中tqdm模块的用法
一.简介 tqdm是Python中专门用于进度条美化的模块,通过在非while的循环体内嵌入tqdm,可以得到一个能更好展现程序运行过程的提示进度条,本文就将针对tqdm的基本用法进行介绍. 二.基本 ...
- Titanic幸存预测分析(Kaggle)
分享一篇kaggle入门级案例,泰坦尼克号幸存遇难分析. 参考文章: 技术世界,原文链接 http://www.jasongj.com/ml/classification/ 案例分析内容: 通过训练集 ...
- 20155321 2016-2017-2 《Java程序设计》第三周学习总结
20155321 2016-2017-2 <Java程序设计>第三周学习总结 教材学习内容总结 4.1 类与对象 定义类用class关键字,建立实例用new关键字 一个原始码中可有多个类定 ...
- PHP学习笔记之析构函数以及static,self,parent关键字
引用 $jordan1 = &$jordan; 当jordan1 = null; //此时会直接调用析构函数 而当无&时,就需要等到所有的引用都为null时,才调用析构函数析构 乔丹 ...
- BZOJ1208_宠物收养所_KEY
题目传送门 平衡树的题. 因为题目给出条件(其实自己也知道):同一时间呆在收养所中的,要么全是宠物,要么全是领养者,这些宠物和领养者的个数不会超过10000个. 所以只要维护一颗平衡树,它的里面要不全 ...
- SPOJ 694&&SPOJ705: Distinct Substrings
DISUBSTR - Distinct Substrings 链接 题意: 询问有多少不同的子串. 思路: 后缀数组或者SAM. 首先求出后缀数组,然后从对于一个后缀,它有n-sa[i]-1个前缀,其 ...
- cogs1439 货车运输
cogs1439 货车运输 一道傻逼板子题. 边一定在最大生成树上,这个可以用消圈证明 然后kruskal跑一遍再搜一遍再建ST表再跑LCA这题就做完了. RT PS.交上去的代码把Kruskal打成 ...
- IBM X3650M4简单排错方法
如果出问题了,首先看开机的那个地方的灯是否显示正常,有黄色的灯亮一般都不正常: 这种服务器带有一个错误指示板,只需要在电源开关那,如上图,把那个蓝色的按钮往里面按,就能把里面的一个板子抽出来,可以看到 ...
- c# IE浏览器清除缓存没用
再想买更新JS和css文件之后, 使用 internet 里面的删除选项 发现样式和事件还是没用变 最终发现 需要 按 f12 找到这个清缓存才正常解决问题