sentinel 随笔 3-降级处理
0. 像喝点东西,但不知道喝什么
先来段源码,看一下 我们在dashboard 录入的降级规则,都映射到哪些字段上
package com.alibaba.csp.sentinel.slots.block.degrade;public class DegradeRule extends AbstractRule {public DegradeRule(String resourceName) {setResource(resourceName);}/*** Circuit breaking strategy (0: average RT, 1: exception ratio, 2: exception count).*/private int grade = RuleConstant.DEGRADE_GRADE_RT;/*** Threshold count.*/private double count;/*** Recovery timeout (in seconds) when circuit breaker opens. After the timeout, the circuit breaker will* transform to half-open state for trying a few requests.*/private int timeWindow;/*** Minimum number of requests (in an active statistic time span) that can trigger circuit breaking.** @since 1.7.0*/private int minRequestAmount = RuleConstant.DEGRADE_DEFAULT_MIN_REQUEST_AMOUNT;/*** The threshold of slow request ratio in RT mode.*/private double slowRatioThreshold = 1.0d;private int statIntervalMs = 1000;
}
1. sentinel 的断路器实现
- 效果跟 netflix.hystrix 差不离
package com.alibaba.csp.sentinel.slots.block.degrade.circuitbreaker;public abstract class AbstractCircuitBreaker implements CircuitBreaker {protected final DegradeRule rule;protected final int recoveryTimeoutMs;private final EventObserverRegistry observerRegistry;protected final AtomicReference<State> currentState = new AtomicReference<>(State.CLOSED);protected volatile long nextRetryTimestamp;public AbstractCircuitBreaker(DegradeRule rule) {this(rule, EventObserverRegistry.getInstance());}AbstractCircuitBreaker(DegradeRule rule, EventObserverRegistry observerRegistry) {AssertUtil.notNull(observerRegistry, "observerRegistry cannot be null");if (!DegradeRuleManager.isValidRule(rule)) {throw new IllegalArgumentException("Invalid DegradeRule: " + rule);}this.observerRegistry = observerRegistry;this.rule = rule;this.recoveryTimeoutMs = rule.getTimeWindow() * 1000;}// true, 成功获得令牌@Overridepublic boolean tryPass(Context context) {// 断路器关闭// Template implementation.if (currentState.get() == State.CLOSED) {return true;}// 断路器开启if (currentState.get() == State.OPEN) {// 半开状态,允许通过1个请求来尝试,可行的话,即 true// For half-open state we allow a request for probing.return retryTimeoutArrived() && fromOpenToHalfOpen(context);}return false;}// 当前系统时间 >= 下一次重试时间protected boolean retryTimeoutArrived() {return TimeUtil.currentTimeMillis() >= nextRetryTimestamp;}protected boolean fromOpenToHalfOpen(Context context) {if (currentState.compareAndSet(State.OPEN, State.HALF_OPEN)) {// 通知订阅者: 状态的变化 开 -> 半开notifyObservers(State.OPEN, State.HALF_OPEN, null);Entry entry = context.getCurEntry();// 过程中断时的回调,回滚状态entry.whenTerminate(new BiConsumer<Context, Entry>() {@Overridepublic void accept(Context context, Entry entry) {// Note: This works as a temporary workaround for https://github.com/alibaba/Sentinel/issues/1638// Without the hook, the circuit breaker won't recover from half-open state in some circumstances// when the request is actually blocked by upcoming rules (not only degrade rules).if (entry.getBlockError() != null) {// Fallback to OPEN due to detecting request is blockedcurrentState.compareAndSet(State.HALF_OPEN, State.OPEN);notifyObservers(State.HALF_OPEN, State.OPEN, 1.0d);}}});return true;}return false;}private void notifyObservers(CircuitBreaker.State prevState, CircuitBreaker.State newState, Double snapshotValue) {for (CircuitBreakerStateChangeObserver observer : observerRegistry.getStateChangeObservers()) {observer.onStateChange(prevState, newState, rule, snapshotValue);}}
}
从 DegradeRule.grade 可知道:
- 默认的降级策略,即 响应时长
- 除此之外,还支持 异常 的触发方式
下面分别借助两个 AbstractCircuitBreaker 的实现类来说明实现细节
1.1 ResponseTimeCircuitBreaker(RT) 
package com.alibaba.csp.sentinel.slots.block.degrade.circuitbreaker;// 根据请求的响应时间(慢调用比例)
public class ResponseTimeCircuitBreaker extends AbstractCircuitBreaker {private static final double SLOW_REQUEST_RATIO_MAX_VALUE = 1.0d;private final long maxAllowedRt;private final double maxSlowRequestRatio;private final int minRequestAmount;private final LeapArray<SlowRequestCounter> slidingCounter;public ResponseTimeCircuitBreaker(DegradeRule rule) {this(rule, new SlowRequestLeapArray(1, rule.getStatIntervalMs()));}ResponseTimeCircuitBreaker(DegradeRule rule, LeapArray<SlowRequestCounter> stat) {super(rule);AssertUtil.isTrue(rule.getGrade() == RuleConstant.DEGRADE_GRADE_RT, "rule metric type should be RT");AssertUtil.notNull(stat, "stat cannot be null");this.maxAllowedRt = Math.round(rule.getCount());this.maxSlowRequestRatio = rule.getSlowRatioThreshold();this.minRequestAmount = rule.getMinRequestAmount();this.slidingCounter = stat;}@Overridepublic void onRequestComplete(Context context) {SlowRequestCounter counter = slidingCounter.currentWindow().value();Entry entry = context.getCurEntry();if (entry == null) {return;}long completeTime = entry.getCompleteTimestamp();if (completeTime <= 0) {completeTime = TimeUtil.currentTimeMillis();}long rt = completeTime - entry.getCreateTimestamp();if (rt > maxAllowedRt) {counter.slowCount.add(1);}counter.totalCount.add(1);handleStateChangeWhenThresholdExceeded(rt);}private void handleStateChangeWhenThresholdExceeded(long rt) {if (currentState.get() == State.OPEN) {return;}if (currentState.get() == State.HALF_OPEN) {// In detecting request// TODO: improve logic for half-open recoveryif (rt > maxAllowedRt) {fromHalfOpenToOpen(1.0d);} else {fromHalfOpenToClose();}return;}List<SlowRequestCounter> counters = slidingCounter.values();long slowCount = 0;long totalCount = 0;for (SlowRequestCounter counter : counters) {slowCount += counter.slowCount.sum();totalCount += counter.totalCount.sum();}if (totalCount < minRequestAmount) {return;}double currentRatio = slowCount * 1.0d / totalCount;if (currentRatio > maxSlowRequestRatio) {transformToOpen(currentRatio);}if (Double.compare(currentRatio, maxSlowRequestRatio) == 0 &&Double.compare(maxSlowRequestRatio, SLOW_REQUEST_RATIO_MAX_VALUE) == 0) {transformToOpen(currentRatio);}}static class SlowRequestCounter {private LongAdder slowCount;private LongAdder totalCount;}
}
1.2 ExceptionCircuitBreaker

package com.alibaba.csp.sentinel.slots.block.degrade.circuitbreaker;// 策略:异常比例、异常数
public class ExceptionCircuitBreaker extends AbstractCircuitBreaker {private final int strategy; // 策略的枚举值private final int minRequestAmount; // 最小请求数private final double threshold; // 设置的阈值private final LeapArray<SimpleErrorCounter> stat;public ExceptionCircuitBreaker(DegradeRule rule) {this(rule, new SimpleErrorCounterLeapArray(1, rule.getStatIntervalMs()));}ExceptionCircuitBreaker(DegradeRule rule, LeapArray<SimpleErrorCounter> stat) {super(rule);this.strategy = rule.getGrade();boolean modeOk = strategy == DEGRADE_GRADE_EXCEPTION_RATIO || strategy == DEGRADE_GRADE_EXCEPTION_COUNT;AssertUtil.isTrue(modeOk, "rule strategy should be error-ratio or error-count");AssertUtil.notNull(stat, "stat cannot be null");this.minRequestAmount = rule.getMinRequestAmount();this.threshold = rule.getCount();this.stat = stat;}@Overridepublic void onRequestComplete(Context context) {Entry entry = context.getCurEntry();if (entry == null) {return;}Throwable error = entry.getError();SimpleErrorCounter counter = stat.currentWindow().value();// 异常发生了,累加if (error != null) {counter.getErrorCount().add(1);}// 总数(异常+非异常),同样累加counter.getTotalCount().add(1);// step into ...handleStateChangeWhenThresholdExceeded(error);}private void handleStateChangeWhenThresholdExceeded(Throwable error) {// 断路器早已启动? 好吧,后面不用看了if (currentState.get() == State.OPEN) {return;}// 半开状态,试探一下if (currentState.get() == State.HALF_OPEN) {// In detecting requestif (error == null) {fromHalfOpenToClose();} else {fromHalfOpenToOpen(1.0d);}return;}// 把这个异常计数传播到整个时间窗(LeapArray)的计数器中List<SimpleErrorCounter> counters = stat.values();long errCount = 0;long totalCount = 0;for (SimpleErrorCounter counter : counters) {errCount += counter.errorCount.sum();totalCount += counter.totalCount.sum();}// 虽然有异常,但是比配置的最小请求数还小,那不需要使用断路器if (totalCount < minRequestAmount) {return;}double curCount = errCount;// 如果策略是:按照异常率的话,计算概率if (strategy == DEGRADE_GRADE_EXCEPTION_RATIO) {// Use errorRatiocurCount = errCount * 1.0d / totalCount;}// 这里开启断路器if (curCount > threshold) {transformToOpen(curCount);}}static class SimpleErrorCounter {private LongAdder errorCount;private LongAdder totalCount;public SimpleErrorCounter() {this.errorCount = new LongAdder();this.totalCount = new LongAdder();}public LongAdder getErrorCount() {return errorCount;}public LongAdder getTotalCount() {return totalCount;}public SimpleErrorCounter reset() {errorCount.reset();totalCount.reset();return this;}@Overridepublic String toString() {return "SimpleErrorCounter{" +"errorCount=" + errorCount +", totalCount=" + totalCount +'}';}}
}
相关文章:
sentinel 随笔 3-降级处理
0. 像喝点东西,但不知道喝什么 先来段源码,看一下 我们在dashboard 录入的降级规则,都映射到哪些字段上 package com.alibaba.csp.sentinel.slots.block.degrade;public class DegradeRule extends AbstractRule {public DegradeRule(String…...
如何解决IP能ping通但无法上网的问题?
当我们在网络环境中遇到无法上网的问题时,可能会尝试使用ping命令来测试网络连接是否正常。如果ping测试成功,说明我们的IP地址能够和网络中其他设备进行通信,但是无法上网。这种情况下,我们需要采取一些措施来解决这个问题。本文…...
Autosar实践-CANTp
文章目录 前言一、CanTp是什么?二、Autosar配置三、诊断数据传输流程1.接收单帧失败,上层没有适当的buffer2.成功接收单帧3.成功发送单帧4.成功接收多帧5.成功发送多帧前言 CANTp模块作为提供数据拆包、组包、流控制传输的服务,在Autosar基础软件通信中起着至关重要的作用。…...
Redis简介
Redis(Remote Dictionary Server)是一个开源的键值对(key-value)数据库,支持网络、可基于内存亦可持久化。 Redis的数据结构包括列表(List)、集合(Set)、有序集合&#…...
报错问题修改
Vue 项目报错:‘$‘ is not defined ( no-undef ) 错误原因是不认识 $ 符,他是 JQuery 中得符号,引入了 JQuery 文件里的函数报错onclick is not defined问题(作用域问题) window.onload function (){ onload function (){ 第二种方法…...
专访惠众科技|元宇宙应用如何借助3DCAT实时云渲染实现流畅大并发呈现?
当前互联网流量红利已经逐渐消失,营销同质化愈发严重。在这样的背景下,催生了以为元宇宙 焦点的虚拟产业经济。元宇宙在各行各业中以不同形式快速萌生、成长,呈现出多元化的应用场景。尤其是众多品牌,将元宇宙视为品牌建设与营销新…...
加速开放计算产业化,OCTC五大原则瞄准需求痛点
回顾计算产业过去十余载的历程,开放计算始终是一个绕不开的核心焦点。 始于2011年Facebook发起的数据中心硬件开源项目--开放计算项目(简称:OCP),开放计算犹如星星之火,不仅迅速形成燎原之势,更…...
【RabbitMQ】安装及六种模式
文章目录 安装rabbitmq镜像访问容器内部15672端口映射到外面的端口地址RabbitMQ六种模式Hello world模式Work queues模式Publish/Subscribe模式交换机fanout类型 Routing模式Topics模式RPC模式 rabbitmq:0->1的学习 学习文档:https://www.cnblogs.com…...
数据结构刷题(三十一):1049. 最后一块石头的重量 II、完全背包理论、518零钱兑换II
一、1049. 最后一块石头的重量 II 1.思路:01背包问题,其中dp[j]表示容量为j的背包,最多可以背最大重量为dp[j]。 2.注意:递推公式dp[j] max(dp[j], dp[j - stones[i]] stones[i]);本题中的重量就是价值,所以第二个…...
opencv_c++学习(四)
图像在opencv中的存储方式 在上图中可以看出,在opencv中采用的是像素值来代表每一个像素三通道颜色的深浅。 Mat对象 Mat对象是在OpenCV2.0之后引进的图像数据结构、自动分配内存、不存在内存泄漏的问题,是面向对象的数据结构。分了两个部分࿰…...
基于AT89C51单片机的篮球计时记分设计
点击链接获取Keil源码与Project Backups仿真图: https://download.csdn.net/download/qq_64505944/87771065 源码获取 主要内容: 基于51单片机设计篮球计时计分器,结合单片机串行接口原理,用AT89C51设计一个篮球比赛计分计时器,能够通过数码管显示分数和比赛时间(并设有…...
并发编程-Day2
并发编程 1.共享模型-内存 共享变量在多线程间的<可见性>问题与多条指令执行时的<有序性>问题 1.1Java内存模型 JMM它定义了主存、工作内存抽象概念,底层对应着CPU寄存器、缓存、硬件内存CPU指令优化等. JMM体现在: 原子性-保证指令不会受到线程上…...
第1章 Nginx简介
基于 Nginx版本 1.14.2 ,Tomcat版本 9.0.0 演示 第1章 Nginx简介 1.1 Nginx发展介绍 Nginx (engine x) 是一个高性能的Web服务器和反向代理服务器,也可以作为邮件代理服务器。 Nginx 特点是占有内存少,并发处理能力…...
一个.Net功能强大、易于使用、跨平台开源可视化图表
可视化图表运用是非常广泛的,比如BI系统、报表统计等。但是针对桌面应用的应用,很多报表都是收费的,今天给大家推荐一个免费.Net可视化开源的项目! 项目简介 基于C#开发的功能强大、易于使用、跨平台高质量的可视化图表库&#…...
浅谈 ext2 文件系统的特点、优缺点以及使用场景
ext2(Extended File System 2)是 Linux 中最早的一种文件系统,它是 Linux 文件系统的基础,也被广泛用于其他类 Unix 系统中。下面是 ext2 文件系统的特点、优缺点以及使用场景: 特点: ext2 文件系统可以支…...
Map和Set数据结构和ES6模块化语法
Map和Set数据结构 ●ES6 新增的两种数据结构 ●共同的特点: 不接受重复数据 Set数据结构 ●是一个 类似于 数组的数据结构 ●按照索引排列的数据结构 创建 Set 数据结构 语法: var s new Set([ 数据1, 数据2, 数据3, ... ]) Set 数据结构的属性和方法 ●size 属性 ○语法: 数…...
10_Uboot启动流程_2
目录 _main函数详解 board_init_f函数详解 relocate_code函数详解 relocate_vectors函数详解 board_init_r 函数详解 _main函数详解 在上一章得知会执行_main函数_main函数定义在文件arch/arm/lib/crt0.S 中,函数内容如下: 第76行,设置sp指针为CONFIG_SYS_INIT_SP_ADDR,也…...
python+django汽车4S店零配件保养服务管理系统
汽车4S服务管理系统包括三种用户。管理员、普通员工、客户。 开发语言:Python 框架:django/flask Python版本:python3.7.7 数据库:mysql 数据库工具:Navicat 开发软件:PyCharm django 应用目录结构管…...
STM32F4的输出比较极性和PWM1,PWM2的关系
PWM 输出比较通道 在这里以通用定时器的通道1作为介绍。 如图,左边就是CNT计数器和CCR1第一路的捕获/比较寄存器,它俩进行比较,当CNT>CCR1, 或者CNTCCR1时,就会给输出模式控制器传送一个信号,然后输出模式控制器就…...
易优cms伪静态,EyouCms去除URL中的index.php
针对不同服务器、虚拟空间,运行PHP的环境也有所不同,目前主要分为:Nginx、apache、IIS以及其他服务器。下面分享如何去掉URL上的index.php字符,记得在管理后台清除缓存,对于一些ECS服务器可能要重启nginx等服务! 【Nginx服务器】 在原有的nginx重写文件里新增以下代码片…...
双向互转|IEC104↔Modbus 工业网关,电力 / 工业现场一键通联
一、产品核心定位三格电子推出SG-IEC104-TCP与SG-TCP-IEC104两款工业级网关,专为电力、能源、智能制造场景打造,实现IEC104 与 Modbus 双向协议转换,兼容 DLT645 电表采集,支持 MQTT 上云,打通电力主站与现场设备的数据…...
开始新篇章
此博客发表关于 计算机技术 等方面的文章,欢迎友好评论交流...
无需参考图像的低光照增强:PairLIE论文中的双输入训练策略详解
无需参考图像的低光照增强:PairLIE论文中的双输入训练策略详解 在移动摄影和安防监控等领域,低光照环境下的图像质量提升一直是计算机视觉研究的重点难点。传统低光照增强方法通常依赖于高质量参考图像进行监督学习,这不仅数据采集成本高昂&a…...
仲景GPT:首个中医大语言模型如何革新传统医学诊疗?[特殊字符]
仲景GPT:首个中医大语言模型如何革新传统医学诊疗?🚀 【免费下载链接】CMLM-ZhongJing 首个中医大语言模型——“仲景”。受古代中医学巨匠张仲景深邃智慧启迪,专为传统中医领域打造的预训练大语言模型。 The first-ever Traditio…...
React Hooks 服务器端渲染测试终极指南:如何避免 SSR 常见陷阱 [特殊字符]
React Hooks 服务器端渲染测试终极指南:如何避免 SSR 常见陷阱 🚀 【免费下载链接】react-hooks-testing-library 🐏 Simple and complete React hooks testing utilities that encourage good testing practices. 项目地址: https://gitco…...
新手必看:如何用OpenSCAP快速搞定Linux服务器安全基线检查(附CentOS实战)
从零到精通的OpenSCAP实战:CentOS安全基线检查全流程拆解 刚接手服务器运维的新手常会遇到这样的困惑:明明系统运行正常,安全团队却总说存在"配置风险"。去年我们团队就发生过一起因SSH弱加密算法导致的入侵事件——攻击者仅用2小时…...
文档格式高效破解:NCMDump实现加密文件自由掌控全指南
文档格式高效破解:NCMDump实现加密文件自由掌控全指南 【免费下载链接】ncmdump 项目地址: https://gitcode.com/gh_mirrors/ncmd/ncmdump 在数字化办公时代,你是否曾因收到的加密文档无法跨平台打开而错失重要信息?是否经历过花费数…...
别再手动算面积了!用ArcGIS 10.6的‘汇总统计’功能,5分钟搞定土地利用数据分析
5分钟掌握ArcGIS 10.6汇总统计:土地利用分析效率提升实战 在城乡规划、生态保护等领域的日常工作中,我们经常需要处理各类空间数据。以某市自然资源局为例,工作人员每月需要统计各行政区不同土地利用类型的面积分布情况。传统做法是将属性表导…...
YOLOv10实战:用官方镜像5分钟搭建智能监控原型系统
YOLOv10实战:用官方镜像5分钟搭建智能监控原型系统 想快速验证一个智能监控的想法,却卡在繁琐的环境配置和模型部署上?从安装CUDA、配置Python环境,到调试各种依赖库,可能半天时间就过去了,真正的业务逻辑…...
ERTEC 系列 PROFINET 芯片级硬件过滤器分析
起因是我想在搞一些操作windows进程的事情时,老是需要右键以管理员身份运行,感觉很麻烦。就研究了一下怎么提权,顺手瞄了一眼Windows下用户态权限分配,然后也是感谢《深入解析Windows操作系统》这本书给我偷令牌的灵感吧ÿ…...
