热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

《SpringCloud》学习(二)负载均衡!

第二章负载均衡负载均衡是对系统的高可用、网络压力的缓解和处理能力扩容的重要手段之一。SpringCloudRibbon是一个基于HTTP和TCP的客户端负载均衡工具,

第二章 负载均衡


  负载均衡是对系统的高可用、网络压力的缓解和处理能力扩容的重要手段之一。Spring Cloud Ribbon是一个基于 HTTP 和 TCP 的客户端负载均衡工具,它基于Netflix Ribbon实现,通过 Spring Cloud 的封装,可以让我们轻松地将面向服务的 REST 模板请求自动转换成客户端负载均衡的服务调用。Spring Cloud Ribbon几乎存在于每一个Spring Cloud 构建的微服务和基础设施中。因为微服务间的调用,API 网关的请求转发等内容实际上都是通过Ribbon来实现的

  通过Spring Cloud Ribbon的封装,我们在微服务架构中使用客户端负载均衡调用非常简单,只需要如下两步:

  -服务提供者只需要启动多个服务实例并注册到一个注册中心或是多个相关联的服务注册中心。
  -服务消费者直接通过调用被@LoadBalanced 注解修饰过的 RestTemplate 来实现面向服务的接口调用。


  这样,我们就可以将服务提供者的高可用以及服务消费者的负载均衡调用一起实现了。但是RestTemplate是Spring提供。跟Ribbon的客户端负载均衡又有什么关系,又是如何实现?下文详解。

 

一.LoadBalancerClent 和 RibbonLoadBalancerClient

 

  1.LoadBalancerClent 

  通过@LoadBalanced注解源码的注释中可以知道,该注解用来给RestTemplate做标记,以使用负载均衡的客户端(LoadBalancerClent)来配置它。下图贴出了LoadBalancerClent源码。

  

  1.1 Servicelnstance choose (String serviceid)根据传入的服务名serviceld, 从负载均衡器中挑选一个对应服务的实例。
  1.2 T execute (String serviceid, LoadBalancerRequest request)使用从负载均衡器中挑选出的服务实例来执行请求内容。
  1.3 URI reconstructURI(Serviceinstance instance , URI original )为系统构建 一个合适的host:port形式的URI。

  从方法名的诠释相信大家已经看出一些倪端,但是并不是大家想的那样(先调用choose挑选服务,再组成URI,最后调用execute执行请求)。因为本人这里这里踩过坑,先强调下!

  重要的是execute方法。

  2.RibbonLoadBalancerClient

  RibbonLoadBalancerClient是LoadBalancerClent的实现类。要点是它实现了父类的execute方法。贴出execute的方法实现。

  

  可以看出进入方法就调用自身的getServer方法获取服务,继续。

  

  IloadBalancer.chooseServer方法解释:通过某种策略,从负载均衡器中挑选出个具体的服务实例,也就是这里去真正的去挑选我们调用的服务实例。但是IloadBalancer是一个接口,默认注入的是它的子类实现ZoneAwareLoadBalancer。也就是挑选服务的任务交给了ZoneAwareLoadBalancer。

  至于如何如挑选,在第四节负载均衡策略会详解。

  

二.LoadBalancerAutoConfiguration负载均衡地自动化配置类

  LoadBalancerAutoConfiguration为实现客户端负载均衡地自动化配置类。由于类源码稍长,就不贴了,我下图写出该类主要描述。

  

 

  1.被@ConditionalOnClass(RestTemplate.class)和@ConditionalOnBean(LoadBalancerClent.class)修饰表示在当前工程中必须有RestTemplate的Bean和LoadBalancerCliet的实现 Bean,理所当然嘛。

  2.创建了一个LoadBalancerInerceptor的Bean,用于实现对客户端发起请求时进行拦截, 以实现客户端负载均衡。这里贴出了LoadBalancerInerceptor的源码,我们可以看到在拦截器中注入了 LoadBalancerClient的实现,其实就是上文提到的RibbonLoadBalancerClient类!

   

 

  3.创建了一个RestTemplateCustomizer的Bean, 用于给RestTemplate增加LoadBalancerInterceptor拦截器。
  4.维护了一个被@LoadBalanced 注解修饰的RestTemplate对象列表,并在这里进行初始化,通过调用RestTemplateCustomizer的实例来给需要客户端负载均衡的RestTemplate增加LoadBalancerinInerceptor拦截器。

  我们暂且可以推出:当一个被@LoadBalanced注解修饰的RestTemplate对象向外发起HTTP请求时,会LoadBalancerinterceptor类的intercept函数所拦截,然后调用RibbonLoadBalancerClient类的execute函数。继续向下看!

三.ZoneAwareLoadBalancer负载均衡器

   

  我们已经知道ZoneAwareLoadBalancer是ILoadBalancer的实现类,并且ZoneAwareLoadBalancer.chooseServer方法是挑选出个具体的服务实例。但是ILoadBalancer和ZoneAwareLoadBalancer并不是直接实现关系,他们有多层实现继承关系,如下图。

  

  他们对ILoadBalancer一层层的实现扩展构成了ZoneAwareLoadBalancer,这里对他们具体如何实现扩展不做描述,大家有兴趣的可以去了解下!

  ZoneAwareLoadBalancer中要点:

  1.定义了负载均衡的处理规则IRule对象,负载均衡器实际将服务实例选择任务又委托给了IRule 实例中的choose函数来实现。而在这里,默认初始化了 RoundRobinRule为IRule的实现对象。RoundRobinRule 实现了最基本且常用的线性负载均衡规则(轮询),换而言之就是IRule的实现类就是定义不同的服务选择规则,比如轮询,随机,权重等等

 

  2.实现了服务实例清单在运行期的动态更新能力。同时它还具备了对服务实例清单的过滤功能:我们可以通过过滤器来选择性地获取一批服务实例清单。它定义了两个抽象方法:getInitialListOfServers用于获取初始化的服务实例清单, 而getUpdatedListOfServers用于获取更新的服务实例清单。

  在客户端负载均衡中,所有客户端节点都维护着自己要访问的服务端清单,而这些服务端的清单来自于服务注册中心,如上一章我们介绍的Eureka服务端。在客户端负载均衡中也需要心跳去维护服务端清单的健康性,只是这个步骤需要与服务注册中心配合完成。

  当Ribbon与Eureka联合使用时,Ribbon的服务实例清单RibbonServerList会被DiscoveryEnabledNIWSServerList重写,扩展成从Eureka注册中心中获取服务端列表。目的是为了对服务清单进行负载均衡需要的封装处理。利用Eureka的事件监听器来驱动服务列表的更新操作。它先创建了一个Runnable的线程实现,在该实现中调用了更新服务实例列表的方法, 最后再为这个Runnable线程实现启动了一个定时任务(默认30秒)来执行。

  简而言之ZoneAwareLoadBalancer的职责就是获取到服务清单,让IRole以某种规则选取!

 

  到这里我们就可以先整理下一个简单的负载均衡的流程:

  负载均衡流程&#xff1a;当一个被&#64;LoadBalanced注解修饰的RestTemplate对象向外发起HTTP请求时&#xff0c;会被LoadBalancerinterceptor类的intercept函数所拦截。由于我们在使用RestTemplate时采用了服务名作为host&#xff0c;所以直接从 HttpRequest的URI对象中通过 getHost()就可以拿到服务名&#xff0c;然后调用RibbonLoadBalancerClient类的execute函数&#xff0c;函数中ZoneAwareLoadBalancer的 chooseServer函数通过某种规则获取了负载均衡策略分配到的服务实例对象Server&#xff08;实质此任务委托给IRule的实现类RoundRobinRule<默认轮询>实例中的choose函数来实现&#xff09;&#xff0c;再将获取服务将其内容包装成RibbonServer对象&#xff0c;然后使用该对象再回调 LoadBalancerinterceptor请求拦截器中LoadBalancerRequest的apply(final ServiceInstance instance) 函数&#xff0c;向一个实际的具体服务实例发起请求&#xff0c;因为服务实例有ip,端口等元数据&#xff0c;从而实现一开始以服务名为host的URI请求到 host:post形式的实际访问地址的转换。

 

四.IRule负载均衡策略

   我们已经知道了IRule的实现类即是负载均衡规则&#xff0c;通过注入不同实现类来设定不同的选取策略。我们来看看它的一些常用实现类。

  1. RandomRule&#xff1a;该策略实现了从服务实例清单中随机选择一个服务实例的功能。具体是通过rand.nextint(serverCount&#xff09;函数来获取一个最大为服务数量的随机Int变量&#xff0c;在服务列表通过索引值来返回具体实例。

 

  2. RoundRobinRule&#xff1a;该策略实现了按照线性轮询的方式依次选择每个服务实例的功能。循环条件内&#xff0c;为服务增加了一个count计数变量&#xff0c;该变量会在每次循环之后累加&#xff08;线性轮询的实现则是通过Atomicinteger nextServerCyclicCounter对象实现&#xff0c;每次进行实例选择时通过调用 incrementAndGetModulo函数实现递增&#xff09;。

 

  3. RetryRule&#xff1a;该策略实现了一个具备重试机制的实例选择功能。默认使用了 RoundRobinRule实例。而在choose方法中则实现了对内部定义的策略进行反复尝试的策略&#xff0c;若期间能够选择到具体的服务实例就返回&#xff0c;若一段时间&#xff08;可设置&#xff09;选择不到就根据设置的尝试结束返回 null。

 

  4. WeightedResponseTimeRule&#xff1a;该策略是对RoundRobinRule 的扩展&#xff0c;增加了根据实例的运行情况来计算权重&#xff0c;并根据权重来挑选实例&#xff0c;以达到更优的分配效果。会创建定时任务&#xff08;默认30秒&#xff09;用来为每个服务实例计算权重。权重机制其实是为每个服务生成权重区间&#xff0c;比如根据响应时间为三个服务生成了权重区间&#xff1a;实例A: [0, 100]   实例B: ( 100,150]   实例C: (150,300&#xff09; &#xff08;权重计算这里不做描述&#xff09;。然后会生成一个[0, 最大权重值&#xff09;区间内的随机数。查看随机数在那个区间&#xff0c;就拿到某个服务实例

 

  5. BestAvailableRule&#xff1a;该策略在实现中它注入了负载同时在具体的 choose 算法中利用保存的实例统计信息来选择满足要求的实例。通过遍历负载均衡器中维护的所有服务实例&#xff0c;会过滤掉故障的实例&#xff0c;并找出并发请求数最小的一个&#xff0c;所以该策略的特性是可选出最空闲的实例。

 

  6. PredicateBasedRule&#xff1a;这是一个基于 Predicate 实现的策略&#xff0c; Predicate是对集合进行过滤的条件接口。在choose函数中&#xff0c;先通过子类中实现的 Predicate 逻辑来过滤一部分服务实例&#xff0c;然后再以线性轮询的方式从过滤后的实例清单中选出一个。

 

  之前已经知道负载均衡流程&#xff0c;本节也介绍了常用的负载均衡策略&#xff0c;Spring Cloud负载均衡已经有了一定了解。本文也省略了一些内容比如过滤器工作机制&#xff0c;组装host:port的URI,如何封装负载均衡所需的服务清单等等&#xff0c;有机会的话我会单独介绍下&#xff01;

  


 

本文链接&#xff1a;《Spring Cloud》学习&#xff08;二&#xff09; 负载均衡&#xff01;
转载声明&#xff1a;本博客由静影残月创作。可自由转载、引用&#xff0c;但需署名作者且注明文章出处。

转:https://www.cnblogs.com/crazycheng/p/10826294.html



推荐阅读
  • http:my.oschina.netleejun2005blog136820刚看到群里又有同学在说HTTP协议下的Get请求参数长度是有大小限制的,最大不能超过XX ... [详细]
  • Spring源码解密之默认标签的解析方式分析
    本文分析了Spring源码解密中默认标签的解析方式。通过对命名空间的判断,区分默认命名空间和自定义命名空间,并采用不同的解析方式。其中,bean标签的解析最为复杂和重要。 ... [详细]
  • 在重复造轮子的情况下用ProxyServlet反向代理来减少工作量
    像不少公司内部不同团队都会自己研发自己工具产品,当各个产品逐渐成熟,到达了一定的发展瓶颈,同时每个产品都有着自己的入口,用户 ... [详细]
  • 本文介绍了在Linux下安装和配置Kafka的方法,包括安装JDK、下载和解压Kafka、配置Kafka的参数,以及配置Kafka的日志目录、服务器IP和日志存放路径等。同时还提供了单机配置部署的方法和zookeeper地址和端口的配置。通过实操成功的案例,帮助读者快速完成Kafka的安装和配置。 ... [详细]
  • 本文介绍了Python爬虫技术基础篇面向对象高级编程(中)中的多重继承概念。通过继承,子类可以扩展父类的功能。文章以动物类层次的设计为例,讨论了按照不同分类方式设计类层次的复杂性和多重继承的优势。最后给出了哺乳动物和鸟类的设计示例,以及能跑、能飞、宠物类和非宠物类的增加对类数量的影响。 ... [详细]
  • 负载均衡_Nginx反向代理动静分离负载均衡及rewrite隐藏路径详解(Nginx Apache MySQL Redis)–第二部分
    nginx反向代理、动静分离、负载均衡及rewrite隐藏路径详解 ... [详细]
  • Nginx使用(server参数配置)
    本文介绍了Nginx的使用,重点讲解了server参数配置,包括端口号、主机名、根目录等内容。同时,还介绍了Nginx的反向代理功能。 ... [详细]
  • 本文介绍了Redis的基础数据结构string的应用场景,并以面试的形式进行问答讲解,帮助读者更好地理解和应用Redis。同时,描述了一位面试者的心理状态和面试官的行为。 ... [详细]
  • 本文详细介绍了PHP中与URL处理相关的三个函数:http_build_query、parse_str和查询字符串的解析。通过示例和语法说明,讲解了这些函数的使用方法和作用,帮助读者更好地理解和应用。 ... [详细]
  • 本文介绍了通过ABAP开发往外网发邮件的需求,并提供了配置和代码整理的资料。其中包括了配置SAP邮件服务器的步骤和ABAP写发送邮件代码的过程。通过RZ10配置参数和icm/server_port_1的设定,可以实现向Sap User和外部邮件发送邮件的功能。希望对需要的开发人员有帮助。摘要长度:184字。 ... [详细]
  • 自动轮播,反转播放的ViewPagerAdapter的使用方法和效果展示
    本文介绍了如何使用自动轮播、反转播放的ViewPagerAdapter,并展示了其效果。该ViewPagerAdapter支持无限循环、触摸暂停、切换缩放等功能。同时提供了使用GIF.gif的示例和github地址。通过LoopFragmentPagerAdapter类的getActualCount、getActualItem和getActualPagerTitle方法可以实现自定义的循环效果和标题展示。 ... [详细]
  • 本文介绍了在使用Python中的aiohttp模块模拟服务器时出现的连接失败问题,并提供了相应的解决方法。文章中详细说明了出错的代码以及相关的软件版本和环境信息,同时也提到了相关的警告信息和函数的替代方案。通过阅读本文,读者可以了解到如何解决Python连接服务器失败的问题,并对aiohttp模块有更深入的了解。 ... [详细]
  • 31.项目部署
    目录1一些概念1.1项目部署1.2WSGI1.3uWSGI1.4Nginx2安装环境与迁移项目2.1项目内容2.2项目配置2.2.1DEBUG2.2.2STAT ... [详细]
  • 本文介绍了一个适用于PHP应用快速接入TRX和TRC20数字资产的开发包,该开发包支持使用自有Tron区块链节点的应用场景,也支持基于Tron官方公共API服务的轻量级部署场景。提供的功能包括生成地址、验证地址、查询余额、交易转账、查询最新区块和查询交易信息等。详细信息可参考tron-php的Github地址:https://github.com/Fenguoz/tron-php。 ... [详细]
  • LVS实现负载均衡的原理LVS负载均衡负载均衡集群是LoadBalance集群。是一种将网络上的访问流量分布于各个节点,以降低服务器压力,更好的向客户端 ... [详细]
author-avatar
郑云雪
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有