如题,本文基于Spring Cloud Finchley.SR2

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

首先来看源码,核心是choose方法:

public Server choose(Object key) {int count = 0;//通过轮询选择一个serverServer 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的源码:

这里涉及两个配置:

  1. niws.loadbalancer.availabilityFilteringRule.filterCircuitTripped,默认为true,即是否过滤掉断路的Server(什么是断路我们之后会说)
  2. niws.loadbalancer.availabilityFilteringRule.activeConnectionsLimit,默认为Integer的最大值,每个Server实例最大的活跃连接数(其实就是本机发往这个Server未处理完的请求个数)
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是否为trueif ((CIRCUIT_BREAKER_FILTERING.get() &&//该Server是否为断路状态stats.isCircuitBreakerTripped()) //本机发往这个Server未处理完的请求个数是否大于Server实例最大的活跃连接数|| stats.getActiveRequestsCount() >= activeConnectionsLimit.get()) {return true;}return false;
}

Server是否为断路状态是如何判断的呢?

ServerStats源码,这里详细源码我们不贴了,说一下机制:

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

  1. 计算断路持续时间: (2^失败次数)* 断路时间因子,如果大于最大断路时间,则取最大断路时间
  2. 判断当前时间是否大于上次失败时间+短路持续时间,如果小于,则是断路状态

这里又涉及三个配置(这里需要将default替换成你调用的微服务名称):

  1. niws.loadbalancer.default.connectionFailureCountThreshold,默认为3, 触发判断是否断路的最小失败次数,也就是,默认如果失败三次,就会判断是否要断路了。
  2. niws.loadbalancer.default.circuitTripTimeoutFactorSeconds, 默认为10, 断路时间因子,
  3. 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. Spring Cloud Finchley OpenFeign的重试配置相关的坑

    如题,本文基于Spring Cloud Finchley.SR2 OpenFeign的重试 OpenFeign配置重试后,逻辑分析 对比Daltson和Finchley的基本组件,发现Ribbon还有 ...

  2. Spring Cloud Finchley版中Consul多实例注册的问题处理

    由于Spring Cloud对Etcd的支持一直没能从孵化器中出来,所以目前来说大多用户还在使用Eureka和Consul,之前又因为Eureka 2.0不在开源的消息,外加一些博眼球的标题党媒体使得 ...

  3. Spring Cloud Finchley.SR1 的学习与应用 2 - Consul

    为什么80%的码农都做不了架构师?>>>    Spring Cloud Consul 简介 consul是google开源的一个使用go语言开发的服务发现.配置管理中心服务.内置了 ...

  4. 基于 Spring Cloud 环境污染物数据分析与预测平台

    完整代码:https://download.csdn.net/download/weixin_55771290/87542438 采用微服务架构,基于 Spring Cloud (Finchley.S ...

  5. Spring Cloud Gateway 之获取请求体的几种方式

    一.直接在全局拦截器中获取 伪代码如下 private String resolveBodyFromRequest(ServerHttpRequest serverHttpRequest){Flux& ...

  6. spring cloud gateway - 日志

    spring cloud gateway - 日志 实现日志 前提:spring cloud gateway是基于webflux的项目,所以不能像使用spring mvc一样直接获取request b ...

  7. Spring Cloud 升级最新 Finchley 版本,踩了所有的坑

    转载自   Spring Cloud 升级最新 Finchley 版本,踩了所有的坑 Spring Boot 2.x 已经发布了很久,现在 Spring Cloud 也发布了 基于 Spring Bo ...

  8. springcloud gateway ribbon使用_Github点赞接近 70k 的Spring Cloud学习教程+实战项目推荐!牛批!...

    这篇文章继续来推荐 Spring Cloud 的教程和实战项目了!想必不用不多说,大家都知道 Spring Cloud 的重要程度.几乎稍微有点规模的公司,一般都离不开要和微服务打交道.同时,Spri ...

  9. Spring Cloud【Finchley】- 21 Spring Cloud Stream 构建消息驱动微服务

    文章目录 概述 添加依赖 配置文件配置RabbitMQ的地址信息 接口定义 接收方 @EnableBinding @StreamListener 测试 消费组 发送复杂对象 消息回执 代码 概述 官网 ...

  10. Spring Cloud【Finchley】实战-01注册中心及商品微服务

    文章目录 Spring Cloud[Finchley]专栏 概述 版本说明 搭建Eureka Server注册中心 工程结构 Step1. pom添加依赖 Step2.application.yml ...

最新文章

  1. 按下回车键指向下一个位置的一个函数
  2. 电商平台应该分析哪些数据?具体怎么去分析?
  3. php饿死,男网红出租屋内活活饿死宠物:不尊重生命的人有多可怕?
  4. centos6 mysql 导出sql_centos环境下如何导出数据库
  5. filter 中用spring StopWatch 监控请求执行时间
  6. db2数据备份到mysql_DB2数据库自动备份详解
  7. 【PAT - 甲级1003】Emergency (25分)(Dijkstra,最短路条数,双权值最短路)
  8. 他,是数学天才,是多复变解析函数的创始人
  9. 信息学奥赛一本通 1053:最大数输出 | OpenJudge NOI 1.4 15
  10. python3----字典
  11. 大数据开发工程师招聘要求高吗?
  12. 天猫618,吃货们最爱哪些生鲜品牌?
  13. APP如何在应用商店获取较高的排名?
  14. 【OBS】VS调试启动exe的环境设置
  15. 鑫缘聚禾:拼多多拼团怎么拼
  16. 数据库实验六:完整性语言实验
  17. 【word2vec】算法原理 公式推导
  18. ssh no matching host key type found. Their offer: ssh-rsa
  19. 机器人网络系统时延笔记(LAN+WLAN)
  20. i7处理器好吗_i5和i7区别有多大,性能差距大吗?i5-9400F和i7-9700F的区别对比

热门文章

  1. PCL-07-手眼标定、2D和3D融合
  2. swift5.0的网络请求与数据解析
  3. 学生成绩管理系统 java+mysql中
  4. 十二款企业级VTL性能完全比拼
  5. ACM-ICPC 2018 沈阳赛区网络预赛 Solution
  6. Java基础知识——9.流程控制及大数
  7. 3.分布式计算平台Spark:Core(二)
  8. React Router V6变化
  9. 【IEEE出版,见刊检索稳定|珠海科技学院主办|EI核心,Scopus检索】第二届健康大数据与智能医疗国际会议(ICHIH 2023)
  10. 华为OD机试题,用 Java 解【勾股数元组】问题