zoukankan      html  css  js  c++  java
  • Spring Cloud之Ribbon负载均衡(Spring Cloud 2020.0.3版)

    Spring Cloud Ribbon

    demo代码放在github上 ,需要的请点这里--> demo

    1. Ribbon简介

    一般来说,在生产环境中,各个微服务都会部署多个实例。那么消费者要如何将请求分摊到多个服务提供者实例上呢?负载均衡在系统架构中一个非常重要,不得不去实施的内容,负载均衡是对系统的高可用、网络压力的缓解和处理能力扩容的重要手段之一。通常所说的负载均衡都是指服务端负载均衡,其中分为硬件负载均衡(如F5)和软件负载均衡(如Nginx)。Ribbon是NetFlix发布的客户端负载均衡器,它有助于控制Http和Tcp客户端的行为。通过SpringCloud的封装,可以让我们轻松的将面向服务的REST模板请求自动转换成客户端负载均衡的服务调用。Spring Cloud Ribbon虽然只是一个工具类框架,它不像服务注册中心、配置中心、API网关那样需要独立部署,但是它几乎存在于每一个SpringCloud构建的微服务和基础设施中。

    客户端负载均衡和服务端负载均衡的区别?

    TODO: 最大的区别就是服务清单存储的位置,

    • 服务端负载均衡

    image-20210517151757123

    2. Ribbon的使用

    1. 通过Spring Cloud Ribbon的封装,在微服务架构中使用客户端负载均衡调用非常简单,只需要如下两步:

      • 服务提供者只需要启动多个服务实例并注册到服务注册中心

      • 服务消费者直接通过调用被@LoadBalanced注解修饰过的RestTemplate来实现面向服务的接口调用

    2. 具体布步骤如下:

      1. 在服务消费者微服务的POM文件中添加ribbon的依赖

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

        在spring cloud Eureka依赖中已经包含了spring cloud ribbon,因此无需再次引入。如过已经添加了的spring cloud Eureka依赖,不要添加该依赖,否则会遇到空指针错误。

      2. 服务提供者微服务中给RestTemplate添加@LoadBalanced注解

        @Bean
            @LoadBalanced
            public RestTemplate restTemplate()
            {
                return new RestTemplate();
            }

        image-20210517160434607

      3. 对服务消费者的controller代码进行修改

         @Autowired
            private RestTemplate restTemplate;
        ​
            @Autowired
            private LoadBalancerClient loadBalancerClient;
        ​
            @GetMapping("/user/{id}")
            public User findById(@PathVariable long id)
            {
                //hardCode硬编码方式不可取
               //return restTemplate.getForObject("http://localhost:8000/" + id,User.class);
        //修改成通过微服务的虚拟主机名来访问
                return restTemplate.getForObject("http://userservice/"+id,User.class);
            }
        ​
            @GetMapping("/log-user-instance")
            public void logUserInstances()
            {
                ServiceInstance serviceInstance = loadBalancerClient.choose("userservice");
                log.info("serviceId-->{},Host-->{},port-->{}",serviceInstance.getServiceId(),serviceInstance.getHost(),serviceInstance.getPort());
            }

        新增加了一个API接口,服务消费者访问该接口时打印出IP地址和端口号

        image-20210517160749653

      4. 现在分别启动1个服务注册中和2个服务提供者、1个服务消费者

        • 服务注册中心

          image-20210517161222111

           

        • 服务提供者

          image-20210517161324308

          这里提供一下如何在idea中如何启动两个不同端口号的服务提供者的实例

          • 在服务提供者的配置文件中已经配置了server.port=8000,因此第一个实例直接点击运行就可以咯

            image-20210517162309499

          • 选择Idea右上角启动按钮边上的Edit Configurations,在打开的对话框中,选择UserServiceApplication-->点击复制按钮->VM Options中增加-Dserver.port=8001,Apply应用,如图:

            image-20210517162438058

            最后点击运行就可以运行port=8001的实例咯

        • 服务消费者

          启动服务消费者,然后不断的访问API接口地址http://localhost:8081/log-user-instance,发现交替打印服务消费者的ip地址。

          image-20210517163043521

    搭建过程中遇到的问题:

    添加该依赖后,运行时报空指针错误,去掉该依赖后能正常访问。image-20210517175714002

    报错信息如下:

    image-20210517175601096

    出现该问题的根本原因是Spring Cloud 2020.0.0版本以后对Spring Cloud NetFlix 组件进行剔除,仅保留了Eureka组件,其核心组件 Hystrix、Ribbon、Zuul、Archaius 等均进入维护状态


    旧版本的spring-cloud-netflix-dependencies管理着Netflix所有组件,包括Hystrix、Ribbon、Zuul、Eureka等。而自2020.0版本起,它有且只管理Eureka(包括Server和Client)
    其中Feign虽然最初属Netflix公司,但从9.x版本开始就移交给OpenFeign组织管理了,因此不再划入Netflix管辖范畴。

    简单一句话概括:Spring Cloud 2020.0.0版本彻底删除掉了Netflix除Eureka外的所有组件

    image-20210518111000347

    Spring Cloud 既然把 Netflix 套件大刀阔斧的砍掉了,那总归得有替代方案吧。那是必然的,Spring Cloud 团队给我们推荐了用于替代的组件:

    image-20210518110911185

    image-20210518112004676

    Spring Cloud LoadBalancer 目前仅支持轮询负载均衡策略,相对于 Ribbon 多种高可用策略还是过于简单。

    3. Ribbon负载均衡策略

    很多场景下,可能根据需要自定义Ribbon的配置,例如修改Ribbon的负载均衡规则等。

    方法一和二适合于Spring Cloud 2020.0.0版本之前的版本,方法三适合Spring Cloud 2020.0.0版之后的Spring Cloud版本

    方法一:配置文件的方式

    在application.propertites文件中添加如下代码:

    #更改负载均衡的负载策略
    userservice.ribbon.NFLoadBalancerRuleClassName=com.netflix.loadbalancer.RandomRule

    image-20210517223443589

    方法二:使用Java代码自定义Ribbon配置

    使用Ribbon提供的负载均衡策略很简单

    • 创建具有负载均衡功能的RestTemplate实例

      @Bean
      @LoadBalanced
      RestTemplate restTemplate() {
          return new RestTemplate();
      }

      使用RestTemplate进行rest操作的时候,会自动使用负载均衡策略,它内部会在RestTemplate中加入LoadBalancerInterceptor这个拦截器,这个拦截器的作用就是使用负载均衡。

    • 默认情况下会采用轮询策略,如果希望采用其它策略,则指定IRule实现,如:

      @Bean
      public IRule ribbonRule() {
          return new BestAvailableRule();
      }

    方法三:负载均衡策略配置(适用于Spring Cloud 2020.0.0版之后的版本

    spring cloud加入了一个新模块Spring-Loadbalancer来替代ribbon,有两种负载均衡模式(轮询和随机),默认是用轮询,假如想使用随机或者自定义负载均衡策略,就不能按照以前使用ribbon的模式(注入IRule类,必须引入ribbon依赖),那么如果我使用Loadbalancer的随机负载均衡,要怎么设置呢?官网给出比较详细的方法

    显然官方写了一个切换成随机负载均衡的例子,我们拷贝过来即可。

    image-20210518112950963

    @Bean
            ReactorLoadBalancer<ServiceInstance> randomLoadBalancer(Environment environment,
                                                                    LoadBalancerClientFactory loadBalancerClientFactory) {
                String name = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME);
                return new RandomLoadBalancer(loadBalancerClientFactory
                        .getLazyProvider(name, ServiceInstanceListSupplier.class),
                        name);
    ​
    • 搭建步骤

      1. 把官方的@Bean方法拷贝到自己的配置类(这个类可以放到主启动类所在包及子包下,这一点和Ribbon不同

        image-20210518114000731

      2. 在启动类,使用@LoadBalancerClient或者@LoadBalancerClients注解,加载自己的配置类,由此切换loadBalancer默认的负载均衡策略

        image-20210518114034152

      3. 然后运行代码发现就切换成随机负载均衡策略咯

    image-20210518113209128

    4. Ribbon自定义负载均衡策略

    可以参考这篇博客: https://blog.csdn.net/qq_35799668/article/details/114534023

     

     

     

  • 相关阅读:
    【leetcode】Binary Search Tree Iterator
    【leetcode】Palindrome Partitioning II
    【leetcode】Best Time to Buy and Sell Stock III
    【leetcode】Best Time to Buy and Sell Stock II
    【leetcode】Longest Consecutive Sequence
    【leetcode】Factorial Trailing Zeroes
    【leetcode】Simplify Path
    【leetcode】Generate Parentheses
    【leetcode】Combination Sum II
    【leetcode】Combination Sum
  • 原文地址:https://www.cnblogs.com/seanRay/p/14781110.html
Copyright © 2011-2022 走看看