LVS排程演算法

瀟瀟、寒發表於2018-03-25

核心中的連線排程演算法

IPVS在核心中的負載均衡排程是以連線為粒度的。在HTTP協議(非持久中),每個物件從WEB伺服器上獲取都需要建立一個TCP連線,同一使用者的不同請求會被排程到不同伺服器上,所以這種細粒度的排程在一定程度上可以避免單個使用者訪問的突發性引起伺服器間的負載不平衡。

在核心中的連線排程演算法上,IPVS已實現了以下八種排程演算法:

  • 輪叫排程(Round-Robin Scheduling)
  • 加權輪叫排程(Weighted Round-Robin Scheduling)
  • 最小連線排程(Least-Connection Scheduling)
  • 加權最小連線排程(Weighted Least-Connection Scheduling)
  • 基於區域性性的最少連結(Locality-Based Least Connections Scheduling)
  • 帶複製的基於區域性性最少連結(Locality-Based Least Connections with Replication Scheduling)
  • 目標地址雜湊排程(Destination Hashing Scheduling)
  • 源地址雜湊排程(Source Hashing Scheduling)

1、輪叫排程

該演算法是以輪叫的方式依次將請求排程不同的伺服器,即每次排程執行i = (i + 1)mod n,並選出第i臺伺服器。演算法的優點是簡單,它無需記錄當前所有連線的狀態。它是一種無狀態排程。

在系統實現時,我們引入一個額外條件,當伺服器的權值為零時,表示該伺服器不可用而不被排程。這樣做的目的是將伺服器切出任務(如遮蔽伺服器故障和維護),同時與其他加權演算法保持一致。所以,演算法要作相應的改動,演算法流程如下:

假設有一組伺服器S = {S0, S1, …, Sn-1},一個指示變數i表示上一次選擇的
伺服器,W(Si)表示伺服器Si的權值。變數i被初始化為n-1,其中n > 0。

j = i;
do {
	j = (j + 1) mod n;
	if (W(Sj) > 0) {
		i = j;
		return Si;
	}
} while (j != i);
return NULL;  

輪叫排程演算法假設所有伺服器效能均相同,不管伺服器當前連線數和響應速度,該演算法簡單,不適用於伺服器組中處理效能不一樣的情況,而且當請求服務時間比較大時,輪叫排程演算法容易導致伺服器間的負載不平衡。

2、加權輪叫排程

該演算法可以解決伺服器間效能不一的情況,它是相應的權值表示伺服器的處理效能,伺服器的預設值為1。假設伺服器A的權值為1,B的權值為2,則表示伺服器的處理效能是A的兩倍。加權輪叫演算法是按權值的高低和輪叫方式分配請求到各臺伺服器。加權值高的先收到的連線,權值高的伺服器處理更多的連線,相同權值的伺服器處理相同的連線數。演算法流程如下:

假設有一組伺服器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分別有權值4/3/2,則在一個排程週期內,順序為AABABCABC.次方法也比較簡單,高效。當請求的服務時間變化很大,單獨的加權輪叫排程演算法依然會導致伺服器之間負載不平衡

3、最小連線排程

該演算法是將新的連線請求分配到當前連線數最小的伺服器,最小排程是一種動態排程演算法,它通過伺服器當前所活躍的連線數來估計伺服器的負載情況。排程器需要記錄各個伺服器已連線的數目,當一個請求被排程到某臺伺服器時,其連線數加1;當連線中止或超時,其連線數減一。

在系統實現時,我們也引入當伺服器權值為零時,表示該伺服器不可用或不可被排程,演算法流程如下:

假設有一組伺服器S = {S0, S1, ..., Sn-1},W(Si)表示伺服器Si的權值,
C(Si)表示伺服器Si的當前連線數。

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;

4、加權最小連線排程

該演算法是最小連線排程的超集,各個伺服器用相應的權值表示其處理能力。伺服器的預設值為1,系統管理員可以動態的設定伺服器的權值。加權最小連線排程在排程新連線時儘可能使伺服器的已建立連線數和其權值成比例。

假設有一組伺服器S = {S0, S1, ..., Sn-1},W(Si)表示伺服器Si的權值,
C(Si)表示伺服器Si的當前連線數。所有伺服器當前連線數的總和為
CSUM = ΣC(Si)  (i=0, 1, .. , n-1)。當前的新連線請求會被髮送伺服器Sm,
當且僅當伺服器Sm滿足以下條件
  (C(Sm) / CSUM)/ W(Sm) = min { (C(Si) / CSUM) / W(Si)}  (i=0, 1, . , n-1)
  其中W(Si)不為零
因為CSUM在這一輪查詢中是個常數,所以判斷條件可以簡化為
  C(Sm) / W(Sm) = min { C(Si) / W(Si)}  (i=0, 1, . , n-1)
  其中W(Si)不為零

因為除法所需的CPU週期比乘法多,且在Linux核心中不允許浮點除法,伺服器的
權值都大於零,所以判斷條件C(Sm) / W(Sm) > C(Si) / W(Si) 可以進一步優化
為C(Sm)*W(Si) > C(Si)* W(Sm)。同時保證伺服器的權值為零時,伺服器不被調
度。所以,演算法只要執行以下流程。

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;

  參考:http://www.linuxvirtualserver.org/zh/lvs4.html

相關文章