SpringCloud Ribbon 负载均衡
Spring Cloud Ribbon 是一个基于 HTTP 和 TCP 的客户端负载均衡工具。可以将面向服务的 REST 模板请求自动转化成客户端负载均衡的服务调用。Spring Cloud Ribbon 虽然是一个工具类框架,但它不像服务注册中心、配置中心、API网关那样需要独立部署。但是它几乎存在于每一个 Spring Cloud 构建的微服务和基础设置中。因为微服务间的调用,API 网关的请求转发等内容,实际上都是通过 Ribbon 来实现的,包括 Feign 它也是基于 Ribbon 实现的工具。所以 Spring Cloud Ribbon 的理解和使用,对于我们使用 Spring Cloud 来构建微服务非常重要。
一、概述
【1】是什么:Spring Cloud Ribbon 是基于 Netflix Ribbon实现的一套客户端的负载均衡的工具。简单的说,Ribbon是 Netflix发布的开源项目,主要功能是提供客户端的软件负载均衡算法,将 Netflix 的中间层服务连接在一起。Ribbon 客户端组件提供一系列完善的配置项如连接超时,重试等。简单的说就是在配置文件中列出 Load Balancer(简称LB)后面所有的机器,Ribbon会自动的帮你基于某种规则(如单轮询,随机连接等)去连接这些机器。我们也很容易使用 Ribbon实现自定义的负载均衡算法。
【2】作用:LB,即负载平衡(Load Balance)在微服务或分布式集群中经常用的一种应用。负载平衡简单的说,就是将用户的请求平摊的分配到多个服务,而达到服务的HA(高可用)。常见的负载均衡软件Nginx,LVS,硬件F5等。相应的中间件,例如:Dubbo 和 SpringCloud 中均给我们提供了负载均衡,SpinrgCloud 的负载均衡算法可以自定义。
【3】主要分为两种:1)、集中式LB:偏硬件,即在服务的消费方和提供方之间使用独立的LB设施(可以是硬件F5,也可以是软件Nginx),由该设置负责把访问请求通过某种策略转发至服务的提供方; 2)、进程内LB:将 LB逻辑集成到消费方,消费方从服务注册中心获知有哪些地址可用,然后自己再从这些地址中选择出一个合适的服务器。
Ribbon 就属于进程内 LB,它只是一个库,集成于消费方进程,消费方通过它来获取到服务提供方的地址。
二、Ribbon 初步配置
【1】修改客户端,例如:microservicecloud-consumer-dept-80 工程的 pom.xml 文件;
1 <!-- Ribbon相关 -->
2 <dependency>
3 <groupId>org.springframework.cloud</groupId>
4 <artifactId>spring-cloud-starter-eureka</artifactId>
5 </dependency>
6 <dependency>
7 <groupId>org.springframework.cloud</groupId>
8 <artifactId>spring-cloud-starter-ribbon</artifactId>
9 </dependency>
10 <dependency>
11 <groupId>org.springframework.cloud</groupId>
12 <artifactId>spring-cloud-starter-config</artifactId>
13 </dependency>
14 <dependency>
15 <groupId>org.springframework.boot</groupId>
16 <artifactId>spring-boot-starter-web</artifactId>
17 </dependency>
【2】修改 application.yml,追加 eureka 的服务注册地址;
1 eureka:
2 client:
3 register-with-eureka: false
4 service-url:
5 defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
【3】对 ConfigBean 配置类,添加新注解 @LoadBalance 获得 RestTemplate 时,加入 Ribbon 的配置;
1 @LoadBalanced//Spring Cloud Ribbon是基于Netflix Ribbon实现的一套客户端 负载均衡的工具。
2 public RestTemplate getRestTemplate()
3 {
4 return new RestTemplate();
5 }
【4】主启动类 DeptConsumer80_App 添加 @EnableEurekaClient;
1 @EnableEurekaClient
2 public class DeptConsumer80_App
3 {
【5】修改 deptController_Consumer 客户端访问类;
1 //微服务的名称MICROSERVICECLOUD-DEPT
2 private static final String REST_URL_PREFIX = "http://MICROSERVICECLOUD-DEPT";
3
4 @RequestMapping(value="/comsumer/dept/add")
5 public boolean add(Consumer comsumer){
6 return restTemplate.postForObject(REST_URL_PREFIX+"/dept/add",comsumer,Boolean.class);
7 }
【6】先启动3个 eureka 集群后,在启动 microservicecloud-provider-dept-8001 并注册进 eureka;
【7】启动 microservicecloud-consumer-dept-80;
【8】小结:Ribbon 和 Eureka 整合后 Consumer 可以直接调用服务而不用关心服务和端口号。
三、Ribbon 负载均衡
【1】Ribbon 在工作时分为两步:
①、先选择EurekaServer,它优先选择在同一个区域内负载较少的server;
②、根据用户指定的策略,再从 server取到的服务注册列表中选择一个地址;
【2】实操:①、参考 microservicecloud-provide-dept-8001,创建 microservicecloud-provide-dept-8002 和 8003;
②、新建 8002/8003数据库,各微服务分别连各自的数据库;
③、修改 8002/8003 各自的 yml:修改端口和数据库连接,对外暴露的统一的服务实例名不能修改;

④、启动3个 eureka 集群配置区;
⑤、启动3个 Dept 微服务并各自测试通过;
⑥、启动 microservicecloud-consumer-dept-80;
⑦、客户端通过 Ribbo 完成负载均衡并访问上一步的 Dept微服务;
总结:Ribbo 其实是一个软负载均衡的客户端组件,它可以和其它请求的客户端结合使用,获取 Eureka 中一个实例;
四、Ribbon 核心组件 IRule
Irule:根据特定算法从服务中选取一个要访问的服务。
【1】RoundRobinRule:轮询;
【2】RandomRule:随机;
【3】AvaliabilityFilteringRule:会先过滤掉由于多次访问故障而处于熔断器跳闸状态的服务,还有并发的连接数量超过阈值的服务,然后对剩余的服务列表按照轮询策略进行访问;
【4】WeightedResponseTimeRule:根据平均响应时间计算所有服务的权重,响应时间越快权重越大被选中的概率就越高,刚启动时统计信息不足时,则使用 RoundRobinRule 策略,等统计信息足够,则会切换到 WeightedResponseTimeRule;
【5】RetryRule:先按照 roundRobinRule 的策略获取服务,如果获取失败则会在指定时间内进行重试,获取可用服务;
【6】BestAvailableRule:会过滤掉由于多次访问故障而处于断路器跳闸状态的服务,然后选择一个并发量最小的服务;
【7】ZoneAvoidanceRule:默认规则,复合判断 server 所在区域的性能和 server 的可用性选择器;
以上算法要使用则需要在 customer 端得 configBean.java 配置文件中添加(重要):
@Bean
public IRule myRule()
{
//return new RoundRobinRule();
//return new RandomRule();//达到的目的,用我们重新选择的随机算法替代默认的轮询。
return new RetryRule();
}
五、Ribbon 自定义
【1】修改 microservicecloud-consumer-dept-80;
【2】主启动类添加注解 @RibbonClient:在启动该微服务的时候就能去加载我们的自定义 Ribbon 配置类,从而使配置生效,如:@RibbonClient(name = "MICROSERVICECLOUD-DEPT",configuration=MySelfRule.class)
1 @RibbonClient(name="MICROSERVICECLOUD-DEPT",configuration=MySelfRule.class)
2 public class DeptConsumer80_App
3 {
【3】警告:这个配置类不能放在 @ComponentScan(主启动Java文件的包下面)所扫描的当前包以及子包下,否则我们自定义的这个配置类就会被所有的 Ribbon 客户端共享,也就是说我们达不到特殊化定制的目的。自定义 myrule:(不能和主启动类同一个 package)。不同之处就在于这个类不会扫描到,而是通过 @RibbonClient 注解将其与固定的服务进行绑定。达到与其他微服务不一样的负载均衡算法的目的。
1 @Configuration
2 public class MySelfRule
3 {
4 @Bean
5 public IRule myRule()
6 {
7 //return new RandomRule();// Ribbon默认是轮询,我自定义为随机
8 //return new RoundRobinRule();// Ribbon默认是轮询,我自定义为随机
9 return new RandomRule_ZY();// 我自定义为每台机器5次
10 }
11 }
【4】深度解析:问题:依旧是轮询策略,但是新需求,每个服务器要求被调用5次。即以前是每台机器一次,现在5次。对随机算法源码进行了修改。继承 AbstractLoadBalancerRule 实现负载均衡算法。详细学习,可以参考 GitHub 上 Ribbon 源码。
1 public class RandomRule_ZY extends AbstractLoadBalancerRule {
2 // total = 0 // 当total==5以后,我们指针才能往下走,
3 // index = 0 // 当前对外提供服务的服务器地址,
4 // total需要重新置为零,但是已经达到过一个5次,我们的index = 1
5 // 分析:我们5次,但是微服务只有8001 8002 8003 三台,OK?
6 private int total = 0;// 总共被调用的次数,目前要求每台被调用5次
7 private int currentIndex = 0; // 当前提供服务的机器号
8
9 public Server choose(ILoadBalancer lb, Object key) {
10 if (lb == null) {
11 return null;
12 }
13 Server server = null;
14
15 while (server == null) {
16 if (Thread.interrupted()) {
17 return null;
18 }
19 List<Server> upList = lb.getReachableServers();
20 List<Server> allList = lb.getAllServers();
21
22 int serverCount = allList.size();
23 if (serverCount == 0) {
24 /*
25 * 没有服务器。结束而不管通过,因为后续的通过只会得到更多
26 * 限制性的。
27 */
28 return null;
29 }
30
31 // int index = rand.nextInt(serverCount);// java.util.Random().nextInt(3);
32 // server = upList.get(index);
33
34 // private int total = 0; // 总共被调用的次数,目前要求每台被调用5次
35 // private int currentIndex = 0; // 当前提供服务的机器号
36 if (total < 5) {
37 server = upList.get(currentIndex);
38 total++;
39 } else {
40 total = 0;
41 currentIndex++;
42 if (currentIndex >= upList.size()) {
43 currentIndex = 0;
44 }
45 }
46
47 if (server == null) {
48 /*
49 * 只有当服务器列表以某种方式被修剪时,才会发生这种情况。
50 * 这是暂时的情况。屈服后重试。
51 */
52 Thread.yield();
53 continue;
54 }
55
56 if (server.isAlive()) {
57 return (server);
58 }
59
60 // 不应该真的发生。。但必须是暂时的或是一个错误。
61 server = null;
62 Thread.yield();
63 }
64 return server;
65 }
66
67 public Server choose(Object key) {
68 return choose(getLoadBalancer(), key);
69 }
70
71 public void initWithNiwsConfig(IClientConfig clientConfig) {
72 // TODO Auto-generated method stub
73 }
74 }
SpringCloud Ribbon 负载均衡的更多相关文章
- SpringCloud Ribbon 负载均衡 通过服务器名无法连接的神坑一个
一,问题 采取eureka集群.客户端通过Ribbon调用服务,Ribbon端报下列异常 java.net.UnknownHostException: SERVICE-HI java.lang.Ill ...
- SpringCloud系列——Ribbon 负载均衡
前言 Ribbon是一个客户端负载均衡器,它提供了对HTTP和TCP客户端的行为的大量控制.我们在上篇(猛戳:SpringCloud系列——Feign 服务调用)已经实现了多个服务之间的Feign调用 ...
- SpringCloud系列五:Ribbon 负载均衡(Ribbon 基本使用、Ribbon 负载均衡、自定义 Ribbon 配置、禁用 Eureka 实现 Ribbon 调用)
1.概念:Ribbon 负载均衡 2.具体内容 现在所有的服务已经通过了 Eureka 进行了注册,那么使用 Eureka 注册的目的是希望所有的服务都统一归属到 Eureka 之中进 行处理,但是现 ...
- SpringCloud无废话入门02:Ribbon负载均衡
1.白话负载均衡 在上一篇的介绍中,我们创建了两个一模一样的服务提供者:Provider1和Provider2,然后它们提供的服务也一模一样,都叫Hello-Service.为什么一样的服务我们要部署 ...
- spring-cloud: eureka之:ribbon负载均衡自定义配置(二)
spring-cloud: eureka之:ribbon负载均衡自定义配置(二) 有默认配置的话基本上就是轮询接口,现在我们改用自定义配置,同时支持:轮询,随机接口读取 准备工作: 1.eureka服 ...
- spring-cloud: eureka之:ribbon负载均衡配置(一)
spring-cloud: eureka之:ribbon负载均衡配置(一) 比如我有: 一个eureka服务:8761 两个user用户服务: 7900/7901端口 一个movie服务:8010 1 ...
- SpringCloud学习(4)——Ribbon负载均衡
Ribbon概述 SpringCloud Ribbon是基于Netflix Ribbon实现的一套客户端负载均衡工具. 简单的说, Ribbon是Netflix发布的开源项目, 主要功能是提供客户端软 ...
- spring-cloud配置ribbon负载均衡
spring-cloud配置ribbon负载均衡 ribbon提供的负载均衡就是开箱即用的,简单的不能再简单了 为了顺利演示此demo,你需要如下 需要提前配置eureka服务端,具体看 https: ...
- 浅谈SpringCloud (三) Ribbon负载均衡
什么是负载均衡 当一台服务器的单位时间内的访问量越大时,服务器压力就越大,大到超过自身承受能力时,服务器就会崩溃.为了避免服务器崩溃,让用户有更好的体验,我们通过负载均衡的方式来分担服务器压力. 我们 ...
- SpringCloud学习笔记(2):使用Ribbon负载均衡
简介 Spring Cloud Ribbon是基于Netflix Ribbon实现的一套客户端负载均衡工具,在注册中心对Ribbon客户端进行注册后,Ribbon可以基于某种负载均衡算法,如轮询(默认 ...
随机推荐
- C++ OnlineJudge
基本输入输出 1.接收多行数据,直到文件末尾 1 #include <iostream> 2 //#include <bits/stdc++.h> 3 #include < ...
- 作业一:PCA降维练习
作业一:PCA降维作业 代码 点击查看代码 #author:qiao_px #@Time 2022/10/31 16:11 #@File ceshiPCA.py import pandas as pd ...
- vue项目中axios跨域设置
最近项目中遇到一个问题,测试环境和线上环境需要调同一个接口(接口地址是线上的),本地开发的时候遇到了跨域的问题,刚开始用了fetch解决的,代码如下 方法一 step1:安装包node-fetch,然 ...
- 项目实训 DAY 9
加入页面之间定向的按钮,并改了一个typo
- ImmutablePair和ImmutableTriple的使用
场景 当我们调用某个方法,需要有超过一个值的返回时,我们通常会怎么做,比如现在需要调用方法返回姓名和年龄两个属性(假如姓名为张三,年龄为12). 方式一:使用Map,将Map中分别放入name为key ...
- PTA1002 写出这个数 (20 分)
1002 写出这个数 (20 分) 读入一个正整数 n,计算其各位数字之和,用汉语拼音写出和的每一位数字. 输入格式: 每个测试输入包含 1 个测试用例,即给出自然数 n 的值.这里保证 n 小于 1 ...
- docker出现“Failing to start dockerd: failed to create NAT chain DOCKER”错误
使用Windows的WSL 2里面的Ubuntu安装docker之后,启动docker服务一直失败,提示Docker is not running.使用dockerd命令会出现如下错误: INFO[2 ...
- PTA最大子列和问题
给定K个整数组成的序列{ N1, N2, ..., NK },"连续子列"被定义为{ Ni, Ni+1, ..., Nj },其中 1≤i≤j≤K."最大子列 ...
- Nacos 之 Distro 协议
1. 概述 Distro协议是阿里自研的一个最终一致性协议,继承了 Gossip 以及 Eureka 通信(PeerEurekaNodes)的优点并做进一步优化而出来的: 对于原生的Gossip,由于 ...
- 【.NET】Swagger 允许接口重名
问题: Swagger Failed to load API definition. 相信用过swagger的小伙伴 一定经历过这样的错误,问题点很简单,是接口重名了. 我百度了一下,找不到答案. 谷 ...