irpas技术客

SpringCloud H版 Ribbon使用讲解及自定义负载算法_小毕超

大大的周 763

一、Ribbon

Spring Cloud Ribbon是基于Netflix Ribbon实现的一套客户端 负载均衡的工具。

简单的说,Ribbon是Netflix发布的开源项目,主要功能是提供客户端的软件负载均衡算法和服务调用。Ribbon客户端组件提供一系列完善的配置项如连接超时,重试等。简单的说,就是在配置文件中列出Load Balancer(简称LB)后面所有的机器,Ribbon会自动的帮助你基于某种规则(如简单轮询,随机连接等)去连接这些机器。我们很容易使用Ribbon实现自定义的负载均衡算法。

在前面的文章中,我们讲解到了eureka、zookeeper、consul作为注册中心,及采用 RestTemplate 作为客户端工具调用服务,后面我们也会讲到feign客户端工具。在使用中我们会发现,我们在声明 RestTemplate 时就加了一个@LoadBalanced 就实现了服务负载功能,其实是 ribbon 已经对RestTemplate 做了适配和优化,在RestTemplate 调用服务时会进入ribbon 的 负载规则器 ,选取出合适的请求服务ip 和 端口再交于 RestTemplate 进行http 请求。

上篇文章地址:https://blog.csdn.net/qq_43692950/article/details/121990497

在前面的演示中,我们也发现了,我们其实并没有针对的引入ribbon 的依赖,却也使用了ribbon的功能,ribbon已经附在了 eureka或其他一些cloud工具包中了,因此大多数情况下,我们无需主动配置ribbon的依赖:

二、Ribbon的基本使用

如果是采用 RestTemplate 作为客户端调用工具,只需在声明RestTemplate时加上 @LoadBalanced 即可自动使用 Ribbon的负载功能:

@Configuration public class RestTemplateConfig { @Bean @LoadBalanced public RestTemplate getRestTemplate() { return new RestTemplate(); } }

如果是 feign 客户端工具,当然现在普遍用的是openFeign,在引入openFeign的依赖时,也会附带 ribbon,可以理解为 feign 是一个ribbon + httpclient 的结合封装产品,所以使用feign 时,如果是指定的注册中心的服务,则会自动开启了负载均衡。

三、Ribbon的负载均衡算法

Ribbon默认是采用轮训的算法,当然Ribbon肯定不只是这一种算法,但轮训也是我们项目中比较常用的一个选择,因为现在微服务,强调服务平等,大家都承受相同的压力,便于对服务的管理,但有时我们可能不想使用轮训算法。ribbon 所有的策略算法均实现与IRule 接口,下面我们看下Ribbon为我们提供的算法有哪些:

各个算法的说明:

RoundRobinRule:轮询

RandomRule:随机

AvailabilityFilteringRule:会先过滤掉由于多次访问故障而处于断路器状态的服务,还有并发的连接数量超过阈值的服务,然后对剩余的服务列表按照轮询策略进行访问

WeightedResponseTimeRule:根据平均响应时间计算所有服务的权重,响应时间越快的服务权重越大被选中的概率越大。刚启动时如果统计信息不足,则使用RoundRobinRule(轮询)策略,等统计信息足够,会切换到WeightedResponseTimeRule

RetryRule:先按照RoundRobinRule(轮询)策略获取服务,如果获取服务失败则在指定时间内进行重试,获取可用的服务

BestAvailableRule:会先过滤掉由于多次访问故障而处于断路器跳闸状态的服务,然后选择一个并发量最小的服务

ZoneAvoidanceRule:复合判断Server所在区域的性能和Server的可用性选择服务器

四、切换Ribbon的负载均衡算法

上面我们了解到了,各种ribbon提供的负载算法,下面就需要我们针对性的切换到合适的算法,下面均在服务消费者端修改:

我们将默认的轮训算法替换为随机算法

添加 RibbonLoadBalancedConfig.java public class RibbonLoadBalancedConfig { @Bean public IRule myRule() { //定义为随机算法 return new RandomRule(); } }

注意:官方文档明确给出了警告,这个自定义配置类不能放在@ComponentScan所扫描的当前包下以及子包下,否则我们自定义的这个配置类就会被所有的Ribbon客户端所共享,达不到特殊化定制的目的了。当然如果想要全局的吧ribbon的算法替换掉,就可以放到@ComponentScan扫描的范围,下面我们只对provider服务设置随机算法:

修改主启动类:

添加@RibbonClient注解

@SpringBootApplication @EnableDiscoveryClient @RibbonClient(name = "provider", configuration = RibbonLoadBalancedConfig.class) public class ConsulConsumerApplication { public static void main(String[] args) { SpringApplication.run(ConsulConsumerApplication.class, args); } }

下面再次请求就可以看出,已经不是轮训算法了。

五、自定义Ribbon的负载均衡算法

如果Ribbon自带的算法不能满足我们的需求,我们也可以自定义负载算法,上面我们了解到了,所有的规则都实现于 IRule 接口和 继承AbstractLoadBalancerRule 抽象模板,既然我们要自定义也要符合它的规则,下面我们创建自定义类继承 AbstractLoadBalancerRule模板。

@Slf4j public class MyLoadBalanced extends AbstractLoadBalancerRule { private AtomicInteger atomicInteger = new AtomicInteger(0); @Override public void initWithNiwsConfig(IClientConfig iClientConfig) { } @Override public Server choose(Object key) { return this.choose(this.getLoadBalancer(), key); } private Server choose(ILoadBalancer lb, Object key) { if (lb == null) { log.warn("no load balancer"); return null; } else { List<Server> reachableServers = lb.getReachableServers(); int count = getAndIncrement(); int index = count % reachableServers.size(); Server server = reachableServers.get(index); log.info("访问次数:{} ,当前调用服务ip:{} , port: {} ", count, server.getHost(), server.getPort()); return server; } } public final int getAndIncrement() { int current; int next; do { current = this.atomicInteger.get(); next = current >= Integer.MAX_VALUE ? 0 : current + 1; } while (!this.atomicInteger.compareAndSet(current, next)); return next; } }

上面的程序,我们也是简单实现了一个轮训的效果,以此来作为演示,大家可以根据需求编写自己的算法。

下面将我们的算法替换掉默认的轮训:

public class RibbonLoadBalancedConfig { @Bean public IRule myRule() { //定义为随机算法 // return new RandomRule(); return new MyLoadBalanced(); } }

最后在主启动类中声明:

@SpringBootApplication @EnableDiscoveryClient @RibbonClient(name = "provider", configuration = RibbonLoadBalancedConfig.class) public class ConsulConsumerApplication { public static void main(String[] args) { SpringApplication.run(ConsulConsumerApplication.class, args); } }

再次请求,也是轮训的效果,不过看下打印的日志,走的已经是我们自定义的算法了:

喜欢的小伙伴可以关注我的个人微信公众号,获取更多学习资料!


1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,会注明原创字样,如未注明都非原创,如有侵权请联系删除!;3.作者投稿可能会经我们编辑修改或补充;4.本站不提供任何储存功能只提供收集或者投稿人的网盘链接。

标签: #springcloud #H版 #一RibbonSpring #Cloud #Ribbon实现的一套客户端 #负载均衡的工具