`

大型分布式网站之负载均衡算法

阅读更多

空余时间深入研究下关于大型分布式网站架构设计和实践的电子书,大家可在网上下载看看,稍后我上传到我的博客里,下面是部分心得关于负载均衡算法的,纯手动写的哦,希望对大家有帮助吧。

负载均衡算法的种类很多,常见的负载均衡算法包含轮询法,随机法,源地址哈希法,加权轮询法,加权随机法,最小链接发等,应根据具体的使用场景选取对应的算法。

 1.轮询(Round Robin)法

将请求按顺序轮流分配到后端服务器上,它均衡的对待后端每一台服务器,而不关心服务器实际的链接数和当前的系统负载。

这里通过初始化一个serverWeightMap的map变量来表示服务器地址和权重的映射,以此来模拟轮询算法的实现,其中设置的权重值在后面加权算法中会使用到,此处不做描述,

该变量初始化如下:

 serverWeightMap = new HashMap<String,Intager>();

 serverWeightMap.put('192.168.1.100',1);

 serverWeightMap.put('192.168.1.101',1);

// 权重为4

 serverWeightMap.put('192.168.1.102',4);

 serverWeightMap.put('192.168.1.103',1);

 serverWeightMap.put('192.168.1.104',1);

// 权重为3

 serverWeightMap.put('192.168.1.105',3);

 serverWeightMap.put('192.168.1.106',1);

// 权重为2

 serverWeightMap.put('192.168.1.107',2);

 serverWeightMap.put('192.168.1.108',1);

 serverWeightMap.put('192.168.1.109',1);

 serverWeightMap.put('192.168.1.110',1);

其中IP地址为192.168.1.102的权重为4,192.168.1.105的权重为3,192.168.1.107的权重为2

通过该地址列表,实现的轮询算法的部分关键代码如下:

public static String testRoundRobin(){

 //重新创建一个map,避免出现由于服务器上线和下线导致并发

 Map<String,Integer> serverMap = new HashMap<String,Integer> ();

 serverMap.putAll(serverWeightMap);

 // 取得IP地址list

 Set<String> keySet = serverMap.keySet(); //IP地址字符串

 ArrayList<String>keyList = new ArrayList<String>(); // IP集合字符串转为数组

 keyList.addAll(keySet);

 String server = null;

 synchronized(pos){

  if(pos >= keySet.size()){ // 好像是取得服务器台数 pos自增 >= 11

    pos = 0;

  }

  server = keyList.get(pos); // 获取该台服务器

  pos++;

 }

return server;

}

由于serverWeightMap中的服务器地址日常中是动态的也就是说随时上下架的,比如宕机等,为了避免可能出现的并发问题如数组越界,通过新建方法的局部变量serverMap,先将域变量复制到现在本地,避免被多个线程修改,轮询算法的位置变量pos是为了保证服务器选择的顺序性,需要在操作的时候加上synchronized锁,使得在同一时刻只有一个线程能够修改pos值,否则pos变量被并发修改则无法保证服务器选择的顺序性,

使用轮询策略希望做到请求转移的绝对均衡,付出的代价也蛮大的:为了pos保证变量修改的互斥性,需要引入重量级的锁synchronized会导致该段轮询代码的并发吞吐量会明显的下降,从而导致性能的降低。

 

2.随机法(Random)

通过系统随机函数,根据后端服务器列表的大小值来随机选取其中一台进行访问,根据概率统计论得知:随着调用量的增大,其实际效果越来越接近平均分配流量到每一台后端服务器也可达到轮询的效果

随机算法的代码:

 public static String testRandom(){

     //重新创建一个map,避免出现由于服务器上线和下线导致并发

     Map<String,Integer> serverMap = new HashMap<String,Integer> ();

     serverMap.putAll(serverWeightMap);

      // 取得IP地址list

      Set<String> keySet = serverMap.keySet(); //IP地址字符串

      ArrayList<String>keyList = new ArrayList<String>(); // IP集合字符串转为数组

      keyList.addAll(keySet);

      Random random = new Random();

      int randomPos = random.nextInt(keyLIst.size()); // 这里统计服务器数11

      String server = keyList.get(randomPos );

      return server;

 }

 通过Random的nextInt方法,取到在0~keyList.size()区间的一个随机值,从而从服务器列表中随机获取一台服务器地址,进行返回。基于概率论的统计,吞吐量越大,随机算法的效果越接近于轮询算法的效果。这种方法不会付出太大的性能代价。

 

3.源地址哈希法(Hash)

源地址哈希的意思是获取客户端访问的IP地址值,通过哈希函数计算得到一个数值,用该数值对服务器列表的大小进行取模运算,得到的结果便是访问的服务器的序号。采用哈希法进行负载均衡,同一IP地址的客户端,当后端服务器列表不变时,它每次都会被映射到同一台后端服务器进行访问。

源地址哈希算法实现代码:

public static String testConsumerHash(String remoteip){

     //重新创建一个map,避免出现由于服务器上线和下线导致并发

     Map<String,Integer> serverMap = new HashMap<String,Integer> ();

     serverMap.putAll(serverWeightMap);

      // 取得IP地址list

      Set<String> keySet = serverMap.keySet(); //IP地址字符串

      ArrayList<String>keyList = new ArrayList<String>(); // IP集合字符串转为数组

      keyList.addAll(keySet);

      int hashCode = remoteip.hashCode();

      int serverListSize = keyList.size();

      int serverPos = hashCode % serverListSize;

      return keyList.get(serverPos);

}

通过参数传入的客户端remoteip参数,取得它的哈希值,对服务器列表的大小取模,结果便是选用的服务器在服务器列表中的索引值。该算法保证了相同的客户端IP地址将会被哈希到同一台后端服务器,直到后端服务器列表变更。根据这特性可以在服务器消费者与服务提供者之间的session会话。

 

 4.加权轮询法(Weight Round Robin)

不同的后端服务器可能机器的配置和当前系统的负载并不相同,因此他们的抗压能力也不尽相同。给配置高负载低的机器配置更高的权重,让其处理更多的请求,而配置低负载高的机器则给其分配较低的权重降低其负载,加权轮询能很好的处理这一问题并将请求顺序按照权重分配到后端

加权轮询代码:

public static String testWeightRoundRobin(){

     //重新创建一个map,避免出现由于服务器上线和下线导致并发

     Map<String,Integer> serverMap = new HashMap<String,Integer> ();

     serverMap.putAll(serverWeightMap);

      // 取得IP地址list

      Set<String> keySet = serverMap.keySet(); //IP地址字符串

      Iterator<Strign>it = keySet.iterator();

      List<String>keyList = new ArrayList<String>(); // IP集合字符串转为数组

      while(it.hasNext()){

          String server = it.next();

           Integer weight = serverMap.get(server);

           for(int i=0;i<weight;i++){

              serverList.add(server);

           }

       }

      String server = null;

      synchronized(pos){

          if(pos >= keySet.size()){ // 好像是取得服务器台数 pos自增 >= 11

              pos = 0;

         }

          server = keyList.get(pos); // 获取该台服务器

          pos++;

     }

      return server;

}

与轮询算法相似,只是在获取服务器地址之前增加一段权重计算的代码,根据权重的大小将地址重复的增加到服务器列表中,权重越大该服务器每轮获得的请求数量越多。

 

5.加权随机法(Weight Random)

与加权轮询法类似,加权随机法也是根据后端服务器不同的配置和负载情况,配置不同的权重,不同的是它是安装权重来随机选取服务器的,尔非顺序。

加权随机实现的代码:

public static String testWeightRandom(){

 //重新创建一个map,避免出现由于服务器上线和下线导致并发

     Map<String,Integer> serverMap = new HashMap<String,Integer> ();

     serverMap.putAll(serverWeightMap);

      // 取得IP地址list

      Set<String> keySet = serverMap.keySet(); //IP地址字符串

      Iterator<String> it = keySet.iterator();

      List<String>serverList = new ArrayList<String>(); // IP集合字符串转为数组

      while(it.hasNext()){

          String server = it.next();

           Integer weight = serverMap.get(server);

           for(int i=0;i<weight;i++){

              serverList.add(server);

           }

       }

      Random random = new Random();

      int randomPos = random.nextInt(keyLIst.size()); // 这里统计服务器数11

      String server = keyList.get(randomPos );

      return server;

}

 

6.最小连接数法(Least Connections)

最小连接数法比较灵活和智能,由于后端服务器的配置不尽相同,对于请求的处理有快有慢,它根据后端服务器当前的连接情况,动态地选取其中当前积压连接数最少的那一台服务器来处理当前的请求,尽可能地提高后端服务器的利用效率,将负载合理地分流到每一台服务器。由于最少连接数涉及服务器连接数的汇总和感知,涉及与实现比较复杂繁琐,所以也请大家慎重选择。

如有问题,请多多指点,谢谢!

---------------完------------

 

 

 

 

 

 

 

 

 

分享到:
评论

相关推荐

    大型分布式网站架构与实践

     1.3.2 负载均衡算法 33  1.3.3 动态配置规则 39  1.3.4 ZooKeeper介绍与环境搭建 40  1.3.5 ZooKeeper API使用简介 43  1.3.6 zkClient的使用 47  1.3.7 路由和负载均衡的实现 50  1.4 HTTP服务网关 54  第...

    大型网站架构系列:负载均衡详解

    介绍了负载均衡原理,分类,算法,硬件负载均衡。系统的扩展可分为纵向(垂直)扩展和横向(水平)扩展。纵向扩展,是从单机的角度通过增加硬件处理能力,比如CPU处理能力,内存容量,磁盘等方面,实现服务器处理能力的...

    Fourinone分布式计算框架

    ade的解决方案去解决大集群的分布式缓存,利用硬件负载均衡路由到一组fa?ade服务器上,fa?ade可以自动为缓存内容生成key,并根据key准确找到散落在背后的缓存集群的具体哪台服务器,当缓存服务器的容量到达限制时,...

    网站架构技术

    负载均衡算法 分布式缓存集群的伸缩性设计 memcached分布式缓存集群的访问模型 memcached分布式缓存集群的伸缩性挑战 分布式缓存的一致性hash算法 数据存储服务器集群的伸缩性设计 关系数据库集群的伸缩...

    Fourinone分布式并行计算四合一框架

     但是fourinone并不提供一个分布式存储系统,比如文件数据的导入导出、拆分存储、负载均衡,备份容灾等存储功能,不过开发人员可以利用这些api去设计和实现这些功能,用来满足自己的特定需求。  二、自动化class...

    大型互联网相关技术

    负载均衡 数据库面临的挑战和扩展技术 消息队列 服务化 CDN 分布式缓存 哈希一致性算法

    Java思维导图xmind文件+导出图片

    redis Cluster数据分布算法之Hash slot redis使用常见问题及性能优化思路 redis高可用及高并发实战 缓存击穿、缓存雪崩预防策略 Redis批量查询优化 Redis高性能集群之Twemproxy of Redis 数据存储 MongoDB ...

    大数据处理过程.docx

    大数据时代处理之二:导入/预处理(抽取) 虽然采集端本身会有很多数据库,但是如果要对这些海量数据进行有效的分析,还是应该将这些来自前端的数据导入到一个集中的大型分布式数据库,或者分布式存储集群,并且...

    大数据处理过程(1).docx

    大数据时代处理之二:导入/预处理(抽取) 虽然采集端本身会有很多数据库,但是如果要对这些海量数据进行有效的分析,还是应该将这些来自前端的数据导入到一个集中的大型分布式数据库,或者分布式存储集群,并且...

    fourinone-3.04.25

    但是fourinone并不提供一个分布式存储系统,比如文件数据的导入导出、拆分存储、负载均衡,备份容灾等存储功能,不过开发人员可以利用这些api去设计和实现这些功能,用来满足自己的特定需求。 二、自动化class和jar...

    详解Linux服务器集群.docx

    调度器是服务器集群系统的唯一入口点( ),它可以采用负载均衡技术、基于内容请求分发技术或者两者相结合。在负载均衡技术中,需要服务器池拥有相同的内容提供相同的服务。当 客户请求到达时,调度器只根据服务器...

    大数据分析及处理方法.docx

    导入/预处理 虽然采集端本身会有许多数据库,但是假如要对这些海量数据进行有效的分析,还是应当将这些来自前端的数据导入到一个集中的大型分布式数据库,或者分布式存储集群,并且可以在导入基础上做一些简洁的...

    37篇经过消化的云计算论文

    负载均衡 33,35 数据管理 32 能耗管理 29 安全管理 25 2、云计算平台实例 虚拟机 27,31 存储平台 5,6,12,13,14,19,22,26 计算平台 平台测评 1 云平台集成 10 3、云计算理论模型 描述模型 4 选择模型 20 ...

    37篇经过消化云计算论文打包下载

    负载均衡 33,35 数据管理 32 能耗管理 29 安全管理 25 2、云计算平台实例 虚拟机 27,31 存储平台 5,6,12,13,14,19,22,26 计算平台 平台测评 1 云平台集成 10 3、云计算理论模型 描述模型 4 选择模型 20 编程模型...

    java面试题,180多页,绝对良心制作,欢迎点评,涵盖各种知识点,排版优美,阅读舒心

    180多页面试题,前前后后不间断的更新了两年,准备换工作时,总是拿来看看,有比较好的面试题,也不间断的更新,面试题目录如下: 【基础】面向对象的特征有哪些方面 13 ...4、ZooKeeper在大型分布式系统中的应用 189

    Oracle9i的init.ora参数中文说明

    该参数是构成某个例程的总 SGA 要求的若干参数之一。 默认值 : 派生: SESSIONS 参数的值 (如果正在使用共享服务器体系结构); 否则为 0。 Mts_multiple_listeners: 说明: 指定多个监听程序的地址是分别指定的, ...

Global site tag (gtag.js) - Google Analytics