一、Ribbon 负载均衡

如下图,端口:8001、8002、8003 功能完全相同,高并发的情况下将请求均匀分配给三个端口以减小服务器压力。简单来说就是将用户的请求平均分配到多个服务器上从而达到HA(高可用)

Spring Cloud LoadBalancer 自定义负载策略 spring cloud 负载均衡ribbon的规则配置_ribbon

所以,Ribbon的主要功能是提供客户端的软件负载均衡算法服务调用,其客户端组件提供一系列的配置项,如:连接超时重试等。

简单地说,就是在配置文件中列出 Load Balance(负载均衡 简称 LB )后面的机器,Ribbon会自动帮你基于某种规则(简单轮询、随机连接等)去连接这些机器。

不同于Nginx,Ribbon是本地负载均衡,也就是工程内部负载均衡。即,在调用接口的时候会在注册中心上获取注册。
Nginx是服务器负载均衡,客户端所有请求都会交给Nginx,然后由 Nginx 实现转发请求。即,负载均衡是由服务器端完成的。

一句话:Ribbon = 负载均衡 + RestTemplate调用

Ribbon工作时分为两步:

  1. 先选择 Eureka Server,优先选择同一区域中负载较少的 Server
  2. 再根据用户指定的策略,从 server 取到服务注册列表中选择一个地址。

二、当前项目结构介绍

当前项目中包含四个模块:

Spring Cloud LoadBalancer 自定义负载策略 spring cloud 负载均衡ribbon的规则配置_spring cloud_02

  • 公有API:cloud-api-commons
  • 服务提供者: cloud-provider-payment8001 (端口号8001 )
  • 服务消费者: cloud-consumer-order80 (端口号80 )
  • 注册中心 Eureka: cloud-eureka-server7001(端口号7001 )

前文链接:
项目源码:https://gitee.com/zhangchouchou/spring-cloud-demo/tree/b668ed08207079d3af46faa18ae34929826d7cf6/

三、项目中添加 Ribbon

Ribbon 在 POM 中引用:

<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-ribbon</artifactId> </dependency>

不过因为已经引入 Eureka,Eureka客户端自带 Ribbon,所以不再需要手动引入

Spring Cloud LoadBalancer 自定义负载策略 spring cloud 负载均衡ribbon的规则配置_客户端_03

1. 修改服务提供者 :8001

进入 cloud-provider-payment8001 模块,修改 controller,让他在获取数据时输出端口号。

Spring Cloud LoadBalancer 自定义负载策略 spring cloud 负载均衡ribbon的规则配置_负载均衡_04

2. 复制并修改端口号

将 cloud-provider-payment8001 模块复制一份,模块命名为 cloud-provider-payment8002 ,端口号修改为 8002

Spring Cloud LoadBalancer 自定义负载策略 spring cloud 负载均衡ribbon的规则配置_ribbon_05

3. 调整 80 端口

进入消费者模块(cloud-consumer-order80),在远程调用的 config 中添加负载均衡注解
@LoadBalanced

Spring Cloud LoadBalancer 自定义负载策略 spring cloud 负载均衡ribbon的规则配置_端口号_06

将原来写死的调用路径修改成注册中心的服务名

启动注册中心,查看服务名

Spring Cloud LoadBalancer 自定义负载策略 spring cloud 负载均衡ribbon的规则配置_ribbon_07


修改消费者访问路径

Spring Cloud LoadBalancer 自定义负载策略 spring cloud 负载均衡ribbon的规则配置_spring cloud_08

4. 测试

先单独访问 8001 和 8002 端口,看服务是否正常

Spring Cloud LoadBalancer 自定义负载策略 spring cloud 负载均衡ribbon的规则配置_客户端_09

将 8001 和 8002 的控制台清空,访问消费者(80端口)进行测试

Spring Cloud LoadBalancer 自定义负载策略 spring cloud 负载均衡ribbon的规则配置_端口号_10

第一次查询 8002 端口控制台有内容输出,8001端口无输出

Spring Cloud LoadBalancer 自定义负载策略 spring cloud 负载均衡ribbon的规则配置_端口号_11


第二次查询 8001 端口控制台有内容输出,8002 端口无输出

Spring Cloud LoadBalancer 自定义负载策略 spring cloud 负载均衡ribbon的规则配置_负载均衡_12


多实验几次后发现是轮询输出。

四、Ribbon 核心组件 Irule

可以自定义负载均衡访问策略

  • RoundRobinRule 轮询,默认策略
  • RandomRule 随机

1. 替换说明

官方文档明确声明,需要定义新的配置类实现,这个配置类不能放在 @ComponentScan 所扫描的当前包以及子包下,否则定义的配置类就会被所有 Ribbon 客户端所共享,达不到特殊定制的目的。

SpringBoot默认的扫描包路径是主目录,即*启动类所在的目录。以 80 端口为例,主目录就是 org.zjh.springcloud

Spring Cloud LoadBalancer 自定义负载策略 spring cloud 负载均衡ribbon的规则配置_ribbon_13

2. 新建配置类

创建新目录,并在目录下新建配置类

Spring Cloud LoadBalancer 自定义负载策略 spring cloud 负载均衡ribbon的规则配置_客户端_14

@SpringBootConfiguration
public class MySelfRule {

    @Bean
    public IRule myRule(){
        return new RandomRule(); //定义为随机
      //  return new RoundRobinRule(); //定义为轮询
    }
}

3. 修改启动类

新增完配置类后还没完,还需要在启动类上添加注解,这样才能扫描到添加的配置类
@RibbonClient

Spring Cloud LoadBalancer 自定义负载策略 spring cloud 负载均衡ribbon的规则配置_spring cloud_15

4. 重启 80 服务进行测试

五、算法原理

rest 接口第几次请求数 % 服务器集群总数 = 实际调用服务器位置下标

List<Service> instances = 
	discoveryClient.getInstances("CLOUD-PAYMENT-SERVICE");

如:

  • List [0] instances = 127.0.0.8001
  • List [1] instances = 127.0.0.8002

8001 + 8002 组合成为集群,它们共计2台机器,集群总数为2,按照轮询算法原理:

当总请求数为 1 时: 1 % 2 = 1 对应下标位置为1,获取服务地址 127.0.0.8002
当总请求数为 2 时: 2 % 2 = 0 对应下标位置为0,获取服务地址 127.0.0.8001
当总请求数为 3 时: 3 % 2 = 1 对应下标位置为1,获取服务地址 127.0.0.8002
当总请求数为 4 时: 4 % 2 = 0 对应下标位置为0,获取服务地址 127.0.0.8001
. . . . . .