SpringCloud之负载均衡Ribbon

Ribbon

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

Ribbon配置在消费者模块中

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

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


消费者模块

1、导入依赖

xml 复制代码
  <!-- ribbon  & eureka       -->
  <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-ribbon</artifactId>
      <version>1.4.6.RELEASE</version>
  </dependency>

2、创建配置文件类

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

java 复制代码
@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(); 自定义
    }

}

3、定义负载均衡的规则

实现了IRule的实现类如下:

实现Rule的实现类

具体实现类作用如下:

复制代码
RandomRule:随机规则。使用Random对象从服务列表中随机选择一个服务实例。这种规则在每次请求时都会随机选择一个服务实例,有助于实现请求的均匀分布。

RoundRobinRule:轮询规则。这是Ribbon的默认规则,也是更高级规则的回退策略。它按照顺序依次选择服务实例进行调用,实现了一种简单的负载均衡。

RetryRule:重试规则。这种规则首先使用RoundRobinRule进行服务实例选择,如果选择服务实例失败或在指定时间内没有响应,则会在一定时间内不断进行重试,直到找到可用的服务实例或超时。

WeightedResponseTimeRule:加权响应时间规则。这种规则会根据每个服务实例的平均响应时间计算权重,响应时间越快的服务实例权重越高,被选中的概率也越高。这种规则能够优先将请求分发给性能更好的服务实例。

BestAvailableRule:最佳可用规则。它会选择并发量最小的服务实例进行调用,有助于平衡各个服务实例的负载。

ZoneAvoidanceRule:区域感知规则。在非AWS环境下,可以将其理解为根据机房或Eureka集群来选择服务实例。它会优先选择同区域的服务实例,当同区域的服务实例不可用时,才会选择其他区域的服务实例。

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

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

java 复制代码
/**
 *  注意 这个类不能被主启动类扫描 所以需要放在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) {
    }
}

5、启动器类

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

java 复制代码
@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);
    }
}

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

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

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

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

sql 复制代码
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连接db01

yml 复制代码
# 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
 

7、启动eureka&提供者

启动3个eureka服务、3个提供者和一个消费者

随机访问一个eureka服务界面

比如访问:http://localhost:7001/ 说明3个提供者已经注册到了eureka集群中了

8、测试负载均衡

默认的负载均衡策略是轮询

如果需要修改负载均衡策略可以再配置文件类中设置

java 复制代码
@Configuration
public class ConfigBean {
    @Bean
    public IRule getRule(){
        return new RandomRule(); // 随机
//        return new MyRule(); 自定义
    }
}

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

相关推荐
黄俊懿2 小时前
【深入理解SpringCloud微服务】Spring-Security作用与原理解析
java·后端·安全·spring·spring cloud·微服务·架构师
叫致寒吧6 小时前
Dockerfile
java·spring cloud·eureka
悟空码字9 小时前
从零到一搭建SpringCloud微服务,一场代码世界的“分家”大戏
java·后端·spring cloud
黄俊懿10 小时前
【深入理解SpringCloud微服务】Gateway源码解析
java·后端·spring·spring cloud·微服务·gateway·架构师
刘个Java11 小时前
手搓遥控器通过上云api执行航线
java·redis·spring cloud·docker
没有bug.的程序员11 小时前
Ribbon vs LoadBalancer 深度解析
jvm·后端·spring cloud·微服务·ribbon·架构·gc调优
黄俊懿1 天前
【深入理解SpringCloud微服务】Seata(AT模式)源码解析——全局事务的回滚
java·后端·spring·spring cloud·微服务·架构·架构师
云老大TG:@yunlaoda3601 天前
华为云国际站代理商NAT的高可用与弹性具体是如何实现的?
服务器·数据库·华为云·负载均衡
码农小卡拉1 天前
Java多线程:CompletableFuture使用详解(超详细)
java·开发语言·spring boot·python·spring·spring cloud
秋邱1 天前
Java面向对象进阶:封装、继承、多态的实现逻辑与实战案例
java·开发语言·后端·spring cloud·ar·restful