第五章 Ribbon负载均衡服务调用

Ribbon负载均衡服务调用

1. Ribbon概述

Spring Cloud Ribbon是一个基于HTTP和TCP的客户端负载均衡工具,它基于Netflix Ribbon实现。通过Spring Cloud的封装,可以让我们轻松地将面向服务的REST模版请求自动转换成客户端负载均衡的服务调用。Spring Cloud Ribbon虽然只是一个工具类框架,它不像服务注册中心、配置中心、API网关那样需要独立部署,但是它几乎存在于每一个Spring Cloud构建的微服务和基础设施中。因为微服务间的调用,API网关的请求转发等内容,实际上都是通过Ribbon来实现的,包括后续我们将要介绍的Feign,它也是基于Ribbon实现的工具。所以,对Spring Cloud Ribbon的理解和使用,对于我们使用Spring Cloud来构建微服务非常重要。

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

官网:Getting Started · Netflix/ribbon Wiki · GitHub Ribbon进入维护期,未来方案是spring cloud load balancer

负载均衡

  1. LB负载均衡(Load Balance)是什么 简单的说就是将用户的请求平摊的分配到多个服务上,从而达到系统的HA(高可用)。常见的负载均衡有软件Nginx,LVS,硬件F5等。

  2. Ribboh本地负载均衡客户端VS Nginx服务端负载均衡区别 Nginx是服务器负载均衡,客户端所有请求都会交给nginx,然后由nginx实现转发请求。即负载均衡是由服务端实现的。 Ribbon本地负载均衡,在调用微服务接口时候,会在注册中心上获取注册信息服务列表之后缓存到VM本地,从而在本地实现RPC远程服务调用技术。

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

Ribbon在工作时分成两步(ribbon就是负载均衡+RestTemplate) 第一步先选择EurekaServer ,它优先选择在同一个区域内负载较少的server。 第二步再根据用户指定的策略,在从server取到的服务注册列表中选择一个地址。其中Ribbon提供了多种策略:比如轮询、随机和根据响应时间加权。

eureka的jar包自带ribbon:(插件Maven Helper可以查询使用)

2. RestTemplate

官网:https:/doc.spring.io/spring-framework/docs/5.2.2.RELEASE/javadoc-api/org/springframework/web/client/RestTemplate.html

常用方法:

  1. getForObject方法/getForEntity方法

  2. postForObject/postForEntity

object基本返回对象是json,entity是一个返回对象体,有状态码等等信息。

操作cloud-consumer-order80项目修改controller层:

java 复制代码
@GetMapping("/consumer/payment/getForEntity/{id}")
    public CommonResult<Payment> getPayment2(@PathVariable("id") Long id){
        ResponseEntity<CommonResult> entity=restTemplate.getForEntity(PAYMENT_URL+"/payment/get/"+id,CommonResult.class);
        if(entity.getStatusCode().is2xxSuccessful()){
            return entity.getBody();
        }else{
            return new CommonResult<>(444,"操作失败");
        }
    }

测试:

3. Ribbon核心组件IRule

lRule:根据特定算法中从服务列表中选取一个要访问的服务

ctrl+N:(IDEA常用的搜索快捷键_idea搜索快捷键-CSDN博客

Ribbon负载均衡策略

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

Ribbon负载均衡策略替换

策略替换:官方文档明确给出了警告--->这个自定义配置类不能放在@ComponentScan所扫描的当前包下以及子包下,否则我们自定义的这个配置类就会被所有的Ribbon客户端所共享,达不到特殊化定制的目的了。

  1. 修改cloud-consumer-order80项目

  2. 新建myrule.MySelfRule

java 复制代码
@Configuration
public class MySelfRule {
    
    @Bean
    public IRule myRule(){
        return new RandomRule();
    }
}
  1. 主启动类
java 复制代码
@SpringBootApplication
@EnableEurekaClient
@RibbonClient(name = "CLOUD-PAYMENT-SERVICE",configuration = MySelfRule.class)
public class OrderMain80 {
    public static void main(String[] args) {
        SpringApplication.run(OrderMain80.class,args);
    }
}

@RibbonClient(name = "CLOUD-PAYMENT-SERVICE",configuration = MySelfRule.class),不用默认的轮询,使用替换的负载均衡算法。

测试:


4. Ribbon负载均衡算法

Ribbon默认负载轮训算法原理

复制代码
负载均衡算法: rest接口第几次请求数%服务器集群总数量=实际调用服务器位置下标,每次服务重启动后rest接口计数从1开始。
List<ServiceInstance> instances = discoveryClient.getInstances("CLOUD-PAYMENT-SERVICE");
如:
List [0] instances = 127.0.0.1:8002
List [1] instances = 127.0.0.1:8001
8001 + 8002组合成为集群,它们共计2台机器,集群总数为2,按照轮询算法原理:
当总请求数为1时:1%2=1对应下标位置为1,则获得服务地址为127.0.0.1:8001当总请求数位2时:2%2=0对应下标位置为0,则获得服务地址为127.0.0.1:8002当总请求数位3时:3%2=1对应下标位置为1,则获得服务地址为127.0.0.1:8001当总请求数位4时:4%2=O对应下标位置为0,则获得服务地址为127.0.0.1:8002如此类推.....

第几次请求除以总的集群服务的数量取余,余数就是那个服务作为提供者,这样实现了轮询。

RoundRobinRule源码分析

查看RoundRobbinRule源代码主要从IClientConfigAware、IRule、AbtstractLoadBalancerRule、RoundRobinRule、RanomRule、RetryRule、BestAvailableRule、AvailabilityFilteringRule、WeightedResponseTimeRulezi

自定义负载均衡算法

修改cloud-provider-payment8001和cloud-provider-payment8002项目:

java 复制代码
@GetMapping(value = "/payment/lb")
    public String getPaymentLB(){
        return serverPort;
    }

修改cloud-consumer-order80项目:

config包下面的注释@LoadBalancer

java 复制代码
@Configuration
public class ApplicationContextConfig {
​
    @Bean
//    @LoadBalanced   //使用自己定义的负载均衡算法
    public RestTemplate getRestTemplate(){
        return new RestTemplate();
    }
​
}

新建一个接口LoadBalancer和MyLB类:

java 复制代码
@Component
public class MyLB implements LoadBalancer{
​
    private AtomicInteger atomicInteger=new AtomicInteger(0);//原子类
​
    public final int getAndIncrement(){
        int current;
        int next;
        do{
            current=this.atomicInteger.get();
            next=current>=2147483647?0:current+1; //2147483647 int最大值,防止next溢出
        }while (!this.atomicInteger.compareAndSet(current,next));
        System.out.println("********次数next:"+next);
        return next;
    }
    @Override
    public ServiceInstance instance(List<ServiceInstance> serviceInstances) {
        int index = getAndIncrement()%serviceInstances.size();
        return serviceInstances.get(index);
    }
}

contrller层:

java 复制代码
@Resource
    private LoadBalancer loadBalancer;
    @Resource
    private DiscoveryClient discoveryClient;
​
    @GetMapping(value = "/consumer/payment/lb")
    public String getPaymentLB(){
        List<ServiceInstance> instances=discoveryClient.getInstances("CLOUD-PAYMENT-SERVICE");
        if(instances == null || instances.size() <= 0){
            return null;
        }
        ServiceInstance serviceInstance=loadBalancer.instance(instances);
        URI uri = serviceInstance.getUri();
        return restTemplate.getForObject(uri+"/payment/lb",String.class);
    }

测试:

相关推荐
半旧夜夏9 小时前
【保姆级】微服务组件环境搭建(Docker Compose版)
java·linux·spring cloud·微服务·云原生·容器
阿狸猿13 小时前
论系统负载均衡设计方法
运维·负载均衡
phltxy15 小时前
RabbitMQ集群运维:仲裁队列与负载均衡
运维·rabbitmq·负载均衡
Devin~Y16 小时前
从内容社区到AIGC客服:Spring Boot、Redis、Kafka、K8s、RAG的三轮大厂Java面试对话(附标准答案)
java·spring boot·redis·spring cloud·kafka·kubernetes·micrometer
西凉的悲伤17 小时前
Spring Boot 、Spring Cloud 微服务架构认证授权方案
spring boot·spring cloud·微服务·架构·认证授权
phltxy2 天前
HAProxy安装与RabbitMQ负载均衡配置
分布式·rabbitmq·负载均衡
西凉的悲伤2 天前
Spring Cloud Gateway介绍
java·spring cloud·gateway
JAVA社区2 天前
Java高级全套教程(十)—— SpringCloudAlibaba超详细实战详解
java·开发语言·spring cloud·面试·职场和发展
JAVA社区3 天前
Java高级全套教程(九)—— SpringCloud超详细实战详解
java·开发语言·后端·spring cloud·面试·职场和发展