详解Spring Cloud负载均衡重要组件Ribbon中重要类的用法

Ribbon是Spring Cloud Netflix全家桶中负责负载均衡的组件,它是一组类库的集合。通过Ribbon,程序员能在不涉及到具体实现细节的基础上“透明”地用到负载均衡,而不必在项目里过多地编写实现负载均衡的代码。

比如,在某个包含Eureka和Ribbon的集群中,某个服务(可以理解成一个jar包)被部署在多台服务器上,当多个服务使用者同时调用该服务时,这些并发的请求能被用一种合理的策略转发到各台服务器上。

事实上,在使用Spring Cloud的其它各种组件时,我们都能看到Ribbon的痕迹,比如Eureka能和Ribbon整合,而在后文里将提到的提供网关功能Zuul组件在转发请求时,也可以整合Ribbon从而达到负载均衡的效果。

从代码层面来看,Ribbon有如下三个比较重要的接口。

第一,ILoadBalancer,这也叫负载均衡器,通过它,我们能在项目里根据特定的规则合理地转发请求,常见的实现类有BaseLoadBalancer。

第二,IRule,这个接口有多个实现类,比如RandomRule和RoundRobinRule,这些实现类具体地定义了诸如“随机“和”轮询“等的负载均衡策略,我们还能重写该接口里的方法来自定义负载均衡的策略。

在BaseLoadBalancer类里,我们能通过IRule的实现类设置负载均衡的策略,这样该负载均衡器就能据此合理地转发请求。

第三,IPing接口,通过该接口,我们能获取到当前哪些服务器是可用的,我们也能通过重写该接口里的方法来自定义判断服务器是否可用的规则。在BaseLoadBalancer类里,我们同样能通过IPing的实现类设置判断服务器是否可用的策略。

1 ILoadBalancer:负载均衡器接口

在Ribbon里,我们还可以通过ILOadBalancer这个接口以基于特定的负载均衡策略来选择服务器。

通过下面的ILoadBalancerDemo.java,我们来看下这个接口的基本用法。这个类是放在4.2部分创建的RabbionBasicDemo项目里,代码如下。

//省略必要的package和import代码
  public class ILoadBalancerDemo {
    public static void main(String[] args){
      //创建ILoadBalancer的对象
      ILoadBalancer loadBalancer = new BaseLoadBalancer();
      //定义一个服务器列表
       List<Server> myServers = new ArrayList<Server>();
      //创建两个Server对象
      Server s1 = new Server("ekserver1",8080);
      Server s2 = new Server("ekserver2",8080);
      //两个server对象放入List类型的myServers对象里
      myServers.add(s1);
      myServers.add(s2);
      //把myServers放入负载均衡器
      loadBalancer.addServers(myServers);
      //在for循环里发起10次调用
      for(int i=0;i<10;i++){
      //用基于默认的负载均衡规则获得Server类型的对象
        Server s = loadBalancer.chooseServer("default");
      //输出IP地址和端口号
        System.out.println(s.getHost() + ":" + s.getPort());
      }
   }
  }

在第5行里,我们创建了BaseLoadBalancer类型的loadBalancer对象,而BaseLoadBalancer是负载均衡器ILoadBalancer接口的实现类。

在第6到第13行里,我们创建了两个Server类型的对象,并把它们放入了myServers里,在第15行里,我们把List类型的myServers对象放入了负载均衡器里。

在第17到22行的for循环里,我们通过负载均衡器模拟了10次选择服务器的动作,具体而言,是在第19行里,通过loadBalancer的chooseServer方法以默认的负载均衡规则选择服务器,在第21行里,我们是用“打印”这个动作来模拟实际的“使用Server对象处理请求”的动作。

上述代码的运行结果如下所示,其中我们能看到,loadBalancer这个负载均衡器把10次请求均摊到了2台服务器上,从中确实能看到 “负载均衡”的效果。

第二,IRule,这个接口有多个实现类,比如RandomRule和RoundRobinRule,这些实现类具体地定义了诸如“随机“和”轮询“等的负载均衡策略,我们还能重写该接口里的方法来自定义负载均衡的策略。

在BaseLoadBalancer类里,我们能通过IRule的实现类设置负载均衡的策略,这样该负载均衡器就能据此合理地转发请求。

第三,IPing接口,通过该接口,我们能获取到当前哪些服务器是可用的,我们也能通过重写该接口里的方法来自定义判断服务器是否可用的规则。在BaseLoadBalancer类里,我们同样能通过IPing的实现类设置判断服务器是否可用的策略。

ekserver2:8080
  ekserver1:8080
  ekserver2:8080
  ekserver1:8080
  ekserver2:8080
  ekserver1:8080
  ekserver2:8080
  ekserver1:8080
  ekserver2:8080
 ekserver1:8080

2 IRule:定义负载均衡规则的接口

在Ribbon里,我们可以通过定义IRule接口的实现类来给负载均衡器设置相应的规则。在下表里,我们能看到IRule接口的一些常用的实现类。


实现类的名字


负载均衡的规则


RandomRule


采用随机选择的策略


RoundRobinRule


采用轮询策略


RetryRule


采用该策略时,会包含重试动作


AvailabilityFilterRule


会过滤些多次连接失败和请求并发数过高的服务器


WeightedResponseTimeRule


根据平均响应时间为每个服务器设置一个权重,根据该权重值优先选择平均响应时间较小的服务器


ZoneAvoidanceRule


优先把请求分配到和该请求具有相同区域(Zone)的服务器上

在下面的IRuleDemo.java的程序里,我们来看下IRule的基本用法。

 //省略必要的package和import代码
  public class IRuleDemo {
    public static void main(String[] args){
    //请注意这是用到的是BaseLoadBalancer,而不是ILoadBalancer接口
    BaseLoadBalancer loadBalancer = new BaseLoadBalancer();
      //声明基于轮询的负载均衡策略
      IRule rule = new RoundRobinRule();
    //在负载均衡器里设置策略
      loadBalancer.setRule(rule);
      //如下定义3个Server,并把它们放入List类型的集合中
      List<Server> myServers = new ArrayList<Server>();
      Server s1 = new Server("ekserver1",8080);
      Server s2 = new Server("ekserver2",8080);
      Server s3 = new Server("ekserver3",8080);
      myServers.add(s1);
      myServers.add(s2);
      myServers.add(s3);
      //在负载均衡器里设置服务器的List
      loadBalancer.addServers(myServers);
      //输出负载均衡的结果
      for(int i=0;i<10;i++){
        Server s = loadBalancer.chooseServer(null);
        System.out.println(s.getHost() + ":" + s.getPort());
     }
    }
  }

这段代码和上文里的ILoadBalancerDemo.java很相似,但有如下的差别点。

1 在第5行里,我们是通过BaseLoadBalancer这个类而不是接口来定义负载均衡器,原因是该类包含setRule方法。

2 在第7行定义了一个基于轮询规则的rule对象,并在第9行里把它设置进负载均衡器。

3 在第19行里,我们是把包含3个Server的List对象放入负载均衡器,而不是之前的两个。由于这里存粹是为了演示效果,所以我们就放入一个根本不存在的“ekserver3”服务器。

运行该程序后,我们可以看到有10次输出,而且确实是按“轮询”的规则有顺序地输出3个服务器的名字。如果我们把第7行的代码改成如下,那么就会看到 “随机”地输出服务器名。

IRule rule = new RandomRule();  

3  IPing:判断服务器是否可用的接口

在项目里,我们一般会让ILoadBalancer接口自动地判断服务器是否可用(这些业务都封装在Ribbon的底层代码里),此外,我们还可以用Ribbon组件里的IPing接口来实现这个功能。

在下面的IRuleDemo.java代码里,我们将演示IPing接口的一般用法。

//省略必要的package和import代码
  class MyPing implements IPing {
    public boolean isAlive(Server server) {
      //如果服务器名是ekserver2,则返回false
      if (server.getHost().equals("ekserver2")) {
        return false;
      }
      return true;
    }
  }

第2行定义的MyPing类实现了IPing接口,并在第3行重写了其中的isAlive方法。

在这个方法里,我们根据服务器名来判断,具体而言,如果名字是ekserver2,则返回false,表示该服务器不可用,否则返回true,表示当前服务器可用。

public class IRuleDemo {
    public static void main(String[] args) {
      BaseLoadBalancer loadBalancer = new BaseLoadBalancer();
      //定义IPing类型的myPing对象
      IPing myPing = new MyPing();
      //在负载均衡器里使用myPing对象
      loadBalancer.setPing(myPing);
      //同样是创建三个Server对象并放入负载均衡器
      List<Server> myServers = new ArrayList<Server>();
      Server s1 = new Server("ekserver1", 8080);
      Server s2 = new Server("ekserver2", 8080);
      Server s3 = new Server("ekserver3", 8080);
      myServers.add(s1);
      myServers.add(s2);
      myServers.add(s3);
      loadBalancer.addServers(myServers);
      //通过for循环多次请求服务器
      for (int i = 0; i < 10; i++) {
        Server s = loadBalancer.chooseServer(null);
        System.out.println(s.getHost() + ":" + s.getPort());
      }
    }
  }

在第12行的main函数里,我们在第15行创建了IPing类型的myPing对象,并在第17行把这个对象放入了负载均衡器。通过第18到第26行的代码,我们创建了三个服务器,并把它们也放入负载均衡器。

在第28行的for循环里,我们依然是请求并输出服务器名。由于这里的负载均衡器loadBalancer中包含了一个IPing类型的对象,所以在根据策略得到服务器后,会根据myPing里的isActive方法来判断该服务器是否可用。

由于在这个方法里,我们定义了ekServer2这台服务器不可用,所以负载均衡器loadBalancer对象始终不会把请求发送到该服务器上,也就是说,在输出结果中,我们不会看到“ekserver2:8080”的输出。

从中我们能看到IPing接口的一般用法,我们可以通过重写其中的isAlive方法来定义“判断服务器是否可用“的逻辑,在实际项目里,判断的依据无非是”服务器响应是否时间过长“或”发往该服务器的请求数是否过多“,而这些判断方法都封装在IRule接口以及它的实现类里,所以在一般的场景中我们用到IPing接口。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • spring cloud 之 客户端负载均衡Ribbon深入理解

    一.负载均衡 负载均衡(Load Balance): 建立在现有网络结构之上,它提供了一种廉价有效透明的方法扩展网络设备和服务器的带宽.增加吞吐量.加强网络数据处理能力.提高网络的灵活性和可用性.其意思就是分摊到多个操作单元上进行执行,例如Web服务器.FTP服务器.企业关键应用服务器和其它关键任务服务器等,从而共同完成工作任务. 1.服务端负载均衡:客户端请求到负载均衡服务器,负载均衡服务器根据自身的算法将该请求转给某台真正提供业务的服务器,该服务器将响应数据给负载均衡服务器,负载均衡服务器最

  • SpringCloud Ribbon 负载均衡的实现

    前言 Ribbon是一个客户端负载均衡器,它提供了对HTTP和TCP客户端的行为的大量控制.我们在上篇(猛戳:SpringCloud系列--Feign 服务调用)已经实现了多个服务之间的Feign调用,服务消费者调用服务提供者,本文记录Feign调用Ribbon负载均衡的服务提供者 GitHub地址:https://github.com/Netflix/ribbon 官方文档:https://cloud.spring.io/spring-cloud-static/spring-cloud-net

  • 详解spring cloud中使用Ribbon实现客户端的软负载均衡

    开篇 本例是在springboot整合H2内存数据库,实现单元测试与数据库无关性和使用RestTemplate消费spring boot的Restful服务两个示例的基础上改造而来 在使用RestTemplate来消费spring boot的Restful服务示例中,我们提到,调用spring boot服务的时候,需要将服务的URL写死或者是写在配置文件中,但这两种方式,无论哪一种,一旦ip地址发生了变化,都需要改动程序,并重新部署服务,使用Ribbon的时候,可以有效的避免这个问题. 前言:

  • Spring Cloud 负载均衡器 Ribbon原理及实现

    Ribbon简介 分布式系统中,各个微服务会部署多个实例,如何将服务消费者均匀分摊到多个服务提供者实例上,就要使用到负载均衡器 Ribbon 是负载均衡器 ,它提供了很多负载均衡算法,例如轮询.随即等,在配置服务提供者地址后,可以将服务消费者请求均匀的分发 为服务消费者整合Ribbon 添加 Ribbon 依赖库 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spri

  • SpringCloud客户端的负载均衡Ribbon的实现

    前言:微服务架构,不可避免的存在单个微服务有多个实例,那么客户端如何将请求分摊到多个微服务的实例上呢?这里我们就需要使用负载均衡了 一.Ribbon简介 Ribbon是Netflix发布的负载均衡器,它有助于控制HTTP和TCP客户端的行为.为Ribbon配置服务提供者地址列表后,Ribbon就可基于某种负载均衡算法,自动地帮助服务消费者去请求.Ribbon默认为我们提供了很多的负载均衡算法,例如:轮询,随机等,也可自定义: Ribbon的GitHub: https://github.com/N

  • 详解SpringCloud Ribbon 负载均衡通过服务器名无法连接的神坑

    一,问题 采取eureka集群.客户端通过Ribbon调用服务,Ribbon端报下列异常 java.net.UnknownHostException: SERVICE-HI java.lang.IllegalStateException: No instances available for SERVICE-HI java.lang.IllegalStateException: Request URI does not contain a valid hostname: http://SERVI

  • SpringCloud Ribbon负载均衡实例解析

    这篇文章主要介绍了SpringCloud Ribbon负载均衡实例解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 Spring Cloud集成了Ribbon,结合Eureka,可实现客户端的负载均衡. 下面实现一个例子,结构下图所示. 一.服务器端 1.创建项目 开发工具:IntelliJ IDEA 2019.2.3 IDEA中创建一个新的SpringBoot项目,名称为"cloud-server",SpringBoot版本选择2

  • 详解Spring Cloud负载均衡重要组件Ribbon中重要类的用法

    Ribbon是Spring Cloud Netflix全家桶中负责负载均衡的组件,它是一组类库的集合.通过Ribbon,程序员能在不涉及到具体实现细节的基础上"透明"地用到负载均衡,而不必在项目里过多地编写实现负载均衡的代码. 比如,在某个包含Eureka和Ribbon的集群中,某个服务(可以理解成一个jar包)被部署在多台服务器上,当多个服务使用者同时调用该服务时,这些并发的请求能被用一种合理的策略转发到各台服务器上. 事实上,在使用Spring Cloud的其它各种组件时,我们都能

  • Spring Cloud负载均衡组件Ribbon原理解析

    目录 前言 一个问题引发的思考 Ribbon的简单使用 Ribbon 原理分析 LoadBalancerAutoConfiguration 自动装配 RestTemplateCustomizer LoadBalancerInterceptor RibbonLoadBalancerClient#execute ZoneAwareLoadBalancer 负载均衡器 如何获取所有服务 如何判断服务是否可用 Ribbon 的负载均衡算法 总结 微服务体系下的 Spring Cloud Netflix

  • 详解spring cloud构建微服务架构的网关(API GateWay)

    前言 在我们前面的博客中讲到,当服务A需要调用服务B的时候,只需要从Eureka中获取B服务的注册实例,然后使用Feign来调用B的服务,使用Ribbon来实现负载均衡,但是,当我们同时向客户端暴漏多个服务的时候,客户端怎么调用我们暴漏的服务了,如果我们还想加入安全认证,权限控制,过滤器以及动态路由等特性了,那么就需要使用Zuul来实现API GateWay了,下面,我们先来看下Zuul怎么使用. 一.加入Zuul的依赖 <dependency> <groupId>org.spri

  • 详解spring cloud使用Hystrix实现单个方法的fallback

    本文介绍了spring cloud-使用Hystrix实现单个方法的fallback,分享给大家,具体如下: 一.加入Hystrix依赖 <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-hystrix</artifactId> </dependency> 二.编写Controller package c

  • 详解Spring Cloud 跨服务数据聚合框架

    AG-Merge Spring Cloud 跨服务数据聚合框架 解决问题 解决Spring Cloud服务拆分后分页数据的属性或单个对象的属性拆分之痛, 支持对静态数据属性(数据字典).动态主键数据进行自动注入和转化, 其中聚合的静态数据会进行 一级混存 (guava). 举个栗子: 两个服务,A服务的某张表用到了B服务的某张表的值,我们在对A服务那张表查询的时候,把B服务某张表的值聚合在A服务的那次查询过程中 示例 具体示例代码可以看 ace-merge-demo 模块 |------- ac

  • 详解spring cloud整合Swagger2构建RESTful服务的APIs

    前言 在前面的博客中,我们将服务注册到了Eureka上,可以从Eureka的UI界面中,看到有哪些服务已经注册到了Eureka Server上,但是,如果我们想查看当前服务提供了哪些RESTful接口方法的话,就无从获取了,传统的方法是梳理一篇服务的接口文档来供开发人员之间来进行交流,这种情况下,很多时候,会造成文档和代码的不一致性,比如说代码改了,但是接口文档没有改等问题,而Swagger2则给我们提供了一套完美的解决方案,下面,我们来看看Swagger2是如何来解决问题的. 一.引入Swag

  • 详解SpringCloud的负载均衡

    目录 一.什么是负载均衡 二.负载均衡的简单分类 三.为什么需要做负载均衡 四.springCloud如何开启负载均衡 五.IRule 1.RandomRule:表示随机策略,它将从服务清单中随机选择一个服务: 2.ClientConfigEnabledRoundRobinRule:ClientConfigEnabledRoundRobinRule并没有实现什么特殊的处理逻辑,但是他的子类可以实现一些高级策略, 当一些本身的策略无法实现某些需求的时候,它也可以做为父类帮助实现某些策略,一般情况下

  • 详解spring cloud config实现datasource的热部署

    关于spring cloud config的基本使用,前面的博客中已经说过了,如果不了解的话,请先看以前的博客 spring cloud config整合gitlab搭建分布式的配置中心 spring cloud config分布式配置中心的高可用 今天,我们的重点是如何实现数据源的热部署. 1.在客户端配置数据源 @RefreshScope @Configuration// 配置数据源 public class DataSourceConfigure { @Bean @RefreshScope

  • 详解spring cloud config整合gitlab搭建分布式的配置中心

    在前面的博客中,我们都是将配置文件放在各自的服务中,但是这样做有一个缺点,一旦配置修改了,那么我们就必须停机,然后修改配置文件后再进行上线,服务少的话,这样做还无可厚非,但是如果是成百上千的服务了,这个时候,就需要用到分布式的配置管理了.而spring cloud config正是用来解决这个问题而生的.下面就结合gitlab来实现分布式配置中心的搭建.spring cloud config配置中心由server端和client端组成, 前提:在gitlab中的工程下新建一个配置文件config

  • 详解Spring Cloud Feign 熔断配置的一些小坑

    1.在使用feign做服务调用时,使用继承的方式调用服务,加入Hystrix的熔断处理fallback配置时,会报错,已解决. 2.使用feign默认配置,熔断不生效,已解决. 最近在做微服务的学习,发现在使用feign做服务调用时,使用继承的方式调用服务,加入Hystrix的熔断处理fallback配置时,会报错,代码如下: @RequestMapping("/demo/api") public interface HelloApi { @GetMapping("user/

随机推荐