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】"业精于勤,荒于嬉;行成于思,毁于随。"------韩愈。

相关推荐
一元咖啡18 分钟前
SpringCloud Gateway转发请求到同一个服务的不同端口
spring·spring cloud·gateway
天天扭码1 小时前
五天SpringCloud计划——DAY2之单体架构和微服务架构的选择和转换原则
java·spring cloud·微服务·架构
跳跳的向阳花2 小时前
03-03、SpringCloud第三章,负载均衡Ribbon和Feign
spring cloud·ribbon·负载均衡
天天扭码17 小时前
五天SpringCloud计划——DAY1之mybatis-plus的使用
java·spring cloud·mybatis
luckywuxn1 天前
Spring Cloud Alibaba、Spring Cloud 与 Spring Boot各版本的对应关系
spring boot·spring·spring cloud
linweidong1 天前
MariaDB面试题及参考答案
linux·运维·数据库·负载均衡·dba·mariadb·后端面试
wclass-zhengge2 天前
SpringCloud篇(服务网关 - GateWay)
spring boot·spring cloud·gateway
荆州克莱2 天前
Redis | Redis常用命令及示例总结(API)
spring boot·spring·spring cloud·css3·技术
RainbowSea2 天前
5. Spring Cloud OpenFeign 声明式 WebService 客户端的超详细使用
java·spring·spring cloud