SpringCloudAlibaba微服务实战系列(四)Sentinel熔断降级、异常fallback、block细致处理

news2024/11/27 7:36:44

SpringCloudAlibaba Sentinel降级和熔断

接着上篇文章的内容,在Sentinel中如何进行降级和熔断呢?

熔断降级规则

降级规则

在Sentinel中降级主要有三个策略:RT、异常比例、异常数,也是针对某个资源的设置。而在1.8.0+版本后RT改为了慢调用比例

需要设置允许的慢调用 RT(即最大的响应时间),请求的响应时间大于该值则统计为慢调用。当单位统计时长(statIntervalMs)内请求数目大于设置的最小请求数目,并且慢调用的比例大于阈值,则接下来的熔断时长内请求会自动被熔断。经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN 状态),若接下来的一个请求响应时间小于设置的慢调用 RT 则结束熔断,若大于设置的慢调用 RT 则会再次被熔断。

RT:表示该资源1s内处理请求的平均响应时间。

注意:RT值的上限时4900ms,及时超过也是4900ms,如需自定义,可以在启动sentinel时增加参数

-Dcsp.sentinel.statistic.max.rt=x

慢调用比例

依旧是在簇点链路的列表视图选择/sentinelTest一行,进入熔断,设置参数如图:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sGUoQXMY-1690077568501)(../imgs3/1.png)]

RT设置为800ms,熔断时长设置为20s,为了测试效果,把接口睡眠1s。

@RequestMapping("/sentinelTest")
public String sentinelTest() throws InterruptedException {
    Thread.sleep(1000);
    return "sentinel-consumer9001 sentinelTest" + RandomUtils.nextInt(0, 1000);
}

解读:响应时间超过RT值的请求被称为慢调用。在单位时间(上图的统计时长1s)内,请求的数量大于最小请求数(5),且慢调用的比例>=阈值,此资源进入熔断状态(20s内不可用)。

Jmeter请求/sentinelTest,使用10个线程执行100次结果。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-10RfprgA-1690077568503)(../imgs3/2.png)]

前面几个请求是正常返回数据,后面全部降级处理,直接返回提示信息(此时该资源已经进入了熔断状态,可以理解为家里的电闸给关了,必须重新打开电闸,才能恢复使用电力)。后面这个资源无论怎样被调用,都无法进入接口,直接返回提示。

异常比例

当单位统计时长(statIntervalMs)内请求数目大于设置的最小请求数目,并且异常的比例大于阈值,则接下来的熔断时长内请求会自动被熔断。经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN 状态),若接下来的一个请求成功完成(没有错误)则结束熔断,否则会再次被熔断。异常比率的阈值范围是 [0.0, 1.0],代表 0% - 100%

表示请求该资源的异常总数占比。先模拟一个异常

@RequestMapping("/sentinelTest")
public String sentinelTest() {
    int i = 1 / 0;	// 除数为0
    return "sentinel-consumer9001 sentinelTest" + RandomUtils.nextInt(0, 1000);
}

设置规则

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kviEhxbh-1690077568503)(../imgs3/3.png)]

解读:当1s内,请求数量>5,且异常的比例大于80%,熔断20s

调用资源

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-c5jTOk65-1690077568504)(../imgs3/4.png)]

前几个请求正常请求返回异常提示,而后面的所有请求直接被拒绝访问。

异常数

该资源近1分钟内的异常数量。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1q8O3llS-1690077568504)(../imgs3/5.png)]

解读:当1s内,请求数量>5,且异常的数量>=10,熔断20s

经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN 状态),若接下来的一个请求成功完成(没有错误)则结束熔断,否则会再次被熔断。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eZyC2RzK-1690077568505)(../imgs3/6.png)]

当到11个请求仍然是异常时,直接熔断。

系统规则

之前的所有规则都是针对某个资源(接口)而言的,后面我们将针对整个应用设置系统规则。相对更加粗粒度,属于应用级别的入口流量控制。那么相对应的也有几种规则:

  • LOAD:负载,当系统负载超过设定值,且发现线程数超过预估系统容量就会触发保护机制。
  • RT:整个应用上所有资源平均的响应时间,而不是固定某个资源
  • 线程数:设定整个系统所能使用的业务线程数阈值,不固定某个资源
  • 入口QPS:整个应用所有的每秒处理的请求数
  • CPU使用率:这个应用占用的CPU的百分比

使用时可以根据服务器的情况设置即可。

授权规则

授权规则是根据调用方判断调用资源的请求是否应该被允许访问。Sentinel提供了黑白名单的授权类型,白名单表示允许调用资源,黑名单则不允许调用资源。

在java中实现相关的接口,将返回值交给sentinel处理。(注意:这里是在服务提供者方设置的

@Component
public class CustomRequestOriginParser implements RequestOriginParser {
    @Override
    public String parseOrigin(HttpServletRequest httpServletRequest) {
        String origin = httpServletRequest.getParameter("origin"); // 区分来源,本质通过request域获取来源标识
        if (StringUtils.isEmpty(origin)) {
            throw new RuntimeException("origin不能为空");
        }
        return origin; // 将返回的结果交给sentinel处理
    }
}

然后配置个授权规则

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qZlV3SQw-1690077568506)(../imgs3/7.png)]

资源名/test设置app为黑名单

当请求provider服务上的接口时,若origin为空则会被拒绝访问,若origin=app时仍会被拒绝,而其他的值则是可以访问

D:\springcloud\doc>curl localhost:8002/test?origin=app
==>Blocked by Sentinel (flow limiting)
D:\springcloud\doc>curl localhost:8002/test?origin=pc
==>sentinel-provider8002 test()921

使用@SentinelResource注解

之前主要是利用Sentinel仪表板控制一些参数保护应用。后面我们使用@SentinelResource注解根据实际情况实现定制化功能,对应用的保护更加细粒度。

现在限制达到阈值时,直接提示Blocked by Sentinel(flow limiting),提示不太友好,需要实现更精细化的控制。

blockHandler属性–负责响应控制面板配置

添加一个接口/blockHandlerTest资源名为blockHandlerTest,如果违反Sentinel控制台的规则,则进入blockHandlerTestHander。

@RequestMapping("/blockHandlerTest")
@SentinelResource(value = "blockHandlerTest", blockHandler = "blockHandlerTestHandler")
public String blockHandlerTest(String params) {
    return "Test#blockHandlerTest" + RandomUtils.nextInt(0, 1000);
}

public String blockHandlerTestHandler(String params, BlockException bl) {
    return "Test#blockHandlerTest" + RandomUtils.nextInt(0, 1000) + bl.getMessage();
}

注意:blockHandlerTestHandler方法的返回值要和原方法一致,并且除了原有的参数,还要带上BlockException的参数

设置一个流控,在@SentinelResouce注解中我们把资源名设置为blockHandlerTest,那么设置流控也是针对这个资源设置,让后面的请求进入我们自定义的处理中。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-H3ZqQxww-1690077568506)(../imgs3/8.png)]

可以看到,流控超过阈值后,其他的所有请求都是走的我们自定义的处理器。

热点规则

在一段时间内访问很频繁的资源是热点资源,需要针对资源做参数化定制。

@RequestMapping("/testHotKeyA")
@SentinelResource(value = "testHotKeyA", blockHandler = "blockTestHotKeyA")
public String testHotKeyA(@RequestParam(value = "orderId", required = false) String orderId,
                          @RequestParam(value = "userId", required = false) String userId) {
    return "Test#testHotKeyA" + RandomUtils.nextInt(0, 1000);
}

public String blockTestHotKeyA(String orderId, String userId, BlockException bl) {
    return "Test#blockTestHotKeyA" + RandomUtils.nextInt(0, 1000) + bl.getMessage();
}

去sentinel页面上加一个热点key规则

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tPEIErRB-1690077568507)(../imgs3/9.png)]

索引从0开始,那么获取的就是我们的orderId参数,在调用/testHotKeyA时要加上oderId参数否则不生效。

在这里插入图片描述

正确进入处理。

同时,我们可以对热点资源具体的某个参数值做阈值限制。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WeFEBvdq-1690077568508)(../imgs3/11.png)]

上图是对orderId为111或222时,阈值设置为500.再次测试,基本上不会进入自定义的处理中。但是为其他值时还是会进入我们的自定义处理。

fallback处理

前面是针对违反sentinel控制台规则做的处理,那么当我们的业务层面出现问题时,要做异常回滚等,则要使用fallback处理。同样是@SentinelResource中的属性。sentinel-1.6.0之前的版本是不支持针对业务异常处理的

@RequestMapping("/fallbackTest")
@SentinelResource(value = "fallbackTest", fallback = "fallbackHandler")
public String fallbackTest(String params) {
    int i = 1 / 0;
    return "Test#fallbackTest" + RandomUtils.nextInt(0, 1000);
}

public String fallbackHandler(String params) {
    return "Test#fallbackHandler" + RandomUtils.nextInt(0, 1000);
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cGmfv2T9-1690077568508)(../imgs3/12.png)]

所有的请求都进入到异常处理的方法中了。

fallback+blockHandler

@RequestMapping("/sentinelUnionTest")
@SentinelResource(value = "sentinelUnionTest", fallback = "sentinelUnionTestFallback", blockHandler = "sentinelUnionTestBlockHandler")
public String sentinelUnionTest(String params) {
    int i = 1 / 0;
    return "Test#fallbackTest" + RandomUtils.nextInt(0, 1000);
}

public String sentinelUnionTestFallback(String params) {
    return "Test#sentinelUnionTestFallback" + RandomUtils.nextInt(0, 1000);
}


public String sentinelUnionTestBlockHandler(String params, BlockException bl) {
    return "Test#sentinelUnionTestBlockHandler" + RandomUtils.nextInt(0, 1000) + bl.getMessage();
}

sentinelUnionTest资源设置流控,调用接口观察结果

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nP7LNAIb-1690077568509)(../imgs3/14.png)]

第一个接口是正常进入到了fallback处理,然后后面的请求因为超过阈值,直接进入block处理中了。

忽略异常–exceptionsToIngnore

fallback定义的方法可以针对所有类型的异常,我们也可以忽略某些异常。

@RequestMapping("/fallbackTest")
@SentinelResource(value = "fallbackTest", fallback = "fallbackHandler", exceptionsToIgnore = ArithmeticException.class)
public String fallbackTest(String params) {
    int i = 1 / 0;
    return "Test#fallbackTest" + RandomUtils.nextInt(0, 1000);
}

public String fallbackHandler(String params) {
    return "Test#fallbackHandler" + RandomUtils.nextInt(0, 1000);
}

模拟了一个计算异常,但是此异常被忽略了,所以不会进入到fallbackHandler中进行处理,而是直接jvm抛异常给客户端响应。

代码优化

前面的代码中都是把fallback和block全都写在了一起,这样是不符合程序单一性原则的,毕竟controller层有很多之外的逻辑,二来别的类也不好复用。

sentinel考虑到这些情况,在@SentinelResource中有blockHandlerClassfallbackClass。顾名思义,blockHandlerClass中写blockHandler函数,fallbackClass中写fallback的函数。

// 异常fallback
public class ExceptionHandler {
    public static String sentinelTestFallback(String params) {
        return "testCon#sentinelTestFallback" + RandomUtils.nextInt(0, 1000);
    }
}
// blockHandler处理
public class BlockHandler {
    public static String sentinelBlock(String params, BlockException e) {
        return "testCon#sentinelBlock" + RandomUtils.nextInt(0, 1000);
    }
}

两个类中的方法必须是static 修饰的,且参数要和原方法保持一致,否则无法解析噢

接口原方法

@RequestMapping("/sentinelUnionTest")
@SentinelResource(value = "sentinelUnionTest",
                  fallbackClass = ExceptionHandler.class, fallback = "sentinelTestFallback",  // 指定类和方法名
                  blockHandlerClass = BlockHandler.class, blockHandler = "sentinelBlock")     // 指定类和方法名
public String sentinelUnionTest(String params) {
    int i = 1 / 0;
    return "Test#fallbackTest" + RandomUtils.nextInt(0, 1000);
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/780300.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

python post请求编码问题

在日常的python使用中,必不可少的就是爬虫相关的知识。 爬虫也常会遇到一个问题,即就是编码的问题。 如下: 通过抓包可以看到额,实际python提交的参数为,如下格式: 那这种的签名必不可能通过&#xff0…

FPGA实现串口回环

文章目录 前言一、串行通信1、分类1、同步串行通信2、异步串行通信 2、UART串口通信1、UART通信原理2、串口通信时序图 二、系统设计1、系统框图2.RTL视图 三、源码1、串口发送模块2、接收模块3、串口回环模块4、顶层模块 四、测试效果五、总结六、参考资料 前言 环境&#xff…

【框架篇】Spring Boot核心介绍及项目创建(详细教程)

Spring Boot介绍及项目创建 一,Spring Boot 核心介绍 Spring Boot 是基于 Spring 开发的一种轻量级的全新框架,不仅继承了 Spring 框架原有的优秀特性,而且还通过简化配置来进一步简化了 Spring 应用的整个搭建和开发过程。通过Spring Boot&…

NO.453 最小操作次数使数组元素相等

题目 给你一个长度为 n 的整数数组,每次操作将会使 n - 1 个元素增加 1 。返回让数组所有元素相等的最小操作次数。 思路 本题要求,获取最小操作次数,即在满足所有元素均相等的情况下,操作次数最少。 由于本题无法确定最终元素…

火车头采集器伪原创插件【php源码】

火车头采集是一款基于Python语言开发的网络爬虫工具&#xff0c;用于快速高效地从互联网上采集数据并存储到本地或远程数据库。它简单易用且功能强大&#xff0c;在各行各业广泛应用。 火车头采集器AI伪原创PHP源码&#xff1a; <?php header("Content-type: text/h…

(四)springboot实战——springboot的事件与监听器原理

前言 本节内容是关于springboot的一些核心原理的总结&#xff0c;包括springboot的事件原理、生命周期流程、事件触发流程等核心内容的介绍&#xff0c;从而帮助我们更好的理解与使用springboot&#xff0c;这里只做概念性的内容总结&#xff0c;实战的部分请关注作者后续博客…

数学建模-分类模型 Fisher线性判别分析

论文中1. 判别分析系数 2. 分类结果 多分类问题 勾选内容和上面一样

06微分方程模型练习

用Matlab求解微分方程 y ′ − 2 y 2 x 2 2 x , y ( 0 ) 1 y-2y2x^{2}2x,y\left( 0\right) 1 y′−2y2x22x,y(0)1 y1 dsolve(Dy-2*y2*x.^22*x) y2 dsolve(Dy-2*y2*x.^22*x,y(0)1,x)用Matlab分别求解微分方程 y ′ − 2 y 2 x 2 2 x , y ( 0 ) 1 y-2y2x^{2}2x,y\left…

C语言动态内存管理(二)经典笔试题

第二篇内容为大家详细剖析关于动态内存管理的几个经典笔试题 目录 四、笔试题1.请问运行Test函数会有什么样的结果&#xff1f;结果&#xff1a;结果运行出错的原因&#xff1a;本题目注意点&#xff1a;改正该题目的错误&#xff1a;正确修改1&#xff1a;&#xff08;利用传值…

Electron入门学习_使用预加载脚本

学习网址&#xff1a; https://www.electronjs.org/zh/docs/latest/tutorial/tutorial-preload 1.什么是预加载脚本 Electorn 的主进程是一个拥有完全操作系统访问权限的Node.js ,除了Electron 模组&#xff0c;之外&#xff0c;您也可以访问Node.js 内置模块和所有通过npm安装…

质效两全:媒体服务的创新“顶设”

做媒体服务&#xff0c;一定要有刻入骨髓的抽象思维。 视频化浪潮汹涌、生成式人工智能AIGC极速迭代、体验需求和应用场景愈发多样......面对“视频生产力”的变革&#xff0c;我们能否透过纷繁复杂的表象&#xff0c;洞察音视频行业的“真正需求”&#xff1f; 是否存在一套…

【mysql数据库】MySQL7在Centos7的环境安装

说明&#xff1a; 安装与卸载中&#xff0c;用户全部切换成为root&#xff0c;⼀旦安装&#xff0c;普通用户就能使用。初期练习&#xff0c;mysql不进行用户管理&#xff0c;全部使⽤root进⾏&#xff0c;尽快适应mysql语句&#xff0c;后⾯学了用户管理&#xff0c;在考虑新…

matlab dot()函数求矩阵内积,三维 ,多维 详解

matlab dot()函数求矩阵内积&#xff0c;三维 &#xff0c;多维 详解 Cdot(A,b,X)&#xff0c;这个参数X 只能取1,或者2。1 表示按列&#xff0c;2表示按行&#xff0c;如果没有参数。默认按列。 1&#xff09;按列优先计算 Cdot(A,B)dot(A,B,1)[a1*b1a4*b4 ,a2*b2a5*b5 ,a…

html,css初学

安装VSCODE ,插件&#xff1a;live server &#xff0c;html support html 然后为了更好地理解&#xff0c;请逐步输入&#xff0c;并及时查看效果 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><title>D…

A--自动收小麦机--2023河南萌新联赛第(二)场:河南工业大学

链接&#xff1a;登录—专业IT笔试面试备考平台_牛客网 来源&#xff1a;牛客网 示例1 输入 4 1 2 1 1 4 5 2 2 2 3 4 输出 10 说明 在第4格放出水流后&#xff0c;水流会流向第3格&#xff0c;由于第3格高度比第4格低&#xff0c;所以水流继续向左流向第2格&#xff0…

爬虫的编解码方式

get请求的quote方法 我们在对爬取一个网页的时候&#xff0c;我们复制了这个网页的地址&#xff0c;但我们发现在将他粘贴下来以后不会是汉字&#xff0c;而是一串字符&#xff0c;这时候&#xff0c;我们需要去对字符进行编码&#xff0c;以便于我们能够继续去爬取网页。 例…

markdown编写数学公式

在计算机这一块&#xff0c;我们肯定会接触到数学&#xff0c;数学中又包含很多公式&#xff0c;但是到现在&#xff0c;手写这些公式应该不陌生&#xff0c;但是如果让你电脑敲出来&#xff0c;你绝对很懵逼&#xff0c;这也造成了我们有时候写笔记时一些公式没办法在电脑上像…

ffmpeg离线安装ffmpeg-4.1.4-amd64-static.tar.xz

1.下载离线包 John Van Sickle - FFmpeg Static Builds 找历史版本&#xff1a;Index of /ffmpeg/old-releases 我选择是的4.1.4版本 2.解压 tar -xvJf ffmpeg-4.1.4-amd64-static.tar.xz 3.移动文件到opt目录下 4.添加全局链接 ln -s /opt/ffmpeg-4.1.4-amd64-static/ffm…

【C++基础(五)】类和对象(上)

&#x1f493;博主CSDN主页:杭电码农-NEO&#x1f493;   ⏩专栏分类:C初阶之路⏪   &#x1f69a;代码仓库:NEO的学习日记&#x1f69a;   &#x1f339;关注我&#x1faf5;带你学习C   &#x1f51d;&#x1f51d; 类和对象-上 1. 前言2. 类的引入3. 类的定义4. 类的…

代码随想录-回溯(组合问题)|ACM模式

目录 前言&#xff1a; 77.组合 题目描述&#xff1a; 输入输出示例&#xff1a; 思路和想法&#xff1a; 216. 组合总和 III 题目描述&#xff1a; 输入输出示例&#xff1a; 思路和想法&#xff1a; 17. 电话号码的字母组合 题目描述&#xff1a; 输入输出描述&a…