【SpringCloud】Netflix源码解析之Ribbon:负载均衡策略的定义和实现
Ribbon负载均衡策略定义
IRule其实就只做了一件事情Server choose(Object key),可以看到这个功能是在LB中定义(要求)的,LB把这个功能委托给IRule来实现。不同的IRule可以向LB提供不同的负载均衡算法。
public interface IRule{
public Serverchoose(Object key);
public void setLoadBalancer(ILoadBalancerlb);
public ILoadBalancergetLoadBalancer();
}
com.netflix.loadbalancer包下面的提供了常用的几种策略。有RoundRobinRule、RandomRule这样的不依赖于Server运行状况的策略,也有AvailabilityFilteringRule、WeightedResponseTimeRule等多种基于收集到的Server运行状况决策的策略。判断运行状况时有,判断单个server的,也有判断整个zone的,适用于各种不同场景需求。
实现上有些策略可以继承一个既存的简单策略用于某些启动时候,也可以包含一个简单策略。甚至有ZoneAvoidanceRule这样的可以包含复合谓词的条件判断。TODOTODO IRue hireachy
Ribbon自带负载均衡策略比较
| 策略名 | 策略声明 | 策略描述 | 实现说明 |
| BestAvailableRule | public class BestAvailableRule extends ClientConfigEnabledRoundRobinRule | 选择一个最小的并发请求的server | 逐个考察Server,如果Server被tripped了,则忽略,在选择其中ActiveRequestsCount最小的server |
| AvailabilityFilteringRule | public class AvailabilityFilteringRule extends PredicateBasedRule | 过滤掉那些因为一直连接失败的被标记为circuit tripped的后端server,并过滤掉那些高并发的的后端server(active connections 超过配置的阈值) | 使用一个AvailabilityPredicate来包含过滤server的逻辑,其实就就是检查status里记录的各个server的运行状态 |
| WeightedResponseTimeRule | public class WeightedResponseTimeRule extends RoundRobinRule | 根据相应时间分配一个weight,相应时间越长,weight越小,被选中的可能性越低。 | 一个后台线程定期的从status里面读取评价响应时间,为每个server计算一个weight。Weight的计算也比较简单responsetime 减去每个server自己平均的responsetime是server的权重。当刚开始运行,没有形成statas时,使用roubine策略选择server。 |
| RetryRule | public class RetryRule extends AbstractLoadBalancerRule | 对选定的负载均衡策略机上重试机制。 | 在一个配置时间段内当选择server不成功,则一直尝试使用subRule的方式选择一个可用的server |
| RoundRobinRule | public class RoundRobinRule extends AbstractLoadBalancerRule | roundRobin方式轮询选择server | 轮询index,选择index对应位置的server |
| RandomRule | public class RandomRule extends AbstractLoadBalancerRule | 随机选择一个server | 在index上随机,选择index对应位置的server |
| ZoneAvoidanceRule | public class ZoneAvoidanceRule extends PredicateBasedRule | 复合判断server所在区域的性能和server的可用性选择server | 使用ZoneAvoidancePredicate和AvailabilityPredicate来判断是否选择某个server,前一个判断判定一个zone的运行性能是否可用,剔除不可用的zone(的所有server),AvailabilityPredicate用于过滤掉连接数过多的Server。 |
Ribbon自带负载均衡策略实现解析
1. com.netflix.loadbalancer.BestAvailableRule
功能:选择一个最小的并发请求的server
主要代码:逐个考察Server,如果Server被tripped了,则忽略,在选择其中ActiveRequestsCount最小的server
for (Serverserver: serverList) {
ServerStatsserverStats = loadBalancerStats.getSingleServerStat(server);
if (!serverStats.isCircuitBreakerTripped(currentTime)) {
int concurrentConnections = serverStats.getActiveRequestsCount(currentTime);
if (concurrentConnections < minimalConcurrentConnections) {
minimalConcurrentConnections = concurrentConnections;
chosen = server;
}
}
2 com.netflix.loadbalancer.AvailabilityFilteringRule
功能:过滤掉那些因为一直连接失败的被标记为circuit tripped的后端server,并过滤掉那些高并发的的后端server(active connections 超过配置的阈值)
主要代码:使用一个AvailabilityPredicate来包含过滤server的逻辑,其实就就是检查status里记录的各个server的运行状态,过滤掉那些高并发的的后端server(active connections 超过配置的阈值)
boolean com.netflix.loadbalancer.AvailabilityPredicate.shouldSkipServer(ServerStatsstats)
{
if ((CIRCUIT_BREAKER_FILTERING.get() && stats.isCircuitBreakerTripped())
|| stats.getActiveRequestsCount() >= activeConnectionsLimit.get()) {
return true;
}
return false;
}
3 com.netflix.loadbalancer.WeightedResponseTimeRule
功能:根据相应时间分配一个weight,相应时间越长,weight越小,被选中的可能性越低。 ”
主要代码:一个后台线程定期的从status里面读取评价响应时间,为每个server计算一个weight。Weight的计算也比较简单responsetime 减去每个server自己平均的responsetime是server的权重。当刚开始运行,没有形成statas时,使用roubine策略选择server。
class DynamicServerWeightTask extends TimerTask {
public void run() {
ServerWeightserverWeight = new ServerWeight();
serverWeight.maintainWeights();
}
}
maintainWeights(){
List<Double> finalWeights = new ArrayList<Double>();
for (Serverserver : nlb.getAllServers()) {
ServerStatsss = stats.getSingleServerStat(server);
double weight = totalResponseTime – ss.getResponseTimeAvg();
weightSoFar += weight;
finalWeights.add(weightSoFar);
}
setWeights(finalWeights);}
Serverchoose(ILoadBalancerlb, Object key)
{
double randomWeight = random.nextDouble() * maxTotalWeight;
// pick the server index based on the randomIndex
int n = 0;
for (Double d : currentWeights) {
if (d >= randomWeight) {
serverIndex = n;
break;
} else {
n++;
}
}
server = allList.get(serverIndex);}
4 com.netflix.loadbalancer.RetryRule
功能:对选定的负载均衡策略机上重试机制。
主要代码:在一个配置时间段内当选择server不成功,则一直尝试使用subRule的方式选择一个可用的server
answer = subRule.choose(key);
if (((answer == null) || (!answer.isAlive()))
&& (System.currentTimeMillis() < deadline)) {
InterruptTasktask = new InterruptTask(deadline - System.currentTimeMillis());
while (!Thread.interrupted()) {
answer = subRule.choose(key);
if (((answer == null) || (!answer.isAlive()))
&& (System.currentTimeMillis() < deadline)) {
/* pause and retry hoping it’s transient */
Thread.yield();
} else {
break;
}
}
task.cancel();
5 com.netflix.loadbalancer.RoundRobinRule
功能:roundRobin方式轮询选择server
主要代码:轮询index,选择index对应位置的server
List<Server> allServers = lb.getAllServers();
int upCount = reachableServers.size();
int serverCount = allServers.size();
int nextServerIndex = incrementAndGetModulo(serverCount);
server = allServers.get(nextServerIndex);
6 com.netflix.loadbalancer.RandomRule
功能:随机选择一个server
主要代码:在index上随机,选择index对应位置的server
List<Server> upList = lb.getReachableServers();
List<Server> allList = lb.getAllServers();
int serverCount = allList.size();
int index = rand.nextInt(serverCount);
server = upList.get(index);
7 com.netflix.loadbalancer.ZoneAvoidanceRule
功能:复合判断server所在区域的性能和server的可用性选择server
主要代码:使用ZoneAvoidancePredicate和AvailabilityPredicate来判断是否选择某个server,前一个,以一个区域为单位考察可用性,对于不可用的区域整个丢弃,从剩下区域中选可用的server。判断出最差的区域,排除掉最差区域。在剩下的区域中,将按照服务器实例数的概率抽样法选择,从而判断判定一个zone的运行性能是否可用,剔除不可用的zone(的所有server),AvailabilityPredicate用于过滤掉连接数过多的Server。
public com.netflix.loadbalancer.PredicateBasedRule.Serverchoose(Object key) {
ILoadBalancerlb = getLoadBalancer();
Optional<Server> server = getPredicate().chooseRoundRobinAfterFiltering(lb.getAllServers(), key);
if (server.isPresent()) {
return server.get();
}
}
参照现有的若干中rule的实现风格,根据我们自己需要也可以开发出自定义的负载均衡策略。完。
参考资料:
http://www.tuicool.com/articles/7zIbIb3
【SpringCloud】Netflix源码解析之Ribbon:负载均衡策略的定义和实现的更多相关文章
- Spring-cloud & Netflix 源码解析:Eureka 服务注册发现接口 ****
http://www.idouba.net/spring-cloud-source-eureka-client-api/?utm_source=tuicool&utm_medium=refer ...
- springcloud(十四)、ribbon负载均衡策略应用案例
一.eureka-server服务中心项目不再创建 二.eureka-common-empdept公共组件项目不再掩饰 三.创建eureka-client-provider-empdept-one提供 ...
- Sentinel源码解析四(流控策略和流控效果)
引言 在分析Sentinel的上一篇文章中,我们知道了它是基于滑动窗口做的流量统计,那么在当我们能够根据流量统计算法拿到流量的实时数据后,下一步要做的事情自然就是基于这些数据做流控.在介绍Sentin ...
- Ribbon负载均衡策略与自定义配置new
Ribbon负载均衡策略 配置 对调用的某个服务启用某种负载策略 1)通过配置文件配置 hello: ribbon: NFLoadBalancerRuleClassName:com.netflix.l ...
- Ribbon负载均衡策略与自定义配置
Ribbon负载均衡策略 配置 对调用的某个服务启用某种负载策略 1)通过配置文件配置 hello: ribbon: NFLoadBalancerRuleClassName:com.netflix.l ...
- spring cloud深入学习(四)-----eureka源码解析、ribbon解析、声明式调用feign
基本概念 1.Registe 一一服务注册当eureka Client向Eureka Server注册时,Eureka Client提供自身的元数据,比如IP地址.端口.运行状况指标的Uri.主页地址 ...
- SpringCloud无废话入门02:Ribbon负载均衡
1.白话负载均衡 在上一篇的介绍中,我们创建了两个一模一样的服务提供者:Provider1和Provider2,然后它们提供的服务也一模一样,都叫Hello-Service.为什么一样的服务我们要部署 ...
- SpringCloud学习笔记(2):使用Ribbon负载均衡
简介 Spring Cloud Ribbon是基于Netflix Ribbon实现的一套客户端负载均衡工具,在注册中心对Ribbon客户端进行注册后,Ribbon可以基于某种负载均衡算法,如轮询(默认 ...
- SpringCloud微服务实现生产者消费者+ribbon负载均衡
一.生产者springcloud_eureka_provider (1)目录展示 (2)导入依赖 <dependency> <groupId>org.springframewo ...
随机推荐
- 怎么处理stdClass::__set_state
处理后 处理方法 function object2array_pre(&$object) { if (is_object($object)) { $arr = (array)($object) ...
- session过期情况下ajax请求不会触发重新登录的问题
在拦截器中添加以下逻辑 String requestType = request.getHeader("X-Requested-With"); if (!StringUtils.i ...
- HDU 6194 string string string(后缀自动机)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=3238 [题目大意] 给出一个字符串求其出现恰好k次的子串数量 [题解] 对串建立AC自 ...
- 【Trie】【枚举约数】Codeforces Round #482 (Div. 2) D. Kuro and GCD and XOR and SUM
题意: 给你一个空的可重集,支持以下操作: 向其中塞进一个数x(不超过100000), 询问(x,K,s):如果K不能整除x,直接输出-1.否则,问你可重集中所有是K的倍数的数之中,小于等于s-x,并 ...
- 移动web开发经验总结(1)
1.<meta name="viewport" content="initial-scale=1.0, maximum-scale=1.0, minimum-sca ...
- py脚本打包exe可执行文件
python3以上版本打包exe需要扩展软件:cx_freeze 下载地址:http://cx-freeze.sourceforge.net/ 1)安装后在\Python32\Scripts\cxfr ...
- Ajax-验证码
function validateCode(){ var code=document.getElementById("code").value; var spanObj=docum ...
- django源码(2.0.2)粗解之命令行执行
前言 django的命令行在整个的django web开发中都会经常用到,而且是必须得用到.所以,能够了解下django的命令行实现其实是非常有帮助的. 如果大家比较关心django命令的详细说明和使 ...
- PPT文化
PPT文化,yes or no? 知识是有体系的,有的时候刚接触的时候可以 推导技术 ,汇报.吹牛都可以应用上,并且可以让别人想想. 但是实际应用技术,就需要涉及很多详细的技术细节,如果少掉一个看似极 ...
- Installing Node.js via package manager | Node.js
Installing Node.js via package manager | Node.js i386 (32-bit)