负载均衡的几种算法原理及代码实现

服务器 数据中心 算法
轮询算法: 将接收到的请求依次转发到后端服务器上,它均衡对待(一视同仁)所有服务器,而不关心当前服务器实际连接数及当前系统负载。

轮询算法: 将接收到的请求依次转发到后端服务器上,它均衡对待(一视同仁)所有服务器,而不关心当前服务器实际连接数及当前系统负载。 这里实现一个简单的轮询系统:

  1. public class RoundRobin { 
  2.    static Integer  position = 0; 
  3.    public static List<String> initServerList() { 
  4.        List<String> servers = new ArrayList<>(); 
  5.        servers.add("192.168.10.00"); 
  6.        servers.add("192.168.10.01"); 
  7.        servers.add("192.168.10.02"); 
  8.        servers.add("192.168.10.03"); 
  9.        servers.add("192.168.10.04"); 
  10.        servers.add("192.168.10.05"); 
  11.        servers.add("192.168.10.06"); 
  12.        return servers; 
  13.    } 
  14.    public static String getServerUrl() { 
  15.        //新建立一个List赋值,避免服务器上下线导致的并发问题 
  16.        List<String> serverList = new ArrayList<>(); 
  17.        serverList.addAll(initServerList()); 
  18.        String server = null
  19.        synchronized (position){ 
  20.            if(position >= serverList.size()) { 
  21.                position = 0; 
  22.            } 
  23.            server = serverList.get(position); 
  24.            position ++; 
  25.        } 
  26.        return server; 
  27.    } 
  28.    public static void main(String[] args) { 
  29.        while (true){ 
  30.            System.out.println(getServerUrl()); 
  31.        } 
  32.    } 

在实际生产环境中,我们还得考虑诸多因素,比如:

[[238078]]

新增服务器ip如何处理? 这个比较简单,直接添加到initServerList()即可。

出现服务宕机怎么办? 比如192.168.10.01 所在服务器挂掉了,请求被转发给它,就会报错。这时,需要服务的消费者考虑容错处理,在这种情况下,比如再发一次请求,那就会被转发到192.168.10.02 机器上,正常。 该方法***缺点是引用了悲观锁 synchronized,影响系统的并发性能。

每台机器的配置不一样,有单核CPU,2G内存,有8核CPU,32G内存。这种情形下,使用上述轮询,那就不公平了,对弱配置机器,压力很大。 这个,我们可以引入

加权轮询: 每台服务器,给一个权重值,权值高的,多分配点儿请求,权值少的,少分配点儿请求,。 实现思路也很简单,根据权值,重新构建服务列表,然后再轮询。上个图示:

如下是代码实现:

  1. public class WeightRoundRobin { 
  2.    static Integer  position = 0; 
  3.    public static Map<String, Integer> initServicesMap() { 
  4.        Map<String, Integer> servicesMap = new HashMap<>(); 
  5.        servicesMap.put("192.168.10.00", 1); 
  6.        servicesMap.put("192.168.10.02", 3); 
  7.        servicesMap.put("192.168.10.03", 3); 
  8.        servicesMap.put("192.168.10.04", 5); 
  9.        servicesMap.put("192.168.10.05", 5); 
  10.        servicesMap.put("192.168.10.06", 5); 
  11.        return servicesMap; 
  12.    } 
  13.    public static String getServerUrl() { 
  14.        //新建立一个List赋值,避免服务器上下线导致的并发问题 
  15.        Map<String, Integer> initMap = new HashMap<>(); 
  16.        initMap = initServicesMap(); 
  17.        Set<String> servicesSet = new HashSet<>(); 
  18.        servicesSet.addAll(initMap.keySet()); 
  19.        Iterator<String> servicesIterator = servicesSet.iterator(); 
  20.        List<String> servicesList = new ArrayList<>(); 
  21.        while (servicesIterator.hasNext()) { 
  22.            String server = servicesIterator.next(); 
  23.            Integer weight = initMap.get(server); 
  24.            if(weight > 0) { 
  25.                for(int i=0; i<weight; i++) { 
  26.                    servicesList.add(server); 
  27.                } 
  28.            } 
  29.        } 
  30.        String server = null
  31.        synchronized (position){ 
  32.            if(position >= servicesList.size()) { 
  33.                position = 0; 
  34.            } 
  35.            server = servicesList.get(position); 
  36.            position ++; 
  37.        } 
  38.        return server; 
  39.    } 
  40.    public static void main(String[] args) { 
  41.        while (true){ 
  42.            System.out.println(getServerUrl()); 
  43.        } 
  44.    } 

随机算法:

顾名思义:现有N个服务器ip地址,请求来了后,随机转发到某个服务器上。从概率的角度来说,随着请求数的增多,最终每台服务器分配到的请求,近似于均等。这就比轮询算法少了个悲观锁,并发性能上,有了极大的提升。

实现也很简单:

如下:

  1. public class RandomDemo { 
  2.    public static List<String> initServerList() { 
  3.        List<String> servers = new ArrayList<>(); 
  4.        servers.add("192.168.10.00"); 
  5.        servers.add("192.168.10.01"); 
  6.        servers.add("192.168.10.02"); 
  7.        servers.add("192.168.10.03"); 
  8.        servers.add("192.168.10.04"); 
  9.        servers.add("192.168.10.05"); 
  10.        servers.add("192.168.10.06"); 
  11.        return servers; 
  12.    } 
  13.    public static String getServerUrl() { 
  14.        //新建立一个List赋值,避免服务器上下线导致的并发问题 
  15.        List<String> serverList = new ArrayList<>(); 
  16.        serverList.addAll(initServerList()); 
  17.        int position = new Random().nextInt(serverList.size()); 
  18.        return serverList.get(position); 
  19.    } 
  20.    public static void main(String[] args) { 
  21.        while (true) { 
  22.            System.out.println(getServerUrl()); 
  23.        } 
  24.    } 

但他也有与简单轮询算法一样的问题:

对于不同性能的服务器,依旧一视同仁,那其实是不公平的。低配置,应该少分点请求嘛。

这就有了

加权随机算法,其实现思想同 加权轮询算法一样,给不同配置的服务器,配置不同的权重值。代码实现也同加权轮询思路一样,构建出符合权重值的服务集合后,再进行随机选取,这里就不写了,留给大家自己去写吧。

源地址哈希(hashCode)法 : 根据客户端的请求ip,通过哈希计算,得到一个数值,随后与服务器列表个数,进行取模计算,得到该请求 访问服务器列表的序号。该方法,有个好处是,当服务器列表不变时,某个客户端,会始终访问某一个固定的服务器,这样就可以构建一个客户端--服务器之间,有状态的session。

代码实现:

  1. public class HashDemo {  
  2.    public static List<String> initServerList() {  
  3.        List<String> servers = new ArrayList<>();  
  4.        servers.add("192.168.10.00");  
  5.        servers.add("192.168.10.01");  
  6.        servers.add("192.168.10.02");  
  7.        servers.add("192.168.10.03");  
  8.        servers.add("192.168.10.04");  
  9.        servers.add("192.168.10.05");  
  10.        servers.add("192.168.10.06");  
  11.        return servers;  
  12.    }  
  13.    public static String getServerUrl() {  
  14.        //新建立一个List赋值,避免服务器上下线导致的并发问题  
  15.        List<String> serverList = new ArrayList<>();  
  16.        serverList.addAll(initServerList());  
  17.        int requestIpHashCode = "192.168.10.06.109".hashCode();  
  18.        int position = requestIpHashCode % serverList.size();  
  19.        return serverList.get(position);  
  20.    }  
  21.    public static void main(String[] args) {  
  22.        while (true) {  
  23.            System.out.println(getServerUrl());  
  24.        }  
  25.    }  
  26. }  

 【编辑推荐】

责任编辑:武晓燕 来源: GIS大数据开发
相关推荐

2019-04-12 09:00:01

负载均衡Java服务器

2018-04-10 10:49:17

负载均衡算法服务器

2010-04-21 15:06:37

负载均衡算法

2017-02-09 16:16:24

Java负载均衡算法

2019-12-26 09:13:00

算法硬件软件

2015-09-25 09:56:37

负载均衡

2010-05-06 12:18:34

IP负载均衡

2010-04-26 15:04:08

负载均衡器

2020-04-27 10:00:53

负载均衡互联网架构

2010-05-04 16:10:51

负载均衡算法

2021-10-21 10:02:37

Java开发代码

2021-10-10 13:31:14

Java负载均衡算法

2023-02-07 06:42:24

Pulsar负载均衡

2019-04-29 11:00:14

架构负载均衡互联网

2023-03-03 08:26:32

负载均衡算法服务

2024-03-28 13:10:20

负载均衡LVSHaproxy

2010-04-22 17:53:36

Apache负载均衡

2019-08-26 08:36:09

负载均衡高可用Nginx

2019-12-27 09:29:46

负载均衡算法哈希算法

2010-11-19 12:53:53

梭子鱼负载均衡
点赞
收藏

51CTO技术栈公众号