我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Spring Cloud负载均衡组件Ribbon原理是什么

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Spring Cloud负载均衡组件Ribbon原理是什么

这篇文章主要介绍“Spring Cloud负载均衡组件Ribbon原理是什么”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Spring Cloud负载均衡组件Ribbon原理是什么”文章能帮助大家解决问题。

    微服务体系下的 Spring Cloud Netflix 套件中 Ribbon 的主要用于负载均衡,底层默认使用 RestTemplate 通讯,并提供了 7 种负载均衡策略

    前言

    在微服务中,对服务进行拆分之后,必然会带来微服务之间的通信需求,而每个微服务为了保证高可用性,又会去部署集群,那么面对一个集群微服务进行通信的时候,如何进行负载均衡也是必然需要考虑的问题。那么有需求自然就有供给,由此一大批优秀的开源的负载均衡组件应运而生,本文就让我们一起来分析一下 Spring Cloud Netflix 套件中的负载均衡组件 Ribbon

    一个问题引发的思考

    首先我们来看一个问题,假如说我们现在有两个微服务,一个 user-center,一个 user-order,我现在需要在 user-center 服务中调用 user-order 服务的一个接口。

    这时候我们可以使用 HttpClientRestTemplate 等发起 http 请求,user-center 服务端口为 8001,如下图所示:

    @RestController@RequestMapping(value = "/user")public class UserController {    @Autowired    private RestTemplate restTemplate;    @Bean    public RestTemplate restTemplate(){        return new RestTemplate();    }    @GetMapping("/order")    public String queryOrder(){        return restTemplate.getForObject("http://localhost:8002/order/query",String.class);    }}

    user-order 服务中只是简单的定义了一个接口,user-order 服务端口为 8002

    @RestController@RequestMapping(value = "/order")public class UserOrderController {    @GetMapping(value = "/query")    public String queryAllOrder(){        return "all orders";    }}

    这时候只需要将两个服务启动,访问 http://localhost:8001/user/order 就可以获取到所有的订单信息。

    可以看到,这样是可以在两个微服务之间进行通讯的,但是,假如说我们的 user-order 服务是一个集群呢?这时候怎么访问呢?因为 user-order 服务已经是集群,所以必然需要一种算法来决定应该请求到哪个 user-order 服务中,最简单的那么自然就是随机或者轮询机制,轮询或者随机其实就是简单的负载均衡算法,而 Ribbon 就是用来实现负载均衡的一个组件,其内部支持轮询,等算法。

    Ribbon的简单使用

    接下来我们看看 Ribbon 的简单使用。

    首先改造 user-order 服务,在 user-order 服务中定义一个服务名配置:

    spring.application.name=user-order-service

    user-order 服务中的 UserOrderController 稍微改造一下,新增一个端口的输出来区分:

    @RestController@RequestMapping(value = "/order")public class UserOrderController {    @Value("${server.port}")    private int serverPort;    @GetMapping(value = "/query")    public String queryAllOrder(){        return "订单来自:" + serverPort;    }}
    • 通过 VM 参数 -Dserver.port=8002-Dserver.port=8003 分别来启动两个 user-order 服务。

    • 接下来改造 user-center 服务,在 user-center 服务中引入 Ribbon 的相关依赖:

     <dependency>      <groupId>org.springframework.cloud</groupId>      <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>      <version>2.2.3.RELEASE</version>    </dependency>
    • user-center 服务中新增一个 Ribbon 相关配置,列举出需要访问的所有服务:

    user-order-service.ribbon.listOfServers=\  localhost:8002,localhost:8003
    • user-center 服务中的 UserController 进行改造:

    @RestController@RequestMapping(value = "/user")public class UserController {    @Autowired    private RestTemplate restTemplate;    @Autowired    private LoadBalancerClient loadBalancerClient;    @Bean    public RestTemplate restTemplate(){        return new RestTemplate();    }    @GetMapping("/order")    public String queryOrder(){        //获取一个 user-order 服务        ServiceInstance serviceInstance = loadBalancerClient.choose("user-order-service");        String url = String.format("http://%s:%s",serviceInstance.getHost(),serviceInstance.getPort()) + "/order/query";        return restTemplate.getForObject(url,String.class);    }}

    这时候我们再次访问 http://localhost:8001/user/order 就可以看到请求的 user-order 服务会在 80028003 之间进行切换。

    Ribbon 原理分析

    看了上面 Ribbon 的使用示例,会不会觉得有点麻烦,每次还需要自己去获取 ip 和端口,然后格式化 url,但是其实实际开发过程中我们并不会通过这么原始的方式来编写代码,接下来我们再对上面的示例进行一番改造:

    @RestController@RequestMapping(value = "/user")public class UserController3 {    @Autowired    private RestTemplate restTemplate;    @Bean    @LoadBalanced    public RestTemplate restTemplate(){        return new RestTemplate();    }    @GetMapping("/order")    public String queryOrder(){        return restTemplate.getForObject("http://user-order-service/order/query",String.class);    }}

    在这个示例中,主要就是一个关键主键起了作用:@LoadBalanced。

    @LoadBalanced 注解

    进入 @LoadBalanced 注解中,我们可以看到,这个注解其实没有任何逻辑,只是加了一个 @Qualifier 注解:

    Spring Cloud负载均衡组件Ribbon原理是什么

    这个注解大家应该很熟悉了,常用语同一个 Bean 有多个不同名称注入的场景。

    @Qualifier注解

    下面我们通过一个例子来演示一下 Qualifier注解的用法。

    新建一个空的 TestDemo 类,并新增一个 TestConfiguration 类来创建不同名称的 TestDemo

    @Configurationpublic class TestConfiguration {    @Bean("testDemo1")    public TestDemo testDemo(){        return new TestDemo();    }    @Bean("testDemo2")    public TestDemo testDemo2(){        return new TestDemo();    }}

    这时候我们如果需要注入 TestDemo,那么有很多种办法,具体的使用就需要看业务需要来决定。

    • 方法一:直接使用 @Autowired,并使用 List 集合来接收 Bean,这样所有 TestDemo 类型的 Bean 都会被注入。

    • 方法二:通过使用 @Resource(name = "testDemo1") 注解来指定名称,这样就可以只注入一个 Bean

    • 方法三:通过使用 @Resource@Qualifier(value = "testDemo1") 来指定一个 Bean,其实这种方式和方法二的效果基本一致。

    • 方法四:使用 @Autowired@Qualifier 注解来注入,不指定任何名称,如下所示:

    @Configurationpublic class TestConfiguration {    @Bean("testDemo1")    public TestDemo testDemo(){        return new TestDemo();    }    @Bean("testDemo2")    public TestDemo testDemo2(){        return new TestDemo();    }}

    这时候运行之后我们发现不会有任何 Bean 被注入到集合中,这是因为当使用这种方式来注入时,Spring 会认为当前只需要注入被 @Qualifier 注解标记的 Bean,而我们上面定义的两个 TestDemo 都没有被 @Qualifier 修饰。

    这时候,我们只需要在 TestConfiguration 稍微改造,在 TestDemo 的定义上加上 @Qualifier 修饰即可:

    @Configurationpublic class TestConfiguration {    @Bean("testDemo1")    @Qualifier    public TestDemo testDemo(){        return new TestDemo();    }    @Bean("testDemo2")    @Qualifier    public TestDemo testDemo2(){        return new TestDemo();    }}

    这时候再去运行,就会发现,testDemo1testDemo2 都会被注入。

    LoadBalancerAutoConfiguration 自动装配

    SpringCloud 是基于 SpringBoot 实现的,所以我们常用的这些分布式组件都会基于 SpringBoot 自动装配来实现,我们进入 LoadBalancerAutoConfiguration 自动装配类可以看到,RestTemplate 的注入加上了 @LoadBalanced,这就是为什么我们前面的例子中加上了 @LoadBalanced 就能被自动注入的原因:

    Spring Cloud负载均衡组件Ribbon原理是什么

    RestTemplateCustomizer

    上面我们看到,RestTemplate 被包装成为了 RestTemplateCustomizer,而 RestTemplateCustomizer 的注入如下:

    Spring Cloud负载均衡组件Ribbon原理是什么

    可以看到这里面加入了一个拦截器 LoadBalancerInterceptor,事实上即使不看这里,我们也可以猜测到,我们直接使用服务名就可以进行通讯的原因必然是底层有拦截器对其进行转换成 ip 形式,并在底层进行负载均衡选择合适的服务进行通讯。

    LoadBalancerInterceptor

    LoadBalancerInterceptorRibbon 中默认的一个拦截器,所以当我们调用 RestTemplategetObject 方法时,必然会调用拦截器中的方法。

    从源码中可以看到,LoadBalancerInterceptor 中只有一个 intercept() 方法:

    Spring Cloud负载均衡组件Ribbon原理是什么

    RibbonLoadBalancerClient#execute

    继续跟进 execute 方法会进入到 RibbonLoadBalancerClient 类(由 RibbonAutoConfiguration 自动装配类初始化)中:

    Spring Cloud负载均衡组件Ribbon原理是什么

    这个方法中也比较好理解,首先获取一个负载均衡器,然后再通过 getServer 方法获取一个指定的服务,也就是当我们有多个服务时,到这里就会选出一个服务进行通讯。

    进入 getServer 方法:

    Spring Cloud负载均衡组件Ribbon原理是什么

    我们看到,最终会调用 ILoadBalancer 中的 chooseServer 方法,而 ILoadBalancer 是一个顶层接口,这时候具体会调用哪个实现类那么就需要先来看一下类图:

    Spring Cloud负载均衡组件Ribbon原理是什么

    这里直接看类图也无法看出到底会调用哪一个,但是不论调用哪一个,我们猜测他肯定会有一个地方去初始化这个类,而在 Spring 当中一般就是自动装配类中初始化或者 Configuration 中初始化,而 ILoadBalancer 正是在 RibbonClientConfiguration 类中被加载的:

    Spring Cloud负载均衡组件Ribbon原理是什么

    ZoneAwareLoadBalancer 负载均衡器

    ZoneAwareLoadBalancer 的初始化会调用其父类 DynamicServerListLoadBalancer 进行初始化,然后会调用 restOfInit 方法进行所有服务的初始化。

    如何获取所有服务

    使用 Ribbon 后,我们通讯时并没有指定某一个 ip 和端口,而是通过服务名来调用服务,那么这个服务名就可能对应多个真正的服务,那么我们就必然需要先获取到所有服务的 ip 和端口等信息,然后才能进行负载均衡处理。

    获取所有服务有两种方式:

    • 从配置文件获取

    • Eureka 注册中心获取(需要引入注册中心)。

    初始化服务的方式是通过启动一个 Scheduled 定时任务来实现的,默认就是 30s 更新一次,其实在很多源码中都是通过这种方式来定时更新的,因为源码要考虑的使用的简单性所以不太可能引入一个第三方中间件来实现定时器。

    具体的源码如下所示:enableAndInitLearnNewServersFeature() 方法启动的定时任务最终仍然你是调用 updateListOfServers() 方法来更新服务。

    Spring Cloud负载均衡组件Ribbon原理是什么

    最终在获取到服务之后会调用父类 BaseLoadBalancer 中的将所有服务设置到 allServerList 集合中(BaseLoadBalancer 类中维护了一些负载均衡需要使用到的服务相关信息)。

    如何判断服务是否可用

    当我们获取到配置文件(或者 Eureka 注册中心)中的所有服务,那么这时候能直接执行负载均衡策略进行服务分发吗?显然是不能的,因为已经配置好的服务可能会宕机(下线),从而导致服务不可用,所以在 BaseLoadBalancer 中除了有一个 allServerList 集合来维护所有服务器,还有一个集合 upServerList 用来维护可用服务集合,那么如何判断一个服务是否可用呢?答案就是通过心跳检测来判断一个服务是否可用。

    心跳检测 Task

    在讲心跳检测之前,我们先看一下 BaseLoadBalancer 中的 setServersList 方法,有一段逻辑比较重要:

    Spring Cloud负载均衡组件Ribbon原理是什么

    Spring Cloud负载均衡组件Ribbon原理是什么

    这段逻辑我们看到,默认情况下,如果 Ping 的策略是 DummyPing,那么默认 upServerList = allServerList,而实际上,假如我们没有进行进行特殊配置,其实默认的就是 DummyPing,这也是在 RibbonClientConfiguration 类中被加载的:

    Spring Cloud负载均衡组件Ribbon原理是什么

    BaseLoadBalancer 初始化过程中,也会启动一个 Scheduled 定时任务去定时更新任务,最终和 forceQuickPing() 方法一样,调用一个默认策略来触发心跳检测,而默认策略就是 DummyPing,也就是默认所有服务都是可用的。

    Spring Cloud负载均衡组件Ribbon原理是什么

    虽然默认不执行真正的心跳检测操作,但是 Netflix 中提供了 PingUrl 等其他策略,PingUrl 其实就是发起一个 http 请求,如果有响应就认为服务可用,没响应就认为服务不可用。

    修改心跳检测策略可以通过如下配置切换(user-order-service 为客户端的服务名),既然是可配置的,那么也可以自己实现一个策略,只需要实现 IPing 接口即可。

    user-order-service.ribbon.NFLoadBalancerPingClassName=com.netflix.loadbalancer.PingUrl

    Ribbon 的负载均衡算法

    当获取到可用服务之后,那么最后应该选择哪一个服务呢?这就需要使用到负载均衡策略,在 Ribbon 中,可以通过配置修改,也可以自定义负载均衡策略(实现 IRule 接口)。

    • RandomRule:随机算法

    • RoundRobinRule:轮询算法

    • ZoneAvoidanceRule:结合分区统计信息筛选出合适的分区(默认的负载均衡算法)

    • RetryRule:在 deadline 时间内,如果请求不成功,则重新发起请求知道找到一个可用的服务。

    • WeightedResponseTimeRule:根据服务器的响应时间计算权重值,服务器响应时间越长,这个服务器的权重就越小,会有定时任务对权重值进行更新。

    • AvailabilityFilteringRule:过滤掉短路(连续 3 次连接失败)的服务和高并发的服务。

    • BestAvailableRule:选择并发数最低的服务器

    负载均衡算法可通过以下配置进行修改:

    user-order-service.ribbon.NFLoadBalancerRuleClassName=Rule规则的类名

    关于“Spring Cloud负载均衡组件Ribbon原理是什么”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识,可以关注编程网行业资讯频道,小编每天都会为大家更新不同的知识点。

    免责声明:

    ① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

    ② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

    Spring Cloud负载均衡组件Ribbon原理是什么

    下载Word文档到电脑,方便收藏和打印~

    下载Word文档

    猜你喜欢

    Spring Cloud负载均衡组件Ribbon原理是什么

    这篇文章主要介绍“Spring Cloud负载均衡组件Ribbon原理是什么”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Spring Cloud负载均衡组件Ribbon原理是什么”文章能帮助大家解
    2023-06-30

    ribbon负载均衡的原理是什么

    Ribbon负载均衡的原理是通过在客户端发起请求时选择合适的服务实例来实现负载均衡。Ribbon通过与服务注册中心进行通信获取服务实例列表,并利用一定的负载均衡算法(如轮询、随机、加权轮询等)来选择合适的服务实例进行请求转发。这样可以有效地
    ribbon负载均衡的原理是什么
    2024-04-09

    spring cloud集成ribbon负载均衡怎么实现

    这篇文章主要介绍“spring cloud集成ribbon负载均衡怎么实现”,在日常操作中,相信很多人在spring cloud集成ribbon负载均衡怎么实现问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”s
    2023-06-21

    ribbon负载均衡策略是什么

    Ribbon负载均衡策略是Netflix开源的一种用于负载均衡的策略。它是一个基于客户端的负载均衡器,主要用于在微服务架构中选择目标服务的实例。Ribbon的负载均衡策略包括以下几种:1. 随机策略(Random):随机选择一个可用的服务实
    2023-09-07

    Spring Cloud中的负载均衡策略是什么

    本篇内容介绍了“Spring Cloud中的负载均衡策略是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!IRule这是所有负载均衡策略的
    2023-06-19

    云负载均衡原理是什么

    云负载均衡原理是将来自客户端的请求分发到多个服务器上,以实现负载均衡和提高系统的可用性和性能。云负载均衡的原理主要包括以下几个方面:1. 请求分发:云负载均衡器接收到客户端的请求后,会根据一定的算法(例如轮询、最少连接数等)将请求分发给后端
    2023-09-01

    OSPF负载均衡原理是什么?

      OSPF负载均衡原理是什么?作为一名网络工程师,相信大家对OSPF一定不会陌生。同样的,负载均衡也是非常熟悉的概念。  OSPF和负载均衡简介  OSPF是Open Shortest Path First的首字母缩写,指的是开放式最短路径优先,它是一个内部网关协议,也就是我们常说的IGP,主要是用于在单一自治系统内
    OSPF负载均衡原理是什么?
    2024-04-18

    zookeeper负载均衡原理是什么

    Zookeeper是一个分布式协调服务,而不是负载均衡器。它的主要功能是提供分布式系统中的数据管理和协调服务。然而,Zookeeper可以被用于实现一些负载均衡机制。实现负载均衡的一种常见方式是使用Zookeeper作为服务注册和发现的中心
    2023-09-01

    SpringCloud Ribbon负载均衡使用策略是什么

    这篇“SpringCloud Ribbon负载均衡使用策略是什么”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“SpringC
    2023-07-05

    负载均衡技术原理是什么

    负载均衡技术的原理是将网络流量分配到多个服务器上,以实现更好的性能、可靠性和可扩展性。具体原理如下:1. 负载均衡器位于客户端和服务器之间,接收来自客户端的请求。2. 负载均衡器使用一定的算法来判断请求应该被分配到哪个服务器上处理。常见的算
    2023-09-07

    nginx负载均衡的原理是什么

    Nginx负载均衡的原理是将客户端的请求分发给多个后端服务器,以实现请求的平衡分配和提高系统的性能和可扩展性。具体而言,Nginx负载均衡的原理包括以下几个步骤:1. 客户端发起请求:客户端将请求发送给Nginx服务器。2. Nginx接收
    2023-09-02

    全局负载均衡原理是什么

    全局负载均衡是一种网络技术,用于将网络流量分散到多个服务器或网络节点上,以提高系统的性能和可靠性。其主要原理如下:1. DNS解析:当用户通过域名访问网站时,首先会进行DNS解析,将域名解析为服务器的IP地址。2. 请求分发:全局负载均衡器
    2023-09-07

    dubbo负载均衡轮询原理是什么

    Dubbo的负载均衡轮询原理是指当多个服务提供者同时存在时,将请求按照顺序依次分发给每个服务提供者,每个提供者处理完一个请求后再依次处理下一个请求,循环往复,直到所有请求都被处理完毕。具体的实现原理如下:1. Dubbo通过维护一个服务提供
    2023-10-09

    四层负载均衡的原理是什么

    四层负载均衡的原理是在传输层(第四层)工作,它通过检测和管理传入的请求流量,将请求分发到多个服务器,以实现负载均衡和高可用性。其基本原理包括以下几个步骤:1. 客户端发送请求:当客户端发送请求到负载均衡设备时,负载均衡设备会接收到这些请求。
    2023-09-07

    nginx负载均衡算法及原理是什么

    Nginx负载均衡算法及原理主要涉及以下几个方面:1. 轮询(Round Robin)算法:Nginx默认采用的是轮询算法,即将请求按顺序轮流分配给后端服务器。每个请求依次分配给不同的服务器,直到所有服务器都被分配了一次,然后重新循环分配。
    2023-10-08

    负载均衡slb的工作原理是什么

    负载均衡(SLB)是一种网络技术,通过将网络流量分发到多台服务器上,以达到提高性能、可靠性和可伸缩性的目的。其工作原理如下:客户端发起请求:客户端向负载均衡器发送请求,请求可以是HTTP、TCP或UDP等。负载均衡器接收请求:负载均衡器接收
    负载均衡slb的工作原理是什么
    2024-04-09

    dubbo负载均衡的实现原理是什么

    Dubbo负载均衡的实现原理是通过在服务提供方和消费方之间选择合适的调用方式和节点来实现负载均衡。具体原理如下:服务提供方:在Dubbo中,服务提供方会将自身的服务注册到注册中心,并提供给消费方可以调用的服务节点列表。Dubbo支持多种负载
    dubbo负载均衡的实现原理是什么
    2024-04-09

    负载均衡的原理及使用方法是什么

    负载均衡是一种用于分配网络请求负载的技术,它通过将网络请求分配给多个后端服务器来提高系统的性能、可靠性和可扩展性。负载均衡的原理是基于以下几个方面:1. 请求调度:负载均衡器接收到来自客户端的请求后,会根据一定的算法(如轮询、最小连接数、最
    2023-09-01

    编程热搜

    • Python 学习之路 - Python
      一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
      Python 学习之路 - Python
    • chatgpt的中文全称是什么
      chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
      chatgpt的中文全称是什么
    • C/C++中extern函数使用详解
    • C/C++可变参数的使用
      可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
      C/C++可变参数的使用
    • css样式文件该放在哪里
    • php中数组下标必须是连续的吗
    • Python 3 教程
      Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
      Python 3 教程
    • Python pip包管理
      一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
      Python pip包管理
    • ubuntu如何重新编译内核
    • 改善Java代码之慎用java动态编译

    目录