当前位置: 首页 > news >正文

负载均衡器:Ribbon和LoadBalance

一、负载均衡介绍

1、什么是负载均衡?

     阿里云对负载均衡的定义:

     负载均衡是一种对流量进行按需分发的服务,通过将流量分发到不同的后端服务器来扩展应

     用系统的吞吐能力,并且可以消除系统中的单点故障,提升应用系统的可用性。

2、负载均衡的2种方式

     负载均衡一般分:服务端负载均衡 和 客户端负载均衡

2.1、服务端负载均衡

      传统的方式前端发送请求会到我们的的nginx上去,nginx作为反向代理,然后路由给后端的

      服务器,由于负载均衡算法是nginx提供的,而nginx是部署到服务器端的,所以这种方式又

      被称为服务器端负载均衡。如下图所示:

             

2.2、客户端负载均衡

       假如现在有三个用户中心实例,订单中心可以通过discoveryClient 获取到用户中心的实例信

       息,如果我们在订单中心写一个负载均衡  的规则计算请求那个实例,交给restTemplate进行

       请求,这样也可以实现负载均衡,这个算法里面,负载均衡是由订单中心提供的,而订单中

       心相对于用户中心是一个客户端,所以这种方式又称为客户端负负载均衡。如下图所示:

               

          在订单中心(服务调用方)编写负载均衡方法如下:

 /*** DiscoveryClient 是 nacos 提供的类,通过该类可以获取Nacos注册中心的服务列表*/@Autowiredprivate DiscoveryClient discoveryClient;@GetMapping("/order/create")public String createOrder(Integer productId,Integer userId){/*** 准备:向nacos 注册多个(这里启动3个)名称为 shop-stock 的服务** todo : 2种负载均衡的方式*    1)通过类 DiscoveryClient 获取Nacos 服务注册中心种服务名称为 shop-stock 的服务列表,*          然后通过随机数或轮询的方式 获取服务**/List<ServiceInstance> instances =  discoveryClient.getInstances("shop-stock");//获取目标服务地址List<String> targetUrl = instances.stream().map(instance -> instance.getUri().toString()+"/stock/reduce/").collect(Collectors.toList());//随机获取服务int index = ThreadLocalRandom.current().nextInt(targetUrl.size());String target = targetUrl.get(index);//调用目标服务String result2 = restTemplate.getForObject(target + productId, String.class);return "sucess";}

二、Ribbon

1、Ribbon是什么?

     Ribbon是Netflix开源的客户端侧负载均衡器;更加直观说就是ribbon就是简化上边方法createOrder中的这段代码的小组件,不过他比我们的代码要强大一些,他给他们提供了丰富

的负载均衡算法;如下图所示:

        

     

2、Ribbon 重要接口及内置的负载均衡策略

2.1、Ribbon 重要的接口

接口作用默认值
IClientConfig读取配置DefaultclientConfigImpl
IRule负载均衡规则,选择实例ZoneAvoidanceRule
IPing筛选掉ping不通的实例默认采用DummyPing实现,该检查策略是一个特殊的实现,<br />实际上它并不会检查实例是否可用,而是始终返回true,默认认为所<br />有服务实例都是可用的.
ServerList<Server>交给Ribbon的实例列表Ribbon: ConfigurationBasedServerList<br /> Spring Cloud Alibaba: NacosServerList
ServerListFilter过滤掉不符合条件的实例ZonePreferenceServerListFilter
ILoadBalancerRibbon的入口ZoneAwareLoadBalancer
ServerListUpdater更新交给Ribbon的List的策略PollingServerListUpdater

2.2、Ribbon内置的负载均衡策略

规则名称特点
RandomRule随机选择一个Server
RetryRule对选定的负责均衡策略机上充值机制,在一个配置时间段内当选择Server不成功,则一直尝试使用subRule的方式选择一个可用的Server
RoundRobinRule轮询选择,轮询index,选择index对应位置Server
WeightedResponseTimeRule根据相应时间加权,相应时间越长,权重越小,被选中的可能性越低
ZoneAvoidanceRule(默认是这个)该策略能够在多区域环境下选出最佳区域的实例进行访问。在没有Zone的环境下,类似于轮询(RoundRobinRule)

3、Ribbon 使用步骤

      前期准备:启动3个shop-stock 服务和一个shop-order服务,在shop-order 中引入Ribbon

      远程调用shop-stock

3.1、引入 netflix ribbon 依赖

          注意:若你的项目中已经引入了 alibaba nacos discovery ,就没必要再引入 netflix ribbon

          ,因为 alibaba nacos discovery 中包含了  netflix ribbon;如下图所示:

                    

         netflix ribbon 依赖如下所示:

<!--spring-cloud-starter-netflix-ribbon -->
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-ribbon</artifactId><version>2.2.10.RELEASE</version>
</dependency>

2、配置Ribbon负载均衡策略(重点)

     Ribbon 负载均衡策略的配置方式有2种,分别是:类配置 和 配置文件配置

     注意:这一步不是必须项,若没有配置Ribbon的负载均衡策略,Ribbon 则使用默认的负载均

                衡策略。

                java 类配置的优先级要高于配置文件配置

2.1、使用配置类的方式配置

         使用配置类的方式配置Ribbon 负载均衡策略分为2步,分别是:编写注入Ribbon负载均衡

          配置类 和 为Ribbon指定负载均衡策略,下边详细看下这2个步骤;

2.1.1、编写注入Ribbon负载均衡

            编写配置类RibbonConfig 来注入 Ribbon 负载均衡策略;

            有一点要注意,即类 RibbonConfig上并没有添加注解 @Configuration,主要原因有2个,

            即:

                  1)若 RibbonConfig 上加了注解 @Configuration,这种方式配置全局的负载均衡策略

                        有bug,不支持使用;推荐使用注解@RibbonClients 来配置全局的负载均衡策略

                  2)若 RibbonConfig 上加了注解 @Configuration,该负载均衡策略就成了全局负载均

                        衡策略,粒度太大。

            RibbonConfig 示例代码如下:

/***************************************************** Ribbon 配置类,用于配置Ribbon 相关信息,如:负载均衡策略** todo 注意:*    Ribbon 配置类 上并没有添加注解 @Configuration,因为我想只在远程调用 shop-stock 模块时使用RibbonConfig*    中配置的负载均衡策略;*    若 RibbonConfig 上加了注解 @Configuration,该类中的负载均衡策略就变成了全局的负载均衡策略,*     shop-order调用任何模块都会使用该类中的负载均衡策略。*     注意:这种方式配置全局的负载均衡策略有bug,不支持使用;推荐使用注解@RibbonClients 来配置全局的负载均衡策略**** @author * @date 2025/6/13 9:15****************************************************/
public class RibbonConfig {/*** 采用类配置Ribbon负载均衡策略* 向spring 种注入指定的 Ribbon 负载均衡实例,哪个Ribbon负载均衡策略被实例化了,RPC远程调用时就用* 哪个负载均衡策略;即通过配置类手动指定Ribbon的负载均衡策略**/@Beanpublic IRule ribbonRule(){//指定Ribbon的负载均衡策略为随机return new RandomRule();}
}

2.1.2、为Ribbon指定负载均衡策略

            Ribbon 提供了注解 @RibbonClient和@RibbonClients 来选择负载均衡策略;

             @RibbonClient 可以用来为某个服务指定Ribbon的负载均衡策略(如:shop-stock),

            粒度比较细,@RibbonClients 是用来为当前客户端段服务配置全局的Ribbon负载均衡

            策略,@RibbonClient和@RibbonClients 需要标注在 @Configuration 配置类上

           示例代码如下:

/***************************************************** 配置类,不编写什么内容,用于指定调用目标服务(如:shop-stack)时所采用的负载均衡策略** @author * @date 2025/6/13 9:55****************************************************//*** 注解 @RibbonClient 用于指定当前服务(如:shop-order)以哪个负载均衡策略调用目标服务(如:shop-stack)*/
//@RibbonClient(name = "shop-stack",configuration = RibbonConfig.class)
/*** 注解 @RibbonClients 用于全局的配置Ribbon负载均衡策略,通过 RestTemplate 远程调用每个服务* 时,负载均衡策略都是 RibbonConfig 中配置的策略**/
@RibbonClients(defaultConfiguration = RibbonConfig.class)
@Configuration
public class StockRibbonConfig {
}

2.2、使用配置文件的方式配置Ribbon负载均衡策略

         配置文件内容如下:

    

   

3、开启远程调用的负载均衡

      在实例化远程调用工具(如:RestTemplate)的Bean 上加上注解 @LoadBalanced 来开启

      远程调用的负载均衡(即整合 Ribbon),示例代码如下:

@LoadBalanced@Beanpublic RestTemplate restTemplate(){RestTemplate restTemplate = new RestTemplate();return restTemplate;}

   

4、在通过 RestTemplate 远程调用 shop-stock 服务时,就可以实现Ribbon的负载均衡了;

      示例代码如下:

@GetMapping("/order/create")public String createOrder(Integer productId,Integer userId){/*** 测试 RestTemplate 的负载均衡* 准备:向nacos 注册多个名称为 shop-stock 的服务** todo : 2种负载均衡的方式*    1)通过类 DiscoveryClient 获取Nacos 服务注册中心种服务名称为 shop-stock 的服务列表,*          然后通过随机数或轮询的方式 获取服务*    2)在配置类种注入 RestTemplate 时,加上注解 @LoadBalanced,即整合Ribbon,使用Ribbon的负载均衡来实现*          远程调用*//**//方式1:List<ServiceInstance> instances =  discoveryClient.getInstances("shop-stock");//获取目标服务地址List<String> targetUrl = instances.stream().map(instance -> instance.getUri().toString()+"/stock/reduce/").collect(Collectors.toList());//随机获取服务int index = ThreadLocalRandom.current().nextInt(targetUrl.size());String target = targetUrl.get(index);//调用目标服务String result2 = restTemplate.getForObject(target + productId, String.class);*///方式2:String result = restTemplate.getForObject("http://shop-stock/stock/reduce/" + productId, String.class);return "sucess";}

三、LoadBalancer

1、LoadBalancer 介绍

      Spring Cloud LoadBalancer是Spring Cloud官方自己提供的客户端负载均衡器,抽象和实现,

      用来替代Ribbon(已经停更)

2、LoadBalancer 与Ribbon 的对比

      LoadBalancer 与Ribbon 的对比列表如下:

组件组件提供的负载策略支持负载的客户端
Ribbon随机 RandomRule 轮询 RoundRobinRule 重试 RetryRule 最低并发 BestAvailableRule 可用过滤 AvailabilityFilteringRule 响应时间加权重 ResponseTimeWeightedRule 区域权重 ZoneAvoidanceRuleFeign或openfeign、RestTemplate
Spring Cloud LoadbalancerRandomLoadBalancer 随机(高版本有)RoundRobinLoadBalancer 轮询(默认)Feign或openfeign、RestTemplate、WebClient(WebFlux 异步)

3、整合 LoadBalancer

3.1、升级 Spring Cloud

         若你的Spring Cloud 是Hoxton之前的版本,最好升级到 Hoxton 之后的版本;

         因为如果是Hoxton之前的版本,默认负载均衡器为Ribbon,需要移除Ribbon引用和

         增加配置spring.cloud.loadbalancer.ribbon.enabled: false(不启用ribbon)

3.2、在 nacos discovery 依赖中排除 Ribbon 的依赖,并引入 LoadBalancer 依赖,如下图:

         

3.3、开启远程调用负载均衡

         在实例化远程调用工具(如:RestTemplate)的Bean 上加上注解 @LoadBalanced 来

         开启远程调用的负载均衡(即整合 LoadBalancer);

         可选配置:

         跟Ribbon 一样,LoadBalancer也提供了注解 @LoadBalancerClient 和

         @LoadBalancerClients 用于显式的指定 LoadBalancer的负载均衡策略;

         @LoadBalancerClient 和 @LoadBalancerClients 需要标注在 @Configuration

         配置类上,

        如下所示:

/***************************************************** 配置类,注入 RestTemplate* @author lbf* @date 2025/6/13 15:30****************************************************//*** 配置使用 loadbalancer 负载均衡器,* 局部的负载均衡器,使用name指定目标服务,configuration 指定调用目标服务所使用的负载均衡器,如:shop-stock*/
@LoadBalancerClient(name = "shop-stock",configuration = LoadBalancerClientConfiguration.class)
/*** 使用注解 @LoadBalancerClients 配置全局的负载均衡器,表示在当前服务中远程调用任何目标服务,所使用的* 负载均衡器都是 CustomRandomLoadBalancerClient*/
//@LoadBalancerClients(defaultConfiguration = LoadBalancerClientConfiguration.class)
@Configuration
public class RestTemplateConfig {/**** 注解 @LoadBalanced 开启远程调用的负载均衡*/@LoadBalanced@Beanpublic RestTemplate restTemplate(){return new RestTemplate();}
}

3.4、在通过 RestTemplate 远程调用 shop-stock 服务时,就可以实现LoadBalancer的负载均衡了

        如下图所示:

            

4、自定义 LoadBalancer 负载均衡策略

      LoadBalancer 中 自定义负载均衡策略需要通过注解 @LoadBalancerClient 或

      @LoadBalancerClients 来显式的指定才能生效。

      示例代码如下:

            

/***************************************************** 自定义随机选择的负载均衡器* 自定义负载均衡器用法:*     1)实现接口 ReactorServiceInstanceLoadBalancer 自定义负载均衡器*     2)在@Configuration  配置类上使用注解** @author * @date 2025/6/13 15:49****************************************************/
public class CustomRandomLoadBalancerClient implements ReactorServiceInstanceLoadBalancer {// 服务列表private ObjectProvider<ServiceInstanceListSupplier> serviceInstanceListSupplierProvider;public CustomRandomLoadBalancerClient(ObjectProvider<ServiceInstanceListSupplier> serviceInstanceListSupplierProvider) {this.serviceInstanceListSupplierProvider = serviceInstanceListSupplierProvider;}@Overridepublic Mono<Response<ServiceInstance>> choose(Request request) {ServiceInstanceListSupplier supplier = serviceInstanceListSupplierProvider.getIfAvailable();return supplier.get().next().map(this::getInstanceResponse);}/*** 使用随机数获取服务** @param instances  服务列表* @return*/private Response<ServiceInstance> getInstanceResponse(List<ServiceInstance> instances) {System.out.println("进来了");if (instances.isEmpty()) {return new EmptyResponse();}System.out.println("进行随机选取服务");// 随机算法int size = instances.size();Random random = new Random();ServiceInstance instance = instances.get(random.nextInt(size));return new DefaultResponse(instance);}
}/***************************************************** 配置类,注入 RestTemplate* @author * @date 2025/6/13 15:30****************************************************//*** 配置使用 loadbalancer 负载均衡器,* 局部的负载均衡器,使用name指定目标服务,configuration 指定调用目标服务所使用的负载均衡器,如:shop-stock*/
@LoadBalancerClient(name = "shop-stock",configuration = CustomRandomLoadBalancerClient.class)
/*** 使用注解 @LoadBalancerClients 配置全局的负载均衡器,表示在当前服务中远程调用任何目标服务,所使用的* 负载均衡器都是 CustomRandomLoadBalancerClient*/
//@LoadBalancerClients(defaultConfiguration = CustomRandomLoadBalancerClient.class)
/*** 表示在当前服务中,远程调用服务 shop-stock 使用的负载均衡器是 CustomRandomLoadBalancerClient,* 调用其他服务使用的负载均衡器是 LoadBalancerClientConfiguration*/
/**
@LoadBalancerClients(value = {@LoadBalancerClient(name = "shop-stock",configuration = CustomRandomLoadBalancerClient.class)},defaultConfiguration = LoadBalancerClientConfiguration.class)*/
@Configuration
public class RestTemplateConfig {/**** 注解 @LoadBalanced 开启远程调用的负载均衡*/@LoadBalanced@Beanpublic RestTemplate restTemplate(){return new RestTemplate();}
}

5、LoadBalancer 的重试机制配置

      具体配置如下:

spring:cloud:loadbalancer:#以下配置为LoadBalancerProperties 配置类clients:#default 表示去全局配置,如要针对某个服务,则填写毒地应的服务名称即可default:retry:enbled: true#是否所有的的请求都重试,false表示只有GET请求才重试retryOnAllOperation: true#同一个实例的重试次数,不包括第一次调用:比如第填写3 ,实际会调用4次maxRetriesOnSameServiceInstance: 3#其他实例的重试次数,多节点情况下使用maxRetriesOnNextServiceInstance: 0

相关文章:

  • thinkphp8提升之查询
  • 深度解析JavaScript闭包:从原理到高级应用
  • 物理“硬核”切换镜头!Pura 80 Ultra一镜双目镜头切换的仪式感
  • Veeam Backup Replication系统的安装与使用
  • 低温对FPGA的核心影响
  • 温度对IO通信的影响
  • LCEL:LangChain 表达式语言详解与测试工程师的实践指南
  • 【unitrix】 1.7 规范化常量类型结构(standardization.rs)
  • java面试总结-20250609
  • python+django/flask+uniapp宠物中心信息管理系统app
  • JAVA理论第十八章-JWT杂七杂八
  • 写作词汇积累(A):颇有微词、微妙(“微”字的学习理解)
  • 大小端的区别
  • 【DSP笔记 · 第5章】数字滤波器的蓝图:从数学公式到硬件实现的艺术
  • 时间序列数据库技术深度解析:核心原理与最佳实践
  • FWFW - Find Websites From World
  • GeoTools:gt-referencing模块
  • MVVM框架:让前端开发像搭积木一样简单!
  • 山东大学软件学院项目实训:基于大模型的模拟面试系统项目总结(九)
  • wifi架构
  • 房产网站建设/运营商推广5g技术
  • 免费开放的api网站应用/营销网站建设多少钱
  • 大连在哪里/乐云seo
  • 小城市做网站/爱站网长尾关键词挖掘工具的作用
  • wordpress免登录评论/整站外包优化公司
  • 网站建设销售兼职合同/随州今日头条新闻