Java 負載均衡的 5 種算法實現(xiàn)原理
前言:
什么是負載均衡:
指由多臺服務(wù)器以對稱的方式組成一個服務(wù)器集合,每臺服務(wù)器都具有等價的地位,都可以單獨對外提供服務(wù)而無須其他服務(wù)器的輔助。通過某種 負載分擔(dān)技術(shù),將外部發(fā)送來的請求均勻分配到對稱結(jié)構(gòu)中的某一臺服務(wù)器上,而接收到請求的服務(wù)器獨立地回應(yīng)客戶的請求。負載均衡能夠平均分配客戶請求到服 務(wù)器陣列,借此提供快速獲取重要數(shù)據(jù),解決大量并發(fā)訪問服務(wù)問題,這種集群技術(shù)可以用最少的投資獲得接近于大型主機的性能;
一、負載均衡算法簡介
1、輪詢法
將請求按順序輪流地分配到后端服務(wù)器上,它均衡地對待后端的每一臺服務(wù)器,而不關(guān)心服務(wù)器實際的連接數(shù)和當(dāng)前的系統(tǒng)負載;
2、隨機法
通過系統(tǒng)的隨機算法,根據(jù)后端服務(wù)器的列表大小值來隨機選取其中的一臺服務(wù)器進行訪問。由概率統(tǒng)計理論可以得知,隨著客戶端調(diào)用服務(wù)端的次數(shù)增多, 其實際效果越來越接近于平均分配調(diào)用量到后端的每一臺服務(wù)器,也就是輪詢的結(jié)果;
3、源地址哈希法
源地址哈希的思想是根據(jù)獲取客戶端的IP地址,通過哈希函數(shù)計算得到的一個數(shù)值,用該數(shù)值對服務(wù)器列表的大小進行取模運算,得到的結(jié)果便是客服端要訪問服務(wù)器的序號。采用源地址哈希法進行負載均衡,同一IP地址的客戶端,當(dāng)后端服務(wù)器列表不變時,它每次都會映射到同一臺后端服務(wù)器進行訪問;
4、加權(quán)輪詢法
不同的后端服務(wù)器可能機器的配置和當(dāng)前系統(tǒng)的負載并不相同,因此它們的抗壓能力也不相同。給配置高、負載低的機器配置更高的權(quán)重,讓其處理更多的請;而配置低、負載高的機器,給其分配較低的權(quán)重,降低其系統(tǒng)負載,加權(quán)輪詢能很好地處理這一問題,并將請求順序且按照權(quán)重分配到后端;
5、加權(quán)隨機法
與加權(quán)輪詢法一樣,加權(quán)隨機法也根據(jù)后端機器的配置,系統(tǒng)的負載分配不同的權(quán)重。不同的是,它是按照權(quán)重隨機請求后端服務(wù)器,而非順序;
二、代碼實現(xiàn)負載均衡五種算法
1.輪詢法
import java.util.*; import java.util.concurrent.ConcurrentHashMap; public class TestRoundRobin { // 1.定義map, key-ip,value-weight static Map<String,Integer> ipMap= new HashMap<>(); static { ipMap.put("192.168.13.1",1); ipMap.put("192.168.13.2",1); ipMap.put("192.168.13.3",1); } // Integer sum=0; Integer pos = 0; public String RoundRobin(){ Map<String,Integer> ipServerMap=new ConcurrentHashMap<>(); ipServerMap.putAll(ipMap); // 2.取出來key,放到set中 Set<String> ipset=ipServerMap.keySet(); // 3.set放到list,要循環(huán)list取出 ArrayList<String> iplist=new ArrayList<String>(); iplist.addAll(ipset); String serverName=null; // 4.定義一個循環(huán)的值,如果大于set就從0開始 synchronized(pos){ if (pos>=ipset.size()){ pos=0; } serverName=iplist.get(pos); //輪詢+1 pos ++; } return serverName; } public static void main(String[] args) { TestRoundRobin testRoundRobin=new TestRoundRobin(); for ( int i=0;i<10;i++){ String serverIp=testRoundRobin.RoundRobin(); System.out.println(serverIp); } } }
2.加權(quán)輪詢法
import java.util.*; import java.util.concurrent.ConcurrentHashMap; public class TestWeightRobin { // 1.map, key-ip,value-weight static Map<String,Integer> ipMap= new HashMap<>(); static { ipMap.put("192.168.13.1",1); ipMap.put("192.168.13.2",2); ipMap.put("192.168.13.3",4); } Integer pos=0; public String WeightRobin(){ Map<String,Integer> ipServerMap=new ConcurrentHashMap<>(); ipServerMap.putAll(ipMap); Set<String> ipSet=ipServerMap.keySet(); Iterator<String> ipIterator=ipSet.iterator(); //定義一個list放所有server ArrayList<String> ipArrayList=new ArrayList<String>(); //循環(huán)set,根據(jù)set中的可以去得知map中的value,給list中添加對應(yīng)數(shù)字的server數(shù)量 while (ipIterator.hasNext()){ String serverName=ipIterator.next(); Integer weight=ipServerMap.get(serverName); for ( int i = 0;i < weight ;i++){ ipArrayList.add(serverName); } } String serverName=null; if (pos>=ipArrayList.size()){ pos=0; } serverName=ipArrayList.get(pos); //輪詢+1 pos ++; return serverName; } public static void main(String[] args) { TestWeightRobin testWeightRobin=new TestWeightRobin(); for ( int i =0;i<10;i++){ String server=testWeightRobin.WeightRobin(); System.out.println(server); } } }
3.隨機法
import java.util.*; import java.util.concurrent.ConcurrentHashMap; public class TestRandom { // 1.定義map, key-ip,value-weight static Map<String,Integer> ipMap= new HashMap<>(); static { ipMap.put("192.168.13.1",1); ipMap.put("192.168.13.2",2); ipMap.put("192.168.13.3",4); } public String Random() { Map<String,Integer> ipServerMap=new ConcurrentHashMap<>(); ipServerMap.putAll(ipMap); Set<String> ipSet=ipServerMap.keySet(); //定義一個list放所有server ArrayList<String> ipArrayList=new ArrayList<String>(); ipArrayList.addAll(ipSet); //循環(huán)隨機數(shù) Random random=new Random(); //隨機數(shù)在list數(shù)量中?。?-list.size) int pos=random.nextInt(ipArrayList.size()); String serverNameReturn= ipArrayList.get(pos); return serverNameReturn; } public static void main(String[] args) { TestRandom testRandom=new TestRandom(); for ( int i =0;i<10;i++){ String server=testRandom.Random(); System.out.println(server); } } }
4.加權(quán)隨機
import java.util.*; import java.util.concurrent.ConcurrentHashMap; public class TestRobinRandom { // 1.定義map, key-ip,value-weight static Map<String,Integer> ipMap= new HashMap<>(); static { ipMap.put("192.168.13.1",1); ipMap.put("192.168.13.2",2); ipMap.put("192.168.13.3",4); } public String RobinRandom(){ Map<String,Integer> ipServerMap=new ConcurrentHashMap<>(); ipServerMap.putAll(ipMap); Set<String> ipSet=ipServerMap.keySet(); Iterator<String> ipIterator=ipSet.iterator(); //定義一個list放所有server ArrayList<String> ipArrayList=new ArrayList<String>(); //循環(huán)set,根據(jù)set中的可以去得知map中的value,給list中添加對應(yīng)數(shù)字的server數(shù)量 while (ipIterator.hasNext()){ String serverName=ipIterator.next(); Integer weight=ipServerMap.get(serverName); for ( int i=0;i<weight;i++){ ipArrayList.add(serverName); } } //循環(huán)隨機數(shù) Random random=new Random(); //隨機數(shù)在list數(shù)量中取(1-list.size) int pos=random.nextInt(ipArrayList.size()); String serverNameReturn= ipArrayList.get(pos); return serverNameReturn; } public static void main(String[] args) { TestRobinRandom testRobinRandom=new TestRobinRandom(); for ( int i =0;i<10;i++){ String server=testRobinRandom.RobinRandom(); System.out.println(server); } } }
5.源地址哈希法
import java.util.ArrayList; import java.util.HashMap; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; public class ipHash { // 1.定義map, key-ip,value-weight static Map<String,Integer> ipMap= new HashMap<>(); static { ipMap.put("192.168.13.1",1); ipMap.put("192.168.13.2",2); ipMap.put("192.168.13.3",4); } public String ipHash(String clientIP){ Map<String,Integer> ipServerMap=new ConcurrentHashMap<>(); ipServerMap.putAll(ipMap); // 2.取出來key,放到set中 Set<String> ipset=ipServerMap.keySet(); // 3.set放到list,要循環(huán)list取出 ArrayList<String> iplist=new ArrayList<String>(); iplist.addAll(ipset); //對ip的hashcode值取余數(shù),每次都一樣的 int hashCode=clientIP.hashCode(); int serverListsize=iplist.size(); int pos=hashCode%serverListsize; return iplist.get(pos); } public static void main(String[] args) { ipHash iphash=new ipHash(); String servername= iphash.ipHash("192.168.21.2"); System.out.println(servername); } }
到此這篇關(guān)于Java 負載均衡的 5 種算法實現(xiàn)原理的文章就介紹到這了,更多相關(guān)Java 負載均衡的 算法實現(xiàn)原理內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringBoot集成JmsTemplate(隊列模式和主題模式)及xml和JavaConfig配置詳解
這篇文章主要介紹了SpringBoot集成JmsTemplate(隊列模式和主題模式)及xml和JavaConfig配置詳解,本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-08-08mybatis sum(參數(shù)) 列名作為參數(shù)的問題
這篇文章主要介紹了mybatis sum(參數(shù)) 列名作為參數(shù)的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-01-01Java 數(shù)據(jù)結(jié)構(gòu)與算法系列精講之背包問題
背包問題是一個非常典型的考察動態(tài)規(guī)劃應(yīng)用的題目,對其加上不同的限制和條件,可以衍生出諸多變種,若要全面理解動態(tài)規(guī)劃,就必須對背包問題了如指掌2022-02-02java發(fā)送短信系列之限制日發(fā)送次數(shù)
這篇文章主要為大家詳細介紹了java發(fā)送短信系列之限制日發(fā)送次數(shù),詳細介紹了限制每日向同一個用戶(根據(jù)手機號和ip判斷)發(fā)送短信次數(shù)的方法,感興趣的小伙伴們可以參考一下2016-02-02Netty學(xué)習(xí)之理解selector原理示例
這篇文章主要為大家介紹了Netty學(xué)習(xí)之理解selector原理示例使用分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪<BR>2023-07-07