【深入理解SpringCloud微服务】Sentinel实战与原理剖析

news/2024/10/31 15:54:30/

【深入理解SpringCloud微服务】Sentinel实战与原理剖析

  • Sentinel功能
  • Sentinel三种用法
    • 硬编码
    • 注解
    • 拦截器
    • 什么时候使用注解方式,什么时候使用拦截器方式?
  • Sentinel原理

Sentinel功能

Sentinel和Hystrix一样,也是一个微服务容错保护框架,想要知道Sentinel拥有什么功能,看一下它的控制台就知道了。

在这里插入图片描述

除了流控和熔断以外,比起Hystrix还增加了热点规则、系统规则、授权规则、集群流控等功能,所有Sentinel对比Hystrix是功能更丰富的。

在这里插入图片描述

Sentinel三种用法

硬编码

引入依赖

        <dependency><groupId>com.alibaba.csp</groupId><artifactId>sentinel-core</artifactId><version>1.8.4</version></dependency>

示例代码:

/*** @author huangjunyi* @date 2024/4/9 18:30* @desc*/
public class SentinelDemo {// 注册流控规则static {List<FlowRule> rules = new ArrayList<>();FlowRule rule = new FlowRule();// 定义资源名称rule.setResource("hello");// QPS模式限流,每秒2个rule.setGrade(RuleConstant.FLOW_GRADE_QPS);rule.setCount(2);rules.add(rule);FlowRuleManager.loadRules(rules);}private static void hello() {Entry entry = null;try {// 通过SphU.entry(资源名)记录统计数据并执行给定资源的规则检查entry = SphU.entry("hello");System.out.println("hello");} catch (BlockException e) {System.out.println("限流了");} finally {if (entry != null) {// 最后必须调用Entry#exit()才算完成// Entry#exit()会进行一些数据的统计以及决定断路器是否打开entry.exit();}}}public static void main(String[] args) {hello();hello();// 第三次就限流了hello();}}

执行代码后,可以看到第三次输出就流控了。
在这里插入图片描述

Sentinel的整体思路就是两步:

  1. 服务启动的时候往各种Mananger注册规则,比如以流控为例,就是往FlowRuleManager当中注册流控规则FlowRule,并且每个规则都有一个资源名称与其对应。
  2. 然后执行目标业务逻辑前先执行SphU.entry(资源名),根据资源名称从FlowRuleManager(还是以流控为例)寻找对应的FlowRule进行校验,校验通过则执行业务逻辑,校验失败则抛异常。最后还要调用entry.exit()进行收尾工作。

在这里插入图片描述

Sentinel硬编码的使用方式是最原始的使用方式,后面两种方式都是基于硬编码方式做的扩展。想要理解Sentinel的原理,首先要了解硬编码方式的实现原理。

注解

引入依赖:除了sentinel-core以外,还要引入sentinel-annotation-aspectj

        <dependency><groupId>com.alibaba.csp</groupId><artifactId>sentinel-annotation-aspectj</artifactId><version>1.8.4</version></dependency>

配置类:

/*** @author huangjunyi* @date 2024/4/10 19:45* @desc*/
@Configuration
public class AspectConfig {// 配置Sentinel的切面类,才能使@SentinelResource注解生效@Beanpublic SentinelResourceAspect sentinelResourceAspect() {return new SentinelResourceAspect();}}

初始化流控规则:

/*** @author huangjunyi* @date 2024/4/8 19:06* @desc*/
@Component
public class FlowRuleInit {@PostConstructpublic void init() {initFlowRules();}// 初始化流控规则,也可以在控制台中配置private static void initFlowRules(){List<FlowRule> rules = new ArrayList<>();FlowRule rule = new FlowRule();rule.setResource("hello");rule.setGrade(RuleConstant.FLOW_GRADE_QPS);rule.setCount(2);rules.add(rule);FlowRuleManager.loadRules(rules);}}

Controller:

/*** @author huangjunyi* @date 2024/4/8 19:00* @desc*/
@RestController
public class HelloController {// @SentinelResource主键指定资源名,以及降级回调方法@SentinelResource(value = "hello", blockHandler = "flowBlockHandler")@GetMapping("/hello")public String hello() {System.out.println("hello");return "hello";}// 被流控时的降级回调方法public String flowBlockHandler(BlockException blockException) {return "被流控了!";}}

注解方式就是在目标方法上添加@SentinelResource注解,注解指定资源名称与配置的流控规则一致,流控效果就会生效。

在这里插入图片描述

如果是引入的spring-cloud-starter-alibaba-sentinel依赖,那就不需要配置Sentinel切面类了,spring-cloud-starter-alibaba-sentinel已经通过自动装配的方式帮我们配置好了。

在这里插入图片描述

拦截器

最后是拦截器的方式,这种方式是最方便的,不需要添加注解,默认是请求路径作为资源名称。

引入依赖:除了sentinel-core以外,还要引入sentinel-spring-webmvc-adapter

        <dependency><groupId>com.alibaba.csp</groupId><artifactId>sentinel-spring-webmvc-adapter</artifactId><version>1.8.4</version></dependency>

配置拦截器

/*** @author huangjunyi* @date 2024/4/8 19:04* @desc*/
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {@Overridepublic void addInterceptors(InterceptorRegistry registry) {SentinelWebMvcConfig config = new SentinelWebMvcConfig();config.setBlockExceptionHandler(new DefaultBlockExceptionHandler());// 设置为true,资源名称前面要带方法名,设置为false则不需要config.setHttpMethodSpecify(true);config.setWebContextUnify(true);config.setOriginParser(request -> request.getHeader("S-user"));// 添加Sentinel的拦截器registry.addInterceptor(new SentinelWebInterceptor(config)).order(Integer.MIN_VALUE).addPathPatterns("/**");}
}

配置流控规则,或者直接在控制台配置:

/*** @author huangjunyi* @date 2024/4/8 19:06* @desc*/
@Component
public class FlowRuleInit {@PostConstructpublic void init() {initFlowRules();}// 初始化流控规则,也可以在控制台中配置private static void initFlowRules(){List<FlowRule> rules = new ArrayList<>();FlowRule rule = new FlowRule();// 由于拦截器的httpMethodSpecify属性配置为true,// 资源名称前面要带上方法名rule.setResource("GET:/hello");rule.setGrade(RuleConstant.FLOW_GRADE_QPS);rule.setCount(2);rules.add(rule);FlowRuleManager.loadRules(rules);}}

Controller:

/*** @author huangjunyi* @date 2024/4/8 19:00* @desc*/
@RestController
public class HelloController {@GetMapping("/hello")public String hello() {System.out.println("hello");return "hello";}}

使用拦截器方式,就不需要声明@SentinelResource注解了,如果通过控制台配置规则的话,甚至连上面FlowRuleInit的流控规则配置都可以不需要,只需要引入依赖jar包,然后配置一个拦截器即可。

在这里插入图片描述

Sentinel拦截器方式其实就是在拦截器SentinelWebInterceptor中执行硬编码时的模板代码。

在SentinelWebInterceptor的preHandle方法中执行SphU.entry(resourceName)方法,如果检查通过,则执行业务逻辑;检查不通过则抛出异常BlockException,SentinelWebInterceptor也会catch住异常并做相应处理。

最后SentinelWebInterceptor的afterCompletion方法会调用entry.exit()进行收尾。

在这里插入图片描述

什么时候使用注解方式,什么时候使用拦截器方式?

注解方式是网上示例最多的,但是如果我们有一百个一千个接口,难不成每个接口声明一个注解?也不是不可以,但何必这么麻烦呢?此时通过拦截器方式,默认以接口路径作为资源名称,不是更方便吗?剩下的就是在控制台配置规则。

但是拦截器方式也有注解方式做不到的地方,比如配置降级处理逻辑,以及热点参数限流。

在这里插入图片描述

这样,什么时候使用注解方式,什么时候使用拦截器方式,就很清楚了。

Sentinel原理

Sentinel底层利用了责任链模式,去处理每个不同的规则。

在这里插入图片描述

当第一次调用SphU.entry()方法时,会通过SPI机制加载指定的所有ProcessorSlot实现类,组装成一个ProcessorSlotChain,ProcessorSlotChain中每个Slot通过next指针链接形成一个单选链表。

SphU.entry()方法每次都会以责任链的方式沿着ProcessorSlotChain里的每个Slot往下执行,一旦某个Slot校验不通过,则终止不再往下,chain中的所有slot都校验通过,则返回Entry对象。

在这里插入图片描述

ProcessorSlotChain中有许多类型的Slot,我们不需要全部了解,但是有两个特别重要的我们必须要知道,一个是FlowSlot,另一个是DegradeSlot。FlowSlot对应流控规则的处理,DegradeSlot对应熔断规则的处理。它们俩一般放在chain的最末尾。

在这里插入图片描述


http://www.ppmy.cn/news/1543377.html

相关文章

多语言语音转写系统:实时记录,跨场景应用的高效助手

一、系统介绍 该系统通过优化的音频特征提取算法与自定义语言模型&#xff0c;提供高精度的转写服务&#xff0c;并能够实现多语言支持和本地化部署。作为一款开源工具&#xff0c;用户可在思通数科AI多模态能力平台上免费体验或下载集成&#xff0c;获得一键式转写解决方案。…

100种算法【Python版】第24篇——Bellman-Ford算法

本文目录 1 算法原理2 路径计算的实现步骤3 python代码4 算法应用1 算法原理 Bellman-Ford算法由美国计算机科学家理查德贝尔曼(Richard Bellman)和洛伊德福特(Lloyd Ford)于1958年提出。最初设计用于解决图论中的单源最短路径问题,尤其适用于含有负权边的图。该算法的提…

Vue项目中动态路由与权限控制:router.beforeEach的使用及无token重定向登录页

在现代前端项目中&#xff0c;权限控制是一个非常重要的环节。Vue Router作为Vue官方的路由管理器&#xff0c;为我们提供了强大的路由管理功能。在本文中&#xff0c;我们将探讨如何在Vue项目中使用router.beforeEach钩子函数来实现动态路由权限控制&#xff0c;并在用户未登录…

【网络原理】——图解HTTPS如何加密(通俗简单易懂)

阿华代码&#xff0c;不是逆风&#xff0c;就是我疯 你们的点赞收藏是我前进最大的动力&#xff01;&#xff01; 希望本文内容能够帮助到你&#xff01;&#xff01; 目录 一&#xff1a;HTTP为什么不安全 二&#xff1a;HTTPS加密过程 1&#xff1a;密码学中的概念 &…

【缓存与加速技术实践】Redis 高可用

文章目录 Redis 高可用1. 持久化2. 主从复制3. 哨兵&#xff08;Sentinel&#xff09;4. Cluster集群持久化持久化的方式RDB 持久化触发条件执行流程启动时加载 AOF 持久化开启 AOF执行流程启动时加载 RDB 和 AOF 的优缺点 redis性能管理查看 Redis 内存使用内存碎片率内存使用…

C# .NET最小API?

在.NET 5/6中&#xff0c;你可以使用最小API来创建高性能的HTTP API。最小API提供了一种更轻量级的构建API的方式&#xff0c;它允许你直接在Program.cs文件中定义路由和处理程序&#xff0c;而不需要使用传统的MVC控制器。 什么是最小API&#xff1f; 最小API是一个用于构建HT…

【测试平台】Ewomail 邮件服务器搭建

一、邮件服务器背景介绍 背景介绍 使用的是开源的Ewomail邮件服务器&#xff0c;方便QA同学在进行业务测试时&#xff0c;通过测试平台自动注册邮件新账号&#xff0c; 减少手工注册的操作。前端页面调用的底层注册邮箱就是我们即将搭建的邮件服务器。 服务访问关系 前端 -&…

数学建模汇总

模型汇总 数学建模算法汇总 数据分析 数据的统计描述和分析 数据处理 用Python进行数据挖掘&#xff08;数据预处理&#xff09; Python机器学习库SKLearn&#xff1a;数据预处理 在Python中进行数据清洗和预处理缺失值处理缺失值补全 灵敏度分析 研究与分析一个系统&…