返回LVS系列文章:http://www.cnblogs.com/f-ck-need-u/p/7576137.htmlhtml
加权调度算法(wrr)是一种很常见的调度算法。它们按照权重比例进行调度,但实际调度选中的节点顺序可能和想象中并不同。它们有各自的算法支持,但不管什么算法,对于a、b、c三个节点,若是它们的权重比例为a:b:c=x:y:z
,在节点都健康的状况下,每一轮轮询过程当中a老是被选中x次,b老是被选中y次,c老是被选中z次,只不过被选中的顺序可能因算法不一样而不一样,nginx
因此,本文主要介绍lvs和nginx的wrr算法是如何计算的。算法
首先,给一个LVS官方手册给的加权调度算法公式:后端
假设有一组服务器S = {S0, S1, …, Sn-1},W(Si)表示服务器Si的权值,一个
指示变量i表示上一次选择的服务器,指示变量cw表示当前调度的权值,max(S)
表示集合S中全部服务器的最大权值,gcd(S)表示集合S中全部服务器权值的最大
公约数。变量i初始化为-1,cw初始化为零。服务器
while (true) { i = (i + 1) mod n; if (i == 0) { cw = cw - gcd(S); if (cw <= 0) { cw = max(S); if (cw == 0) return NULL; } } if (W(Si) >= cw) return Si; }
好比,A、B、C三个后端的权重比是2:3:4
,那么一个调度循环内的调度顺序是CBCABCABC。code
若是你不想从算法公式里找规律,那么看下面。htm
记住三个权重调度规则:
1.先约分
2.从最大权重开始调度
3.同权重的后端,从前向后调度blog
例如,三台后端A:B:C=2:3:4
。这里无法约分。get
A:B:C=2:3:3
,B和C权重相同,从B开始调度A:B:C=2:2:3
,因此下次调度CA:B:C=2:2:2
,下次从A开始A:B:C=1:2:2
A:B:C=1:1:2
A:B:C=1:1:1
A:B:C=0:1:1
A:B:C=0:0:1
A:B:C=0:0:0
因此,每一个调度循环的调度顺序为:CBCABCABC变量
调度过程以下图:
再给个示例,A:B:C:D=2:4:6:8
首先约分,获得A:B:C:D=1:2:3:4
因此,调度顺序是DCDBCDABCD。
之前nginx的wrr调度算法和lvs的算法相似,都是直接剃短高权重节点的权重值,最后趋于均衡。但这样的算法实际上对请求而言并不均衡,好比a:b:c = 5:1:1
,调用的顺序将是aaaaabc、aaaaabc,a将被连续屡次调用。
后来nginx的wrr算法改进了,变得更复杂一些,但更趋于调度均衡。
假设a:b:c=A:B:C
,算法是这样的:
a:b:c=A-N:B:C
(A-N+A):(B+B):(C+C)
,而后选中最大的权重节点,假如选中B。选中以后,对选中的节点的权重减去总权重N,因而比例变为(2A-N):(2B-N):2C
例如,a:b:c=4:3:2
的调度过程为:总权重为4+3+2=9
a:b:c=-5:3:2
a:b:c=-1:6:4
,选中b
a:b:c=-1:-3:4
a:b:c=3:0:6
,选中c
a:b:c=3:0:-3
a:b:c=7:3:-1
,选中a
a:b:c=-2:3:-1
a:b:c=2:6:1
,选中b
a:b:c=2:-3:1
a:b:c=6:0:3
,选中a
a:b:c=-3:0:3
a:b:c=1:3:5
,选中c
a:b:c=1:3:-4
a:b:c=5:6:-2
,选中b
a:b:c=5:-3:-2
a:b:c=9:0:0
,选中a
a:b:c=0:0:0
一轮循环完成,调度的顺序是a b c a b a c b a
,这轮循环完成以后,它们的比例变为0:0:0
,下一个请求到来,加上原始权重后回到原比例4:3:2
。
若是是两后端节点,它们的比例为3:1,它们的调度顺序将是aaba aaba aaba...