Sentinel断路器与熔断降级【源码笔记】
前言
Sentinel的熔断降级通过断路器实现,本文通过介绍熔断器的定义、如何构建熔断器、断路器校验逻辑、断路器状态转换、异常/慢调用熔断流量是如何统计等方面梳理断路器的工作原理和实现方式。
一、断路器定义
Sentinel中的熔断降级使用断路器实现,先看下断路器概念,来自维基百科的定义:
断路器有分简单与较进阶的版本,简单的断路器只需要知道服务是否可用。而较进阶的版本比起前者更有效率。进阶的断路器带有至少三个状态:
关闭:断路器在预设的情形下是呈现关闭的状态,而断路器本身“带有”计数功能,每当错误发生一次,计数器也就会进行“累加”的动作,到了一定的错误发生次数断路器就会被“开启”,这个时候亦会在内部启用一个计时器,一旦时间到了就会切换成半开启的状态。
开启:在开启的状态下任何请求都会“直接”被拒绝并且抛出异常讯息。
半开启:在此状态下断路器会允许部分的请求,如果这些请求都能成功通过,那么就意味着错误已经不存在,则会被“切换回”关闭状态并“重置”计数。倘若请求中有“任一”的错误发生,则会回复到“开启”状态,并且重新计时,给予系统一段休息时间
说明:从概念中可以看出断路器的关键点在于统计流量与三种状态的转换。
二、构建断路器
我们通过DegradeRuleManager.loadRules或者getProperty().updateValue使降级规则生效时,会将DegradeRule转换为断路器CircuitBreaker。
断路器由两类构成,慢调用使用ResponseTimeCircuitBreaker,异常数和异常比例使用ExceptionCircuitBreaker。
断路器类图
三、断路器校验
DegradeSlot负责熔断规则的校验,tryPass方法执行具体的判断。
判断的逻辑
如果熔断器状态为关闭,则返回true,即允许请求通过。
如果熔断器状态为开启,并且已经超过熔断时长以及开启状态成功转换为半开启(探测)状态,则返回true,即允许请求通过。
如果熔断器状态为开启,并且还在熔断时长内,则返回false,禁止请求通过。
那探测和开启状态都允许请求通过,在“熔断降级说明”文章中知道,探测状态只允许一个请求通过,这个是在哪里控制的呢?
四、断路器状态转换
在调用Entry#exit()时,会触发插槽链条的退出调用。具体到熔断降级DegradeSlot#exit方法。通过circuitBreaker.onRequestComplete回调熔断器执行状态切换。
1.异常熔断器状态转换
ExceptionCircuitBreaker负责异常数/异常比例的熔断,通过滑动窗口统计发生错误数及请求总数。
详细熔断逻辑
2.慢调用熔断器状态转换
ResponseTimeCircuitBreaker负责慢调用的熔断,通过滑动窗口统计慢调用数量及总的请求数。
详细熔断逻辑
五、滑动窗口流量统计
1.异常熔断流量统计
异常熔断ExceptionCircuitBreaker的流量统计通过SimpleErrorCounterLeapArray实现,默认采样窗口sampleCount为1,统计区间intervalInMs为1秒。
2.慢调用熔断流量统计
慢调用熔断ResponseTimeCircuitBreaker的流量统计通过SlowRequestLeapArray实现,默认采样窗口sampleCount为1,统计区间intervalInMs为1秒。
说明:具体滑动窗口的统计逻辑见文章“Sentinel基于滑动窗口的流量统计【源码笔记】”。
作者丨梁勇 来源丨瓜农老梁 欢迎关注公众号「瓜农老梁」
「瓜农老梁 学习同行」
- 数据结构和算法——二叉树
- 【专业技术】谷歌浏览器实现Javascript扩展
- 数据结构和算法——二叉排序树
- 通过shell脚本生成查询表数据的sql (r2笔记63天)
- Linux C 编程——多线程
- 数据结构和算法——Huffman树和Huffman编码
- 简单易学的机器学习算法——K-Means++算法
- 梯度下降原理及Python实现
- 海量数据迁移之通过rowid切分大表(r2笔记62天)
- 简单易学的机器学习算法——K-近邻算法
- 使用Python绘制点击图、热图
- 使用shell生成状态报表(r2笔记61天)
- 利用d3.js对QQ群资料进行大数据可视化分析
- 海量数据迁移之分区并行切分(r2笔记60天)
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 宝塔如何安装 MDClub
- Jackson 的 JsonManagedReference 和 JsonBackReference 注解
- leetcode哈希表之独一无二的出现次数
- Vue 网站首页加载优化
- Swift日常开发随笔
- vue入门003~vue项目引入element并创建一个登录页面
- vue入门002~vue项目的两种创建方式
- IntelliJ IDEA,WebStorm,PhpStorm破解到2089年
- 小程序订阅消息推送(含源码)java实现小程序推送,springboot实现微信消息推送
- 借助云开发10行代码实现短信验证码的发送
- 借助云开发实现小程序订阅消息(模板消息)推送功能
- 1小时实战入门小程序开发,历史上的今天案例讲解
- 小程序实现全屏幕高斯模糊背景图
- 小程序顶部导航栏,可滑动,可动态选中放大
- 小程序不同页面的异步回调,callback和promise的使用讲解