負載均衡(LoadBalance),它的職責是將網絡請求,或者其餘形式的負載「均攤」到不一樣的機器上。避免集羣中部分服務器壓力過大,而另外一些服務器比較空閒的狀況。經過負載均衡,可讓每臺服務器獲取到適合本身處理能力的請求。服務器
常見的負載均衡的實現方法有多種,如隨機、輪詢、hash一致性等。本文使用隨機法實現負載均衡。網絡
隨機數法就是幾個數中隨機獲取一個數字,而後獲取這個數據對應的服務器。負載均衡
/** * 服務器類 */ public class Server { private String serverName; public Server(String name) { this.serverName = name; } public String getServerName() { return serverName; } public void setServerName(String serverName) { this.serverName = serverName; } @Override public String toString() { return "Server{serverName:"+this.getServerName()+"}"; } }
public class LoadBalance_Random { //用來存放全部的服務器 static List<Server> ServerList = new ArrayList<Server>(); //隨機數生成器 private static final Random r = new Random(); //初始化 模擬集羣中提供服務的服務器 static{ Server server1 = new Server("server1"); Server server2 = new Server("server2"); Server server3 = new Server("server3"); ServerList.add(server1); ServerList.add(server2); ServerList.add(server3); } public static void main(String[] args) { //模擬10個請求來獲取對應的服務器 for(int i=0;i<10;i++){ Server server_random = doSelect(ServerList); System.out.println(server_random); } } /** * 選擇服務器 * @param serverList * @return */ private static Server doSelect(List<Server> serverList) { Server server = null; //服務器的個數 int serverNum = serverList.size(); //隨機獲取一個 int serverIndex = r.nextInt(serverNum); server = serverList.get(serverIndex); return server; } }
執行main方法測試,結果以下:dom
在每臺服務器的配置性能等各方面都同樣時,使用這種隨機方法也是可取的,由於每臺服務器獲取的要處理的請求的數據量的機率是同樣的。可是有時候,咱們的服務器不必定都是相同的配置,每一臺服務器的性能都有必定的差別性,致使服務器提供服務的能力的差別,好比上邊咱們有3臺服務器,Server1每秒可處理5個請求,Server2每秒只能處理3個請求,Server3每秒只能處理2個請求,此時若是咱們有10個請求過來了,咱們分別給3個Server3個請求處理,因爲Server3只能處理2個請求,這時就會致使服務3不可用。ide
對這種不一樣服務能力的服務實現負載均衡,咱們可使用加權隨機法。對每一個服務標記權重,提升處理能力強的服務器的權重,下降服務能力若的服務器的權重,即根據能力的大小分配對應比例的請求數。性能
修改上述代碼,給服務加權重測試
/** * 服務器類 */ public class Server { private String serverName; private int weight;//權重 public Server(String name, int weight) { this.serverName = name; this.weight = weight; } @Override public String toString() { return "Server{serverName:"+this.getServerName()+",weight:"+this.getWeight()+"}"; } // 省略getter 和 setter方法 }
初始化時指定服務器的權重this
//初始化 模擬集羣中提供服務的服務器 static{ Server server1 = new Server("server1", 5); Server server2 = new Server("server2", 3); Server server3 = new Server("server3", 2); ServerList.add(server1); ServerList.add(server2); ServerList.add(server3); }
根據權重值獲取服務code
private static Server doSelectWithWeight(List<Server> serverList) { Server server = null; int totalWeight = 0; //全部服務器的總權重 boolean isSame = true;//默認全部服務器的權重都相同 for(int i=0; i<serverList.size(); i++){ //獲取當前服務器得權重 int serverWeight = serverList.get(i).getWeight(); //權重累加 totalWeight = totalWeight + serverWeight; //i = 0時默認仍是權重都同樣 //從第二個開始檢測每一個服務器得權重是否是都同樣,只須要與它得前一個服務得權重相比就能夠了 if(isSame && i>0){ int preServerWeight = serverList.get(i-1).getWeight(); if(serverWeight != preServerWeight){//當前服務器權重和前一個服務器得權重不相同 isSame = false; } } } if(!isSame){//服務器得權重不是都同樣 //在總權重下獲取一個隨機數 int index = r.nextInt(totalWeight); // for(int i=0;i<serverList.size();i++){ int serverWeight = serverList.get(i).getWeight(); //判斷獲取得隨機數落在總權重得哪個區間 //3臺服務器得得權重分別爲5 3 2 總和爲10 [0到5)這個區間屬於服務器1 [5到8)這個區間屬於服務器2 【8到10)這個區間屬於服務器3 //如 獲取到得隨機數是6 6-5=1 大於0 說明不在服務器1得區間,遍歷 1-3= -2 小於0 說明它落在了服務器2所在得區間 就能夠得對應服務器 index = index - serverWeight; if(index < 0){ return serverList.get(i); } } }else{ //全部服務器權重都同樣時,按照徹底隨機法隨機獲取一個服務器 server = doSelect(serverList); } return server; }
使用main方法測試server
public static void main(String[] args) { //模擬20個請求獲取對應的服務 for(int i=0;i<20;i++){ Server server_random_weight = doSelectWithWeight(ServerList); System.out.println(server_random_weight); } }
測試結果以下
從測試結果圖中能夠看到,權重大的獲取到的請求數多,相反權重小的獲取到的請求數越小。