负载均衡算法的简单介绍及实现!

<span style="font-size:14px;">serverWeightMap = new HashMap<String, Integer>();
serverWeightMap.put("192.168.1.100", 1);
serverWeightMap.put("192.168.1.101", 1);
//权重为4
serverWeightMap.put("192.168.1.102", 4);
serverWeightMap.put("192.168.1.103", 1);
serverWeightMap.put("192.168.1.104", 1);
//权重为3
serverWeightMap.put("192.168.1.105", 3);
serverWeightMap.put("192.168.1.106", 1);
//权重为2
serverWeightMap.put("192.168.1.107", 2);
serverWeightMap.put("192.168.1.108", 1);
serverWeightMap.put("192.168.1.109", 1);
serverWeightMap.put("192.168.1.110", 1);</span>


1:轮询(Round Robin)法

轮询很容易理解,将请求按顺序轮流的分配到后端服务器上,它均衡的对待后端每一台服务器,而不关心服务器实际的连接数和当前的系统负载。

<span style="font-size:14px;"><span style="font-size:14px;">//轮询法
private static String testRoundRobin() {
	//重新创建一个map,避免出现由于服务器上线和下线导致的并发问题
	Map<String, Integer> serverMap = new HashMap<String, Integer>();
	serverMap.putAll(serverWeightMap);
	
	//取得IP地址的list
	Set<String> keySet = serverMap.keySet();
	ArrayList<String> keyList = new ArrayList<String>();
	keyList.addAll(keySet);
	
	String server = null;
	
	synchronized(pos){
		if(pos >= keySet.size()){
			pos = 0;
		}
		server = keyList.get(pos);
		pos++;
	}
	
	return server;
}</span></span>

使用轮询策略的目的在于:希望做到请求转移的绝对均衡,但付出的性能代价也是相当大的。为了pos保证变量修改的互斥性,需要引入重量级的悲观锁synchronized,将会导致该段轮询代码的并发吞吐量发生明显的下降。


2:随机(Random)法

通过系统随机函数,根据后端服务器列表大小值来随机选取其中一台进行访问

<span style="font-size:14px;">//随机法
private static String testRandom() {
	//重新创建一个map,避免出现由于服务器上线和下线导致的并发问题
	Map<String, Integer> serverMap = new HashMap<String, Integer>();
	serverMap.putAll(serverWeightMap);
	
	//取得IP地址的list
	Set<String> keySet = serverMap.keySet();
	ArrayList<String> keyList = new ArrayList<String>();
	keyList.addAll(keySet);
	
	Random random = new Random();
	int randomPos = random.nextInt(keyList.size());
	
	String server = keyList.get(randomPos);
	return server;
}</span>

基于概率统计理论,吞吐量越大,随机算法的效果越接近于轮询算法的效果,因此,你还会考虑一定要用需要付出一定性能代价的轮询算法吗?


3:原地址哈希(Hash)法

原地址哈希的思想是获取客户端访问的IP地址值,通过哈希函数计算得到一个数值,用该数值对服务器列表的大小进行取模运算,得到的结果便是要访问的服务器序号

<span style="font-size:14px;">//源地址哈希(Hash)法
private static String testConsumerHash(String remoteip) {
	//重新创建一个map,避免出现由于服务器上线和下线导致的并发问题
	Map<String, Integer> serverMap = new HashMap<String, Integer>();
	serverMap.putAll(serverWeightMap);
	
	//取得IP地址的list
	Set<String> keySet = serverMap.keySet();
	ArrayList<String> keyList = new ArrayList<String>();
	keyList.addAll(keySet);
	
	int hashCode = remoteip.hashCode();
	int serverListSize = keyList.size();
	int serverPos = hashCode % serverListSize;
	
	return keyList.get(serverPos);
}</span>
通过参数传入客户端的remoteIP参数,取得它的哈希值,对服务器列表大小取模,结果便是选用的服务器列表中的索引值。该算法保证了相同的客户端IP地址将会被“哈希”到同一台后端服务器,直到后端服务器列表变更。根据此特性可以在服务消费者和服务提供者之间建立有状态的session会话


4:加权轮询(Weight Round Robin)法

不同的后端服务器可能机器的配置和当前系统的负载并不相同,因此他们的抗压能力也不尽相同。给配置高、负载低的机器配置更高的权重,让其处理更多的请求,而配置低、负载高的机器,则给其分配较低的权重,降低其系统负载,加权轮询能很好的处理这一问题,并将请求顺序且按照权重分配到后端

<span style="font-size:14px;">//加权轮询法
private static String testWeightRoundRobin() {
	//重新创建一个map,避免出现由于服务器上线和下线导致的并发问题
	Map<String, Integer> serverMap = new HashMap<String, Integer>();
	serverMap.putAll(serverWeightMap);
	
	//取得IP地址的list
	Set<String> keySet = serverMap.keySet();
	Iterator<String> it = keySet.iterator();
	
	List<String> serverList = new ArrayList<String>();
	
	while (it.hasNext()) {
		String server = it.next();
		Integer weight = serverMap.get(server);
		for (int i = 0; i < weight; i++) {
			serverList.add(server);
		}
	}
	
	String server = null;
	
	synchronized(pos){
		if(pos >= serverList.size()){
			pos = 0;
		}
		server = serverList.get(pos);
		pos++;
	}
	
	return server;
}</span>

与轮询法类似,只是在获取服务器地址之前增加了一段权重计算的代码,根据权重的大小,将地址重复的增加到服务器地址列表中,权重越大,该服务器每轮所获得的请求数量越多


5:加权随机(Weight Random)法

与加权轮询法类似,加权随机法也根据后端服务器不同的配置和负载情况配置不同的权重,不同的是,它是按照权重来随机选取服务器的,而非顺序

<span style="font-size:14px;">//加权随机法
private static String testWeightRandom() {
	//重新创建一个map,避免出现由于服务器上线和下线导致的并发问题
	Map<String, Integer> serverMap = new HashMap<String, Integer>();
	serverMap.putAll(serverWeightMap);
	
	//取得IP地址的list
	Set<String> keySet = serverMap.keySet();
	Iterator<String> it = keySet.iterator();
	
	List<String> serverList = new ArrayList<String>();
	
	while (it.hasNext()) {
		String server = it.next(); 
		Integer weight = serverMap.get(server);
		for (int i = 0; i < weight; i++) {
			serverList.add(server);
		}
	}
	
	Random random = new Random();
	int randomPos = random.nextInt(serverList.size());
	String server = serverList.get(randomPos);
	
	return server;
}</span>

6:最小连接数(Least Connections)法
最小链接数算法比较灵活和智能,由于后端服务器的配置不尽相同,对于请求的处理有快有慢,它正式根据后端服务器当前的连接情况,动态的选取其中当前积压连接数最少的一台服务器来处理当前请求,竟可能的提高后端服务器的利用效率,将负载合理的分流到每一台机器。

发布了41 篇原创文章 · 获赞 39 · 访问量 30万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章