在学习Ribbon以前,先看一下这张图,这张图完美的把Ribbon的基础架构给描述出来了架构
这张图的核心是负载均衡管理器,围绕着它的是外面的这5大功能点,我们就从核心开始看而后再带出来其余的功能并发
首先看一下负载均衡器的核心接口ILoadBalancer
负载均衡
public interface ILoadBalancer {
public void addServers(List<Server> newServers);
public Server chooseServer(Object key);
public void markServerDown(Server server);
public List<Server> getReachableServers();
public List<Server> getAllServers();
}复制代码
这个接口中保护了一个基本的负载均衡器所必须的全部功能:dom
addServers(List)
向负载均衡器中添加服务实例 chooseServer(Object)
根据负载均衡策略,从负载均衡器中挑选出一个服务实例 markServerDown(Server)
下线负载均衡器中的某个具体实例 getReachableServers()
返回当前可正常服务的实例列表 getAllServers()
返回全部的服务实例列表 接着来看一下这个接口的UML图学习
首先看AbstractLoadBalancer
这个类,这个类是ILoadBalancer
接口的抽象类实现。在这个抽象类中定义了一个表示服务实例状态的枚举的同时还新增了两个抽象方法:url
public enum ServerGroup{
ALL,
STATUS_UP,
STATUS_NOT_UP
}
public abstract List<Server> getServerList(ServerGroup serverGroup);
public abstract LoadBalancerStats getLoadBalancerStats();复制代码
getServerList(ServerGroup)
:根据分组类型来返回不一样的服务实例列表。 getLoadBalancerStats()
:返回LoadBalancerStatus
对象,这个LoadBalancerStats
对象是用来存储负载均衡器中各个服务实例当前的属性和统计信息的 AbstractLoadBalancer
共有两个实现类,右侧的NoOpLoadBalancer
是一个空的实现类,这里能够忽略不计。这里接着继续看BaseLoadBalancer
spa
BaseLoadBalancer
是负载均衡器的基础实现类,这个类对于接口ILoadBalancer
的全部方法都给予了基础的实现,除此以外还保护了不少重要的对象线程
两个存储当前服务实例对象的列表,一个是包含全部服务、一个是包含正常服务code
@Monitor(name = PREFIX + "AllServerList", type = DataSourceType.INFORMATIONAL)
protected volatile List<Server> allServerList = Collections
.synchronizedList(new ArrayList<Server>());
@Monitor(name = PREFIX + "UpServerList", type = DataSourceType.INFORMATIONAL)
protected volatile List<Server> upServerList = Collections
.synchronizedList(new ArrayList<Server>());复制代码
存储负载系统器各服务实例属性和统计信息的对象cdn
protected LoadBalancerStats lbStats;
复制代码
protected IPing ping = null;
复制代码
IPing
是用来向服务发起心跳检测的,经过心跳检测来判断该服务是否可用。IPing
的实现类有如下几种:
PingUrl
:使用HttpClient去get请求某个url,判断其是否alive PingConstant
:固定返回某服务是否可用,默认返回true NoOpPing
:没有任何操做,直接返回true DummyPing
:一样是直接返回true NIWSDiscoveryPing
:根据服务的实例对象InstanceInfo
的InstanceStatus
去判断,若是为InstanceStatus.UP,则为可用 心跳检测策略对象IPingStrategy
private final static SerialPingStrategy DEFAULT_PING_STRATEGY = new SerialPingStrategy();
protected IPingStrategy pingStrategy = DEFAULT_PING_STRATEGY;
复制代码
默认实现是线型轮询
private final static IRule DEFAULT_RULE = new RoundRobinRule();
protected IRule rule = DEFAULT_RULE;复制代码
IRule
是在选择实例的时候的负载均衡策略对象,默认使用的是RoundRobinRule
线性轮询
除此以外的实现为:
BestAvailableRule
:选择最小请求数 RandomRule
:随机选择 RetryRule
:轮询重试 WeightedResponseTimeRule
:根据响应时间分配权重 ZoneAvoidanceRule
:根据服务的分区可用性轮询 如今继续看BaseLoadBalancer
的子类DynamicServerListLoadBalancer
这个类对基础负载均衡器作了扩展。扩展的功能以下:
public interface ServerList<T extends Server> {
/**
* 获取初始化的服务列表
*/
public List<T> getInitialListOfServers();
/**
* 获取更新后的服务列表
*/
public List<T> getUpdatedListOfServers();
}复制代码
在DynamicServerListLoadBalancer
中默认使用的服务列表实现类是DomainExtractingServerList
,只不过该服务列表内部还定义了一个服务列表,这个服务列表的实现类则是DiscoveryEnabledNIWSServerList
这个最终的服务列表的数据来源则主要依靠EurekaClient从注册中心获取
这个接口定义了一系列的对服务列表的更新操做
public interface ServerListUpdater {
//内部接口
public interface UpdateAction {
//实现对服务列表的更新操做
void doUpdate();
}
//启动服务更新器
void start(UpdateAction updateAction);
//中止服务更新器
void stop();
//返回最近的更新时间戳
String getLastUpdate();
//返回上一次更新到如今的时间间隔(ms)
long getDurationSinceLastUpdateMs();
//返回错过的更新周期数
int getNumberMissedCycles();
//返回核心线程数
int getCoreThreads();
}复制代码
它的实现类有两个:
PollingServerListUpdater
:经过定时任务进行更新 EurekaNotificationServerListUpdater
:利用Eureka的事件监听器来更新 public interface ServerListFilter<T extends Server> {
public List<T> getFilteredListOfServers(List<T> servers);
}复制代码
该接口主要用于根据一些规则过滤传入的服务实例列表,该接口的实现类以下:
ZoneAffinityServerListFilter
:基于Eureka的分区规则对服务实例的过滤 DefaultNIWSServerListFilter
:ZoneAffinityServerListFilter
的子类且没有作特殊的更新 ServerListSubsetFilter
:经过比较服务实例的通讯失败数和并发链接数来剔除那些相对不够健康的实例 ZonePreferenceServerListFilter
:使用SpringCloud整合eureka和ribbon时默认使用的该过滤器。它实现了经过配置或eureka实例无数据的所属区域(Zone)来过滤出同区域的服务实例 ZoneAwareLoadBalancer
则是对DynamicServerListLoadBalancer
的扩展,它主要增长了区域过滤的功能