![cover](https://img-blog.csdnimg.cn/img_convert/498c67ec24ee443eb1da41d57a8dadbb.png)
Ribbon 实现负载均衡
** * 定制 Ribbon 负载均衡策略的配置类 * 该自定义 Ribbon 负载均衡策略配置类 不能在 com.lw.c 包及其子包下 * 否则所有的 Ribbon 客户端都会采用该策略,无法达到特殊化定制的目的 */ @Configuration public class MySelfRibbonRuleConfig { @Bean public IRule myRule(){ //负载均衡
Ribbon 实现负载均衡
Ribbon 是一个客户端的负载均衡器,它可以与 Eureka 配合使用轻松地实现客户端的负载均衡。Ribbon 会先从 Eureka Server(服务注册中心)去获取服务端列表,然后通过负载均衡策略将请求分摊给多个服务端,从而达到负载均衡的目的。
Spring Cloud Ribbon 提供了一个 IRule 接口,该接口主要用来定义负载均衡策略,它有 7 个默认实现类,每一个实现类都是一种负载均衡策略。
序号 | 实现类 | 负载均衡策略 |
1 | RoundRobinRule | 按照线性轮询策略,即按照一定的顺序依次选取服务实例 |
2 | RandomRule | 随机选取一个服务实例 |
3 | RetryRule | 按照 RoundRobinRule(轮询)的策略来获取服务,如果获取的服务实例为 null 或已经失效,则在指定的时间之内不断地进行重试(重试时获取服务的策略还是 RoundRobinRule 中定义的策略),如果超过指定时间依然没获取到服务实例则返回 null 。 |
4 | WeightedResponseTimeRule | WeightedResponseTimeRule 是 RoundRobinRule 的一个子类,它对 RoundRobinRule 的功能进行了扩展。 根据平均响应时间,来计算所有服务实例的权重,响应时间越短的服务实例权重越高,被选中的概率越大。刚启动时,如果统计信息不足,则使用线性轮询策略,等信息足够时,再切换到 WeightedResponseTimeRule。 |
5 | BestAvailableRule | 继承自 ClientConfigEnabledRoundRobinRule。先过滤点故障或失效的服务实例,然后再选择并发量最小的服务实例。 |
6 | AvailabilityFilteringRule | 先过滤掉故障或失效的服务实例,然后再选择并发量较小的服务实例。 |
7 | ZoneAvoidanceRule | 默认的负载均衡策略,综合判断服务所在区域(zone)的性能和服务(server)的可用性,来选择服务实例。在没有区域的环境下,该策略与轮询(RandomRule)策略类似。 |
下面我们就来通过一个实例来验证下,Ribbon 默认是使用什么策略选取服务实例的
示例 5
1. 在 Oracle数据库中执行以下 SQL 语句,准备测试数据。
a.管理员账号创建用户test1,test2.分别授权:链接数据库的权限、数据源权限
b.切换至test1用户。
create table Emp ( Empno NUMBER(4) not null, Ename VARCHAR2(20), Job VARCHAR2(9), Mgr NUMBER(4), HireDate DATE, Sal NUMBER(7,2), Comm NUMBER(7,2), Deptno NUMBER(2) ); alter table Emp add constraint PK_Empno primary key (Empno); insert into emp select empno,ename||':test1',job,mgr,hiredate,sal,comm,deptno from scott.emp; select * from emp
c.切换至test2用户。
create table Emp ( Empno NUMBER(4) not null, Ename VARCHAR2(20), Job VARCHAR2(9), Mgr NUMBER(4), HireDate DATE, Sal NUMBER(7,2), Comm NUMBER(7,2), Deptno NUMBER(2) ); alter table Emp add constraint PK_Empno primary key (Empno); insert into emp select empno,ename||':test2',job,mgr,hiredate,sal,comm,deptno from scott.emp; select * from emp
2. 参考 micro-service-cloud-provider-dept-8001,
再创建两个微服务 Moudle :micro-service-cloud-provider-dept-8002 和 micro-service-cloud-provider-dept-8003。
3. 在 micro-service-cloud-provider-dept-8002 中 application.yml 中,修改端口号、数据库连接信息以及自定义服务名称信息(eureka.instance.instance-id),修改的配置如下。
4. 在 micro-service-cloud-provider-dept-8003 中 application.yml 中,修改端口号以及数据库连接信息,修改的配置如下。
5. 依次启动 micro-service-cloud-eureka-7001/7002/7003(服务注册中心集群)、micro-service-cloud-provider-dept-8001/8002/8003(服务提供者集群)以及 micro-service-cloud-consumer-dept-80(服务消费者)。
6. 使用浏览器连续访问“http://eureka7001.com/consumer/emp/get/7788”,结果如下图。
默认负载均衡策略
通过上图 中 ename 字段取值的变化可以看出,Spring Cloud Ribbon 默认使用轮询策略进行负载均衡。
切换负载均衡策略
Spring Cloud Ribbon 默认使用轮询策略选取服务实例,我们也可以根据自身的需求切换负载均衡策略。
切换负载均衡策略的方法很简单,我们只需要在服务消费者(客户端)的配置类中,将 IRule 的其他实现类注入到容器中即可。
下面我们就通过一个实例,来演示下如何切换负载均衡的策略。
示例 6
1. 在 micro-service-cloud-consumer-dept-80 的配置类 ConfigBean 中添加以下代码,将负载均衡策略切换为 RandomRule(随机)。
2. 重启 micro-service-cloud-consumer-dept-80,使用浏览器访问“http://eureka7001.com/consumer/emp/get/7788”,结果如下图。
切换负载均衡策略为随机
通过上图 中 ename 字段取值的变化可以看出,我们已经将负载均衡策略切换为 RandomRule(随机)。
定制负载均衡策略
通常情况下,Ribbon 提供的这些默认负载均衡策略是可以满足我们的需求的,如果有特殊的要求,我们还可以根据自身需求定制负载均衡策略。
下面我们就来演示下如何定制负载均衡策略。
示例 7
1. 在 micro-service-cloud-consumer-dept-80 中新建一个 com.lw.c.myrule 包,并在该包下创建一个名为 MyRandomRule 的类。
package com.lw.c.myrule; import com.netflix.client.config.IClientConfig; import com.netflix.loadbalancer.AbstractLoadBalancerRule; import com.netflix.loadbalancer.ILoadBalancer; import com.netflix.loadbalancer.Server; import java.util.List; /** * 定制 Ribbon 负载均衡策略 */ public class MyRandomRule extends AbstractLoadBalancerRule { private int total = 0; // 总共被调用的次数,目前要求每台被调用5次 private int currentIndex = 0; // 当前提供服务的机器号 @Override public void initWithNiwsConfig(IClientConfig iClientConfig) { } @Override public Server choose(Object o) { return choose(getLoadBalancer(), o); } /** * 重载选择策略 * @param lb * @param key * @return */ public Server choose(ILoadBalancer lb, Object key) { if (lb == null) { return null; } Server server = null; while (server == null) { if (Thread.interrupted()) { return null; } //获取所有有效的服务实例列表 List<Server> upList = lb.getReachableServers(); //获取所有的服务实例的列表 List<Server> allList = lb.getAllServers(); //如果没有任何的服务实例则返回 null int serverCount = allList.size(); if (serverCount == 0) { return null; } //与随机策略相似,但每个服务实例只有在调用 5 次之后,才会调用其他的服务实例 if (total < 5) { server = upList.get(currentIndex); total++; } else { total = 0; currentIndex++; if (currentIndex >= upList.size()) { currentIndex = 0; } } if (server == null) { Thread.yield(); continue; } if (server.isAlive()) { return (server); } server = null; Thread.yield(); } return server; } }
2. 在 com.lw.myrule 包下创建一个名为 MySelfRibbonRuleConfig 的配置类,将我们定制的负载均衡策略实现类注入到容器中,代码如下。
官方文档中明确提出,该配置类不能在 ComponentScan 注解(SpringBootApplication 注解中包含了该注解)下的包或其子包中,
即自定义负载均衡配置类不能在 com.lw.c 包及其子包下
package com.lw.myrule; import com.lw.c.myrule.MyRandomRule; import com.netflix.loadbalancer.IRule; import com.netflix.loadbalancer.RandomRule; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /** * 定制 Ribbon 负载均衡策略的配置类 * 该自定义 Ribbon 负载均衡策略配置类 不能在 com.lw.c 包及其子包下 * 否则所有的 Ribbon 客户端都会采用该策略,无法达到特殊化定制的目的 */ @Configuration public class MySelfRibbonRuleConfig { @Bean public IRule myRule(){ //负载均衡:随机策略 return new MyRandomRule(); } }
3. 修改位于 com.lw.c 包下的主启动类,在该类上使用 @RibbonClient 注解让我们定制的负载均衡策略生效,代码如下。
package com.lw.c; import com.lw.myrule.MySelfRibbonRuleConfig; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; import org.springframework.cloud.netflix.ribbon.RibbonClient; @SpringBootApplication @EnableEurekaClient //自定义 Ribbon 负载均衡策略在主启动类上使用 RibbonClient 注解,在该微服务启动时, // 就能自动去加载我们自定义的 Ribbon 配置类,从而是配置生效 // name 为需要定制负载均衡策略的微服务名称(application name) configuration 为定制的负载均衡策略的配置类, // 且官方文档中明确提出,该配置类不能在 ComponentScan 注解(SpringBootApplication 注解中包含了该注解)下的包或其子包中, // 即自定义负载均衡配置类不能在 com.lw.c 包及其子包下 @RibbonClient(name = "microServiceCloudProviderEmp", configuration = MySelfRibbonRuleConfig.class) public class MicroServiceCloudConsumerEmp80Application { public static void main(String[] args) { SpringApplication.run(MicroServiceCloudConsumerEmp80Application.class, args); } }
4. 重启 micro-service-cloud-consumer-dept-80,使用浏览器访问“http://eureka7001.com/consumer/emp/get/7788”,结果如下图。
定制负载均衡策略
通过上图中 ename字段取值的变化可以看出,我们定制的负载均衡策略已经生效。
更多推荐
所有评论(0)