常見的簡單負載均衡演算法以及Java實現
讀完本文你將知道:
1. 什麼是負載均衡?
2. 負載均衡的幾種簡單實現:
(1) 輪詢法(Round Robin)
(2)隨機法(Random)
(3)源地址Hash法(Hash)
(4)加權輪詢法(Weight Round Robin)
(5)加權隨機法(Weight Random)
(6)最小連線數法(Least Connections)
1. 什麼是負載均衡?
負載均衡(Load Balance),指由多臺伺服器以對稱的形式組成的一個伺服器集合,每臺伺服器都有等價的地位,都可以單獨對外提供服務而無需其他伺服器的輔助。通過某種負載分擔技術,將外部發送來的請求均勻分配到對稱結構中的一臺伺服器上,而接收到請求的伺服器獨立地迴應客戶的請求。負載均衡能夠平均分配客戶請求到伺服器陳列,藉此提供快速獲取重要資料,解決大量併發訪問服務問題,這種叢集技術可以用最少的投資獲得接近於大型主機的效能。
本文主要講解將“外部發送來的請求均勻分配到對稱結構中的某一臺伺服器上”的各種演算法, 並以Java程式碼來模擬實現。
下面首先來以一個IP列表來模擬叢集中的機器的IP集合。
package distributed;
import java.util.HashMap;
/**
* Created by louyuting on 17/2/7.
*/
public class IPMap {
public static HashMap<String, Integer> serverWeightMap = new HashMap<String, Integer>();
static {
//第一個引數是IP地址,第二個是權重.
serverWeightMap.put("192.168.1.100", 1);
serverWeightMap.put("192.168.1.101", 2);
serverWeightMap.put("192.168.1.102", 3);
serverWeightMap.put("192.168.1.103", 4);
serverWeightMap.put("192.168.1.104", 3);
serverWeightMap.put("192.168.1.105" , 2);
serverWeightMap.put("192.168.1.106", 1);
serverWeightMap.put("192.168.1.107", 2);
serverWeightMap.put("192.168.1.108", 1);
serverWeightMap.put("192.168.1.109", 4);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
1.輪訓法
輪訓法其實就是按照所有地址的序列,從前往後一次訪問,實現程式碼如下:
package distributed;
import java.util.*;
/**
* 輪訓法
*/
public class RoundRobin {
private static Integer pos=0;
public static String getServerIP(){
//重新線上程本地copy一份IPMap, 避免伺服器上線下線導致的併發問題
Map<String, Integer> serverMap = new HashMap<String, Integer>();
serverMap.putAll(IPMap.serverWeightMap);
//取的IP地址的Set
Set<String> ips = serverMap.keySet();
List<String> iplist = new ArrayList<String>();
iplist.addAll(ips);
String server = null;
synchronized (pos){
if(pos > iplist.size())
pos=0;
server = iplist.get(pos);
pos++;
}
return server;
}
/**
*
* @param args
*/
public static void main(String[] args) {
String result = null;
for(int i=0; i<10; i++){
result = getServerIP();
System.out.println("load balance 的地址是:" + result);
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
由於serverWeightMap中的地址列表是動態的,隨時可能有機器上線、下線或者宕機,因此為了避免可能出現的併發問題,方法內部要新建區域性變數serverMap,現將serverMap中的內容複製到執行緒本地,以避免被多個執行緒修改。這樣可能會引入新的問題,複製以後serverWeightMap的修改無法反映給serverMap,也就是說這一輪選擇伺服器的過程中,新增伺服器或者下線伺服器,負載均衡演算法將無法獲知。新增無所謂,如果有伺服器下線或者宕機,那麼可能會訪問到不存在的地址。因此,服務呼叫端需要有相應的容錯處理,比如重新發起一次server選擇並呼叫。
對於當前輪詢的位置變數pos,為了保證伺服器選擇的順序性,需要在操作時對其加鎖,使得同一時刻只能有一個執行緒可以修改pos的值,否則當pos變數被併發修改,則無法保證伺服器選擇的順序性,甚至有可能導致iplist陣列越界。
輪詢法的優點在於:試圖做到請求轉移的絕對均衡。
輪詢法的缺點在於:為了做到請求轉移的絕對均衡,必須付出相當大的代價,因為為了保證pos變數修改的互斥性,需要引入重量級的悲觀鎖synchronized,這將會導致該段輪詢程式碼的併發吞吐量發生明顯的下降。
2.隨機法
通過系統隨機函式,根據後端伺服器列表的大小值來隨機選擇其中一臺進行訪問。由概率統計理論可以得知,隨著呼叫量的增大,其實際效果越來越接近於平均分配流量到每一臺後端伺服器,也就是輪詢的效果。
實現程式碼如下:
package distributed;
import java.util.*;
/**
* Created by louyuting on 17/2/7.
* 隨機法
*/
public class RandomIP {
public static String getServerIP() {
//重新線上程本地copy一份IPMap, 避免伺服器上線下線導致的併發問題
Map<String, Integer> serverMap = new HashMap<String, Integer>();
serverMap.putAll(IPMap.serverWeightMap);
//取的IP地址的Set
Set<String> ips = serverMap.keySet();
List<String> iplist = new ArrayList<String>();
iplist.addAll(ips);
String server = null;
//獲取IP的策略
Random random = new Random();
int pos = random.nextInt(iplist.size());
return iplist.get(pos);
}
/**
* @param args
*/
public static void main(String[] args) {
String result = null;
for(int i=0; i<10; i++){
result = getServerIP();
System.out.println("load balance 的地址是:" + result);
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
整體程式碼思路和輪詢法一致,先重建serverMap,再獲取到server列表。在選取server的時候,通過Random的nextInt方法取0~iplist.size()區間的一個隨機值,從而從伺服器列表中隨機獲取到一臺伺服器地址進行返回。基於概率統計的理論,吞吐量越大,隨機演算法的效果越接近於輪詢演算法的效果。
3.源地址雜湊法
源地址雜湊的思想是獲取客戶端訪問的IP地址值,通過雜湊函式計算得到一個數值,用該數值對伺服器列表的大小進行取模運算,得到的結果便是要訪問的伺服器的序號。源地址雜湊演算法的程式碼實現大致如下:
package distributed;
import java.util.*;
/**
* Created by louyuting on 17/2/7.
* 源地址 hash法
*/
public class HashIP {
public static String getServerIP() {
//重新線上程本地copy一份IPMap, 避免伺服器上線下線導致的併發問題
Map<String, Integer> serverMap = new HashMap<String, Integer>();
serverMap.putAll(IPMap.serverWeightMap);
//取的IP地址的Set
Set<String> ips = serverMap.keySet();
List<String> iplist = new ArrayList<String>();
iplist.addAll(ips);
//獲取IP的策略
//獲取遠端請求的IP地址
String remoteIP = "127.0.0.11";
int hashCode = remoteIP.hashCode();
hashCode = Math.abs(hashCode);//確保hash值是正數. 如果hash值是負數
int ipSize = iplist.size();
int pos = hashCode % ipSize;
return iplist.get(pos);
}
/**
* @param args
*/
public static void main(String[] args) {
String result = null;
for(int i=0; i<10; i++){
result = getServerIP();
System.out.println("load balance 的地址是:" + result);
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
這個方法需要注意的一點是,當獲取到遠端ip的hash值之後,一定要取絕對值,因為如果是負數最後定位的索引就會是負數,導致陣列越界。其實不同負載均衡演算法的重點就在於路由演算法,通過客戶端的ip也就是remoteIp,取得它的Hash值,對伺服器列表的大小取模,結果便是選用的伺服器在伺服器列表中的索引值。
源地址雜湊法的優點在於:保證了相同客戶端IP地址將會被雜湊到同一臺後端伺服器,直到後端伺服器列表變更。根據此特性可以在服務消費者與服務提供者之間建立有狀態的session會話。
源地址雜湊演算法的缺點在於:除非叢集中伺服器的非常穩定,基本不會上下線,否則一旦有伺服器上線、下線,那麼通過源地址雜湊演算法路由到的伺服器是伺服器上線、下線前路由到的伺服器的概率非常低,如果是session則取不到session,如果是快取則可能引發”雪崩”。(快取雪崩指:某些原因導致快取全部失效,意味著所有的資料請求都會到達資料庫,導致資料庫請求暴增,導致資料庫掛掉。)
4. 加權輪詢法
不同的伺服器可能機器配置和當前系統的負載並不相同,因此它們的抗壓能力也不盡相同,給配置高、負載低的機器配置更高的權重,讓其處理更多的請求,而低配置、高負載的機器,則給其分配較低的權重,降低其系統負載。加權輪詢法可以很好地處理這一問題,並將請求順序按照權重分配到後端。加權輪詢法的程式碼實現大致如下:
package distributed;
import java.util.*;
/**
* 加權輪訓法
*/
public class WeightRoundRobin {
private static Integer pos=0;
public static String getServerIP(){
//重新線上程本地copy一份IPMap, 避免伺服器上線下線導致的併發問題
Map<String, Integer> serverMap = new HashMap<String, Integer>();
serverMap.putAll(IPMap.serverWeightMap);
//取的IP地址的Set
Set<String> ips = serverMap.keySet();
Iterator<String> iterator = ips.iterator();
List<String> iplist = new ArrayList<String>();
while (iterator.hasNext()){
String server = iterator.next();
int weight = serverMap.get(server);
//按照權重來新增比例.
for(int i=0; i<weight; i++){
iplist.add(server);
}
}
String server=null;
synchronized (pos){
if(pos > iplist.size())
pos=0;
server = iplist.get(pos);
pos++;
}
return server;
}
/**
*
* @param args
*/
public static void main(String[] args) {
String result = null;
for(int i=0; i<10; i++){
result = getServerIP();
System.out.println("load balance 的地址是:" + result);
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
與輪詢法類似,只是在獲取伺服器地址之前增加了一段權重計算的程式碼,根據權重的大小,將地址重複地增加到伺服器地址列表中,權重越大,該伺服器每輪所獲得的請求數量越多。
5. 加權隨機
與加權輪詢法類似,加權隨機法也是根據後端伺服器不同的配置和負載情況來配置不同的權重。不同的是,它是按照權重來隨機選擇伺服器的,而不是順序。加權隨機法的程式碼實現如下:
package distributed;
import java.util.*;
/**
* Created by louyuting on 17/2/7.
* 隨機法
*/
public class WeightRandom {
public static String getServerIP() {
//重新線上程本地copy一份IPMap, 避免伺服器上線下線導致的併發問題
Map<String, Integer> serverMap = new HashMap<String, Integer>();
serverMap.putAll(IPMap.serverWeightMap);
//取的IP地址的Set
Set<String> ips = serverMap.keySet();
Iterator<String> iterator = ips.iterator();
List<String> iplist = new ArrayList<String>();
while (iterator.hasNext()){
String server = iterator.next();
int weight = serverMap.get(server);
//按照權重來新增比例.
for(int i=0; i<weight; i++){
iplist.add(server);
}
}
//獲取IP的策略
Random random = new Random();
int pos = random.nextInt(iplist.size());
return iplist.get(pos);
}
/**
* @param args
*/
public static void main(String[] args) {
String result = null;
for(int i=0; i<10; i++){
result = getServerIP();
System.out.println("load balance 的地址是:" + result);
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
這段程式碼相當於是隨機法和加權輪詢法的結合,比較好理解,就不解釋了。
6. 最小連線數法
前面幾種方法費盡心思來實現服務消費者請求次數分配的均衡,當然這麼做是沒錯的,可以為後端的多臺伺服器平均分配工作量,最大程度地提高伺服器的利用率,但是實際情況是否真的如此?實際情況中,請求次數的均衡真的能代表負載的均衡嗎?這是一個值得思考的問題。
上面的問題,再換一個角度來說就是:以後端伺服器的視角來觀察系統的負載,而非請求發起方來觀察。最小連線數法便屬於此類。
最小連線數演算法比較靈活和智慧,由於後端伺服器的配置不盡相同,對於請求的處理有快有慢,它正是根據後端伺服器當前的連線情況,動態地選取其中當前積壓連線數最少的一臺伺服器來處理當前請求,儘可能地提高後端伺服器的利用效率,將負載合理地分流到每一臺機器。由於最小連線數設計伺服器連線數的彙總和感知,設計與實現較為繁瑣,此處就不說它的實現了。
相關推薦
常見的簡單負載均衡演算法以及Java實現
讀完本文你將知道: 1. 什麼是負載均衡? 2. 負載均衡的幾種簡單實現: (1) 輪詢法(Round Robin) (2)隨機法(Random) (3)源地址Hash法(Hash) (4)加權輪詢法(Weight Round Robin) (5)加權隨機
常見的負載均衡演算法及其程式碼實現
什麼是負載均衡 負載均衡,英文名稱為Load Balance,指由多臺伺服器以對稱的方式組成一個伺服器集合,每臺伺服器都具有等價的地位,都可以單獨對外提供服務而無須其他伺服器的輔助。通過某種負載分擔技術,將外部發送來的請求均勻分配到對稱結構中的某一臺伺服器上,
多種負載均衡演算法及其Java程式碼實現【網路上較好的轉載】
首先給大家介紹下什麼是負載均衡(來自百科) 負載均衡 建立在現有網路結構之上,它提供了一種廉價有效透明的方法擴充套件 網路裝置和 伺服器的頻寬、增加 吞吐量、加強網路資料處理能力、提高網路的靈活性和可用性。 負載均衡,英文名稱為Load Balance,其意思就
Dijkstra演算法以及java實現_02(程式碼部分)
1.資料庫表的設計: dijsname1和dijsname2是有向圖中的兩個點。 qinmid是這兩個點之間的親密度,將親密度的值作為邊的權值大小。 2.對資料庫中資料進行增刪改查操作: //這裡主要實現了insert(插入)操作和查詢操作(通
負載均衡演算法---Java簡單實現(2)
上一篇介紹了負載均衡的輪詢,隨機,跟hash演算法,這邊我們一起了解下,加權的輪詢以及加權的隨機。其實理解好了輪詢跟隨機演算法,再加權的話其實是差不多的。 看面通過程式碼來了解: (1)為了不重複建立一個server列表,我們先建立一個共有的server列表,如下: pu
負載均衡演算法---Java的簡單實現(1)
最近,大夥常在談論什麼負載均衡,什麼伺服器的,而自己對於這一塊也是不太理解深入模糊,然後就去看書學習,印證自己的想法。下面是自己的一些總結吧: 比較常用的負載均衡演算法,有下面的這一些: (1)輪詢(其實就是迴圈) (2)隨機 (3)hash (4)加權輪詢
負載均衡演算法實現方式
輪詢(Round Robin)法 1.獲取ip列表 2.根據ip在list的中pos順序獲取,server = keyList.get(pos);(使得同一時刻只能有一個執行緒可以修改pos的值) 隨機(Random)法 1.獲取ip列表 2.Random的nextInt方法取0~keyList.s
Round-Robin負載均衡演算法及其實現原理
輪詢排程演算法(Round-Robin Scheduling) 輪詢排程演算法的原理是每一次把來自使用者的請求輪詢分配給內部中的伺服器,從1開始,直到N(內部伺服器個數),然後重新開始迴圈。 演算法的優點是其間接性,它無需記錄當前所有連線的狀態,所以它是一種無狀態排程。 輪詢排程演算法流
常見的幾種負載均衡演算法
1、輪詢將所有請求,依次分發到每臺伺服器上,適合伺服器硬體相同的場景。優點:伺服器請求數目相同; 缺點:伺服器壓力不一樣,不適合伺服器配置不同的情況; 2、隨機請求隨機分配到各臺伺服器上。優點:使用簡單; 缺點:不適合機器配置不同的場景 3、最少連結將請求分配到連線數最少的伺服器上(目前處理請求最少的
8皇后以及N皇后演算法探究,回溯演算法的JAVA實現,非遞迴,迴圈控制及其優化
研究了遞迴方法實現回溯,解決N皇后問題,下面我們來探討一下非遞迴方案 實驗結果令人還是有些失望,原來非遞迴方案的效能並不比遞迴方案效能高 程式碼如下: package com.newflypig.eightqueen; import java.util.Date; /**
8皇后以及N皇后演算法探究,回溯演算法的JAVA實現,非遞迴,資料結構“棧”實現
是使用遞迴方法實現回溯演算法的,在第一次使用二維矩陣的情況下,又做了一次改一維的優化 但是演算法效率仍然差強人意,因為使用遞迴函式的緣故 下面提供另一種回溯演算法的實現,使用資料結構”棧“來模擬,遞迴函式的手工實現,因為我們知道計算機在處理遞迴時的本質就是棧 時間複雜度是一樣的,空間
8皇后以及N皇后演算法探究,回溯演算法的JAVA實現,遞迴方案(一)
八皇后問題,是一個古老而著名的問題,是回溯演算法的典型案例。該問題是國際西洋棋棋手馬克斯·貝瑟爾於1848年提出:在8×8格的國際象棋上擺放八個皇后,使其不能互相攻擊,即任意兩個皇后都不能處於同一行、同一列或同一斜線上,問有多少種擺法。 高斯認為有76種方案。1854年在柏林的象棋雜誌
dubbo 負載均衡演算法實現的學習
隨機數權重演算法 假設一個服務service1 分佈在一個含有4個節點(A, B, C, D)的叢集上。 權重分別為1,2,3,4。那麼一個請求service1 的 到 A,B,C,D 節點的概率為 10%,20%,30%,40%。 一個對於service1 的
Docker教程三之基於Centos7的Nginx環境映象以及簡單負載均衡
上一章我完成了NodeJs映象,NodeJs跑起了服務,那麼這章,我們繼續對該服務進行建立負載的Nginx映象因為負載均衡需要單獨的伺服器,當然,一個伺服器也可以,但是就失去了多伺服器的意義,所以,我還是決定單獨建立一個基於CentOS 7 的 Nginx 環境映象我只需要對
[演算法]常見負載均衡演算法
一、概要 隨著系統日益龐大、邏輯業務越來越複雜,系統架構由原來的單一系統到垂直系統,發展到現在的分散式系統。分散式系統中,可以做到公共業務模組的高可用,高容錯性,高擴充套件性,然而,當系統越來越複雜時,需要考慮的東西自然
排序演算法之氣泡排序的思想以及Java實現
1 基本思想 設排序表長為n,從後向前或者從前向後兩兩比較相鄰元素的值,如果兩者的相對次序不對(A[i-1] > A[i]),則交換它們,其結果是將最小的元素交換到待排序序列的第一個位置,我們
【Dubbo原始碼學習】負載均衡演算法(2)-輪詢演算法的實現
@Overrideprotected <T> Invoker<T> doSelect(List<Invoker<T>> invokers, URL url, Invocation invocation) { String key = invokers.ge
排序演算法之直接插入排序的思想以及Java實現
1,基本思想 假設待排序的資料是陣列A[1….n]。初始時,A[1]自成1個有序區,無序區為A[2….n]。在排序的過程中,依次將A[i] (i=2,3,….,n)從後往前插入到前面已排好序的子陣列A
負載均衡演算法(1):簡單介紹
負載均衡(Load Balance)是分散式系統架構設計中必須考慮的因素之一,它通常是指,將請求/資料【均勻】分攤到多個操作單元上執行,負載均衡的關鍵在於【均勻】。常見網際網路分散式架構如上,分為客戶端層、反向代理nginx層、站點層、服務層、資料層。 什麼是負載均衡 負
機器學習演算法——PCA演算法介紹以及Java實現
PCA演算法 一、演算法概述 主成分分析(PCA)是多元統計分析中用來分析資料的一種方法,PCA通過線性變換將原始資料變換為一組各維度線性無關的表示,可用於提取資料的主要特徵分量,常用於高維資料的降維。 PCA方法最著名的應用應該是在人臉識別中特徵提取及資