【Spring Cloud】详解 Ribbon:负载均衡、多种负载均衡算法的选取、自定义负载均衡算法
  cSz3d9P80y6K 2023年11月02日 44 0

文章目录

  • 1 Ribbon 是什么
  • 2 Ribbon 能做什么
  • 3 项目实战
  • 3.1 项目搭建
  • 3.2 Ribbon 架构图示
  • 3.3 Ribbon 负载均衡:轮询方式
  • 3.4 Ribbon 各种负载均衡算法
  • 3.5 源码分析:RoundRobinRule 负载均衡算法
  • 3.6 Ribbon 选取其他负载均衡算法
  • 3.7 Ribbon 自定义负载均衡算法

1 Ribbon 是什么

【Spring Cloud】详解 Ribbon:负载均衡、多种负载均衡算法的选取、自定义负载均衡算法_负载均衡

2 Ribbon 能做什么

【Spring Cloud】详解 Ribbon:负载均衡、多种负载均衡算法的选取、自定义负载均衡算法_ribbon_02

3 项目实战

3.1 项目搭建

我们以【Spring Cloud】RestTemplate:学习总结、项目实战:服务提供者与服务消费者 中的服务消费者 springcloud-consumer-dept-8002 模块为基础,在此项目的基础上进行内容的改造和 Ribbon 的学习。

添加红框中的依赖

【Spring Cloud】详解 Ribbon:负载均衡、多种负载均衡算法的选取、自定义负载均衡算法_java_03


同时,因为 Ribbon 要去注册中心或者说是服务中心去获取信息,而注册中心由 Eureka 担任,因此自然也要导入 Eureka 的依赖

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

<!--eureka-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
<version>1.4.6.RELEASE</version>
</dependency>

在 8002 项目的 yml 中增加 Eureka 的配置

【Spring Cloud】详解 Ribbon:负载均衡、多种负载均衡算法的选取、自定义负载均衡算法_java_04


在主启动类中开启 Eureka 的自动配置

【Spring Cloud】详解 Ribbon:负载均衡、多种负载均衡算法的选取、自定义负载均衡算法_spring cloud_05


配置类需加一个注解 @LoadBalanced

【Spring Cloud】详解 Ribbon:负载均衡、多种负载均衡算法的选取、自定义负载均衡算法_负载均衡_06


修改控制器中的地址,让它基于 Application 名(微服务名)去访问,而不是写死为某个特定的主机ip和端口,这样便可以通过 Ribbon 的负载均衡机制来进行当前服务提供者的获取。

【Spring Cloud】详解 Ribbon:负载均衡、多种负载均衡算法的选取、自定义负载均衡算法_负载均衡_07

【Spring Cloud】详解 Ribbon:负载均衡、多种负载均衡算法的选取、自定义负载均衡算法_spring_08

接下来启动 7001,7002,7003 三个注册中心,再启动服务提供者 8001,再启动服务消费者 8002,让此服务消费者通过 RestTemplate 来通过 Ribbon 的负载均衡机制去注册中心来获取 服务提供者 8001 的服务

访问成功

【Spring Cloud】详解 Ribbon:负载均衡、多种负载均衡算法的选取、自定义负载均衡算法_spring_09

因此,Ribbon和Eureka整合后Consumer可以直接调用服务而不用再关心地址和端口号。

3.2 Ribbon 架构图示

Ribbon 的架构思路如下:

【Spring Cloud】详解 Ribbon:负载均衡、多种负载均衡算法的选取、自定义负载均衡算法_spring_10


【Spring Cloud】详解 Ribbon:负载均衡、多种负载均衡算法的选取、自定义负载均衡算法_spring cloud_11

3.3 Ribbon 负载均衡:轮询方式

下面就直接用视频教程里的截图来写了,我电脑配置较低,在启动多个微服务项目时实在太卡了,而且一有问题,调试可能又要重启各项目,实在心累,视频截图中的 8002 项目是一个 8001 的复制品,也是一个服务提供者模块,80 项目为消费者,而我的项目中 8002 是消费者模块,只需区分好这一点区别即可)

部署三个服务提供者的微服务:

【Spring Cloud】详解 Ribbon:负载均衡、多种负载均衡算法的选取、自定义负载均衡算法_spring cloud_12


为上述三个服务提供者的微服务项目配置各自的数据库,实体信息中唯一不同的是字段 data_source,这个字段是根据数据库名生成的:

【Spring Cloud】详解 Ribbon:负载均衡、多种负载均衡算法的选取、自定义负载均衡算法_java_13


修改配置

【Spring Cloud】详解 Ribbon:负载均衡、多种负载均衡算法的选取、自定义负载均衡算法_spring cloud_14


启动服务消费者模块 springcloud-consumer-dept-ribbon-80 ,客户端通过Ribbon完成负载均衡并访问上一步的 Dept 微服务 http://localhost/consumer/dept/list多刷新几次注意观察结果!为1、2、3 在轮询这个三个服务名一样的模块,即一种微服务项目的三个部署轮询被请求的服务消费者使用(通过数据库中 data_source 字段的不同来直观看出负载均衡对同一种微服务项目的使用情况),同时轮询也是 Ribbon 的默认选择算法(也可以自定义,此部分内容安排的下文)

【Spring Cloud】详解 Ribbon:负载均衡、多种负载均衡算法的选取、自定义负载均衡算法_负载均衡_15


【Spring Cloud】详解 Ribbon:负载均衡、多种负载均衡算法的选取、自定义负载均衡算法_负载均衡_16


【Spring Cloud】详解 Ribbon:负载均衡、多种负载均衡算法的选取、自定义负载均衡算法_ribbon_17

总结:Ribbon 其实就是一个软负载均衡的客户端组件,他可以和其他所需请求的客户端结合使用,和 Eureka 结合只是其中的一个实例。

3.4 Ribbon 各种负载均衡算法

自定义负载均衡算法涉及到一个叫做 IRule 的接口:

【Spring Cloud】详解 Ribbon:负载均衡、多种负载均衡算法的选取、自定义负载均衡算法_java_18

译:为 LoadBalancer 定义“规则”的接口。规则可以被认为是负载均衡的策略。众所周知的负载平衡策略包括循环、基于响应时间等。

IRule 接口有多种实现类,Ribbon 根据某个预先选取的负载均衡算法从服务列表中选取一个要访问的服务。

【Spring Cloud】详解 Ribbon:负载均衡、多种负载均衡算法的选取、自定义负载均衡算法_spring_19


几种实现类的介绍:

【Spring Cloud】详解 Ribbon:负载均衡、多种负载均衡算法的选取、自定义负载均衡算法_spring_20

查看分析源码:

  • IRule
  • ILoadBalancer
  • AbstractLoadBalancer
  • AbstractLoadBalancerRule:这个抽象父类十分重要!
  • 核心5. RoundRobinRule

3.5 源码分析:RoundRobinRule 负载均衡算法

其中 RoundRobinRule 是默认的负载均衡实现,即轮询方式的负载均衡算法,此类中核心的源码是 choose 方法

public Server choose(ILoadBalancer lb, Object key) {
if (lb == null) {
log.warn("no load balancer");
return null;
}

Server server = null;
int count = 0;
while (server == null && count++ < 10) {
List<Server> reachableServers = lb.getReachableServers();
List<Server> allServers = lb.getAllServers();
int upCount = reachableServers.size();
int serverCount = allServers.size();

if ((upCount == 0) || (serverCount == 0)) {
log.warn("No up servers available from load balancer: " + lb);
return null;
}

int nextServerIndex = incrementAndGetModulo(serverCount);
server = allServers.get(nextServerIndex);

if (server == null) {
/* Transient. */
Thread.yield();
continue;
}

if (server.isAlive() && (server.isReadyToServe())) {
return (server);
}

// Next.
server = null;
}

if (count >= 10) {
log.warn("No available alive servers after 10 tries from load balancer: "
+ lb);
}
return server;
}

choose 方法先检查 ILoadBalancer 是否为 null,而 ILoadBalancer 是在此类的父类中定义的:

【Spring Cloud】详解 Ribbon:负载均衡、多种负载均衡算法的选取、自定义负载均衡算法_ribbon_21


choose 方法之后又获取已注册的微服务,并用 server = allServers.get(nextServerIndex); 来获取服务列表中的下一个服务,达到轮询的目的,之后又是在当前获取的服务如果为空时需进行线程礼让,如果当前获取的服务是存活的并且可以提供服务,那么就选取返回这个服务给 Ribbon相关机构,如果当前循环执行次数超过 10 次,那就要在日志中提示此问题。

3.6 Ribbon 选取其他负载均衡算法

返回相应实现类的 Bean 到 Spring 容器中即可:

【Spring Cloud】详解 Ribbon:负载均衡、多种负载均衡算法的选取、自定义负载均衡算法_spring_22

3.7 Ribbon 自定义负载均衡算法

写在前面:注意配置细节

【Spring Cloud】详解 Ribbon:负载均衡、多种负载均衡算法的选取、自定义负载均衡算法_ribbon_23


中文文档的相关警告:

【Spring Cloud】详解 Ribbon:负载均衡、多种负载均衡算法的选取、自定义负载均衡算法_ribbon_24

具体步骤:

【Spring Cloud】详解 Ribbon:负载均衡、多种负载均衡算法的选取、自定义负载均衡算法_spring_25


2. 在这里新建一个自定义规则的Rubbion类,此处以 RandomRule 类做测试,在公司中可能会要求自定义负载均衡算法,到时候返回自定义的那个负载均衡类即可。

【Spring Cloud】详解 Ribbon:负载均衡、多种负载均衡算法的选取、自定义负载均衡算法_java_26

3. 在主启动类上配置我们自定义的Ribbon,主启动类添加@RibbonClient注解

【Spring Cloud】详解 Ribbon:负载均衡、多种负载均衡算法的选取、自定义负载均衡算法_ribbon_27


3. 启动所有项目,访问测试,看看我们编写的随机算法,现在是否生效即可。

【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年11月08日 0

暂无评论

推荐阅读
  ehrZuhofWJiC   2024年04月26日   39   0   0 日志Java
cSz3d9P80y6K