我们项目配置了AvailabilityFilteringRule作为所有Ribbon调用的负载均衡规则,它有那些坑呢(理解歧义和注意点)?

首先来看com.netflix.loadbalancer.AvailabilityFilteringRule.java源码,核心是choose方法:

public Server choose(Object key) {
int count = 0;
//通过轮询选择一个server
Server server = roundRobinRule.choose(key);
//尝试10次如果都不满足要求,就放弃,采用父类的choose
//这里为啥尝试10次?
//1. 轮询结果相互影响,可能导致某个请求每次调用轮询返回的都是同一个有问题的server
//2. 集群很大时,遍历整个集群判断效率低,我们假设集群中健康的实例要比不健康的多,如果10次找不到,就用父类的choose,这也是一种快速失败机制
while (count++ <= 10) {
if (predicate.apply(new PredicateKey(server))) {
return server;
}
server = roundRobinRule.choose(key);
}
return super.choose(key);
}

轮询是怎么轮询呢,为啥会相互影响?
来看下RoundRobinRule的源码

//多线程轮询算法
private int incrementAndGetModulo(int modulo) {
for (;;) {
//当前值
int current = nextServerCyclicCounter.get();
//新值,通过对于modulo(就是实例个数)取余
int next = (current + 1) % modulo;
//只有设置成功才返回
if (nextServerCyclicCounter.compareAndSet(current, next))
return next;
}
} public Server choose(ILoadBalancer lb, Object key) {
if (lb == null) {
log.warn("no load balancer");
return null;
} Server server = null;
int count = 0;
//这里也是10次,不遍历整个集群,防止一个请求执行过长时间在选server上,快速失败
while (server == null && count++ < 10) {
List<Server> reachableServers = lb.getReachableServers();
List<Server> allServers = lb.getAllServers();
int upCount = reachableServers.size();
int serverCount = allServers.size(); if ((upCount == 0) || (serverCount == 0)) {
log.warn("No up servers available from load balancer: " + lb);
return null;
} int nextServerIndex = incrementAndGetModulo(serverCount);
server = allServers.get(nextServerIndex); if (server == null) {
/* Transient. */
Thread.yield();
continue;
}
//判断server状态
if (server.isAlive() && (server.isReadyToServe())) {
return (server);
} // Next.
server = null;
} if (count >= 10) {
log.warn("No available alive servers after 10 tries from load balancer: "
+ lb);
}
return server;
}

AvailabilityFilteringRule如何判断Server满足条件?

看下判断类AvailabilityPredicate的源码:

这里涉及两个配置:

public boolean apply(@Nullable PredicateKey input) {
LoadBalancerStats stats = getLBStats();
if (stats == null) {
return true;
}
//判断是否满足条件
return !shouldSkipServer(stats.getSingleServerStat(input.getServer()));
} private boolean shouldSkipServer(ServerStats stats) {
//niws.loadbalancer.availabilityFilteringRule.filterCircuitTripped是否为true
if ((CIRCUIT_BREAKER_FILTERING.get() &&
//该Server是否为断路状态
stats.isCircuitBreakerTripped())
//本机发往这个Server未处理完的请求个数是否大于Server实例最大的活跃连接数
|| stats.getActiveRequestsCount() >= activeConnectionsLimit.get()) {
return true;
}
return false;
}

Server是否为断路状态是如何判断的呢?
ServerStats源码,这里详细源码我们不贴了,说一下机制:

断路是通过时间判断实现的。每次失败记录上次失败时间。如果失败了触发判断是否断路的最小失败次数以上的次数,则判断:

计算断路持续时间: (2^失败次数)* 断路时间因子,如果大于最大断路时间,则取最大断路时间。
判断当前时间是否大于上次失败时间+短路持续时间,如果小于,则是断路状态
这里又涉及三个配置(这里需要将default替换成你调用的微服务名称):

  • niws.loadbalancer.default.connectionFailureCountThreshold,默认为3, 触发判断是否断路的最小失败次数,也就是,默认如果失败三次,就会判断是否要断路了。
  • niws.loadbalancer.default.circuitTripTimeoutFactorSeconds, 默认为10, 断路时间因子,
  • niws.loadbalancer.default.circuitTripMaxTimeoutSeconds,默认为30,最大断路时间

ServerStats如何更新呢?
首先是清空,根据我的另一系列文章对于Eureka源码和配置的分析,每次在ribbon从eureka本地定时重新拉取server列表时,就会清空。这个配置是:

#eureka客户端ribbon刷新时间
#默认30s
ribbon.ServerListRefreshInterval=1000

这里我们配置是1秒,也就是1秒内如果断路三次,就会触发断路判断。

然后是怎么增加断路次数?这里我们看调用这个方法的源码,有效调用里面都有一个判断:

if (lbContext.getRetryHandler().isCircuitTrippingException(throwable)) {
//调用增加断路次数
}

这个isCircuitTrippingException,对于默认的DefaultLoadBalancerRetryHandler就是判断是否为SocketException.class, SocketTimeoutException.class这两个异常。如果是,就会记录到断路次数

SocketException.class, SocketTimeoutException.class两个异常的坑与Ribbon连接超时时间
参考我另一篇文章,Ribbon对于SocketTimeOutException重试的坑以及重试代码解析,这里不要把Ribbon的连接超时设置太短,一般如下设置即可:

#ribbon连接超时
ribbon.ConnectTimeout=500

客户端负载均衡Ribbon之三:AvailabilityFilteringRule的坑(Spring Cloud Finchley.SR2)的更多相关文章

  1. 服务注册发现Eureka之三:Spring Cloud Ribbon实现客户端负载均衡(客户端负载均衡Ribbon之三:使用Ribbon实现客户端的均衡负载)

    在使用RestTemplate来消费spring boot的Restful服务示例中,我们提到,调用spring boot服务的时候,需要将服务的URL写死或者是写在配置文件中,但这两种方式,无论哪一 ...

  2. 【springcloud】客户端负载均衡(Ribbon)

    转自:https://blog.csdn.net/pengjunlee/article/details/86594934 服务器端负载均衡负载均衡是我们处理高并发.缓解网络压力和进行服务器扩容的重要手 ...

  3. Spring Cloud入门教程(二):客户端负载均衡(Ribbon)

    对于大型应用系统负载均衡(LB:Load Balancing)是首要被解决一个问题.在微服务之前LB方案主要是集中式负载均衡方案,在服务消费者和服务提供者之间又一个独立的LB,LB通常是专门的硬件,如 ...

  4. 客户端负载均衡Ribbon

    客户端负载均衡Ribbon 一.Ribbon是什么 二.Ribbon实现客户端负载均衡 三.Ribbon负载均衡策略 四.Rest请求模板类解读 4.1 RestTemplate的GET请求 第一种: ...

  5. 【Dalston】【第二章】客户端负载均衡(Ribbon)

    对于大型应用系统负载均衡(LB:Load Balancing)是首要被解决一个问题.在微服务之前LB方案主要是集中式负载均衡方案,在服务消费者和服务提供者之间又一个独立的LB,LB通常是专门的硬件,如 ...

  6. 客户端负载均衡Ribbon之一:Spring Cloud Netflix负载均衡组件Ribbon介绍

    Netflix:['netfliːks] ribbon:英[ˈrɪbən]美[ˈrɪbən]n. 带; 绶带; (打印机的) 色带; 带状物;v. 把…撕成条带; 用缎带装饰; 形成带状;     L ...

  7. spring cloud 之 客户端负载均衡 Ribbon

    一.负载均衡 负载均衡(Load Balance): 建立在现有网络结构之上,它提供了一种廉价有效透明的方法扩展网络设备和服务器的带宽.增加吞吐量.加强网络数据处理能力.提高网络的灵活性和可用性.其意 ...

  8. Spring Cloud第四篇 | 客户端负载均衡Ribbon

    ​ 本文是Spring Cloud专栏的第四篇文章,了解前三篇文章内容有助于更好的理解本文: ​Spring Cloud第一篇 | Spring Cloud前言及其常用组件介绍概览 Spring Cl ...

  9. 客户端负载均衡Ribbon之二:Loadbalance的源码

    Load Balance负载均衡是用于解决一台机器(一个进程)无法解决所有请求而产生的一种算法. 像nginx可以使用负载均衡分配流量,ribbon为客户端提供负载均衡,dubbo服务调用里的负载均衡 ...

随机推荐

  1. 利用Unicode RTLO方法构建恶意文件名

    一:简介 RTLO"字符全名为"RIGHT-TO-LEFTOVERRIDE",是一个不可显示的控制类字符,其本质是unicode 字符."RTLO"字 ...

  2. 【CSP模拟赛】天才绅士少女助手克里斯蒂娜(线段树&读入优化&输出优化)

    题面描述 红莉栖想要弄清楚楼下天王寺大叔的显像管电视对“电话微波炉(暂定)”的影响.选取显像管的任意一个平面,一开始平面内有个n电子,初始速度分别为vi,定义飘升系数为 $$\sum_{1\leqsl ...

  3. NAT端口映射综合详解

  4. Android中Popupwindow和Dialog的区别

    Android中的对话框有两种:PopupWindow和AlertDialog.它们都可以实现弹窗功能,但是他们之间有一些差别,下面总结了一点. (1)Popupwindow在显示之前一定要设置宽高, ...

  5. [Linux] 内核通知链 notifier

    Linux 内核中每个模块之间都是独立的,如果模块需要感知其他模块的事件,就需要用到内核通知链. 最典型的通知链应用就是 LCD 和 TP 之间,TP 需要根据 LCD 的亮灭来控制是否打开关闭触摸功 ...

  6. ls命令的简单实现

    ls命令的简单实现 目标:简单的实现ls命令 实现的mic_ls命令主要功能 1.循环遍历目录 2.列出目标目录所有的子目录和文件 3.列出文件的文件权限,所有者,文件大小等详细信息 参数 -r 循环 ...

  7. name_scope与variable_scope 详解

    版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/lucky7213/article/deta ...

  8. IdHTTPServer开发https服务器

    IdHTTPServer开发https服务器 该篇经验同样适用于DATASNAP和UNIGUI,因为它们都基于INDY10. 1)需要TIdServerIOHandlerSSLOpenSSL控件 2) ...

  9. SQL Server 静默安装

    SQL Server 安装时,需要在各个安装窗口进行选择和设置,若需要在多台服务器安装相同的数据库,静默安装是比较省事的. 当安装 SQL Server  到最后一步,会有一个安装配置文件 Confi ...

  10. 【转】php7+IIS 配置环境(windows环境)

    继php7+apache2.4 配置环境(window环境)后,由于B2C项目准备上线:特此小编在阿里云上搭建PHP7环境,为此特写上搭建过程希望正处于搭建php7+IIS(windows环境)中的朋 ...