Java 進階之深入理解負載均衡的 5 種算法實現原理
前言
什么是負載均衡:
指由多臺服務器以對稱的方式組成一個服務器集合,每臺服務器都具有等價的地位,都可以單獨對外提供服務而無須其他服務器的輔助。通過某種 負載分擔技術,將外部發送來的請求均勻分配到對稱結構中的某一臺服務器上,而接收到請求的服務器獨立地回應客戶的請求。負載均衡能夠平均分配客戶請求到服 務器陣列,借此提供快速獲取重要數據,解決大量并發訪問服務問題,這種集群技術可以用最少的投資獲得接近于大型主機的性能;
今天我們就來說說;
一、負載均衡算法簡介
1、輪詢法
將請求按順序輪流地分配到后端服務器上,它均衡地對待后端的每一臺服務器,而不關心服務器實際的連接數和當前的系統負載;
2、隨機法
通過系統的隨機算法,根據后端服務器的列表大小值來隨機選取其中的一臺服務器進行訪問。由概率統計理論可以得知,隨著客戶端調用服務端的次數增多, 其實際效果越來越接近于平均分配調用量到后端的每一臺服務器,也就是輪詢的結果;
3、源地址哈希法
源地址哈希的思想是根據獲取客戶端的IP地址,通過哈希函數計算得到的一個數值,用該數值對服務器列表的大小進行取模運算,得到的結果便是客服端要訪問服務器的序號。采用源地址哈希法進行負載均衡,同一IP地址的客戶端,當后端服務器列表不變時,它每次都會映射到同一臺后端服務器進行訪問;
4、加權輪詢法
不同的后端服務器可能機器的配置和當前系統的負載并不相同,因此它們的抗壓能力也不相同。給配置高、負載低的機器配置更高的權重,讓其處理更多的請;而配置低、負載高的機器,給其分配較低的權重,降低其系統負載,加權輪詢能很好地處理這一問題,并將請求順序且按照權重分配到后端;
5、加權隨機法
與加權輪詢法一樣,加權隨機法也根據后端機器的配置,系統的負載分配不同的權重。不同的是,它是按照權重隨機請求后端服務器,而非順序;
二、代碼實現負載均衡五種算法
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,要循環list取出
- ArrayList<String> iplist=new ArrayList<String>();
- iplist.addAll(ipset);
- String serverName=null;
- // 4.定義一個循環的值,如果大于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.加權輪詢法
- 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>();
- //循環set,根據set中的可以去得知map中的value,給list中添加對應數字的server數量
- 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);
- //循環隨機數
- Random random=new Random();
- //隨機數在list數量中?。?-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.加權隨機
- 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>();
- //循環set,根據set中的可以去得知map中的value,給list中添加對應數字的server數量
- while (ipIterator.hasNext()){
- String serverName=ipIterator.next();
- Integer weight=ipServerMap.get(serverName);
- for (int i=0;i<weight;i++){
- ipArrayList.add(serverName);
- }
- }
- //循環隨機數
- Random random=new Random();
- //隨機數在list數量中取(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,要循環list取出
- ArrayList<String> iplist=new ArrayList<String>();
- iplist.addAll(ipset);
- //對ip的hashcode值取余數,每次都一樣的
- 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);
- }
- }
總結
不進則退,一起加油