原文首发地址:万字详解Spring Cloud 负载均衡组件 Ribbon,针对面试高频题多角度细说Spring Cloud Ribbon
为什么要使用Ribbon
上一章节我们学习了注册中心《阿里面试官问我:到底知不知道什么是Eureka,这次,我没沉默》,我们知道但我们存在多个服务提供者的时候,我们会让所有的服务提供者将服务节点信息都注册到EurekaServer中,然后让客户端去拉取一份服务注册列表到本地,服务消费者会从服务注册列表中找到合适的服务实例信息,通过IP:Port的方式去调用服务。
那么,消费者是如何决定调用哪一个服务实例呢,此时,本章节的主人公Ribbon默默的站了起来,笑着说,没错,正是在下。
Srping Cloud Ribbon 是基于 Netflix Ribbon实现的一套 客户端负载均衡的工具。
简单的说,Ribbon是Netflix发布的开源顶目,主要功能是解析配置中或注册中心的服务列表,通过客户端的软件负均衡算法来实现服务请求的分发。
Ribbon客户端组件提供一系列完善配置项如连接超时,重试等。
简单的说,就是在配置文件中列出LoadBalancer后面所有的机器,Ribbon会自动的帮助你基于某种规则(筒单轮洵,随机连接等)去连接这些机器。
我们也很容易使Ribbon实现自定义负载均衡算法。
Ribbon和Nginx又有什么不同呢?
集中式负载均衡
如图所示就是集中式负载均衡集中式负载均衡就好比房屋中介,他手里有很多房屋信息。
服务消费者就好比是需要租房的租客,我们并不能直接的和房屋主人进行租房交易,而是通过房屋中介选择房屋信息达成租房交易。
也就是说,客户端的请求信息并不会直接去请求服务实例,而是在到达负载均衡器的时候,通过负载均衡算法选择某一个服务实例,然后将请求转发到这个服务实例上。
集中式负载均衡又分为硬件负载均衡,如F5,软件负载均衡,如Nginx。
客户端负载均衡
如图所示就是客户端负载均衡就好比,现在有很多租房app,很多房屋的主人并不想通过中介租房,想省一笔中介费。
很多租客也想省一笔中介费,不想通过中介租房,于是租客将App上的租房信息记录在自己的笔记本上。
但是由于租客租房经验不足,并不知道应该选择哪一套房,此时刚好租客有一个做房屋中介好友(就是这么巧),于是租客将好友请到家里来,让他帮忙出谋划策,选择好房源,然后租客到时候直接去看房租房。
也就是说,此时客户端请求不会再去负载均衡器上进行转发了,客户端自己维护了一套服务列表,要掉用的某个服务实例之前首先会通过负载均衡算法选择一个服务节点,直接将请求发送到该服务节点上。
Ribbon 总体架构
首先我们看一张图:
接下来我们详细介绍下上图所示的Ribbon核心的6个组件接口。
IRule
释义:IRule就是根据特定算法中从服务器列表中选取一个要访问的服务,Ribbon默认的算法为轮询算法。
接下来我们来看一张IRule的类继承关系图:
其中用红色方框圈出来的叶子节点是现在还在使用的负载均衡算法,而用紫色方框圈出来的是已经废弃了的。
由图可知,目前我们使用的负载均衡算法有以下几种:
RoundRobinRule和WeightedResponseTimeRule
首先说明下 RoundRobinRule(轮询)策略,虽然我没有圈出来但是他是很常用的负载均衡算法,表示表示每次都取下一个服务器。
线性轮询算法实现:每一次把来自用户的请求轮流分配给服务器,从1开始,直到N(服务器个数),然后重新开始循环。算法的优点是其简洁性,它无需记录当前所有连接的状态,所以它是一种无状态调度。
通过图上的继承关系我们可知RoundRobinRule和WeightedResponseTimeRule是继承和被继承的关系。
WeightedResponseTimeRule是根据平均响应时间计算所有服务的权重,响应时间越快的服务权重越大被选中的概率越大。
有一个默认每30秒更新一次权重列表的定时任务,该定时任务会根据实例的响应时间来更新权重列表。
但是由于刚启动时如果统计信息不足,则使用RoundRobinRule(轮询)策略,等统计信息足够,会切换到WeightedResponseTimeRule。
AvailabilityFilteringRule
AvailabilityFilteringRule会先过滤掉由于多次访问故障而处于断路器状态的服务,还有并发的连接数量超过阈值的服务,然后对剩余的服务列表按照轮询策略进行访问。
ZoneAvoidanceRule
综合判断Server所在区域的性能和Server的可用性选择服务器。
BestAvailableRule
会先过滤掉由于多次访问故障而处于断路器跳闸状态的服务,然后选择一个并发量最小的服务。
RandomRule
随机选取服务。
使用 ThreadLocalRandom.current().nextInt(serverCount);随机选择。
RetryRule
先按照RoundRobinRule(轮询)的策略获取服务,如果获取的服务失败侧在指定的时间会进行重试,继续获取可用的服务。
自定义负载均衡算法
自定义负载均衡算法主要分三步:
-
实现IRule接口或者继承AbstractLoadBalancerRule类
-
重写choose方法
-
指定自定义的负载均衡策略算法类
首先我们创建一个MyRule类,但是这个类不能随便乱放。
官方文档给出警