文章目錄
三、八種調度算法
調度算法:http://linuxvirtualserver.org/docs/scheduling.html
十種:
輪叫調度rr
加權輪叫調度wrr
最小鏈接調度lc
加權最小鏈接調度wlc
基於局部的最少鏈接 lblc
帶複製的基於局部的最少鏈接 lblcr
目標地址散列調度 dh
源地址散列調度 sh
最短預期延時調度 sed
不排隊調度 nq
靜態調度:rr wrr dh sh
動態調度:lc wlc lblc lblcr sed nq
在各種調度算法中,LVS的ipvs默認使用的是WLC。這種算法在大量請求時的性能是最理想的,但是一般如果要實現粘性session,則一般使用SH算法。
3.1 輪叫調度 rr
按依次循環的方式將請求調度到不同的服務器上,該算法最大的特點就是簡單。輪詢算法假設所有的服務器處理請求的能力都是一樣的,調度器會將所有的請求平均分配給每個真實服務器,不管後端 RS 配置和處理能力,非常均衡地分發下去。
i = (i + 1) mod n
流程
j = i;
do {
j = (j + 1) mod n;
if (W(Sj) > 0) {
i = j;
return Si;
}
} while (j != i);
return NULL;
3.2 加權輪叫 wrr
這種算法比 rr 的算法多了一個權重的概念,可以給 RS 設置權重,權重越高,那麼分發的請求數越多,權重的取值範圍 0 – 100。主要是對rr算法的一種優化和補充, LVS 會考慮每臺服務器的性能,並給每臺服務器添加要給權值,如果服務器A的權值爲1,服務器B的權值爲2,則調度到服務器B的請求會是服務器A的2倍。權值越高的服務器,處理的請求越多。
流程
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;
}
3.3 最少鏈接 lc
這個算法會根據後端 RS 的連接數來決定把請求分發給誰,比如 RS1 連接數比 RS2 連接數少,那麼請求就優先發給 RS1
流程
for (m = 0; m < n; m++) {
if (W(Sm) > 0) {
for (i = m+1; i < n; i++) {
if (W(Si) <= 0)
continue;
if (C(Si) < C(Sm))
m = i;
}
return Sm;
}
}
return NULL;
當各個服務器有相同的處理性能時,最小連接調度算法能把負載變化大的請求分佈平滑到各個服務器上,所有處理時間比較長的請求不可能被髮送到同一臺服務器上。但是,當各個服務器的處理能力不同時,該算法並不理想,因爲 TCP 連接處理請求後會進入 TIME_WAIT 狀態,TCP 的 TIME_WAIT 一般爲 2 分鐘,此時連接還佔用服務器的資源,所以會出現這樣情形,性能高的服務器已處理所收到的連接,連接處於 TIME_WAIT狀態,而性能低的服務器已經忙於處理所收到的連接,還不斷地收到新的連接請求。
3.4 加權最少鏈接 wlc
這個算法比 lc 多了一個權重的概念。
流程
for (m = 0; m < n; m++) {
if (W(Sm) > 0) {
for (i = m+1; i < n; i++) {
if (C(Sm)*W(Si) > C(Si)*W(Sm))
m = i;
}
return Sm;
}
}
return NULL;
3.5 基於局部性的最少連接調度算法 lblc
這個算法是請求數據包的目標 IP 地址的一種調度算法,該算法先根據請求的目標 IP 地址尋找最近的該目標 IP 地址所有使用的服務器,如果這臺服務器依然可用,並且有能力處理該請求,調度器會盡量選擇相同的服務器,否則會繼續選擇其它可行的服務器
目前主要用於 Cache 集羣系統
流程
if (ServerNode[dest_ip] is NULL) then {
n = WLC(S);
if (n is NULL) then return NULL;
ServerNode[dest_ip].server = n;
} else {
n = ServerNode[dest_ip].server;
if ((n is dead) OR (C(n) > W(n) AND
there is a node m with C(m) < W(m)/2))) then {
n = WLC(S);
if (n is NULL) then return NULL;
ServerNode[dest_ip].server = n;
}
}
ServerNode[dest_ip].lastuse = Now;
return n;
此外,對關聯變量 ServerNode[dest_ip]要進行週期性的垃圾回收(Garbage Collection),將過期的目標 IP地址到服務器關聯項進行回收。過期的關聯項是指哪些當前時間(實現時採用系統時鐘節拍數 jiffies)減去最近使用時間超過設定過期時間的關聯項,系統缺省的設定過期時間爲 24 小時。
3.6 複雜的基於局部性最少的連接算法 lblcr
記錄的不是要給目標 IP 與一臺服務器之間的連接記錄,它會維護一個目標 IP 到一組服務器之間的映射關係,防止單點服務器負載過高。
流程
if (ServerSet[dest_ip] is NULL) then {
n = WLC(S);
if (n is NULL) then return NULL;
add n into ServerSet[dest_ip];
} else {
n = WLC(ServerSet[dest_ip]);
if ((n is NULL) OR (n is dead) OR (C(n) > W(n) AND
there is a node m with C(m) < W(m)/2))) then {
n = WLC(S);
if (n is NULL) then return NULL;
add n into ServerSet[dest_ip];
} else
if (|ServerSet[dest_ip]| > 1 AND
Now - ServerSet[dest_ip].lastmod > T) then {
m = WGC(ServerSet[dest_ip]);
remove m from ServerSet[dest_ip];
}
}
ServerSet[dest_ip].lastuse = Now;
if (ServerSet[dest_ip] changed) then
ServerSet[dest_ip].lastmod = Now;
return n;
3.7 目標地址散列調度算法 dh
目標地址散列調度算法先根據請求的目標 IP 地址,作爲散列鍵(Hash Key)從靜態分配的散列表找出對應的服務器,若該服務器是可用的且未超載,將請求發送到該服務器,否則返回空。
該算法是根據目標 IP 地址通過散列函數將目標 IP 與服務器建立映射關係,出現服務器不可用或負載過高的情況下,發往該目標 IP 的請求會固定發給該服務器。
流程
n = ServerNode[hashkey(dest_ip)];
if ((n is dead) OR (W(n) == 0) OR (C(n) > 2*W(n))) then
return NULL;
return n;
3.8 源地址散列調度算法 sh
與目標地址散列調度算法類似,但它是根據源地址散列算法進行靜態分配固定的服務器資源。
3.9 最短預期延時調度 sed
希望在請求少的時候將請求儘可能轉發到性能高的服務器上,sed這種調度算法爲了解決WLC的缺點而生,它不再考慮非活動連接。
sed這種算法也有一定缺陷,在請求量比較少的時候,某個權重下的節點可能一個請求都沒有輪到,而權重大的節點卻輪到了比較多的請求。
(活動連接數+1)*256/權重
3.10 不排隊調度 nq
當有空閒服務器可用時,作業將被髮送到空閒服務器,而不是等待快速的服務器。當沒有可用的空閒服務器時,作業將被髮送到服務器,以最小化其預期延遲(最短預期延遲調度算法)。
這種算法在請求量比較小的時候可以避免sed算法存在的問題,也就是會將請求在sed的結果上進行輪詢調度。例如sed算法的結果當前已經
將請求有轉發到A、B節點,新的請求又被計算到A節點,此時如果有C節點,則NQ算法會將這個新的請求調度到C節點而不是繼續調度到A節點而
不會理會此時A的權重問題,權重的判斷僅僅在sed算法這個步驟進行考慮。也就是NQ算法在sed算法的結果之後增加了輪詢的機制(也會考慮一定程度的權重),
因此這種算法就會盡量不然請求出現排隊的情況,即避免了某個節點非常繁忙而其他節點相對空閒的情況。避免了權重小的節點不會出現沒有請求被調度的情況。
3.11 應用場景
3.11.1 網絡服務
wrr
wlc
3.11.2 web cache
lblc
lblcr
3.11.3 會話保持
sh