负载均衡Java实现

  load balancing

Posted by Xiaoran on August 5, 2018

本文参考自 负载均衡算法及手段

负载均衡算法

private Map<String, Integer> serverMap = new HashMap<>(){ {
        put("192.168.1.100", 1);
        put("192.168.1.101", 1);
        put("192.168.1.102", 4);
        put("192.168.1.103", 1);
        put("192.168.1.104", 1);
        put("192.168.1.105", 3);
        put("192.168.1.106", 1);
        put("192.168.1.107", 2);
        put("192.168.1.108", 1);
        put("192.168.1.109", 1);
        put("192.168.1.110", 1);
    } };

1、随机算法

  • Random:随机,按权重设置随机概率。在一个截面上碰撞的概率高,但调用量越大分布越均匀,而且按概率使用权重后也比较均匀,有利于动态调整提供者权重。
    public void random(){
      List<String> keyList = new ArrayList<String>(serverMap.keySet());
      Random random = new Random();
      int idx = random.nextInt(keyList.size());
      String server = keyList.get(idx);
      System.out.println(server);
    }
    
  • WeightedRandom
    public void weightRandom(){
      Set<String> keySet = serverMap.keySet();
      List<String> servers = new ArrayList<String>();
      for(Iterator<String> it = keySet.iterator();it.hasNext();){
          String server = it.next();
          int weithgt = serverMap.get(server);
          for(int i=0;i<weithgt;i++)
              servers.add(server);
      }
      String server = null;
      Random random = new Random();
      int idx = random.nextInt(servers.size());
      server = servers.get(idx);
      System.out.println(server);
    }
    

2、轮询及加权轮询

  • 轮询 (Round Robbin):当服务器群中各服务器的处理能力相同时,且每笔业务处理量差异不大时,最适合使用这种算法。 轮循,按公约后的权重设置轮循比率。存在慢的提供者累积请求问题,比如:第二台机器很慢,但没挂,当请求调到第二台时就卡在那,久而久之,所有请求都卡在调到第二台上。
    private Integer pos = 0;
    public void roundRobin(){
      List<String> keyList = new ArrayList<>(serverMap.keySet());
      String server = null;
      synchronized (pos){
          if(pos > keyList.size())
              pos = 0;
          server = keyList.get(pos);
          pos++;
      }
      System.out.println(server);
    }
    
  • 加权轮询 (Weighted Round Robbin):为轮询中的每台服务器附加一定权重的算法。比如服务器1权重1,服务器2权重2,服务器3权重3,则顺序为1-2-2-3-3-3-1-2-2-3-3-3- ……
    public void weightRoundRobin(){
      Set<String> keySet = serverMap.keySet();
      List<String> servers = new ArrayList<>();
      for(Iterator<String> it = keySet.iterator();it.hasNext();){
          String server = it.next();
          int weithgt = serverMap.get(server);
          for(int i=0;i<weithgt;i++)
              servers.add(server);
      }
      String server = null;
      synchronized (pos){
          if(pos > keySet.size())
              pos = 0;
          server = servers.get(pos);
          pos++;
      }
      System.out.println(server);
    }
    

3、最小连接及加权最小连接

  • 最少连接 (Least Connections):在多个服务器中,与处理连接数(会话数)最少的服务器进行通信的算法。即使在每台服务器处理能力各不相同,每笔业务处理量也不相同的情况下,也能够在一定程度上降低服务器的负载。

  • 加权最少连接 (Weighted Least Connection):为最少连接算法中的每台服务器附加权重的算法,该算法事先为每台服务器分配处理连接的数量,并将客户端请求转至连接数最少的服务器上。

4、哈希算法

  • 普通哈希
    public void hash(){
      List<String> keyList = new ArrayList<String>(serverMap.keySet());
      String remoteIp = "192.168.2.215";
      int hashCode = remoteIp.hashCode();
      int idx = hashCode % keyList.size();
      String server = keyList.get(Math.abs(idx));
      System.out.println(server);
    }
    
  • 一致性哈希:相同参数的请求总是发到同一提供者。当某一台提供者挂时,原本发往该提供者的请求,基于虚拟节点,平摊到其它提供者,不会引起剧烈变动。

5、IP 地址散列

通过管理发送方 IP 和目的地 IP 地址的散列,将来自同一发送方的分组(或发送至同一目的地的分组)统一转发到相同服务器的算法。当客户端有一系列业务需要处理而必须和一个服务器反复通信时,该算法能够以流(会话)为单位,保证来自相同客户端的通信能够一直在同一服务器中进行处理。

6、URL 散列

通过管理客户端请求 URL 信息的散列,将发送至相同URL的请求转发至同一服务器的算法。