负载均衡服务器的实现包含2个部分
1.根据负载均衡算法和Web服务器列表计算得到集群中一台Web服务器的地址。
2.将请求数据发送到该地址对应的Web服务器上。
负载均衡算法:
1.轮询法
从代码可以看出服务器列表放在一个Map中,然后定义一个全局变量,每次访问都去根据全局变量来取Map的值。
public class RoundRobin
2 {
3 private static Integer pos = 0;
4
5 public static String getServer()
6 {
7 // 重建一个Map,避免服务器的上下线导致的并发问题
8 Map<String, Integer> serverMap =
9 new HashMap<String, Integer>();
10 serverMap.putAll(IpMap.serverWeightMap);
11
12 // 取得Ip地址List
13 Set<String> keySet = serverMap.keySet();
14 ArrayList<String> keyList = new ArrayList<String>();
15 keyList.addAll(keySet);
16
17 String server = null;
18 synchronized (pos)
19 {
20 if (pos > keySet.size())
21 pos = 0;
22 server = keyList.get(pos);
23 pos ++;
24 }
25
26 return server;
27 }
28 }
轮询法的优点在于:试图做到请求转移的绝对均衡。
轮询法的缺点在于:为了做到请求转移的绝对均衡,必须付出相当大的代价,因为为了保证pos变量修改的互斥性,需要引入重量级的悲观锁synchronized,这将会导致该段轮询代码的并发吞吐量发生明显的下降。
2.随机(Random)法
先重建serverMap,再获取到server列表。在选取server的时候,通过Random的nextInt方法取0~keyList.size()区间的一个随机值,从而从服务器列表中随机获取到一台服务器地址进行返回。基于概率统计的理论,吞吐量越大,随机算法的效果越接近于轮询算法的效果。
public class Random 2 { 3 public static String getServer() 4 { 5 // 重建一个Map,避免服务器的上下线导致的并发问题 6 Map<String, Integer> serverMap = 7 new HashMap<String, Integer>(); 8 serverMap.putAll(IpMap.serverWeightMap); 9 10 // 取得Ip地址List 11 Set<String> keySet = serverMap.keySet(); 12 ArrayList<String> keyList = new ArrayList<String>(); 13 keyList.addAll(keySet); 14 15 java.util.Random random = new java.util.Random(); 16 int randomPos = random.nextInt(keyList.size()); 17 18 return keyList.get(randomPos); 19 } 20 }
3.源地址哈希(Hash)法
通过客户端的ip也就是remoteIp,取得它的Hash值,对服务器列表的大小取模,结果便是选用的服务器在服务器列表中的索引值。
public class Hash 2 { 3 public static String getServer() 4 { 5 // 重建一个Map,避免服务器的上下线导致的并发问题 6 Map<String, Integer> serverMap = 7 new HashMap<String, Integer>(); 8 serverMap.putAll(IpMap.serverWeightMap); 9 10 // 取得Ip地址List 11 Set<String> keySet = serverMap.keySet(); 12 ArrayList<String> keyList = new ArrayList<String>(); 13 keyList.addAll(keySet); 14 15 // 在Web应用中可通过HttpServlet的getRemoteIp方法获取 16 String remoteIp = "127.0.0.1"; 17 int hashCode = remoteIp.hashCode(); 18 int serverListSize = keyList.size(); 19 int serverPos = hashCode % serverListSize; 20 21 return keyList.get(serverPos); 22 } 23 }
源地址哈希法的优点在于:保证了相同客户端IP地址将会被哈希到同一台后端服务器,直到后端服务器列表变更。根据此特性可以在服务消费者与服务提供者之间建立有状态的session会话。
源地址哈希算法的缺点在于:除非集群中服务器的非常稳定,基本不会上下线,否则一旦有服务器上线、下线,那么通过源地址哈希算法路由到的服务器是服务器上线、下线前路由到的服务器的概率非常低,如果是session则取不到session,如果是缓存则可能引发"雪崩"。
4.加权轮询(Weight Round Robin)法
在获取服务器地址之前增加了一段权重计算的代码,根据权重的大小,将地址重复地增加到服务器地址列表中,权重越大,该服务器每轮所获得的请求数量越多。
1 public class WeightRoundRobin 2 { 3 private static Integer pos; 4 5 public static String getServer() 6 { 7 // 重建一个Map,避免服务器的上下线导致的并发问题 8 Map<String, Integer> serverMap = 9 new HashMap<String, Integer>(); 10 serverMap.putAll(IpMap.serverWeightMap); 11 12 // 取得Ip地址List 13 Set<String> keySet = serverMap.keySet(); 14 Iterator<String> iterator = keySet.iterator(); 15 16 List<String> serverList = new ArrayList<String>(); 17 while (iterator.hasNext()) 18 { 19 String server = iterator.next(); 20 int weight = serverMap.get(server); 21 for (int i = 0; i < weight; i++) 22 serverList.add(server); 23 } 24 25 String server = null; 26 synchronized (pos) 27 { 28 if (pos > keySet.size()) 29 pos = 0; 30 server = serverList.get(pos); 31 pos ++; 32 } 33 34 return server; 35 } 36 }
5.加权随机(Weight Random)法
加权随机法也是根据后端服务器不同的配置和负载情况来配置不同的权重。不同的是,它是按照权重来随机选择服务器的,而不是顺序。
1 public class WeightRandom 2 { 3 public static String getServer() 4 { 5 // 重建一个Map,避免服务器的上下线导致的并发问题 6 Map<String, Integer> serverMap = 7 new HashMap<String, Integer>(); 8 serverMap.putAll(IpMap.serverWeightMap); 9 10 // 取得Ip地址List 11 Set<String> keySet = serverMap.keySet(); 12 Iterator<String> iterator = keySet.iterator(); 13 14 List<String> serverList = new ArrayList<String>(); 15 while (iterator.hasNext()) 16 { 17 String server = iterator.next(); 18 int weight = serverMap.get(server); 19 for (int i = 0; i < weight; i++) 20 serverList.add(server); 21 } 22 23 java.util.Random random = new java.util.Random(); 24 int randomPos = random.nextInt(serverList.size()); 25 26 return serverList.get(randomPos); 27 } 28 }
6.最小连接数(Least Connections)法
最小连接数算法比较灵活和智能,由于后端服务器的配置不尽相同,对于请求的处理有 快有慢,它正是根据后端服务器当前的连接情况,动态地选取其中当前积压连接数最少的一台服务器来处理当前请求,尽可能地提高后端服务器的利用效率,将负载 合理地分流到每一台机器。由于最小连接数设计服务器连接数的汇总和感知,设计与实现较为繁琐