一、Ribbon 负载均衡
如下图,端口:8001、8002、8003 功能完全相同,高并发的情况下将请求均匀分配给三个端口以减小服务器压力。简单来说就是将用户的请求平均分配到多个服务器上从而达到HA(高可用)
所以,Ribbon的主要功能是提供客户端的软件负载均衡算法和服务调用,其客户端组件提供一系列的配置项,如:连接超时,重试等。
简单地说,就是在配置文件中列出 Load Balance(负载均衡 简称 LB )后面的机器,Ribbon会自动帮你基于某种规则(简单轮询、随机连接等)去连接这些机器。
不同于Nginx,Ribbon是本地负载均衡,也就是工程内部负载均衡。即,在调用接口的时候会在注册中心上获取注册。
Nginx是服务器负载均衡,客户端所有请求都会交给Nginx,然后由 Nginx 实现转发请求。即,负载均衡是由服务器端完成的。
一句话:Ribbon = 负载均衡 + RestTemplate调用
Ribbon工作时分为两步:
- 先选择 Eureka Server,优先选择同一区域中负载较少的 Server
- 再根据用户指定的策略,从 server 取到服务注册列表中选择一个地址。
二、当前项目结构介绍
当前项目中包含四个模块:
- 公有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,所以不再需要手动引入
1. 修改服务提供者 :8001
进入 cloud-provider-payment8001 模块,修改 controller,让他在获取数据时输出端口号。
2. 复制并修改端口号
将 cloud-provider-payment8001 模块复制一份,模块命名为 cloud-provider-payment8002 ,端口号修改为 8002
3. 调整 80 端口
进入消费者模块(cloud-consumer-order80),在远程调用的 config 中添加负载均衡注解@LoadBalanced
将原来写死的调用路径修改成注册中心的服务名
启动注册中心,查看服务名
修改消费者访问路径
4. 测试
先单独访问 8001 和 8002 端口,看服务是否正常
将 8001 和 8002 的控制台清空,访问消费者(80端口)进行测试
第一次查询 8002 端口控制台有内容输出,8001端口无输出
第二次查询 8001 端口控制台有内容输出,8002 端口无输出
多实验几次后发现是轮询输出。
四、Ribbon 核心组件 Irule
可以自定义负载均衡访问策略
-
RoundRobinRule
轮询,默认策略 -
RandomRule
随机
1. 替换说明
官方文档明确声明,需要定义新的配置类实现,这个配置类不能放在
@ComponentScan
所扫描的当前包以及子包下,否则定义的配置类就会被所有 Ribbon 客户端所共享,达不到特殊定制的目的。SpringBoot默认的扫描包路径是主目录,即*启动类所在的目录。以 80 端口为例,主目录就是
org.zjh.springcloud
2. 新建配置类
创建新目录,并在目录下新建配置类
@SpringBootConfiguration
public class MySelfRule {
@Bean
public IRule myRule(){
return new RandomRule(); //定义为随机
// return new RoundRobinRule(); //定义为轮询
}
}
3. 修改启动类
新增完配置类后还没完,还需要在启动类上添加注解,这样才能扫描到添加的配置类@RibbonClient
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
. . . . . .