编码技巧——Sentinel的blockHandler与fallback
本文介绍Sentinel的blockHandler与fallback的区别,背景是:发生限流时,配置的sentinel的blockhandler没有生效而fallback生效了;排查原因,从而给出Sentinel配置异常降级和限流降级的代码写法;
在查看源码前,查阅了相关的技术帖子(1. Sentinel的blockHandler与fallback的区别 2.Sentinel服务熔断[fallBack/blockHandler]),针对同时配置fallback和blockHandler的场景,其中的结论存在不一致,所以决定自己亲手实践下;
1. 未配置fallback和blockHandler
代码如下,仅配置SentinelResource的value,并去sentinel控制台配置单机限流为1;
限流方法:
/*** 测试sentinel的降级方法*/@SentinelResource(value = "testSentinelFallback")public String testSentinelFallback() {return "返回成功ok";}
测试代码:
@Overridepublic String mock() {// 异步调用 模拟并发情况for (int i = 0; i < 5; i++) {CompletableFuture.runAsync(() -> {try {final String result = testSentinelService.testSentinelFallback();log.info("调用返回结果 [result={}]", result);} catch (Throwable e) {log.warn("调用抛出异常", e);}});}return null;}
sentinel后台配置:

执行结果:
调用返回结果 [result=返回成功ok]调用抛出异常
java.lang.reflect.UndeclaredThrowableException: null
Caused by: com.alibaba.csp.sentinel.slots.block.flow.FlowException: null调用抛出异常
java.lang.reflect.UndeclaredThrowableException: null
Caused by: com.alibaba.csp.sentinel.slots.block.flow.FlowException: null
...
2. 仅配置blockHandler
2.1 配置blockHandler时未带上额外参数BlockException
@SentinelResource(value = "testSentinelFallback", blockHandler = "myBlockHandler")public String testSentinelFallback() {return "返回成功ok";}public String myBlockHandler() {return "进入myBlockHandler逻辑";}
执行结果:未进入限流降级方法;
调用返回结果 [result=返回成功ok]调用抛出异常
java.lang.reflect.UndeclaredThrowableException: null
Caused by: com.alibaba.csp.sentinel.slots.block.flow.FlowException: null调用抛出异常
java.lang.reflect.UndeclaredThrowableException: null
Caused by: com.alibaba.csp.sentinel.slots.block.flow.FlowException: null
...
2.2 正确的配置blockHandler
@SentinelResource(value = "testSentinelFallback", blockHandler = "myBlockHandler")public String testSentinelFallback() {return "返回成功ok";}public String myBlockHandler(BlockException blockException) {return "进入myBlockHandler逻辑";}
执行结果:成功进入限流降级方法;
调用返回结果 [result=返回成功ok]调用返回结果 [result=进入myBlockHandler逻辑]调用返回结果 [result=进入myBlockHandler逻辑]
...
2.3 blockHandler能捕获业务异常
@SentinelResource(value = "testSentinelFallback", blockHandler = "myBlockHandler")public String testSentinelFallback() {if (Boolean.TRUE) {throw new BusinessException(FacadeResultCodeEnum.BAD_PARAMS);}return "返回成功ok";}public String myBlockHandler(BlockException blockException) {return "进入myBlockHandler逻辑";}
执行结果:接口被限流时,成功进入限流降级方法;接口出现业务异常时,会抛到外层;
调用抛出异常
BusinessException调用返回结果 [result=进入myBlockHandler逻辑]调用返回结果 [result=进入myBlockHandler逻辑]
...
3. 仅配置fallback
3.1 配置fallback时未带上额外参数Throwable
@SentinelResource(value = "testSentinelFallback", fallback = "myFallback")public String testSentinelFallback() {if (Boolean.TRUE) {throw new BusinessException(FacadeResultCodeEnum.BAD_PARAMS);}return "返回成功ok";}public String myFallback() {return "进入myFallback逻辑";}
执行结果:接口被限流时,或者接口出现业务异常时,都会进入fallback降级方法;
调用返回结果 [result=进入myFallback逻辑]调用返回结果 [result=进入myFallback逻辑]调用返回结果 [result=进入myFallback逻辑]
...
3.2 配置fallback时带上额外参数Throwable
@SentinelResource(value = "testSentinelFallback", fallback = "myFallback")public String testSentinelFallback() {if (Boolean.TRUE) {throw new BusinessException(FacadeResultCodeEnum.BAD_PARAMS);}return "返回成功ok";}public String myFallback(Throwable throwable) {if (throwable instanceof BlockException) {return "进入myFallback逻辑 限流异常";}return "进入myFallback逻辑 业务异常";}
执行结果:接口被限流时,或者接口出现业务异常时,都会进入fallback降级方法;且可以通过异常类型区分出限流异常和业务异常;
调用返回结果 [result=进入myFallback逻辑 业务异常]调用返回结果 [result=进入myFallback逻辑 限流异常]
调用返回结果 [result=进入myFallback逻辑 限流异常]
...
4. 同时配置fallback和blockHandler
@SentinelResource(value = "testSentinelFallback", fallback = "myFallback", blockHandler = "myBlockHandler")public String testSentinelFallback() {if (Boolean.TRUE) {throw new BusinessException(FacadeResultCodeEnum.BAD_PARAMS);}return "返回成功ok";}public String myFallback(Throwable throwable) {if (throwable instanceof BlockException) {return "进入myFallback逻辑 限流异常";}return "进入myFallback逻辑 业务异常";}public String myBlockHandler(BlockException blockException) {return "进入myBlockHandler逻辑";}
执行结果:若blockHandler和fallback都进行了配置,在未触发限流进入到方法逻辑抛出业务异常时,会进入fallback方法;在触发限流时,进入不到方法逻辑,直接抛出BlockException进入blockHandler方法;
5. 结论
5.1 异常捕获逻辑
1. blockHandler
- blockHandler仅处理限流异常;
- 使用blockHandler时,方法签名参数与原方法一致,且必须要在参数的最后位置补充BlockException参数;
- 若未补充BlockException参数则不生效;
2. fallback
- fallback可以处理所有类型异常,包括限流异常和业务异常;
- 使用fallback时,方法签名参数可以与原方法完全一致,或者也接受在参数的最后位置补充Throwable参数;
- 通过对Throwable参数的类型区分是限流异常还是其他异常;
- 当同时生效blockHandler和fallback时,限流异常会优先被blockHandler处理而不再进入fallback逻辑;
5.2 合理的代码写法
(1)同时配置生效blockHandler和fallback分别处理限流异常和业务异常
@SentinelResource(value = "testSentinelFallback", fallback = "myFallback", blockHandler = "myBlockHandler")public String testSentinelFallback() {// ...return "返回成功ok";}public String myFallback(Throwable throwable) {return "进入myFallback逻辑 业务异常";}public String myBlockHandler(BlockException blockException) {return "进入myBlockHandler逻辑";}
(2)仅配置fallback并通过Throwable类型区分限流异常和业务异常
@SentinelResource(value = "testSentinelFallback", fallback = "myFallback")public String testSentinelFallback() {// ...return "返回成功ok";}public String myFallback(Throwable throwable) {if (throwable instanceof com.alibaba.csp.sentinel.slots.block.flow.FlowException) {final FlowRule rule = ((FlowException) throwable).getRule();final double count = rule.getCount();final String resource = rule.getResource();// 打印限流规则信息log.warn("testSentinelFallback触发限流降级 [sentinelResource={} QpsLimit={}]]", resource, count);return null;} else {log.warn("testSentinelFallback触发异常降级 抛出异常", throwable);throw new RuntimeException("testSentinelFallback业务异常");}}
5.3 注解参数释义及注意事项
1. @SentinelResource注解参数说明
| 属性 | 默认值 | 说明 |
|---|---|---|
| blockHandler | 用于在抛出限流/熔断/系统保护等异常的降级处理逻辑,blockHandler 针对BlockException类型的异常,优先级比fallback高 blockHandler 函数访问范围需要是 public,返回类型需要与原方法相匹配,参数类型需要和原方法相匹配并且最后加一个额外的参数,类型为 BlockException; blockHandler 函数默认需要和原方法在同一个类中; | |
| blockHandlerClass | 若希望使用其他类的函数,则可以指定 blockHandlerClass 为对应的类的 Class 对象,注意对应的函数必需为 static 函数,否则无法解析; | |
| defaultFallback | 默认的 fallback 函数名称,可选项,通常用于通用的 fallback 逻辑(即可以用于很多服务或方法); 默认 fallback 函数可以针对所有类型的异常(除了 exceptionsToIgnore 里面排除掉的异常类型)进行处理; 若同时配置了 fallback 和 defaultFallback,则只有 fallback 会生效 | |
| entryType | EntryType.OUT | 资源调用的流量类型,是入口流量(EntryType.IN)还是出口流量(EntryType.OUT),注意系统保护规则只对 IN 生效 |
| exceptionsToIgnore | 用于指定哪些异常被排除掉,不会计入异常统计中,也不会进入 fallback 逻辑中,而是会原样抛出; 优先级高于exceptionsToTrace | |
| exceptionsToTrace | Throwable.class | 用于指定哪些异常不被排除掉;如果属于该类型,则会计入异常统计中,也会进入 fallback 逻辑中,不会原样抛出;不建议修改默认值; |
| fallback | 用于在抛出异常的时候提供 fallback 处理逻辑;fallback 针对所有类型的异常(除了 exceptionsToIgnore 里面排除掉的异常类型) 方法参数列表需要和原函数一致,或者可以额外多一个 Throwable 类型的参数用于接收对应的异常(注意和blockHandler添加的BlockException不一样) | |
| fallbackClass | 类似blockHandlerClass参数 | |
| resourceType | 资源类型,默认0 | |
| value | 资源名称,必需项 |
2. 区分限流异常和熔断异常
限流状态会抛异常:FlowException(继承BlockException)
Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is com.alibaba.csp.sentinel.slots.block.flow.FlowException] with root causecom.alibaba.csp.sentinel.slots.block.flow.FlowException: null
熔断状态会抛异常:DegradeException(继承BlockException)
Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is com.alibaba.csp.sentinel.slots.block.degrade.DegradeException] with root causecom.alibaba.csp.sentinel.slots.block.degrade.DegradeException: null
参考:annotation-support | Sentinel
相关文章:
编码技巧——Sentinel的blockHandler与fallback
本文介绍Sentinel的blockHandler与fallback的区别,背景是:发生限流时,配置的sentinel的blockhandler没有生效而fallback生效了;排查原因,从而给出Sentinel配置异常降级和限流降级的代码写法; 在查看源码前…...
最新成果展示:GaN基Micro-LED热学模型数据库的开发及应用
由于GaN基Micro-LED表面积-体积比增加,其在热学方面的性质有别于大尺寸的LED,如缺陷复合导致的热效应将在发光区域中产生诸多“热”点,导致发光波长不均匀,这将影响后期显示系统的成像稳定性。针对上述问题,天津赛米卡…...
【Vue3】动态组件
动态组件的基本使用 动态组件(Dynamic Components)是一种在 Vue 中根据条件或用户输入来动态渲染不同组件的技术。 在 Vue 中使用动态组件,可以使用 元素,并通过 is 特性绑定一个组件的名称或组件对象。通过在父组件中改变 is 特…...
Java超级玛丽小游戏制作过程讲解 第五天 创建并完成常量类04
//加载障碍物 try {obstacle.add(ImageIO.read(new File(path"brick.png")));obstacle.add(ImageIO.read(new File(path"soil_up.png")));obstacle.add(ImageIO.read(new File(path"soil_base.png"))); } catch (IOException e) {e.printStackTr…...
设置浏览器兼容
浏览器兼容 css兼容 cursor定义手型 Firefox不支持hand,IE支持pointer 解决方法:统一使用pointercss透明 IE:filter:progid:DXImageTransform.Microsoft.Alpha(style0,opacity60) Firefox:opacity:0.6 解决…...
Java # List
ArrayList<>() import java.util.ArrayList; // 引入 ArrayList 类ArrayList<E> objectName new ArrayList<>(); // 初始化 常用方法 方法描述add()将元素插入到指定位置的 arraylist 中addAll()添加集合中的所有元素到 arraylist 中clear()删除 arrayl…...
git原理与使用
目录 引入基本操作分支管理远程操作标签管理 引入 假设你的老板要你设计一个文档,当你设计好了,拿给他看时,他并不是很满意,就要你拿回去修改,你修改完后,再给他看时,他还是不满意,…...
【C语言题解】将一句话的单词进行倒置,标点不倒置。
题目描述:将一句话的单词进行倒置,标点不倒置。比如 “I like beijing.”,经过处理后变为:“beijing. like I”。 文章目录 原题目题目描述:输入描述:输出描述:题目链接: 整体思路分…...
Postman 的简单使用
什么是Postman 在程序开发中用于调试网络程序或者跟踪网页请求。可以对网页进行简单的基本信息调试。Postman最早是作用chrome浏览器插件存在的,但是2018年初Chrome停止对Chrome应用程序的支持。所以现在Postman提供了独立的安装包,不再依赖于Chrome浏览…...
在CentOS7安装部署GitLab服务
CentOS 7 安装 Gitlab 官方安装教程:https://about.gitlab.com/install/ 参考安装教程:https://developer.aliyun.com/article/74395 安装配置 Step1:配置yum源 vim /etc/yum.repos.d/gitlab-ce.repo存入以下内容: [gitlab-c…...
订单系统就该这么设计,稳的一批~
订单功能作为电商系统的核心功能,由于它同时涉及到前台商城和后台管理系统,它的设计可谓是非常重要的。就算不是电商系统中,只要是涉及到需要交易的项目,订单功能都具有很好的参考价值,说它是通用业务功能也不为过。今…...
Agents改变游戏规则,亚马逊云科技生成式AI让基础模型加速工作流
最近,Stability AI正式发布了下一代文生图模型——Stable Diffusion XL 1.0这次的1.0版本是Stability AI的旗舰版生图模型,也是最先进的开源生图模型。 在目前的开放式图像模型中,SDXL 1.0是参数数量最多的。官方表示,这次采用的…...
详细教程:如何搭建废品回收小程序
废品回收是一项环保举措,通过回收和再利用废弃物品,可以减少资源浪费和环境污染。近年来,随着智能手机的普及,小程序成为了推广和运营的重要工具。本文将详细介绍如何搭建一个废品回收小程序。 1. 进入乔拓云网后台 首先…...
什么是双亲委派机制?
什么是双亲委派机制? Parent Delegation Model ,直译过来可能叫做父级委托模型更容易理解 类的加载过程 Java 编译器将 Java源文件编译成.class 文件再由 JVM 加载 .class 文件到内存中JVM 装载完成后得到一个 Class 字节码对象拿到字节码对象之后 &a…...
Mageia 9 RC1 正式发布,Mandriva Linux 发行版的社区分支
导读Mageia 9 首个 RC 已发布。公告写道,自 2023 年 5 月发布 beta 2 以来,Mageia 团队一直致力于解决许多顽固问题并提供安全修复和新特性。 新版本的控制中心添加了用于删除旧内核的新功能,该功能在 Mageia 9 中默认自动启用,用…...
ChatGPT: 人机交互的未来
ChatGPT: 人机交互的未来 ChatGPT背景ChatGPT的特点ChatGPT的应用场景结论 ChatGPT ChatGPT是一种基于大数据和机器学习的人工智能聊天机器人模型。它由国内团队发明、开发,并被命名为Mental AI。ChatGPT的目标是通过模拟自然对话的方式,提供高效、智能…...
Linux 常用操作命令
Linux简介及Ubuntu安装 Linux,免费开源,多用户多任务系统。基于Linux有多个版本的衍生。RedHat、Ubuntu、Debian 安装VMware或VirtualBox虚拟机。具体安装步骤,找百度。 再安装Ubuntu。具体安装步骤,找百度。 常用指令 ls …...
24届近5年重庆邮电大学自动化考研院校分析
今天给大家带来的是重庆邮电大学控制考研分析 满满干货~还不快快点赞收藏 一、重庆邮电大学 学校简介 重庆邮电大学简称"重邮",坐落于直辖市-重庆市,入选国家"中西部高校基础能力建设工程”、国家“卓越工程师教育培养计划…...
如何对oracle和mysql进行 分区分表
前提:使用自带的分区和分表机制进行操作 oracle,mysql分区分表 分区 分区是一种将一个大的表或索引分割成多个小的部分的技术,每个部分称为一个分区。分区可以提高数据的管理和查询效率,因为可以根据不同的条件对不同的分区进行操作&#x…...
Windows下安装Sqoop
Windows下安装Sqoop 一、Sqoop简介二、Sqoop安装2.1、Sqoop官网下载2.2、Sqoop网盘下载2.3、Sqoop安装(以version:1.4.7为例)2.3.1、解压安装包到 D:\bigdata\sqoop\1.4.7 目录2.3.2、新增环境变量 SQOOP_HOME2.3.3、环境变量 Path 添加 %SQO…...
基于距离变化能量开销动态调整的WSN低功耗拓扑控制开销算法matlab仿真
目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.算法仿真参数 5.算法理论概述 6.参考文献 7.完整程序 1.程序功能描述 通过动态调整节点通信的能量开销,平衡网络负载,延长WSN生命周期。具体通过建立基于距离的能量消耗模型&am…...
聊聊 Pulsar:Producer 源码解析
一、前言 Apache Pulsar 是一个企业级的开源分布式消息传递平台,以其高性能、可扩展性和存储计算分离架构在消息队列和流处理领域独树一帜。在 Pulsar 的核心架构中,Producer(生产者) 是连接客户端应用与消息队列的第一步。生产者…...
系统设计 --- MongoDB亿级数据查询优化策略
系统设计 --- MongoDB亿级数据查询分表策略 背景Solution --- 分表 背景 使用audit log实现Audi Trail功能 Audit Trail范围: 六个月数据量: 每秒5-7条audi log,共计7千万 – 1亿条数据需要实现全文检索按照时间倒序因为license问题,不能使用ELK只能使用…...
基础测试工具使用经验
背景 vtune,perf, nsight system等基础测试工具,都是用过的,但是没有记录,都逐渐忘了。所以写这篇博客总结记录一下,只要以后发现新的用法,就记得来编辑补充一下 perf 比较基础的用法: 先改这…...
【android bluetooth 框架分析 04】【bt-framework 层详解 1】【BluetoothProperties介绍】
1. BluetoothProperties介绍 libsysprop/srcs/android/sysprop/BluetoothProperties.sysprop BluetoothProperties.sysprop 是 Android AOSP 中的一种 系统属性定义文件(System Property Definition File),用于声明和管理 Bluetooth 模块相…...
mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包
文章目录 现象:mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包遇到 rpm 命令找不到已经安装的 MySQL 包时,可能是因为以下几个原因:1.MySQL 不是通过 RPM 包安装的2.RPM 数据库损坏3.使用了不同的包名或路径4.使用其他包…...
以光量子为例,详解量子获取方式
光量子技术获取量子比特可在室温下进行。该方式有望通过与名为硅光子学(silicon photonics)的光波导(optical waveguide)芯片制造技术和光纤等光通信技术相结合来实现量子计算机。量子力学中,光既是波又是粒子。光子本…...
算法岗面试经验分享-大模型篇
文章目录 A 基础语言模型A.1 TransformerA.2 Bert B 大语言模型结构B.1 GPTB.2 LLamaB.3 ChatGLMB.4 Qwen C 大语言模型微调C.1 Fine-tuningC.2 Adapter-tuningC.3 Prefix-tuningC.4 P-tuningC.5 LoRA A 基础语言模型 A.1 Transformer (1)资源 论文&a…...
接口自动化测试:HttpRunner基础
相关文档 HttpRunner V3.x中文文档 HttpRunner 用户指南 使用HttpRunner 3.x实现接口自动化测试 HttpRunner介绍 HttpRunner 是一个开源的 API 测试工具,支持 HTTP(S)/HTTP2/WebSocket/RPC 等网络协议,涵盖接口测试、性能测试、数字体验监测等测试类型…...
Spring AI Chat Memory 实战指南:Local 与 JDBC 存储集成
一个面向 Java 开发者的 Sring-Ai 示例工程项目,该项目是一个 Spring AI 快速入门的样例工程项目,旨在通过一些小的案例展示 Spring AI 框架的核心功能和使用方法。 项目采用模块化设计,每个模块都专注于特定的功能领域,便于学习和…...
