3种Sentinel自定义异常,你用过几种?

Spring Cloud Alibaba Sentinel 是目前主流并开源的流量控制和系统保护组件,它提供了强大的限流、熔断、热点限流、授权限流和系统保护及监控等功能。使用它可以轻松的保护我们微服务,在高并发环境下的正常运行。
那么,当程序触发了限流和熔断规则时,如何自定义返回的异常信息呢?这是我们接下来要解决的问题。
0.概述
Spring Cloud Alibaba Sentinel 有以下 3 种自定义异常的实现方式:
- 自定义局部异常
- 自定义(Sentinel)全局异常
- 自定义系统异常
以上这 3 种实现方式,都可以重新定义 Sentinel 的异常返回信息,它们的具体实现如下。
1.自定义局部异常
自定义局部异常是在使用 @SentinelResource 注解时,直接定义的 blockHandler 异常方法,如下代码所示:
@SentinelResource(value = "/user/getuser",
blockHandler = "myBlockHandler")
@RequestMapping("getuser")
public String getUser(Integer uid) {
return "User:" + uid;
}
/**
* 定义限流/熔断等异常
*/
public String myBlockHandler(Integer uid, BlockException e) {
String msg = "未知异常";
if (e instanceof FlowException) {
msg = "请求被限流了";
} else if (e instanceof ParamFlowException) {
msg = "请求被热点参数限流";
} else if (e instanceof DegradeException) {
msg = "请求被降级了";
} else if (e instanceof AuthorityException) {
msg = "没有权限访问";
}
return msg;
}
注意事项
在定义 blockHandler 方法时,需要注意以下 3 个问题:
- 自定义的 blockHandler 方法的返回值,必须要和原方法(使用 @SentinelResource 注解修饰的方法)的返回值保持一致。
- 自定义的 blockHandler 方法的参数必须和原方法参数保持一致。
- 自定义的 blockHandler 方法的方法参数中必须包含 BlockException 参数。
如果不满足以上事项中的任何一项,那么就不能正常匹配到自定义的 blockHandler 方法,并且程序也会报错。
2.自定义全局异常
自定义 Sentinel 全局异常需要实现 BlockExceptionHandler 类,并重写 handle 方法,如下代码所示:
import com.alibaba.csp.sentinel.adapter.spring.webmvc.callback.BlockExceptionHandler;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.block.authority.AuthorityException;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeException;
import com.alibaba.csp.sentinel.slots.block.flow.FlowException;
import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
@Component
public class SentinelExceptionHandler implements BlockExceptionHandler {
@Override
public void handle(HttpServletRequest request, HttpServletResponse response, BlockException e) throws Exception {
String msg = "未知异常";
int status = HttpStatus.TOO_MANY_REQUESTS.value();
if (e instanceof FlowException) {
msg = "请求被限流了";
} else if (e instanceof ParamFlowException) {
msg = "请求被热点参数限流";
} else if (e instanceof DegradeException) {
msg = "请求被降级了";
} else if (e instanceof AuthorityException) {
msg = "没有权限访问";
status = HttpStatus.UNAUTHORIZED.value();
}
response.setContentType("application/json;charset=utf-8");
response.setStatus(status);
response.getWriter().println("{\"msg\": " + msg + ", \"code\": " + status + "}");
}
}
自定义 Sentinel 全局异常是在执行 Sentinel 控制台设置的限流和熔断异常时,执行的全局自定义异常方法。
但是,如果是程序中出现的 Sentinel 报错信息,例如使用热点限流时,因为要配合使用 @SentinelResource 注解时,此时只自定义了 value 属性,未定义局部 blockHandler 方法,此时系统就会报错,但这个时候并不会执行 Sentinel 全局自定义异常,而是程序报错,此时就需要使用系统自定义异常来重新定义异常信息了。
3.自定义系统异常
自定义系统异常需要新建一个异常类,并且使用 @RestControllerAdvice 注解修饰此类,并配合 @ExceptionHandler 注解来完成全局系统异常的获取和定义,具体实现代码如下:
import com.alibaba.csp.sentinel.slots.block.authority.AuthorityException;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeException;
import com.alibaba.csp.sentinel.slots.block.flow.FlowException;
import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowException;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import java.util.HashMap;
import java.util.Map;
@RestControllerAdvice
public class CustomExceptionHandler {
/**
* 限流全局异常
*/
@ExceptionHandler(FlowException.class)
public Map handlerFlowException(){
return new HashMap(){{
put("code", HttpStatus.TOO_MANY_REQUESTS.value());
put("msg", "被限流");
}};
}
/**
* 熔断全局异常
*/
@ExceptionHandler(DegradeException.class)
public Map handlerDegradeException(){
return new HashMap(){{
put("code", HttpStatus.TOO_MANY_REQUESTS.value());
put("msg", "被熔断");
}};
}
/**
* 热点限流异常
*/
@ExceptionHandler(ParamFlowException.class)
public Map handlerparamFlowException(){
return new HashMap(){{
put("code", HttpStatus.TOO_MANY_REQUESTS.value());
put("msg", "热点限流");
}};
}
/**
* Sentinel 权限拦截全局异常
*/
@ExceptionHandler(AuthorityException.class)
@ResponseBody
public Map handlerAuthorityException(){
return new HashMap(){{
put("code", HttpStatus.UNAUTHORIZED.value());
put("msg", "暂无权限");
}};
}
}
此时,只要是系统中出现的 Sentinel 报错信息,都会被此方法所捕获,并通过自定义的代码完成自定义异常信息的返回。
小结
Sentinel 有 3 种自定义异常的实现:自定义局部异常、自定义(Sentinel)全局异常、自定义系统异常。自定义局部异常作用范围比较小,需要给每个资源单独设置才行;而自定义全局异常作用范围比较大,但如果是程序报错,也不会执行其方法,所以需要配合系统异常同时来完成自定义异常的返回。
PS:如果这 3 种自定义异常同时存在,那么它的执行优先级是:自定义局部异常 > 自定义全局异常 > 自定义系统异常。
本文已收录到我的面试小站 www.javacn.site,其中包含的内容有:Redis、JVM、并发、并发、MySQL、Spring、Spring MVC、Spring Boot、Spring Cloud、MyBatis、设计模式、消息队列等模块。
3种Sentinel自定义异常,你用过几种?的更多相关文章
- 几种破解MySQL root密码的几种方法:
几种破解MySQL root密码的几种方法: 方法一 使用phpmyadmin,这是最简单的了,修改mysql库的user表,不过别忘了使用PASSWord函数. 方法二 使用mysqladmin,这 ...
- 运算符关键字。数据区别大小写。日期范围。判空的两种写法。NOT IN的两种写法。IN范围可含NULL,但NOT IN值范围不能含NULL。
比较:>,<,=,>=,<=,<>(!=) 逻辑:AND,OR,NOT 范围:BETWEEN...AND... 范围:IN,NOT IN 判空:IS NULL, I ...
- LVS(Linus Virtual Server):三种负载均衡方式比较+另三种负载均衡方式
还有个姊妹篇也可以参考这个文章:六大Web负载均衡原理与实现 什么是LVS (Linux Virtual Server)? 首先简单介绍一下LVS (Linux Virtual Server)到底 ...
- Java反射获取class对象的三种方式,反射创建对象的两种方式
Java反射获取class对象的三种方式,反射创建对象的两种方式 1.获取Class对象 在 Java API 中,提供了获取 Class 类对象的三种方法: 第一种,使用 Class.forName ...
- FMX有两种消息处理的实现方式,一种是用TMessageManager来实现自定义的消息,另外一种象TEdit中的实现,直接声明消息方法(firemonkey messaging)
看FMX代码,发现有两种消息处理的实现方式,一种是用TMessageManager来实现自定义的消息,另外一种象TEdit中的实现,直接声明消息方法. 早前,看过文章说TMessageManage ...
- 【Java面试】Java有几种文件拷贝方式,哪一种效率最高?
"Java有几种文件拷贝方式,哪一种效率最高?" 这个问题是京东一面的时候,针对4年经验的同学的一个面试题. 大家好,我是Mic,一个工作了14年的Java程序员. 关于这个问题的 ...
- 入口点函数的19种消息,AcRxArxApp只处理16种。
AcRx::AppMsgCode一共有19种消息. 但由IMPLEMENT_ARX_ENTRYPOINT宏实现的App类,只处理了16种消息. 缺: kSuspendMsg = 16, kIni ...
- Delphi一共封装(超类化)了8种Windows基础控件和17种复杂控件
超类化源码: procedure TWinControl.CreateSubClass(var Params: TCreateParams; ControlClassName: PChar); con ...
- java 的对象拷贝(有深浅拷贝两种方式,深拷贝实现的两种方式(逐层实现cloneable接口,序列化的方式来实现))
Java提高篇--对象克隆(复制)(转自:http://www.cnblogs.com/Qian123/p/5710533.html#_label0) 阅读目录 为什么要克隆? 如何实现克隆 浅克 ...
- POI使用:用poi接口不区分xls/xlsx格式解析Excel文档(41种日期格式解析方法,5种公式结果类型解析方法,3种常用数值类型精度控制办法)
一.使用poi解析excel文档 注:全部采用poi接口进行解析,不需要区分xls.xlsx格式,不需要判断文档类型. poi中的日期格式判断仅支持欧美日期习惯,对国内的日期格式并不支持判断,怎么办? ...
随机推荐
- 管理虚拟环境——virtualenvwrapper
1.安装virtualenvwrapper 输入命令:pip install -i https://pypi.douban.com/simple/ virtualenv //下载virtualenvw ...
- 王道oj/problem23
网址:oj.lgwenda.problem/23 代码: #define _CRT_SECURE_NO_WARNINGS#include <stdio.h>#include<stri ...
- ROC 曲线与 PR 曲线
ROC 曲线与 PR 曲线 ROC 曲线与 PR 曲线 ROC 曲线和 PR 曲线是评估机器学习算法性能的两条重要曲线,两者概念比较容易混淆,但是两者的使用场景是不同的.本文主要讲述两种曲线的含义以及 ...
- Nep2023的wp
0x00 闲言碎语 2023.8.14 记录11-13的紧张刺激.46名结赛. 非常高兴能够参加NepCTF2023,以一个初出茅庐的新人的身份参加.ctf的乐趣在于学习和探索,同时我也有想证明自己的 ...
- 期中考试成绩出来了。分数在70~80是等级B。
#多输入 空格分割a = input()b = a.split()c = list(map(int, b))print(c) 等级B 描述 期中考试成绩出来了.分数在70-80是等级B. 输入 请 ...
- nacos-mysql.sql
https://github.com/alibaba/nacos/blob/master/distribution/conf/nacos-mysql.sql # Nacos安装 /home/nacos ...
- Tarjan强连通分量详解
1.简介: 在阅读下列内容之前,请务必了解 图论相关概念 中的基础部分. 强连通的定义是:有向图 G 强连通是指,G 中任意两个结点连通. 强连通分量(Strongly Connected Compo ...
- 【CISCN2019 华北赛区 Day1 Web1】Dropbox 1
一.[CISCN2019 华北赛区 Day1 Web1]Dropbox 1 看题 首先是需要注册登录,然后进入是一个文件上传和下载的页面.尝试php一句话木马和burp抓包修改后缀的木马都失败,看来是 ...
- Fiddler安装,使用及汉化教程
Fiddler安装及汉化教程 一.下载安装 1.下载 官网链接:https://www.telerik.com/download/fiddler 左侧填写用途,邮箱及城市,然后下载就可以 左侧下载即D ...
- 怎么用Python写一个浏览器集群框架
这是做什么用的 框架用途 在采集大量新闻网站时,不可避免的遇到动态加载的网站,这给配模版的人增加了很大难度.本来配静态网站只需要两个技能点:xpath和正则,如果是动态网站的还得抓包,遇到加密的还得j ...