五、负载均衡服务调用Ribbon

男娘i 2023-05-22 06:32 115阅读 0赞

文章目录

  • 一、Ribbon 介绍
    • 1.1 负载均衡策略介绍
    • 1.2 Ribbon 简介
    • 1.3 Ribbon 架构
  • 二、Ribbon 的使用
  • 三、Ribbon 核心组件 IRule
    • 3.1 Ribbon 负载均衡规则介绍
    • 3.2 更改默认的负载均衡规则
    • 3.3 自定义负载均衡规则

一、Ribbon 介绍

1.1 负载均衡策略介绍

① 集中式LB

即在服务的消费方和提供方之间使用的独立的LB设施(可以是硬件,如F5,也可以是软件,如nginx),由该设施负责把访问请求通过某种策略转发至服务的提供方;

② 进程内LB

LB逻辑继承到消费方,消费者从服务注册中心获知哪些地址可用,然后自己再从这些地址中选择出一个合适的服务器。Ribbon就属于进程内LB,它只是一个类库,集成与消费方进程,消费方通过它获取服务提供方的地址

1.2 Ribbon 简介

Spring Cloud Ribbon是基于Netlix Ribbon实现的一套客户端负载均衡的工具。简单的说,RibbonNetflix发布的开源项目,主要功能是提供客户端的软件负载均衡算法和服务调用。Ribbon客户端组件提供一 系列完善的配置项如连接超时,重试等。简单的说,就是在配置文件中列出Load Balancer(简称LB)后面所有的机器,Ribbon会自动的帮助你基于某种规则(如简单轮询,随机连接等)去连接这些机器。我们很容易使用Ribbon实现自定义的负载均衡算法。

不过Ribbon已经进入了维护模式,NetFlix给出的新的负载均衡方案:Spring Cloud Starter Loadbalancer,但还并不完善。

1.3 Ribbon 架构

Ribbon架构

Ribbon在工作时分为两步:

  1. 选择EurekaServer,它优先选择在同一个区域内负载较少的Server
  2. 根据用户指定的策略,在从Server取到的服务注册列表中选择一个地址

其中Ribbon提供多种策略:比如轮询、随机、和根据响应时间加权。

Ribbon其实就是一个软负载均衡的客户端组件,他可以和其他所需请求的客户端结合使用,和Eureka结合只是其中的一个实例。

二、Ribbon 的使用

eureka-client组件中本身封装了ribbon组件,无需再添加
Eureka客户端中已经包含了Ribbon
注入RestTemplate组件:

  1. @Configuration
  2. public class ApplicationContextConfig {
  3. @Bean
  4. @LoadBalanced
  5. public RestTemplate getRestTemplate(){
  6. return new RestTemplate();
  7. }
  8. }

使用RestTemplate调用远程服务:

  1. @Slf4j
  2. @RequestMapping("/order")
  3. @RestController
  4. public class OrderController {
  5. public static final String PAYMENT_URL = "http://CLOUD-PAYMENT-SERVICE";
  6. @Autowired
  7. private RestTemplate restTemplate;
  8. @GetMapping("/{id}")
  9. public CommonResult get(@PathVariable Long id){
  10. log.info("-----远程调用支付服务中-----");
  11. return restTemplate.getForObject(uri+"/payment/"+id,CommonResult.class);
  12. }
  13. }

xxxForObject()xxxForEntity()的区别:

  • xxxForObject()返回对象为响应体中数据转化成的对象,基本上可以理解为Json
  • xxxForEntity()返回对象为ResponseEntity对象, 包含了响应中的一 些重要信息,比如响应头、响应状态码、响应体等
    getForEntity方法

注意:使用Rebbon时,服务提供端的接口参数为实体类时,需要加上注解@RequestBody,因为RestTemplate调用传来的参数为json格式,不加上强转不了。

三、Ribbon 核心组件 IRule

3.1 Ribbon 负载均衡规则介绍






































Ribbon负载均衡算法 功能
com.netflix.loadbalancer.RoundRobinRule 轮询,默认
com.netflix.loadbalancer.RandomRule 随机
com.netflix.loadbalancer.RetryRule 先按照RoundRobinRule的策略获取服务,如果获取服务失败则再指定时间内重试,获取可用服务
WeightResponseTimeRule 对RoundRobinRule的扩展,响应速度越快的实例选择权重越大
BestAvailableRule 会先过滤掉由于多次访问故障而处于断路器跳闸状态的服务,然后选择一个并发量最小的服务
AvailabilityFilterRule 先过滤掉故障实例,再选择并发较小的实例
ZoneAvoidanceRule 默认规则,复合判断server所在区域的性能和server的可用性选择服务器

3.2 更改默认的负载均衡规则

  1. @Configuration
  2. public class MySelfRule {
  3. @Bean
  4. public IRule myRule(){
  5. return new RandomRule();
  6. }
  7. }

主启动类添加注解:

@RibbonClient(name = "CLOUD-PAYMENT-SERVICE",configuration = MySelfRule.class)

注意:这个自定义配置类不能放在@ComponentScan所扫描的当前包下以及子包下。否则我们自定义的这个配置类就会被所有的Ribbon客户端所共享,达不到特殊化定制的目的了,所以这个类最好别放到主启动类下

3.3 自定义负载均衡规则

① 注入RestTemplate代码中删除@LoadBalanced,这样就不会使用默认的算法了。

② 创建LoadBalancer接口

  1. public interface LoadBalancer {
  2. /** * * 从多个服务实例中选择一个服务实例 */
  3. ServiceInstance instance(List<ServiceInstance> instances);
  4. }

③ 实现该接口

实现原理:[ rest接口第几次请求数 % 服务器集群总数量 = 实际调用服务器位置下标 ],每次服务 重启动后rest接口计数从1开始。

  1. @Slf4j
  2. @Component
  3. public class MyLoadBalance implements LoadBalancer {
  4. private AtomicInteger visitCount = new AtomicInteger(0);
  5. @Override
  6. public ServiceInstance instance(List<ServiceInstance> instances) {
  7. int index = getVisitCount()%instances.size();
  8. return instances.get(index);
  9. }
  10. public final int getVisitCount() {
  11. int current = 0;
  12. int next = 0;
  13. do {
  14. current = this.visitCount.get();
  15. next = current >= 2147483647 ? 0 : current + 1;
  16. } while (!this.visitCount.compareAndSet(current, next));
  17. log.info("-----第" + next + "访问-----");
  18. return next;
  19. }
  20. }

乐观锁CAS的介绍:https://blog.csdn.net/qq\_35571554/article/details/82892806

④ 调用

  1. @Slf4j
  2. @RequestMapping("/order")
  3. @RestController
  4. public class OrderController {
  5. @Autowired
  6. private RestTemplate restTemplate;
  7. @Autowired
  8. private DiscoveryClient discoveryClient;
  9. @Autowired
  10. LoadBalancer loadBalancer;
  11. @GetMapping("/{id}")
  12. public CommonResult get(@PathVariable Long id){
  13. List<ServiceInstance> instances = discoveryClient.getInstances("CLOUD-PAYMENT-SERVICE");
  14. if (instances ==null &&instances.size()<0){
  15. return new CommonResult(200,"",null);
  16. }
  17. ServiceInstance instance = loadBalancer.instance(instances);
  18. URI uri = instance.getUri();
  19. log.info("-----远程调用支付服务中-----");
  20. return restTemplate.getForObject(uri+"/payment/"+id,CommonResult.class);
  21. }
  22. }

发表评论

表情:
评论列表 (有 0 条评论,115人围观)

还没有评论,来说两句吧...

相关阅读