相关知识点
冷备与热备
fail-over与fail-back
冗余类型
什么是负载均衡
负载均衡,英文名称为Load Balance,指由多台服务器以对称的方式组成一个服务器集合,每台服务器都具有等价的地位,都可以单独对外提供服务而无须其他服务器的辅助。通过某种负载分担技术,将外部发送来的请求均匀分配到对称结构中的某一台服务器上,而接收到请求的服务器独立地回应客户的请求。负载均衡能够平均分配客户请求到服务器阵列,借此提供快速获取重要数据,解决大量并发访问服务问题,这种集群技术可以用最少的投资获得接近于大型主机的性能。
负载均衡算法在很多地方都有使用,无论是在服务治理中或者是在分布式缓存中都大量的使用,本文主要介绍几种常见的负载均衡的算法.
1.轮询法
轮询法,很好理解,将请求按照顺序轮流的分配到服务器上,他均衡的对待每一台后端的服务器,不关心服务器的的连接数和负载情况.以下代码演示了这种算法.
1public class BalanceServer { 2 public static List<String> servers = 3Arrays.asList("192.168.0.1", "192.168.0.2", "192.168.0.3", "192.168.0.4", 4 "192.168.0.5"); 5 public static int pos = 0; 6 public static String getServer() { 7 String server = null; 8 if (pos >= servers.size()) { 9 pos = 0; 10 } 11 server = servers.get(pos); 12 pos++; 13 return server; 14 } 15 public static void main(String[] args) { 16 for(int i=0;i<10;i++){ 17 System.out.println(BalanceServer.getServer()); 18 } 19 } 20}
轮询的策略目的在于请求的绝对均衡,但是在实际的情况下,可能服务器并不是完全一样,导致有些性能高的服务器不能完全发挥出来.
2.随机法
通过系统的随机函数,根据后端服务器列表的大小来随机获取其中的一台来访问,随着调用量的增大,实际效果越来越近似于平均分配到没一台服务器.和轮询的效果类似, 代码如下:
1public class BalanceServer { 2 public static List<String> servers = Arrays.asList("192.168.0.1", "192.168.0.2", "192.168.0.3", "192.168.0.4", 3 "192.168.0.5"); 4 public static int pos = 0; 5 public static String getServer() { 6 String server = null; 7 Random random = new Random(); 8 int randomPos = random.nextInt(servers.size()); 9 server = servers.get(randomPos); 10 return server; 11 } 12}
和轮询算法比较,在并发的场景下,轮询需要加锁,随机法想比而言性能好点.
3.源地址hash法
源地址hash法的思想是获取客户端访问的ip地址,通过hash函数计算出一个hash值,用该hash值对服务器列表的大小进行取模运算,得到的值就是要访问的服务器的序号,代码如下:
1public class BalanceServer { 2 public static List<String> servers = Arrays.asList("192.168.0.1", "192.168.0.2", "192.168.0.3", "192.168.0.4", 3 "192.168.0.5"); 4 public static int pos = 0; 5 public static String getServer(String ip) { 6 String server = null; 7 int hashCode = ip.hashCode(); 8 pos = hashCode % servers.size(); 9 server = servers.get(pos); 10 return server; 11 } 12}
hash法的好处是,在服务器列表不变的情况下,每次客户端访问的服务器都是同一个服务器.利用这个特性可以有状态的session会话.无需额外的操作就可以实现粘性会话.
4.加权轮询法
刚刚有说道过,不同的服务器性能不同,所以不能一概而论,需要给性能低的服务器给比较低的权重,性能高的给跟高的权重,代码如下:
1public class BalanceServer { 2 public static Map<String, Integer> serverMap = new HashMap<String, Integer>(); 3 public static int pos = 0; 4 static { 5 serverMap.put("192.168.0.1", 1); 6 serverMap.put("192.168.0.2", 1); 7 serverMap.put("192.168.0.3", 4); 8 serverMap.put("192.168.0.4", 3); 9 serverMap.put("192.168.0.5", 3); 10 serverMap.put("192.168.0.6", 2); 11 } 12 public static String getServer() { 13 Set<String> keySet = serverMap.keySet(); 14 Iterator<String> it = keySet.iterator(); 15 List<String> servers = new ArrayList<String>(); 16 while (it.hasNext()) { 17 String server = it.next(); 18 Integer weight = serverMap.get(server); 19 for (int i = 0; i < weight; i++) { 20 servers.add(server); 21 } 22 } 23 String server = null; 24 if (pos >= servers.size()) { 25 pos = 0; 26 } 27 server = servers.get(pos); 28 pos++; 29 return server; 30 } 31 public static void main(String[] args) { 32 for(int i=0;i<14;i++){ 33 System.out.println(BalanceServer.getServer()); 34 } 35 } 36}
5.加权随机法
与加权轮询法类似,加权随机法也是根据后端服务器不同的配置和负载情况来配置不同的权重。不同的是,它是按照权重来随机选择服务器的,而不是顺序。加权随机法的代码实现如下:
1public 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 // 取得Ip地址List 10 Set<String> keySet = serverMap.keySet(); 11 Iterator<String> iterator = keySet.iterator(); 12 List<String> serverList = new ArrayList<String>(); 13 while (iterator.hasNext()) 14 { 15 String server = iterator.next(); 16 int weight = serverMap.get(server); 17 for (int i = 0; i < weight; i++) 18 serverList.add(server); 19 } 20 JAVA.util.Random random = new java.util.Random(); 21 int randomPos = random.nextInt(serverList.size()); 22 return serverList.get(randomPos); 23 } 24}