• SpringCloud之负载均衡Ribbon


    Ribbon

    是一个客户端负载均衡工具,主要功能是将面向服务的Rest模板(RestTemplate)请求转换成客户端负载均衡的服务调用。通过Ribbon,开发人员可以在客户端实现请求的负载均衡,而无需单独部署负载均衡器。Ribbon支持多种负载均衡算法,如轮询、随机、加权等,只需要在配置文件类中添加@LoadBalanced

    Ribbon配置在消费者模块中

    之前写过消费者的模块 =>SpringCloud之消费者

    本文章的目的是:利用Ribbon实现负载均衡

    在这里插入图片描述

    消费者模块

    1、导入依赖

      
      <dependency>
          <groupId>org.springframework.cloudgroupId>
          <artifactId>spring-cloud-starter-ribbonartifactId>
          <version>1.4.6.RELEASEversion>
      dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    2、创建配置文件类

    只需要在RestTemplate上添加 @LoadBalanced注解

    @Configuration
    public class ConfigBean {
        /**
         * http请求
         * @return
         */
        @Bean
        @LoadBalanced // 使用Ribbon
        public RestTemplate getRestTemplate(){
            return new RestTemplate();
        }
    
        @Bean
        public IRule getRule(){
            return new RandomRule(); // 随机
    //        return new MyRule(); 自定义
        }
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    3、定义负载均衡的规则

    实现了IRule的实现类如下:
    在这里插入图片描述

    实现Rule的实现类

    具体实现类作用如下:

    RandomRule:随机规则。使用Random对象从服务列表中随机选择一个服务实例。这种规则在每次请求时都会随机选择一个服务实例,有助于实现请求的均匀分布。
    
    RoundRobinRule:轮询规则。这是Ribbon的默认规则,也是更高级规则的回退策略。它按照顺序依次选择服务实例进行调用,实现了一种简单的负载均衡。
    
    RetryRule:重试规则。这种规则首先使用RoundRobinRule进行服务实例选择,如果选择服务实例失败或在指定时间内没有响应,则会在一定时间内不断进行重试,直到找到可用的服务实例或超时。
    
    WeightedResponseTimeRule:加权响应时间规则。这种规则会根据每个服务实例的平均响应时间计算权重,响应时间越快的服务实例权重越高,被选中的概率也越高。这种规则能够优先将请求分发给性能更好的服务实例。
    
    BestAvailableRule:最佳可用规则。它会选择并发量最小的服务实例进行调用,有助于平衡各个服务实例的负载。
    
    ZoneAvoidanceRule:区域感知规则。在非AWS环境下,可以将其理解为根据机房或Eureka集群来选择服务实例。它会优先选择同区域的服务实例,当同区域的服务实例不可用时,才会选择其他区域的服务实例。
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    4、自定义负载均衡的规则

    自定义负载均衡需要注意的是自己创建的MyRule类不能和项目启动器类放在同一个文件夹内,即不能被Spring Boot扫描到。所以需要放置在启动类所在的包之外的独立包中。

    /**
     *  注意 这个类不能被主启动类扫描 所以需要放在com.jyl下的目录
     */
    @Configuration
    public class MyRule  extends AbstractLoadBalancerRule {
        /**
         * 实现一个每个服务只能访问5次,访问五次后换下一个服务
         * @param lb
         * @param key
         * @return
         */
        private int total = 0 ;// 被调用的次数
        private int currentIndex = 0 ; // 当前被调用的服务
    
        public MyRule(){
    
        }
    
    //    @SuppressWarnings({"RCN_REDUNDANT_NULLCHECK_OF_NULL_VALUE"})
        public Server choose(ILoadBalancer lb, Object key) {
            if (lb == null) {
                return null;
            } else {
                Server server = null;
    
                while(server == null) {
                    if (Thread.interrupted()) {
                        return null;
                    }
                    // 获得活着的服务
                    List<Server> upList = lb.getReachableServers();
                    // 获得全部的服务
                    List<Server> allList = lb.getAllServers();
                    int serverCount = allList.size();
                    if (serverCount == 0) {
                        return null;
                    }
    //                // 生成区间随机数
    //                int index = this.chooseRandomInt(serverCount);
    //                // 随机获取一个
    //                server = (Server)upList.get(index);
    
                    if(total < 5){
                        server = upList.get(currentIndex);
                        total++;
                    }else {
                        total = 0 ;
                        currentIndex++ ; // 5 + 1
                        if (currentIndex > upList.size()){
                            currentIndex = 0 ;
                        }
                        // 从活着的服务中, 获取指定的服务来进行操作
                        server = upList.get(currentIndex);
                    }
    
    
                    if (server == null) {
                        Thread.yield();
                    } else {
                        if (server.isAlive()) {
                            return server;
                        }
    
                        server = null;
                        Thread.yield();
                    }
                }
    
                return server;
            }
        }
        protected int chooseRandomInt(int serverCount) {
            return ThreadLocalRandom.current().nextInt(serverCount);
        }
    
        public Server choose(Object key) {
            return this.choose(this.getLoadBalancer(), key);
        }
    
        public void initWithNiwsConfig(IClientConfig clientConfig) {
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82

    5、启动器类

    需要添加@RibbonClient注解 需要的参数是name=“Eureka界面中的Application提供者的名称” 和configuration =自定义类

    @SpringBootApplication
    @EnableEurekaClient
    //再微服务启动的时候就可以加载自定义ribbon类
    @RibbonClient(name = "SPRINGCLOUD-PROVIDER-DEPT",configuration = MyRule.class)
    public class DeptConsumer_80 {
        public static void main(String[] args) {
            SpringApplication.run(DeptConsumer_80.class,args);
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    6、创建数据库&提供者模块

    到这里还没有结束 ,需要体验到负载均衡的效果,需要使用三个提供者,三个提供者要使用不同的数据库

    之前有写过提供者的案例=>这里!!!

    创建数据库名db01、db02、db03,创建相同的dept表如下:

    CREATE TABLE `dept` (
      `deptno` bigint(20) NOT NULL AUTO_INCREMENT,
      `dname` varchar(50) DEFAULT NULL,
      `db_source` varchar(50) DEFAULT NULL,
      PRIMARY KEY (`deptno`)
    ) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8;
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    只需要修改配置文件中的数据库名提供者依次连接数据库,如:提供者1连接db01

    # spring 的配置
    
    spring:
      application:
        name: springcloud-provider-dept
      datasource:
        type: com.alibaba.druid.pool.DruidDataSource
        driver-class-name: org.gjt.mm.mysql.Driver
        url: jdbc:mysql://localhost:3306/数据库名?useUnicode=true&useSSL=false&characterEncoding=utf-8
        username: root
        password: root
     
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    7、启动eureka&提供者

    启动3个eureka服务、3个提供者和一个消费者
    在这里插入图片描述
    随机访问一个eureka服务界面
    比如访问:http://localhost:7001/ 说明3个提供者已经注册到了eureka集群中了

    在这里插入图片描述

    8、测试负载均衡

    默认的负载均衡策略是轮询
    在这里插入图片描述
    如果需要修改负载均衡策略可以再配置文件类中设置

    @Configuration
    public class ConfigBean {
        @Bean
        public IRule getRule(){
            return new RandomRule(); // 随机
    //        return new MyRule(); 自定义
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    【每日自勉+1】“业精于勤,荒于嬉;行成于思,毁于随。”——韩愈。

  • 相关阅读:
    Linux系统——Session ID(负载均衡如何保持会话)
    一文了解SAAS开发、模板定制开发、全定制开发
    RTP/RTCP 协议讲解
    js变量的声明带var与不带的区别
    十大经典排序算法
    哈希-闭散列
    设计模式之桥接模式应用例题
    【华为机试真题 JAVA】字符串子序列II-100
    TextChanged
    使用JMX监控ZooKeeper和Kafka
  • 原文地址:https://blog.csdn.net/weixin_46171048/article/details/138191382