Java 負載均衡的 5 種算法實現(xiàn)原理

前言:
什么是負載均衡:
指由多臺服務(wù)器以對稱的方式組成一個服務(wù)器集合,每臺服務(wù)器都具有等價的地位,都可以單獨對外提供服務(wù)而無須其他服務(wù)器的輔助。通過某種 負載分擔技術(shù),將外部發(fā)送來的請求均勻分配到對稱結(jié)構(gòu)中的某一臺服務(wù)器上,而接收到請求的服務(wù)器獨立地回應(yīng)客戶的請求。負載均衡能夠平均分配客戶請求到服 務(wù)器陣列,借此提供快速獲取重要數(shù)據(jù),解決大量并發(fā)訪問服務(wù)問題,這種集群技術(shù)可以用最少的投資獲得接近于大型主機的性能;
一、負載均衡算法簡介

1、輪詢法
將請求按順序輪流地分配到后端服務(wù)器上,它均衡地對待后端的每一臺服務(wù)器,而不關(guān)心服務(wù)器實際的連接數(shù)和當前的系統(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地址的客戶端,當后端服務(wù)器列表不變時,它每次都會映射到同一臺后端服務(wù)器進行訪問;
4、加權(quán)輪詢法
不同的后端服務(wù)器可能機器的配置和當前系統(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ù)量中取(1-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配置詳解,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-08-08
mybatis sum(參數(shù)) 列名作為參數(shù)的問題
這篇文章主要介紹了mybatis sum(參數(shù)) 列名作為參數(shù)的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-01-01
Java 數(shù)據(jù)結(jié)構(gòu)與算法系列精講之背包問題
背包問題是一個非常典型的考察動態(tài)規(guī)劃應(yīng)用的題目,對其加上不同的限制和條件,可以衍生出諸多變種,若要全面理解動態(tài)規(guī)劃,就必須對背包問題了如指掌2022-02-02
java發(fā)送短信系列之限制日發(fā)送次數(shù)
這篇文章主要為大家詳細介紹了java發(fā)送短信系列之限制日發(fā)送次數(shù),詳細介紹了限制每日向同一個用戶(根據(jù)手機號和ip判斷)發(fā)送短信次數(shù)的方法,感興趣的小伙伴們可以參考一下2016-02-02

