負載均衡算法的簡單介紹及實現!

<span style="font-size:14px;">serverWeightMap = new HashMap<String, Integer>();
serverWeightMap.put("192.168.1.100", 1);
serverWeightMap.put("192.168.1.101", 1);
//權重爲4
serverWeightMap.put("192.168.1.102", 4);
serverWeightMap.put("192.168.1.103", 1);
serverWeightMap.put("192.168.1.104", 1);
//權重爲3
serverWeightMap.put("192.168.1.105", 3);
serverWeightMap.put("192.168.1.106", 1);
//權重爲2
serverWeightMap.put("192.168.1.107", 2);
serverWeightMap.put("192.168.1.108", 1);
serverWeightMap.put("192.168.1.109", 1);
serverWeightMap.put("192.168.1.110", 1);</span>


1:輪詢(Round Robin)法

輪詢很容易理解,將請求按順序輪流的分配到後端服務器上,它均衡的對待後端每一臺服務器,而不關心服務器實際的連接數和當前的系統負載。

<span style="font-size:14px;"><span style="font-size:14px;">//輪詢法
private static String testRoundRobin() {
	//重新創建一個map,避免出現由於服務器上線和下線導致的併發問題
	Map<String, Integer> serverMap = new HashMap<String, Integer>();
	serverMap.putAll(serverWeightMap);
	
	//取得IP地址的list
	Set<String> keySet = serverMap.keySet();
	ArrayList<String> keyList = new ArrayList<String>();
	keyList.addAll(keySet);
	
	String server = null;
	
	synchronized(pos){
		if(pos >= keySet.size()){
			pos = 0;
		}
		server = keyList.get(pos);
		pos++;
	}
	
	return server;
}</span></span>

使用輪詢策略的目的在於:希望做到請求轉移的絕對均衡,但付出的性能代價也是相當大的。爲了pos保證變量修改的互斥性,需要引入重量級的悲觀鎖synchronized,將會導致該段輪詢代碼的併發吞吐量發生明顯的下降。


2:隨機(Random)法

通過系統隨機函數,根據後端服務器列表大小值來隨機選取其中一臺進行訪問

<span style="font-size:14px;">//隨機法
private static String testRandom() {
	//重新創建一個map,避免出現由於服務器上線和下線導致的併發問題
	Map<String, Integer> serverMap = new HashMap<String, Integer>();
	serverMap.putAll(serverWeightMap);
	
	//取得IP地址的list
	Set<String> keySet = serverMap.keySet();
	ArrayList<String> keyList = new ArrayList<String>();
	keyList.addAll(keySet);
	
	Random random = new Random();
	int randomPos = random.nextInt(keyList.size());
	
	String server = keyList.get(randomPos);
	return server;
}</span>

基於概率統計理論,吞吐量越大,隨機算法的效果越接近於輪詢算法的效果,因此,你還會考慮一定要用需要付出一定性能代價的輪詢算法嗎?


3:原地址哈希(Hash)法

原地址哈希的思想是獲取客戶端訪問的IP地址值,通過哈希函數計算得到一個數值,用該數值對服務器列表的大小進行取模運算,得到的結果便是要訪問的服務器序號

<span style="font-size:14px;">//源地址哈希(Hash)法
private static String testConsumerHash(String remoteip) {
	//重新創建一個map,避免出現由於服務器上線和下線導致的併發問題
	Map<String, Integer> serverMap = new HashMap<String, Integer>();
	serverMap.putAll(serverWeightMap);
	
	//取得IP地址的list
	Set<String> keySet = serverMap.keySet();
	ArrayList<String> keyList = new ArrayList<String>();
	keyList.addAll(keySet);
	
	int hashCode = remoteip.hashCode();
	int serverListSize = keyList.size();
	int serverPos = hashCode % serverListSize;
	
	return keyList.get(serverPos);
}</span>
通過參數傳入客戶端的remoteIP參數,取得它的哈希值,對服務器列表大小取模,結果便是選用的服務器列表中的索引值。該算法保證了相同的客戶端IP地址將會被“哈希”到同一臺後端服務器,直到後端服務器列表變更。根據此特性可以在服務消費者和服務提供者之間建立有狀態的session會話


4:加權輪詢(Weight Round Robin)法

不同的後端服務器可能機器的配置和當前系統的負載並不相同,因此他們的抗壓能力也不盡相同。給配置高、負載低的機器配置更高的權重,讓其處理更多的請求,而配置低、負載高的機器,則給其分配較低的權重,降低其系統負載,加權輪詢能很好的處理這一問題,並將請求順序且按照權重分配到後端

<span style="font-size:14px;">//加權輪詢法
private static String testWeightRoundRobin() {
	//重新創建一個map,避免出現由於服務器上線和下線導致的併發問題
	Map<String, Integer> serverMap = new HashMap<String, Integer>();
	serverMap.putAll(serverWeightMap);
	
	//取得IP地址的list
	Set<String> keySet = serverMap.keySet();
	Iterator<String> it = keySet.iterator();
	
	List<String> serverList = new ArrayList<String>();
	
	while (it.hasNext()) {
		String server = it.next();
		Integer weight = serverMap.get(server);
		for (int i = 0; i < weight; i++) {
			serverList.add(server);
		}
	}
	
	String server = null;
	
	synchronized(pos){
		if(pos >= serverList.size()){
			pos = 0;
		}
		server = serverList.get(pos);
		pos++;
	}
	
	return server;
}</span>

與輪詢法類似,只是在獲取服務器地址之前增加了一段權重計算的代碼,根據權重的大小,將地址重複的增加到服務器地址列表中,權重越大,該服務器每輪所獲得的請求數量越多


5:加權隨機(Weight Random)法

與加權輪詢法類似,加權隨機法也根據後端服務器不同的配置和負載情況配置不同的權重,不同的是,它是按照權重來隨機選取服務器的,而非順序

<span style="font-size:14px;">//加權隨機法
private static String testWeightRandom() {
	//重新創建一個map,避免出現由於服務器上線和下線導致的併發問題
	Map<String, Integer> serverMap = new HashMap<String, Integer>();
	serverMap.putAll(serverWeightMap);
	
	//取得IP地址的list
	Set<String> keySet = serverMap.keySet();
	Iterator<String> it = keySet.iterator();
	
	List<String> serverList = new ArrayList<String>();
	
	while (it.hasNext()) {
		String server = it.next(); 
		Integer weight = serverMap.get(server);
		for (int i = 0; i < weight; i++) {
			serverList.add(server);
		}
	}
	
	Random random = new Random();
	int randomPos = random.nextInt(serverList.size());
	String server = serverList.get(randomPos);
	
	return server;
}</span>

6:最小連接數(Least Connections)法
最小鏈接數算法比較靈活和智能,由於後端服務器的配置不盡相同,對於請求的處理有快有慢,它正式根據後端服務器當前的連接情況,動態的選取其中當前積壓連接數最少的一臺服務器來處理當前請求,竟可能的提高後端服務器的利用效率,將負載合理的分流到每一臺機器。

發佈了41 篇原創文章 · 獲贊 39 · 訪問量 30萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章