美文网首页
负载均衡算法

负载均衡算法

作者: 麦大大吃不胖 | 来源:发表于2021-02-21 00:16 被阅读0次

by shihang.mai

1. 随机

  1. 将所有需要负载均衡的机器抽象成对象,放入list
  2. 利用new Random().nextInt(configs.size())获取随机下标
  3. 从list中获取目标机器
//随机算法
public class RandomLoadbalanceStrategy  implements LoadbalanceStrategy{
  //ProviderConfig-需要负载均衡的对象,例如10台机,那么这个list就有10个ProviderConfig对象
    //Object不用管
  @Override
  public ProviderConfig select(List<ProviderConfig configs, Object object) {
      int index = new Random().nextInt(configs.size());
      return configs.get(index);
  }
}

2. 加权随机算法

  1. 将所有需要负载均衡的机器抽象成对象,放入list
  2. 根据权重和list重新构建new list
  3. new Random().nextInt(newConfigs.size()-1)获取随机下标;
  4. 从new list中获取目标机器
public class WeightRandomLoadbalanceStrategy implements LoadbalanceStrategy{

  @Override
  public ProviderConfig select(List<ProviderConfig configs, Object object) {

      List<ProviderConfig newConfigs = new ArrayList<();

      for(ProviderConfig config:configs){

          for(int i = 0; i< config.getWeight(); i++){
              newConfigs.add(config);
          }
      }

      int index = new Random().nextInt(newConfigs.size()-1);
      return newConfigs.get(index);
  }
}

3. 轮询

  1. 将所有需要负载均衡的机器抽象成对象,放入list
  2. 用一个Map<String,Integer存储<接口名,调用次数,目的为了每个接口进行负载均衡
  3. 获取当前调用接口的次数,用次数%list.size,获取此次调用的下标
  4. 从list中获取目标机器
public class PollingLoadbalanceStrategy implements LoadbalanceStrategy {

  //使用一个Map来缓存每类应用的轮询索引
  private Map<String,Integer indexMap = new ConcurrentHashMap<();

  public ProviderConfig select(List<ProviderConfig configs, Object object){

      Integer index = indexMap.get(getKey(configs.get(0)));
      if(index == null){
          index = 0;
      }
      else {
          index++;
      }
      int i = index%configs.size();
      indexMap.put(getKey(configs.get(0)),index);
      return configs.get(i);


  }

  public String getKey(ProviderConfig config){

      return  config.getInterfaceName();
  }
}

4. 加权轮询

  1. 将所有需要负载均衡的机器抽象成对象,放入list
  2. 用一个Map<String,Integer存储<接口名,调用次数,目的为了每个接口进行负载均衡
  3. 根据权重和list重新构建new list
  4. 获取当前调用接口的次数,用次数%list.size,获取此次调用的下标
  5. 从new list中获取目标机器
public class WeightPollingLoadbalanceStrategy implements LoadbalanceStrategy {

  private Map<String,Integer indexMap = new ConcurrentHashMap<();

  List<ProviderConfig newConfigs = null;

  public ProviderConfig select(List<ProviderConfig configs, Object object){

      if(newConfigs==null){
          newConfigs = new ArrayList<();
          for(ProviderConfig config:configs){

              for(int i = 0; i< config.getWeight(); i++){
                  newConfigs.add(config);
              }
          }
      }
      Integer index = indexMap.get(getKey(configs.get(0)));
      if(index == null){
          index = 0;
      }
      else {
          index++;
      }

      int i = index%newConfigs.size();
      indexMap.put(getKey(configs.get(0)),index);
      return newConfigs.get(i);
  }

  public String getKey(ProviderConfig config){

      return  config.getInterfaceName();
  }
}

5. 最小时延算法

  1. 将所有需要负载均衡的机器抽象成对象,放入list,包括延时时间
  2. 排序取第一个获取目标机器
public class LeastActiveLoadbalanceStrategy implements  LoadbalanceStrategy{

  public ProviderConfig select(List<ProviderConfig configs, Object object){

      ProviderConfig[] registryConfigs= new ProviderConfig[configs.size()];
      configs.toArray(registryConfigs);
      Arrays.sort(registryConfigs,(x,y)-{
          if(x.getCallTime()<y.getCallTime()){
              return -1;
          }else if(x.getCallTime()==y.getCallTime()){
              return 0;
          }else{
              return 1;
          }
      });

      return registryConfigs[0];
  }
}

6. 一致性哈希

  1. 将所有需要负载均衡的机器抽象成对象,放入list
  2. 为解决数据倾斜问题,每个节点虚拟化出多个节点,即如果有10个节点,那么每个节点+1-5 做hash,形成50个节点
  3. 这些节点全部放入TreeMap
  4. 当有请求过来时,将这个请求也hash,在TreeMap中找到最近的目标机器
public class UniformityHashLoadbalanceStrategy  implements  LoadbalanceStrategy{

  private static final int VIRTUAL_NODES = 5;

  SortedMap<Integer, ProviderConfig sortedMap = null;
  public ProviderConfig select(List<ProviderConfig configs, Object object){

      if(null==sortedMap){
          sortedMap = new TreeMap();
          for(ProviderConfig config:configs){
              for(int j = 0; j < VIRTUAL_NODES; j++){
                  sortedMap.put(caculHash(getKey(config.getHost(),config.getPort(),"&&node"+j)),config);
              }
          }
      }

      System.out.println(sortedMap);

      //需要请求的地址hash
      Integer requestHashcCode = caculHash((String)object);

      SortedMap<Integer, ProviderConfig subMap = sortedMap.subMap(requestHashcCode,Integer.MAX_VALUE);
      ProviderConfig result= null;
      if(subMap.size()  != 0){
          Integer index = subMap.firstKey();
          result =  subMap.get(index);
      }
      else{
          result = sortedMap.get(0);
      }

      //// 打印测试数据

      new PrintResult(sortedMap,requestHashcCode).print();

      /////

      return  result;


  }
  private String getKey(String host,int port,String node){
      return new StringBuilder().append(host).append(":").append(port).append(node).toString();
  }

  private int caculHash(String str){

     /* int hashCode =  str.hashCode();
      hashCode = (hashCode<0)?(-hashCode):hashCode;
      return hashCode;*/

      final int p = 16777619;
      int hash = (int)2166136261L;
      for (int i = 0; i < str.length(); i++)
          hash = (hash ^ str.charAt(i)) * p;
      hash += hash << 13;
      hash ^= hash  7;
      hash += hash << 3;
      hash ^= hash  17;
      hash += hash << 5;

      // 如果算出来的值为负数则取其绝对值
      if (hash < 0)
          hash = Math.abs(hash);
      return hash;

  }

}
//用于打印测试数据
//@Data
class PrintResult{

  private  boolean flag =false;
  private SortedMap<Integer, ProviderConfig sortedMap;
  private int requestHashcCode;

  public PrintResult(SortedMap<Integer, ProviderConfig sortedMap, int requestHashcCode) {
      this.sortedMap = sortedMap;
      this.requestHashcCode = requestHashcCode;
  }

  public void print(){

      sortedMap.forEach((k,v)-{

          if( (false == flag) && ( k  requestHashcCode)){
              System.out.println("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
          }
          System.out.println("hashcode: " + k + "  " + v.getHost()+":"+v.getPort());
          if( (false == flag) && ( k  requestHashcCode)){
              System.out.println("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
              flag = true;
          }

      });

      System.out.println("------------------请求的hashcode:"+requestHashcCode);

  }
}

参考博客:https://www.cnblogs.com/lgjlife/p/10727245.html

相关文章

网友评论

      本文标题:负载均衡算法

      本文链接:https://www.haomeiwen.com/subject/eagzxltx.html