Sentinel隔离、降级、授权规则详解

news2024/9/22 15:50:42

文章目录

  • Feign整合Sentinel
  • 线程隔离
  • 熔断降级
  • 授权规则
  • 自定义异常结果

上一期教程讲解了 Sentinel 的限流规则: Sentinel限流规则,这一期主要讲述 Sentinel 的 隔离、降级和授权规则

虽然限流可以尽量避免因高并发而引起的服务故障,但服务还会因为其它原因而故障。而要将这些故障控制在一定范围,避免雪崩,就要靠线程隔离(舱壁模式)和熔断降级手段了

不管是线程隔离还是熔断降级,都是对客户端(调用方) 的保护

Feign整合Sentinel

在 SpringCloud 中,微服务调用一般都是通过 Feign 来实现的,因此做客户端保护必须整合Feign和Sentinel

Feign 的使用在之前的教程中有详细讲解过:Eureka结合Feign

实现的步骤如下:

1.在调用方的 application.yml 文件中,开启 Feign 对 Sentinel 的支持

feign:
  sentinel:
    enabled: true # 开启feign对sentinel的支持

2.为 FeignClient 编写失败后的降级逻辑

这里有两种方式:

FallbackClass,这种方式无法对远程调用的异常做处理
FallbackFactory,这种方式可以对远程调用的异常做处理

这里我们选择 FallbackFactory

定义一个类 UserClientFallbackFactory(名字可以任意),然后实现接口 FallbackFactory<UserClient>,这里泛型要和对应的 Feign 客户端对应

@Component
public class UserClientFallbackFactory implements FallbackFactory<UserClient> {

    @Override
    public UserClient create(Throwable cause) {
        return new UserClient() {
            @Override
            public String user() {
                cause.printStackTrace();
                // 异常时返回空值
                return "";
            }
        };
    }
    
}

3.在 Feign 客户端的 @FeignClient 注解中,添加属性 fallbackFactory,值就是刚才定义的类的 class 对象

@FeignClient(name = "service2", url = "http://127.0.0.1:8082", fallbackFactory = UserClientFallbackFactory.class)

这里为了方便,就直接定义了对应服务的 url,如果结合了注册中心,这里只需要填写对应的服务名即可

4.启动测试

访问对应服务端点后,进入 Sentinel 控制台,可以看到如下界面,表示 Feign 已经成功整合了 Sentinel

image-20240724142527550

然后添加限流规则,将 QPS 设为 1,测试异常情况

image-20240724143327743

然后快速刷新浏览器,可以发现限流后,返回了空值,即触发了 Feign 客户端的失败降级逻辑

image-20240724143438130

线程隔离

线程隔离有两种方式实现:

1.线程池隔离

这种方式就是将服务消费者的资源划分成一个又一个独立的线程池,假设某一服务提供者挂掉了,也只有一个线程池的资源会被耗尽,不会导致所有的资源被耗尽

优点:

① 支持主动超时(可以通过线程池来控制线程,比如发现某个线程耗时较长,就可以直接终止这个线程)
② 支持异步调用(自己的线程继续接收消息,把调用交给线程池里的线程)

缺点: 线程的额外开销比较大(需要开启的线程较多,同时CPU还需要进行线程的上下文切换)

场景: 低扇出(扇出指的是原本的请求分散后的请求数),扇出越高,需要开启的线程就越多

2.信号量隔离(Sentinel 默认采用)

信号量隔离指的是不会为每个业务创建一个线程池,而是会统计当前业务已经使用的线程数,然后进行限制。当达到这个限制时,就会阻止对这个业务的请求,即限制每个业务能使用的线程数量

优点: 轻量级,无额外开销

缺点:

① 不支持主动超时
② 不支持异步调用

场景: 高频调用、高扇出

下面是两种方式的对比图:

线程隔离两种方式

在 Sentinel 控制台中,可以选择阈值类型,共有两种:

image-20240724143541602

① QPS:就是每秒的请求数
② 线程数:是该资源能使用的 tomcat 线程数的最大值。也就是通过限制线程数量,实现舱壁模式,对应信号量隔离

熔断降级

熔断降级是解决雪崩问题的重要手段。其思路是由断路器统计服务调用的异常比例、慢请求比例,如果超出阈值则会熔断该服务,即拦截访问该服务的一切请求。而当服务恢复时,断路器会放行访问该服务的请求

断路器是由内部的状态机实现的:

断路器状态机

整个的流程是:正常情况下,断路器关闭,处于 Closed 状态。如果断路器统计的慢调用或异常比例达到失败阈值,会开启断路器,进入 Open 状态,此时的请求会快速失败。直到熔断时间结束,会进入 Half-Open 状态(断路器半开启状态),此时会尝试放行一次请求,如果此次请求成功,则关闭断路器,进入 Closed 状态;如果请求失败,则重新打开断路器,回到 Open 状态,并重复刚才的过程

断路器熔断策略有三种:慢调用、异常比例、异常数

1.慢调用

业务的响应时长(RT)大于指定时长的请求认定为慢调用请求。在指定时间内,如果请求数量超过指定请求数,并且慢调用比例大于设定的阈值,则触发熔断

例如,在 Sentinel 控制台中选择新增降级规则,并填写如下信息

image-20240724144201880

image-20240724144336008

这个表单的信息表示,响应时长(RT) 超过 500ms 的调用是慢调用,统计最近 10000ms 内的请求,如果请求量不少于 10 次,并且慢调用比例不低于 0.5,则触发熔断,熔断时长为 5 秒。然后进入 half-open 状态,放行一次请求做测试

2.异常比例或异常数

统计指定时间内的调用,如果调用次数超过指定请求数,并且出现异常(指的是程序抛出的异常)的比例达到设定的比例阈值(或超过指定异常数),则触发熔断

例如,设置如下的降级规则

image-20240724144712522

image-20240724144737893

这两种设置方式都是一样的,区别在于一个是设置异常比例,一个是设置异常数,但表达的意思都是,统计最近 1000ms 内的请求,如果请求量不少于 10 次,并且异常比例不低于 0.4(或异常数不少于2),则触发熔断,熔断时长为 5 秒。然后进入 half-open 状态,放行一次请求做测试

授权规则

授权规则可以对调用方的来源做控制,有白名单黑名单两种方式

白名单:来源(origin)在白名单内的调用者允许访问
黑名单:来源(origin)在黑名单内的调用者不允许访问

在控制台中可以选择新增授权规则,此时就可以选择黑名单或白名单两种方式

image-20240724150439205

image-20240724150505414

Sentinel 是通过 RequestOriginParser 接口中的 parseOrigin() 方法来获取请求的来源的

public interface RequestOriginParser {
    /**
     * 从请求request对象中获取origin,获取方式自定义
     */
    String parseOrigin(HttpServletRequest request);
}

但是,默认情况下,这个方法的返回值永远是 “default”。也就是说,Sentinel 默认无法区分所有的请求。因此,我们需要自己实现这个接口,并且编写业务逻辑

案例:

限定只允许从网关发来的请求来访问 service1

实现步骤如下:

1.编写类,实现 RequestOriginParser 接口并编写 parseOrigin() 方法,从 HTTP 请求中获取名为 origin 的请求头并返回

@Component
public class HeaderOriginParser implements RequestOriginParser {
    @Override
    public String parseOrigin(HttpServletRequest httpServletRequest) {
        String origin = httpServletRequest.getHeader("origin");
        if(StringUtils.isEmpty(origin)) {
            origin = "blank";
        }
        System.out.println(origin);
        return origin;
    }
}

2.在 gateway 网关服务中,利用过滤器添加 origin 请求头,值为 gateway

server:
  port: 10010 # 网关端口
spring:
  application:
    name: gateway # 服务名称
  cloud:
    gateway:
      routes: # 网关路由配置
        - id: service1
          uri: http://localhost:8081 # 路由的目标地址
          predicates: # 路由断言,判断请求是否符合路由规则的条件
            - Path=/service1/** # 路径断言
      default-filters:
        - AddRequestHeader=origin,gateway # 添加名为origin的请求头,值为gateway

3.在控制台中配置授权规则

image-20240724160931183

4.测试

首先直接跨过网关访问 service1,如下图所示,可以发现访问失败

image-20240724161006709

然后,通过网关来访问 service1,如下图所示,可以发现访问成功

image-20240724161029014

自定义异常结果

默认情况下,发生限流、降级、授权拦截时,都会抛出异常到调用方。如果要自定义异常时的返回结果,需要实现 BlockExceptionHandler 接口

public interface BlockExceptionHandler {
    /**
     * 处理请求被限流、降级、授权拦截时抛出的异常:BlockException
     */
    void handle(HttpServletRequest request, HttpServletResponse response, BlockException e) throws Exception;
;}

可以看到,handle() 方法中有一个类型为 BlockException 的参数,这个参数表示了具体的异常,而 BlockException 包含很多个子类,分别对应不同的场景,如下所示

异常说明
FlowException限流异常
ParamFlowException热点参数限流的异常
DegradeException降级异常
AuthorityException授权规则异常
SystemBlockException系统规则异常

实现自定义异常返回结果的具体方式是,定义一个类,实现 BlockExceptionHandler 接口,然后编写业务逻辑,如下所示:

@Component
public class SentinelExceptionHandler implements BlockExceptionHandler {
    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response, BlockException e) throws Exception {
        String msg = "未知异常";
        int status = 429;
        if (e instanceof FlowException) {
            msg = "请求被限流了";
        } else if (e instanceof ParamFlowException) {
            msg = "请求被热点参数限流";
        } else if (e instanceof DegradeException) {
            msg = "请求被降级了";
        } else if (e instanceof AuthorityException) {
            msg = "没有权限访问";
            status = 401;
        }
        response.setContentType("application/json;charset=utf-8");
        response.setStatus(status);
        response.getWriter().println("{\"msg\": " + msg + ", \"status\": " + status + "}");
    }
}

然后进行测试。先在控制台创建流控规则,将 QPS 设为1,如下

image-20240724162045896

然后快速刷新浏览器,结果如下所示,可以看出异常结果和代码所展现的一致

image-20240724162226250

其他的测试也是类似的,但是发现热点规则无法触发该逻辑,用 debug 设置断点发现在异常时没有进入到对应的代码里

因此建议对于热点规则的异常,直接使用全局异常处理即可,如下所示:

@RestControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(ParamFlowException.class)
    public void handleParamFlowException(HttpServletRequest request, HttpServletResponse response, Exception e)
            throws IOException {
        response.setContentType("application/json;Charset=utf-8");
        response.setStatus(429);
        response.getWriter().println("{\"msg\": " + "请求被热点参数限流" + ", \"status\": " + 429 + "}");
    }

}

测试后发现异常结果可以正常显示

image-20240724164030872

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

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

相关文章

【玩转C语言】第五讲--->数组-->一维和多维深度理解

&#x1f525;博客主页&#x1f525;&#xff1a;【 坊钰_CSDN博客 】 欢迎各位点赞&#x1f44d;评论✍收藏⭐ 引言&#xff1a; 大家好&#xff0c;我是坊钰&#xff0c;为了让大家深入了解C语言&#xff0c;我开创了【玩转C语言系列】&#xff0c;将为大家介绍C语言相关知识…

你还在为文件翻译烦恼吗?试试这四款神器,轻松搞定一切!

现如今的信息传播速度不断得加快&#xff0c;无论是中外交流还是学习&#xff0c;也越来越多小语种出现在我们的工作和生活当中来了&#xff0c;其中不伐一些文件批量的形式&#xff0c;所以今天就具体来探讨一下&#xff0c;关于文件翻译的四款辅助工具&#xff1a; 一、福昕在…

openGauss触发器详解

openGauss 是一款开源关系型数据库管理系统&#xff0c;广泛应用于企业级应用中。随着数据量的增长和业务逻辑的复杂化&#xff0c;数据库管理和操作的自动化需求越来越高。触发器&#xff08;Triggers&#xff09;作为数据库中重要的编程工具&#xff0c;能够极大地简化复杂操…

广州机房服务器搬迁布线方案

友力科技&#xff08;广州&#xff09;有限公司&#xff0c;专业从事数据中心机房建设、改造和搬迁工程。友力科技&#xff08;广州&#xff09;有限公司提供的服务内容包括但不限于&#xff1a;原数据中心设备下架准备、沿途运输、新数据中心上架运行、数据迁移等。 友力科技…

前端面试细节重难点(十二)(已工作|做分享)

1、如何区分在react、vue和js中的是否传递e参数&#xff1f;事件对象e都要通过event作为实参显示传递形参才可接收到吗&#xff1f; 答&#xff1a;&#xff08;1&#xff09;在原生JavaScript中&#xff1a;事件对象e需要通过函数参数显式传递。 &#xff08;2&#xff09;在R…

观测云加入华为云「新加坡云联盟」,引领亚太创新潮流

7月19日&#xff0c;「新加坡云联盟」在华为云新加坡峰会2024上正式宣告成立。这一创新的联合不仅是新加坡乃至整个亚太地区云服务领域的重要里程碑&#xff0c;更是全球数字化转型进程中的关键一步。 观测云作为联盟的首批成员之一&#xff0c;在成立仪式上精彩亮相&#xff0…

探索能源管理体系认证的意义与实施

能源管理体系&#xff08;Energy Management System, EnMS&#xff09;是一个综合性的框架&#xff0c;旨在帮助企业系统地管理能源使用&#xff0c;提升能源效率&#xff0c;实现可持续发展的目标。这个体系包括了企业的组织结构、职责分配、惯例、程序、过程以及资源管理。通…

Linux中为qt添加opencv

一. 安装OpenCV库&#xff1a; 打开终端&#xff0c;输入以下命令安装OpenCV&#xff1a; sudo apt-get update sudo apt-get install libopencv-dev二. 配置Qt项目 在Qt Creator中打开项目&#xff0c;然后编辑.pro文件&#xff0c;添加以下内容&#xff1a; INCLUDEPATH …

2024年必备的9大CRM工具选购指南

本文介绍的工具有&#xff1a;纷享销客、Zoho CRM、八百客、红圈通、简道云、简信CRM、Salesforce、HubSpot CRM、Apptivo。 在选择合适的CRM系统时&#xff0c;许多企业面临着功能繁多、选择困难的痛点。对于中小企业来说&#xff0c;找到一个既能提高客户关系管理效率&#x…

Java基础-Java多线程机制

(创作不易&#xff0c;感谢有你&#xff0c;你的支持&#xff0c;就是我前行的最大动力&#xff0c;如果看完对你有帮助&#xff0c;请留下您的足迹&#xff09; 目录 一、引言 二、多线程的基本概念 1. 线程与进程 2. 多线程与并发 3. 多线程的优势 三、Java多线程的实…

GUL图形化界面操作(上部)

目录 AWT Frame对象&#xff1a;创建窗口 ​编辑 该对象相关的属性 设置窗口大小&#xff08;对象.setsize(int,int)&#xff09; 让窗口可以显现出来&#xff08;对象.setVisible(bool)&#xff09; 设置窗口标题&#xff08;对象.setTitle(String)&#xff09; 设置窗…

MySQL学习(14):索引使用规则

1. 索引语法 #创建索引 create [unique|fulltext] index 索引名 on 表名 (字段名,...); #字段可以有多个 #如果不加unique或fulltext&#xff0c;那么将创建一个普通索引 #在InnoDB引擎小&#xff0c;创建的索引默认是Btree结构#查看索引 show index from 表名;#删除索引 drop…

折叠群控FPV穿越机技术详解

折叠群控FPV穿越机技术是一个结合了多项高端技术和飞行理念的创新系统。以下是该技术的详细解析&#xff1a; 1. 技术概述&#xff1a; - FPV穿越机&#xff1a;FPV&#xff0c;全称First Person View&#xff0c;即“第一人称视角”&#xff0c;是指通过无人机上搭载的摄像头&…

Python+Pytest+Allure+Yaml+Pymysql+Jenkins+GitLab运行原理

PythonPytestAllureYamlPymysqlJenkinsGitLab运行原理逻辑及调用关系 GitLab代码仓&#xff1a; Jenkins工作空间&#xff1a; 代码&#xff1a; 测试报告展示&#xff1a;

医疗器械上市欧美,需要什么样的网络安全相关申报文件?

医疗器械在欧美上市时&#xff0c;需要提交的网络安全相关申报文件主要包括以下几个方面&#xff0c;这些要求基于欧美地区的法律法规和监管机构的指导文件。 一、美国FDA要求 1. 网络安全管理计划 内容&#xff1a;制造商需要提交一份网络安全管理计划&#xff0c;该计划应包含…

blender顶点乱飞的问题解决

初学blender&#xff0c;编辑模式下移动某些顶点&#xff0c;不管是移动还是滑动都会出现定点乱飞的问题&#xff0c;后来才发现是开了吸附工具的原因&#xff01;&#xff01;&#xff01;&#xff01; 像下面这样&#xff0c;其实我只是在Z轴上移动&#xff0c;但是就跑的很…

经纬恒润与奇瑞汽车签订新能源项目重点供应商合作协议,共同开启合作新篇章

近日&#xff0c;2024年国家级芜湖经开区汽车零部件生态大会成功举行&#xff0c;经纬恒润受邀出席&#xff0c;与行业各伙伴齐聚经开区&#xff0c;同绘发展蓝图&#xff0c;助力经开区汽车产业高质量发展。会上&#xff0c;经纬恒润与奇瑞汽车签署合作协议&#xff0c;成为奇…

2-43 基于matlab的RBF网络自适应控制应用

基于matlab的RBF网络自适应控制应用&#xff0c;使用RBF网络逼近一级倒立摆模型中未知的非线性函数部分&#xff0c;即用RBF网络代替一级倒立摆模型中未知非线性函数部分&#xff0c;从而设计自适应控制&#xff0c;实现一级倒立摆的平衡控制。程序已调通&#xff0c;可直接运行…

卡夫卡(Kafka)框架详解:从背景到应用实践

卡夫卡&#xff08;Kafka&#xff09;框架详解&#xff1a;从背景到应用实践 引言 在大数据和分布式系统日益普及的今天&#xff0c;数据处理和消息传递成为了支撑复杂业务系统的关键基础设施。Apache Kafka&#xff0c;作为一个高性能的分布式消息队列系统&#xff0c;因其高…

qt 如何制作动态库插件

首先 首先第一点要确定我们的接口是固定的&#xff0c;也就是要确定 #ifndef RTSPPLUGIN_H #define RTSPPLUGIN_H #include "rtspplugin_global.h" typedef void (*func_callback)(uint8_t* data,int len,uint32_t ssrc,uint32_t ts,const char* ipfrom,uint16_t f…