負載均衡實現之隨機數


負載均衡(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方法測試,結果如下:

​ 在每台服務器的配置性能等各方面都一樣時,使用這種隨機方法也是可取的,因為每台服務器獲取的要處理的請求的數據量的概率是一樣的。但是有時候,我們的服務器不一定都是相同的配置,每一台服務器的性能都有一定的差異性,導致服務器提供服務的能力的差異,比如上邊我們有3台服務器,Server1每秒可處理5個請求,Server2每秒只能處理3個請求,Server3每秒只能處理2個請求,此時如果我們有10個請求過來了,我們分別給3個Server3個請求處理,由於Server3只能處理2個請求,這時就會導致服務3不可用。

​ 對這種不同服務能力的服務實現負載均衡,我們可以使用加權隨機法。對每個服務標記權重,提高處理能力強的服務器的權重,降低服務能力若的服務器的權重,即根據能力的大小分配對應比例的請求數。

​ 修改上述代碼,給服務加權重

/**
 * 服務器類
 */
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方法
}

​ 初始化時指定服務器的權重

	//初始化   模擬集群中提供服務的服務器
	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);
	}

​ 根據權重值獲取服務

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方法測試

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);
		}
	}

測試結果如下

從測試結果圖中可以看到,權重大的獲取到的請求數多,相反權重小的獲取到的請求數越小。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2026 CODEPRJ.COM