当前位置: 首页 > news >正文

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

文章目录

  • 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> {@Overridepublic UserClient create(Throwable cause) {return new UserClient() {@Overridepublic 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 {@Overridepublic 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: service1uri: 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 {@Overridepublic 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

相关文章:

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

文章目录 Feign整合Sentinel线程隔离熔断降级授权规则自定义异常结果 上一期教程讲解了 Sentinel 的限流规则&#xff1a; Sentinel限流规则&#xff0c;这一期主要讲述 Sentinel 的 隔离、降级和授权规则 虽然限流可以尽量避免因高并发而引起的服务故障&#xff0c;但服务还…...

C++11 列表初始化与类型声明

目录 ​ 0.前言 1.C11介绍 2.统一的列表初始化 2.1{}初始化 2.2initializer_list 2.2.1initializer_list 的基本用法 2.2.2用于类的 initializer_list 构造函数 2.2.3与标准库容器的结合 2.2.4优势与注意事项 3.新声明 3.1auto 3.1.1基本用法 3.1.2优势 3.1.3注意事项 3.2declt…...

缓存策略自定义:Laravel应用性能优化秘籍

缓存策略自定义&#xff1a;Laravel应用性能优化秘籍 在现代Web应用中&#xff0c;缓存是一种提高应用性能和响应速度的有效手段。Laravel框架提供了强大的缓存机制&#xff0c;支持多种缓存驱动&#xff0c;如文件、数据库、Redis等。然而&#xff0c;在某些情况下&#xff0…...

python连接sqlserver,封装操作

1封装 # 导入Flask类 import pymssql import tracebackclass Mssql(object):# 连接库def base(database):connect pymssql.connect(usersa,password123456,databasef{database},charsetutf8,as_dictTrue)if connect:print("数据库连接成功&#xff01;")else:print…...

原生PHP/JS自主开发的交友内核框架婚恋交友系统V10

本文来自&#xff1a;婚恋交友系统V10 - 源码1688 应用介绍 原生PHP/JS自主开发的交友内核框架&#xff0c;极高性能、无捆绑、自主权、无流水扣点、独立全开源 01脱单盲盒&#xff1a;脱单盲盒类似于漂流瓶&#xff0c;先将自己《投放》到盲盒中&#xff0c;另一伴有缘将您取…...

如何在Java、Python、GO程序中使用AI人脸识别API接口

AI人脸识别是一种通过面部识别或确认一个人身份的软件。它通过识别和测量图像中的面部特征来工作。面部识别可以识别图像或视频中的人脸&#xff0c;确定两幅图像中的人脸是否属于同一个人&#xff0c;或者在大量现有图像中搜索人脸。 AI人脸识别的优势是什么&#xff1f; 高…...

在vue使用MQTT

在vue中使用MQTT 最近有个需求&#xff0c;需要前端直接链接mqtt&#xff0c;想到后面可能多出使用&#xff0c;就封装成了hooks 中间遇到了一个坑&#xff0c;就是浏览器默认不支持mqtt协议&#xff0c;其借助了webSocket实现的mqtt协议&#xff0c; 而mqtt默认未开启webSocke…...

DNS、网关、IP、DHCP

DNS、网关、IP、DHCP&#xff1a;深入剖析与理解 在计算机网络的世界中&#xff0c;DNS、网关、IP和DHCP是四个至关重要的概念&#xff0c;它们共同构建了互联网的基础架构&#xff0c;确保了数据的准确传输和设备的有效连接。本文将深入剖析这四个概念&#xff0c;帮助读者更…...

vue2 vue3 props 的处理机制

在 Vue 2 中&#xff0c;props 是单向数据流&#xff0c;父组件向子组件传递的 props 默认情况下是不具有响应式特性的。这意味着当父组件的数据发生变化时&#xff0c;如果传递给子组件的 props 发生变化&#xff0c;子组件不会自动更新视图。 具体来说&#xff0c;在 Vue 2 …...

C++第十弹 ---- vector的介绍及使用

目录 前言vector的介绍及使用1. vector的使用1.1 vector的定义1.2 iterator的使用1.3 vector空间增长问题1.4 vector增删查改 2. vector迭代器失效问题(重点) 总结 前言 本文介绍了C中的vector数据结构及其使用方法。 更多好文, 持续关注 ~ 酷酷学!!! 正文开始 vector的介绍…...

ValueError: invalid literal for int() with base 10: ‘a‘

ValueError: invalid literal for int() with base 10: ‘a‘ 目录 ValueError: invalid literal for int() with base 10: ‘a‘ 【常见模块错误】 【解决方案】 欢迎来到英杰社区https://bbs.csdn.net/topics/617804998 欢迎来到我的主页&#xff0c;我是博主英杰&#xff…...

[C++探索]初始化列表,static成员,友元函数,内部类,匿名对象

&#x1f496;&#x1f496;&#x1f496;欢迎来到我的博客&#xff0c;我是anmory&#x1f496;&#x1f496;&#x1f496; 又和大家见面了 欢迎来到C探索系列 作为一个程序员你不能不掌握的知识 先来自我推荐一波 个人网站欢迎访问以及捐款 推荐阅读 如何低成本搭建个人网站…...

搭建自己的金融数据源和量化分析平台(二):读取上交所股票列表

我在上交所没发现上交所有像深交所一样的一键下载股票xls文档的按钮&#xff0c;因此上交所的股票列表读取就会比较麻烦。总体思路是查出来所有股票的代码之后根据股票代码逐一发起HTTP请求读取公司英文名、总股本、流通股本等详细信息&#xff0c;这就导致上交所爬虫的网络交互…...

Kafka知识总结(分区机制+压缩机制+拦截器+副本机制)

文章收录在网站&#xff1a;http://hardyfish.top/ 文章收录在网站&#xff1a;http://hardyfish.top/ 文章收录在网站&#xff1a;http://hardyfish.top/ 文章收录在网站&#xff1a;http://hardyfish.top/ 分区机制 分区策略 分区策略是决定生产者将消息发送到哪个分区的…...

WordPress原创插件:搜索引擎抓取首图seo图片

WordPress原创插件&#xff1a;搜索引擎抓取首图seo图片 插件设置 插件将在网站头部添加适当的meta标签&#xff0c;以便百度等搜索引擎抓取指定的固定图像。 插件下载 https://download.csdn.net/download/huayula/89596527...

Android Framework 之AMS

它管理了系统的四大组件:Activity、Service、ContentProvider、Broadcast。 它除了管理四大组件外&#xff0c;同时也负责管理和调度所有的进程 AMS相关目录结构 AMS代码主要在下面几个目录(AndroidQ上AMS相关部分功能移到了wm下)&#xff1a; frameworks/base/core/java/andro…...

AnConda环境配置学习笔记

AnConda环境配置 个人笔记&#xff0c;自己学习使用。 1、软件安装 去官网或者是清华大学镜像下载 2、环境配置 Conda 查看版本&#xff1a;conda --version 更新所有库 conda update --all&#xff08;千万不要跟新&#xff0c;版本不匹配&#xff09; matploitlib安装cond…...

架构师的36项修炼 学习笔记

架构师的36项修炼 学习笔记 分布式缓存 缓存特点 1.技术简单 2.性能提升明显 3.应用场景多 缓存数据存储 hash表 缓存的关键指标 命中率 缓存失效方式 超时失效 LLT 实时清除 代理缓存 反向代理缓存 多层反向代理缓存 内容分发网络CDN 通读缓存 包括代理缓存…...

Python | “IndexError: tuple index out of range” 【已解决】

Python | “IndexError: tuple index out of range” 【已解决】 IndexError: tuple index out of range 深度解析与实战指南 在Python编程中&#xff0c;IndexError: tuple index out of range是一个常见的错误&#xff0c;它发生在尝试访问元组&#xff08;或其他可索引的数…...

Linux上部署easySpider及基本使用

一、安装及简介 默认使用Chrome浏览器。 1、下载压缩包 官网&#xff1a;易采集EasySpider&#xff1a;无代码可视化爬虫/浏览器自动化测试软件 Linux版只适用于Ubuntu 20.04及以上版本、Deepin、Debian及其衍生版本。 &#xff08;建议使用&#xff09;下载网址/Github下…...

conda相比python好处

Conda 作为 Python 的环境和包管理工具&#xff0c;相比原生 Python 生态&#xff08;如 pip 虚拟环境&#xff09;有许多独特优势&#xff0c;尤其在多项目管理、依赖处理和跨平台兼容性等方面表现更优。以下是 Conda 的核心好处&#xff1a; 一、一站式环境管理&#xff1a…...

Prompt Tuning、P-Tuning、Prefix Tuning的区别

一、Prompt Tuning、P-Tuning、Prefix Tuning的区别 1. Prompt Tuning(提示调优) 核心思想:固定预训练模型参数,仅学习额外的连续提示向量(通常是嵌入层的一部分)。实现方式:在输入文本前添加可训练的连续向量(软提示),模型只更新这些提示参数。优势:参数量少(仅提…...

Qt/C++开发监控GB28181系统/取流协议/同时支持udp/tcp被动/tcp主动

一、前言说明 在2011版本的gb28181协议中&#xff0c;拉取视频流只要求udp方式&#xff0c;从2016开始要求新增支持tcp被动和tcp主动两种方式&#xff0c;udp理论上会丢包的&#xff0c;所以实际使用过程可能会出现画面花屏的情况&#xff0c;而tcp肯定不丢包&#xff0c;起码…...

Linux简单的操作

ls ls 查看当前目录 ll 查看详细内容 ls -a 查看所有的内容 ls --help 查看方法文档 pwd pwd 查看当前路径 cd cd 转路径 cd .. 转上一级路径 cd 名 转换路径 …...

PL0语法,分析器实现!

简介 PL/0 是一种简单的编程语言,通常用于教学编译原理。它的语法结构清晰,功能包括常量定义、变量声明、过程(子程序)定义以及基本的控制结构(如条件语句和循环语句)。 PL/0 语法规范 PL/0 是一种教学用的小型编程语言,由 Niklaus Wirth 设计,用于展示编译原理的核…...

SQL慢可能是触发了ring buffer

简介 最近在进行 postgresql 性能排查的时候,发现 PG 在某一个时间并行执行的 SQL 变得特别慢。最后通过监控监观察到并行发起得时间 buffers_alloc 就急速上升,且低水位伴随在整个慢 SQL,一直是 buferIO 的等待事件,此时也没有其他会话的争抢。SQL 虽然不是高效 SQL ,但…...

使用LangGraph和LangSmith构建多智能体人工智能系统

现在&#xff0c;通过组合几个较小的子智能体来创建一个强大的人工智能智能体正成为一种趋势。但这也带来了一些挑战&#xff0c;比如减少幻觉、管理对话流程、在测试期间留意智能体的工作方式、允许人工介入以及评估其性能。你需要进行大量的反复试验。 在这篇博客〔原作者&a…...

WPF八大法则:告别模态窗口卡顿

⚙️ 核心问题&#xff1a;阻塞式模态窗口的缺陷 原始代码中ShowDialog()会阻塞UI线程&#xff0c;导致后续逻辑无法执行&#xff1a; var result modalWindow.ShowDialog(); // 线程阻塞 ProcessResult(result); // 必须等待窗口关闭根本问题&#xff1a…...

[论文阅读]TrustRAG: Enhancing Robustness and Trustworthiness in RAG

TrustRAG: Enhancing Robustness and Trustworthiness in RAG [2501.00879] TrustRAG: Enhancing Robustness and Trustworthiness in Retrieval-Augmented Generation 代码&#xff1a;HuichiZhou/TrustRAG: Code for "TrustRAG: Enhancing Robustness and Trustworthin…...

五子棋测试用例

一.项目背景 1.1 项目简介 传统棋类文化的推广 五子棋是一种古老的棋类游戏&#xff0c;有着深厚的文化底蕴。通过将五子棋制作成网页游戏&#xff0c;可以让更多的人了解和接触到这一传统棋类文化。无论是国内还是国外的玩家&#xff0c;都可以通过网页五子棋感受到东方棋类…...