Spring Cloud Ribbon负载均衡
ribbon的版本是:ribbon-loadbalancer-2.3.0
一.IRule
:定义了选择负载均衡策略的基本操作。通过调用choose()方法,就可以选择具体的负载均衡策略。
package com.netflix.loadbalancer;
/**
* Interface that defines a "Rule" for a LoadBalancer. A Rule can be thought of
* as a Strategy for loadbalacing. Well known loadbalancing strategies include
* Round Robin, Response Time based etc.
*
* @author stonse
*
*/
public interface IRule{
/*
* choose one alive server from lb.allServers or
* lb.upServers according to key
*
* @return choosen Server object. NULL is returned if none
* server is available
*/
// 选择目标服务节点
public Server choose(Object key);
// 设置负载均衡策略
public void setLoadBalancer(ILoadBalancer lb);
// 获取负载均衡策略
public ILoadBalancer getLoadBalancer();
}
二.ILoadBalancer
接口定义了ribbon负载均衡的常用操作
package com.netflix.loadbalancer;
import java.util.List;
/**
* Interface that defines the operations for a software loadbalancer. A typical
* loadbalancer minimally need a set of servers to loadbalance for, a method to
* mark a particular server to be out of rotation and a call that will choose a
* server from the existing list of server.
*
* @author stonse
*
*/
public interface ILoadBalancer {
/**
* Initial list of servers.
* This API also serves to add additional ones at a later time
* The same logical server (host:port) could essentially be added multiple times
* (helpful in cases where you want to give more "weightage" perhaps ..)
*
* @param newServers new servers to add
*/
public void addServers(List<Server> newServers);
/**
* Choose a server from load balancer.
*
* @param key An object that the load balancer may use to determine which server to return. null if
* the load balancer does not use this parameter.
* @return server chosen
*/
public Server chooseServer(Object key);
/**
* To be called by the clients of the load balancer to notify that a Server is down
* else, the LB will think its still Alive until the next Ping cycle - potentially
* (assuming that the LB Impl does a ping)
*
* @param server Server to mark as down
*/
public void markServerDown(Server server);
/**
* @deprecated 2016-01-20 This method is deprecated in favor of the
* cleaner {@link #getReachableServers} (equivalent to availableOnly=true)
* and {@link #getAllServers} API (equivalent to availableOnly=false).
*
* Get the current list of servers.
*
* @param availableOnly if true, only live and available servers should be returned
*/
@Deprecated
public List<Server> getServerList(boolean availableOnly);
/**
* @return Only the servers that are up and reachable.
*/
public List<Server> getReachableServers();
/**
* @return All known servers, both reachable and unreachable.
*/
public List<Server> getAllServers();
三.AbstractLoadBalancerRule
实现了IRule
接口和IClientConfigAware
接口,主要对IRule
接口的2个方法进行了简单封装。
AbstractLoadBalancerRule是每个负载均衡策略需要直接继承的类,Ribbon提供的几个负载均衡策略,都继承了这个抽象类。同理,我们如果需要自定义负载均衡策略,也要继承这个抽象类。
package com.netflix.loadbalancer;
import com.netflix.client.IClientConfigAware;
/**
* Class that provides a default implementation for setting and getting load balancer
* @author stonse
*/
public abstract class AbstractLoadBalancerRule implements IRule, IClientConfigAware {
private ILoadBalancer lb;
@Override
public void setLoadBalancer(ILoadBalancer lb){
this.lb = lb;
}
@Override
public ILoadBalancer getLoadBalancer(){
return lb;
}
}
四.AbstractLoadBalancerRule
的实现类就是ribbon的具体负载均衡策略
1,轮询策略(RoundRobinRule)
2,随机策略(RandomRule)
3,可用过滤策略(AvailabilityFilteringRule)
4,响应时间权重策略(WeightedResponseTimeRule)
5,轮询失败重试策略(RetryRule)
6,并发量最小可用策略(BestAvailableRule)
7,复合判断server所在区域的性能和server的可用性选择server (ZoneAvoidanceRule)
策略名 | 策略描述 | 实现说明 |
---|---|---|
RandomRule | 随机选择一个 server | 在 index 上随机,选择 index 对应位置的 Server |
RoundRobinRule | 轮询选择 server | 轮询 index,选择 index 对应位置的 server |
ZoneAvoidanceRule | 复合判断 server 所在区域的性能和 server 的可用性选择 server | 使用 ZoneAvoidancePredicate 和 AvailabilityPredicate 来判断是否选择某个 server。ZoneAvoidancePredicate 判断判定一个 zone 的运行性能是否可用,剔除不可用的 zone(的所有 server);AvailabilityPredicate 用于过滤掉连接数过多的 server。 |
BestAvailableRule | 选择一个最小并发请求的 server | 逐个考察 server,如果 server 被 tripped 了则忽略,在选择其中activeRequestsCount 最小的 server |
AvailabilityFilteringRule | 过滤掉那些因为一直连接失败的被标记为 circuit tripped 的后端 server,并过滤掉那些高并发的的后端 server(activeConnections 超过配置的阈值) | 使用一个 AvailabilityPredicate 来包含过滤 server 的逻辑,其实就就是检查 status 里记录的各个 server 的运行状态 |
WeightedResponseTimeRule | 根据 server 的响应时间分配一个 weight,响应时间越长,weight 越小,被选中的可能性越低 | 一个后台线程定期的从 status 里面读取评价响应时间,为每个 server 计算一个 weight。weight 的计算也比较简单,responseTime 减去每个 server 自己平均的 responseTime 是 server 的权重。当刚开始运行,没有形成 status 时,使用 RoundRobinRule 策略选择 server。 |
RetryRule | 对选定的负载均衡策略机上重试机制 | 在一个配置时间段内当选择 server 不成功,则一直尝试使用 subRule 的方式选择一个可用的 server |
默认情况下,Ribbon 采用 ZoneAvoidanceRule 规则。因为大多数公司是单机房,所以一般只有一个 zone,而 ZoneAvoidanceRule 在仅有一个 zone 的情况下,会退化成轮询的选择方式,所以会和 RoundRobinRule 规则类似。
经典的负载均衡规则可以整理如下:
轮询(Round Robin) or 加权轮询(Weighted Round Robin)
随机(Random) or 加权随机(Weighted Random)
源地址哈希(Hash) or 一致性哈希(ConsistentHash)
最少连接数(Least Connections)
最小响应时间(ResponseTime)
五.BaseLoadBalancer
是一个负载均衡器,是ribbon框架提供的负载均衡器。Spring Cloud对ribbon封装以后,直接调用ribbon的负载均衡器来实现微服务客户端的负载均衡。
ribbon框架本身提供了几个负载均衡器,BaseLoadBalancer只是其中之一。
Spring Cloud提供了2个接口:ServiceInstanceChooser和LoadBalancerClient,这2个接口就是客户端负载均衡的定义。具体实现类是RibbonLoadBalancerClient。RibbonLoadBalancerClient#choose()方法根据微服务实例的serviceId,然后使用配置的负载均衡策略,打到对于的微服务实例节点上。
执行逻辑:
- Spring Cloud RibbonLoadBalancerClient#choose()调用ribbon框架的BaseLoadBalancer.
- BaseLoadBalancer#chooseServer()选择具体的负载均衡策略(RoundRibonRule),然后执行。
六.自定义负载均衡策略
Ribbon不仅实现了几种负载均衡策略,也为开发者提供了自定义负载均衡策略的支持。
自定义负载均衡策略有3个关键点:
- 继承抽象类AbstractLoadBalancerRule
- 自定义的负载均衡策略类,不能放在@ComponentScan所扫描的当前包和子包下。
- 在主启动类上添加@RibbonClient注解,或者在配置文件中指定哪个微服务使用自定义负载均衡策略
在自定义 Ribbon 配置的时候,会有全局和客户端两种级别。相比来说,客户端级别是更细粒度的配置。针对每个服务,Spring Cloud Netflix Ribbon 会创建一个 Ribbon 客户端,并且使用服务名作为 Ribbon 客户端的名字。
@RibbonClient注解的使用方法如下:
@RibbonClient(name=“微服务名称”, configuration=“自定义配置类.class”)
#配置文件中配置项如下:
服务名称.NFLoadBalancerRuleClassName=com.netflix.loadbalancer.RandomRule