zoukankan      html  css  js  c++  java
  • SpringCloud Ribbon(负载均衡)

    1.负载均衡LB

    全称Load Balance,将用户的请求平摊到多个服务器上,从而达到系统的HA。
    1)集中式LB

    在服务消费者和服务提供者之间使用独立的LB设施,如硬件,由该设施负责把访问请求通过某种策略转发至服务提供方。
    2)进程内LB

    将LB逻辑继承到服务消费者,消费者从服务注册中心获知有哪些地址可用,然后从这些地址中选择一个合适的来使用。Ribbon属于进程内LB。

    2.Ribbon定义

    只使用restTemplate问题是服务的地址是写死的,不利于维护,没有进行负载均衡。而Ribbon基于NetFlix Ribbon实现的一套客户端负载均衡的工具。但它可以结合RestTemplate进行服务之间的调用。

    3.项目实战

    3.1基础环境搭建

    源代码:https://github.com/zhongyushi-git/cloud-ribbon-demo.git

    说明:由于Eureka2.0已停止维护,故这里使用consul作为服务注册中心,使用RestTemplate进入服务的调用,使用Ribbon进行服务的负载均衡。

    1)创建一个maven工程名为cloud-ribbon-demo,删除src目录

    2)在pom中导入依赖,对SpringBoot和SpringCloud版本进行锁定

       <properties>
            <spring.boot.version>2.2.2.RELEASE</spring.boot.version>
            <spring.cloud.version>Hoxton.SR1</spring.cloud.version>
        </properties>
    
        <!--  依赖管理,父工程锁定版本-->
        <dependencyManagement>
            <dependencies>
                <dependency>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-dependencies</artifactId>
                    <version>${spring.boot.version}</version>
                    <type>pom</type>
                    <scope>import</scope>
                </dependency>
                <dependency>
                    <groupId>org.springframework.cloud</groupId>
                    <artifactId>spring-cloud-dependencies</artifactId>
                    <version>${spring.cloud.version}</version>
                    <type>pom</type>
                    <scope>import</scope>
                </dependency>
            </dependencies>
        </dependencyManagement>

    3.2搭建服务提供者

    1)新建maven子模块(cloud-provider8001),导入依赖

         <dependencies>
            <!--web-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-consul-discovery</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-actuator</artifactId>
            </dependency>
        </dependencies>

    2)新建启动类ProviderMain8001并添加注解

    package com.zys.cloud;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
    
    @SpringBootApplication
    @EnableDiscoveryClient
    public class ProviderMain8001 {
        public static void main(String[] args) {
            SpringApplication.run(ProviderMain8001.class, args);
        }
    }

    3)配置application.yml

    server:
      port: 8001
    
    spring:
      application:
        name: cloud-consul-provider
      cloud:
        consul:
          host: localhost
          port: 8500
          discovery:
            service-name: ${spring.application.name}

    4)新建controller接口

    package com.zys.cloud.controller;
    
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    @RestController
    @RequestMapping("/user")
    public class UserController {
    
        @Value("${server.port}")
        private String port;
    
        @GetMapping("/get")
        public String get() {
            return "我是服务提供者,端口:" + port;
        }
    }

    5)启动服务,可看到已注册到consul。

    6)根据服务提供者ProviderMain8001,再分别创建ProviderMain8002和ProviderMain8003.

    3.3搭建服务消费者

    1)新建maven子模块(cloud-consumer80),导入依赖

         <dependencies>
            <!--web-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-consul-discovery</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-actuator</artifactId>
            </dependency>
        </dependencies>

    2)新建启动类ConsumerMain80并添加注解

    package com.zys.cloud;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
    
    @SpringBootApplication
    @EnableDiscoveryClient
    public class ConsumerMain80 {
        public static void main(String[] args) {
            SpringApplication.run(ConsumerMain80.class, args);
        }
    }

    3)配置application.yml

    server:
      port: 80
    
    spring:
      application:
        name: cloud-consul-consumer
      cloud:
        consul:
          host: localhost
          port: 8500
          discovery:
            service-name: ${spring.application.name}

    4)创建配置类,注入RestTemplate

    package com.zys.cloud.config;
    
    import org.springframework.cloud.client.loadbalancer.LoadBalanced;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.client.RestTemplate;
    
    @Configuration
    public class ConfigBean {
    
        @Bean
        @LoadBalanced
        public RestTemplate getRestTemplate() {
            return new RestTemplate();
        }
    }

    要在方法上加@LoadBalanced,否则在服务调用时会报错。添加注解后,在服务调用时,就会根据其负载均衡策略进行服务的负载转发和请求。

    5)新建controller接口

    package com.zys.cloud.controller;

    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    import org.springframework.web.client.RestTemplate;

    @RestController
    @RequestMapping("/consumer")
    public class UserController {
    private final String BASE_URL = "http://cloud-consul-provider";

    @Autowired
    private RestTemplate restTemplate;

    @GetMapping("/get")
    public String addUser() {
    return restTemplate.getForObject(BASE_URL + "/user/get", String.class);
    }

    }

    在设置请求路径时,http后面是cloud-consul-provider,这就指定了要调用的服务的名字。这样方便维护,又达到了负载均衡的效果。

    5)启动服务,可看到已注册到consul。访问http://localhost/consumer/get,第一次调用的是端口为8001的服务,刷新一次调用的是8002服务,再刷新一次调用的是8003服务,依次轮询。原因是其按默认的轮询策略进行负载的。

    6)负载分析。虽然全文都在说Ribbon,但却没有引入其依赖,又能达到效果,这是为何?原因是在引入引入consul时就其已引入了Ribbon,就无需再次引入。

    4.Ribbon负载均衡策略

    4.1负载策略说明

    Ribbon的核心组件是IRule,它的作用就是根据特定的算法从服务列表中选择一个要访问的服务。下面是Ribbon中定义的几种策略:

    策略 描述
    RandomRule 随机
    RoundRobinRule 轮询,按照顺序选择server,是Ribbon默认的策略
    RetryRule 重试,在一个配置时间段内,当选择server不成功,则一直尝试选择一个可用的server
    BestAvailableRule 最低并发,逐个考察server,如果server断路器打开,则忽略,再选择其中并发链接最低的server
    AvailabilityFilteringRule 可用过滤,过滤掉一直失败并被标记为circuit tripped的server,过滤掉那些高并发链接的server
    ResponseTimeWeightedRule 响应时间加权重,根据server的响应时间分配权重,响应时间越长,权重越低,被选择到的概率也就越低。
    ZoneAvoidanceRule 区域权重,综合判断server所在区域的性能和server的可用性,轮询选择server并且判断一个AWS Zone的运行性能是否可用,剔除不可用的Zone中的所有server

    4.2切换默认的策略

    有时需要切换默认策略时,也很简单,在服务消费者中进行配置即可。

    假设要把轮询策略改为随机策略,步骤如下:

    1)在配置类中注入RandomRule

        @Bean
        public IRule RandomRule(){
            return new RandomRule();
        }

    截图如下:

    2)重启服务消费者,进行测试,发现已是随机调用各个服务。

    就是这么简单,你学废了吗?感觉有用的话,给笔者点个赞吧 !
  • 相关阅读:
    京东Java面试题(二)
    京东Java面试题(一)
    阿里java面试题
    Java垃圾回收机制
    MyBatis面试题
    Java IO流总结
    Spring中文文档
    Vue.js实战之组件之间的数据传递
    Vue.js实战之Vuex的入门教程
    Vue系列——在vue项目中使用jQuery及其第三方插件
  • 原文地址:https://www.cnblogs.com/zys2019/p/15097447.html
Copyright © 2011-2022 走看看