Ribbon 是 Netflix 出品的一套负载均衡组件,提供了许多 Rule 规则从负载列表中选取合适的 server 实例。当实例出现问题时候,需要将这部分异常的服务提供者从负载列表中剔除,从而避免雪崩效应。而 Riibbon 本身具有自动移除问题实例的功能,于是我们可以结合 Ribbon 对现有的负载均衡策略做一些改进,实现自动故障剔除功能。

工作流程

Ribbon 中实现自动移除问题实例的 Rule 是 AvailabilityFilteringRule,它的运行原理如上图所示,大致可以分为以下几步:

  1. 在 LoadbalancerCommand 发起 choose server 请求时候,首先会通过 RoundRobinRule 去服务器列表 serverList 获取 server,此处 RoundRobinRule 是修改过的带权重的加权轮询算法器。
  2. 从 RoundRobinRule 获取一个 server 之后,会 AvailabilityPredicate 这个断言器去判断是否是问题实例。简单来说,就是从 LoadBalancerStats 中获取这个 server 的状态 serverStats,然后在 serverStats 这个状态机中去判断是否应该断路。
  3. 经过 serverStats 的断路判断之后,如果是需要断路的,那么表明是问题实例,如果不需要,则返回给 LoadBalancerCommand 一个正常的 server 实例。
  4. LoadBalancerCommand 在处理完请求后,无论成功与否都对 serverStats 做一次相应的状态记录。

服务状态 ServerStats

结合实际业务需求,在 serverStats 中,目前定义了两类异常,连接异常 (主要指 tcp 层面的,包括 sokcetException,socketTimeoutException,ConnectException) 以及不可用异常(主要是底层通信框架 rxNetty 抛出的异常,包括 timeoutException 以及 PoolExhaustedException)。

参数定义

考虑到两种异常的发生场景的差异,为这两类异常分别设置了各自的连续失败阈值 (connectionFailureThreshold,unavailableThreshold) 以及断路超时时间(connectionFailureCircuitTimeout,unavailableCircuitTimeout)。其中不可用异常参数 (unavailableThreshold,unavailableCircuitTimeout) 会暴露给使用者,使用 springboot 的项目可以直接读取 yml 文件或者托管到第三方配置中心。

而其中连接失败异常相关的参数,考虑到较为底层,使用者不大关心,是默认设置好了,只通过读取环境变量的方式来允许改动。

断路器工作原理

从上面定义的参数就指定,目前断路器统计失败是靠连续失败次数去判断断路逻辑的。之后可以根据不同场景做不同的适配。目前断路器的工作算法大致如下

  1. 计算累计连接失败计数 successiveConnectionFailureCount 是否超过 链接失败阈值 connectionFailureThreshold。如果 successiveConnectionFailureCount < connectionFailureThreshold,即尚未超过限额,则熔断时间为 0 ;反之,如果超过限额,则进行步骤 2 的计算
  2. 计算失败基数,最大不得超过 16。diff = (failureCount - threshold) > 16 ? 16 : (failureCount - threshold)
  3. 根据超时因子 timeoutFactor(目前默认写死为 10) 计算超时时间:blackOutSeconds = (1 << diff) * timeoutFactor;
  4. 超时时间不得超过最大超时时间 connectionFailureCircuitTimeout 上线
  5. 计算完连接失败异常相应的超时时间 connectionFailureblackOutPeriod 之后,用不可用异常对应的参数去重复一下 1-4 步骤算出不可用异常对应的超时时间 unavailableblackOutPeriod。两者取最大值作为 blackOutPeriod。
  6. 将最后一次失败时间 lastConnectionFailedTimestamp 加上 blackOutPeriod 超时间隔,作为当前断路器刚关闭的时间。
  7. 每一次请求来,只要比较当前时间与步骤 6 算出的时间即可,如果当前时间较大,说明过了断路器刚关闭的时间,可以正常提供服务,否则表明服务是断路状态。

当有链接失败情况出现断路逻辑时,将会最多:1<<16 * 10 = 655360 s (如果超过自定义超时时间阈值,则最大为自定义超时时间),最少 1<<0*10 = 10 s 的请求熔断时间,再此期间内,此 Server 将会被忽略。熔断的超时时间在没有超过自定义超时阈值的情况下,会随着该 server 的失败次数呈指数级动态增加。如果当自定义阈值很大,而一个服务实例连续失败很多次,那他基本就没什么希望被调用到了。。

框架中算法实现如下:

    private long getCircuitBreakerBlackoutPeriod(AtomicInteger atomicInteger, Integer threshold, Integer circuitTimeout) {        final int failureCount = atomicInteger.get();        if (failureCount             return 0;        }        final int diff = (failureCount - threshold) > 16 ? 16 : (failureCount - threshold);        int blackOutSeconds = (1 <        if (blackOutSeconds > circuitTimeout) {            blackOutSeconds = circuitTimeout;        }        return blackOutSeconds * 1000L;    }

记录服务状态

当 loadBalancerCommand 对服务请求做出处理之后,根据返回的状态对 serverStats 做出记录。

  1. 每当服务正常返回时候,会清空两种异常的熔断统计。
  2. 每当服务异常,但是异常不是定义的两种异常中的任何一种,也会清空两种异常的熔断统计。
  3. 每当服务异常,并且异常是两种异常中的一种,则会增加相应异常的熔断统计,并刷新最后失败时间 lastConnectionFailedTimestamp 这一参数。

服务路由规则

AvailabilityFilteringRule 通过一定的规则选择合适的 server 实例。首先它用 roundRobinRule 加权轮询算法选取一个 sevrer 实例。接着对选出的 server 实例应用上述的断路算法判断是否应该断路,如果是断路状态,那么将会重新通过 roundRobinRule 去选择 server 实例,这里最多重试 10 次。如果经过了 10 次,还没有选出合适的实例,意味着也许所有实例都被熔断了。那么死活还是得挑一个的,这里会通过父类 Rule 去选择实例,而父类 rule 的断言器定义的是 always true。

public Server choose(Object key) {        int count = 0;        Server server = roundRobinRule.choose(key);        while (count++ <= 10) {            if (predicate.apply(new PredicateKey(server))) {                return server;            }            server = roundRobinRule.choose(key);        }        return super.choose(key);    }


作者:fredalxin

来源链接:

https://fredal.xin/loadbalancer-with-ribbon

剔除重复_微服务发生故障后,我是如何做到自动剔除异常的Server?相关推荐

  1. java 熔断器模式_微服务架构熔断器机制的概念以及常用组件类型

    熔断器机制是我们在学习微服务编程开发的时候需要重点掌握的一个编程技术知识点,而今天我们就通过案例分析来了解一下,熔断器机制的概念以及常用组件类型都有哪些. 所谓熔断器机制,即类似电流的保险器,当然电压 ...

  2. 微服务笔记:第一章_微服务简介|Eureka注册中心|Nacos注册中心|Nacos配置管理|Feign|Gateway服务网关

    微服务笔记:第一章_微服务简介|Eureka注册中心|Nacos注册中心|Nacos配置管理|Feign|Gateway服务网关 1. 微服务简介 1.1 服务架构演变 1.2 SpringCloud ...

  3. 微服务配置中心是干啥的_微服务之配置中心ConfigKeeper

    在微服务架构中,配置中心是必不可少的基础服务.ConfigKeeper已开源,本文将深度分析配置中心的核心内容,错过「Spring Cloud中国社区北京沙龙-2018.10.28 」的同学将从本篇文 ...

  4. 微服务可靠性测试_微服务可靠性设计

    1.背景 微服务化之后,系统分布式部署,传统单个流程的本地API调用被拆分成多个微服务之间的跨网络调用,由于引入了网络通信.序列化和反序列化等操作,系统发生故障的概率提高了很多.微服务故障,有些是由于 ...

  5. hystrix 页面_微服务 | 使用Hystrix实现Spring Cloud的熔断机制

    1. 熔断机制介绍 在介绍熔断机制之前,我们需要了解微服务的雪崩效应.在微服务架构中,微服务是完成一个单一的业务功能,这样做的好处是可以做到解耦,每个微服务可以独立演进.但是,一个应用可能会有多个微服 ...

  6. docker容器 eureka 集成_微服务:基于 Docker 的微服务架构之分布式企业级实践参考...

    编者按:本文分享自CSDN技术博客,作者为 FlyWine,所有权归原著者.若有不妥,联系本头条号以做必要处理. 目录 Microservice 和 Docker 服务发现模式 客户端发现模式 Net ...

  7. java微服务是什么_微服务架构:什么是微服务

    博主 本文为微服务连载第一篇,如果有幸看到,还请找个时间仔细阅读,欢迎收藏或转载,如有不足之处烦请留言指正,共同进步,希望对你有帮助,谢谢 引言 和朋友聊天,招聘,看个行业要闻都是微服务... 最近几 ...

  8. java什么叫做微服务_微服务学习笔记——什么是微服务

    Martin Fowler:简而言之,微服务架构风格这种开发方法,是以开发一组小型服务的方式来开发一个独立的应用系统的.其中每个小型服务都运行在自己的进程中,并经常采用HTTP资源API这样轻量的机制 ...

  9. mysql微服务查询问题_微服务架构下,Mysql读写分离后,数据库CPU飙升卡壳问题解析...

    前言 最近系统(基于SpringCloud+K8s)上线,运维团队早上8点左右在群里反馈,系统登录无反应!我的第一反应是Mysql数据库扛不住了. 排查问题也是一波三折,有网络问题,也有mysql读写 ...

最新文章

  1. 安装sql server 2008 报错
  2. Python中通过PyPDF2实现PDF加密
  3. Mysql如何统计表的大小
  4. 一入前端深似海,从此红尘是路人系列第七弹之孤独的剑客-单例模式
  5. C++设计模式详解之命令模式解析
  6. LeetCode(226)——翻转二叉树(JavaScript)
  7. 云计算只是云存储的一个子问题
  8. 简单函数编写_strcpy、_stroverchg、_strcmp
  9. python导出pdf_是程序员,就用python导出pdf
  10. IT运维服务体系建设思路
  11. 新年贺卡php,幼儿新年贺卡内容 元旦贺卡图片手工制作
  12. Wi-Fi环境下基于注意力机制及深度学习的鲁棒被动感知技术
  13. 海量服务实践──手 Q 游戏春节红包项目设计与总结(上篇)
  14. windows防火墙是干什么的_Windows 之 防火墙
  15. android+4.4+打印功能,安卓android4.4新增打印支付功能
  16. 怎么理解面向对象编程【java基础第一讲】
  17. 人员招聘与培训实务【3】
  18. Unity3D研究院之两种方式播放游戏视频
  19. 国机精工,上柴股份,共创草坪,成交量异动检测
  20. idea ctrl+alt+向左箭头不能用

热门文章

  1. (二)图像处理技术概述
  2. 软件工程(2019)第四次作业-结队作业
  3. Linux系统编程——基于文件描述符的文件操作(1)
  4. HDU4549 M斐波那契数列 —— 斐波那契、费马小定理、矩阵快速幂
  5. krpano·分组图片地图插件
  6. DispatcherServlet默认配置
  7. Spring MVC 3 深入总结
  8. 18.实现标准的Dispose模式
  9. Oracle sqlplus 各种登录方式
  10. mysql插入大量数据总结