返回LVS系列文章:http://www.cnblogs.com/f-ck-need-u/p/7576137.html
加權調度算法(wrr)是一種很常見的調度算法。它們按照權重比例進行調度,但實際調度選中的節點順序可能和想象中並不一樣。它們有各自的算法支持,但無論什么算法,對於a、b、c三個節點,如果它們的權重比例為a:b:c=x:y:z,在節點都健康的情況下,每一輪輪詢過程中a總是被選中x次,b總是被選中y次,c總是被選中z次,只不過被選中的順序可能因算法不同而不同,
所以,本文主要介紹lvs和nginx的wrr算法是如何計算的。
lvs的wrr調度算法
1.加權調度算法公式
首先,給一個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。
如果你不想從算法公式里找規律,那么看下面。
2.加權調度通俗規律
記住三個權重調度規則:
1.先約分
2.從最大權重開始調度
3.同權重的后端,從前向后調度
例如,三台后端A:B:C=2:3:4。這里沒法約分。
- 調度C
調度之后,比率變成A:B:C=2:3:3,B和C權重相同,從B開始調度 - 調度B
調度之后,比率變成A:B:C=2:2:3,所以下次調度C - 調度C
調度之后,比率變成A:B:C=2:2:2,下次從A開始
當權重全部調整到相同值時,就按照先后順序不斷循環,直到調度完所有權重 - 調度A,調度之后,比率變成
A:B:C=1:2:2 - 調度B,調度之后,比率變成
A:B:C=1:1:2 - 調度C,調度之后,比率變成
A:B:C=1:1:1 - 調度A,調度之后,比率變成
A:B:C=0:1:1 - 調度B,調度之后,比率變成
A:B:C=0:0:1 - 調度C,調度之后,比率變成
A:B:C=0:0:0 - 進入下一個調度循環,順序是:CBCABCABC
所以,每個調度循環的調度順序為:CBCABCABC
調度過程如下圖:

再給個示例,A:B:C:D=2:4:6:8
首先約分,得到A:B:C:D=1:2:3:4
- 調度D
- 調度C
- 調度D
- 調度B
- 調度C
- 調度D
- 調度A
- 調度B
- 調度C
- 調度D
所以,調度順序是DCDBCDABCD。
nginx的wrr調度算法
以前nginx的wrr調度算法和lvs的算法類似,都是直接剃短高權重節點的權重值,最后趨於均衡。但這樣的算法實際上對請求而言並不均衡,比如a:b:c = 5:1:1,調用的順序將是aaaaabc、aaaaabc,a將被連續多次調用。
后來nginx的wrr算法改進了,變得更復雜一些,但更趨於調度均衡。
假設a:b:c=A:B:C,算法是這樣的:
- 所有權重加總得到總權重(total):A+B+C=N
- 第一個請求進來,選擇權重最大的。假設為a,於是選中A。選中之后,對選中的節點的權重減去總權重N,於是現在的比例是
a:b:c=A-N:B:C - 第二個請求進入,將比如全部加上原始比例(eff_weight),得到
(A-N+A):(B+B):(C+C),然后選中最大的權重節點,假如選中B。選中之后,對選中的節點的權重減去總權重N,於是比例變為(2A-N):(2B-N):2C - 之后每個請求進來,都首先加上原始比例,然后選擇權重最大的,並對最大的權重值減去總權重N。
- 每一輪詢的最后一次調度,都會使被選中的節點權重變為N,其它權重變為0,減去總權重之后全部變成0,使得下一輪輪詢調度開始,重新回到原始比例。
例如,a:b:c=4:3:2的調度過程為:總權重為4+3+2=9
- 第1個請求,a權重最大,選中a
- 選中之后,比例變為
a:b:c=-5:3:2
- 選中之后,比例變為
- 第2個請求,加上原始比例,得到
a:b:c=-1:6:4,選中b- 選中之后,比例變為
a:b:c=-1:-3:4
- 選中之后,比例變為
- 第3個請求,加上原始比例,得到
a:b:c=3:0:6,選中c- 選中之后,比例變為
a:b:c=3:0:-3
- 選中之后,比例變為
- 第4個請求,加上原始比例,得到
a:b:c=7:3:-1,選中a- 選中之后,比例變為
a:b:c=-2:3:-1
- 選中之后,比例變為
- 第5個請求,加上原始比例,得到
a:b:c=2:6:1,選中b- 選中之后,比例變為
a:b:c=2:-3:1
- 選中之后,比例變為
- 第6個請求,加上原始比例,得到
a:b:c=6:0:3,選中a- 選中之后,比例變為
a:b:c=-3:0:3
- 選中之后,比例變為
- 第7個請求,加上原始比例,得到
a:b:c=1:3:5,選中c- 選中之后,比例變為
a:b:c=1:3:-4
- 選中之后,比例變為
- 第8個請求,加上原始比例,得到
a:b:c=5:6:-2,選中b- 選中之后,比例變為
a:b:c=5:-3:-2
- 選中之后,比例變為
- 第9個請求,加上原始比例,得到
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...
