Sentinel从入门到“精通”,从源码层面学习Sentinel

B站视频讲解


文章目录

  • 一、安装
    • 1、原生使用
    • 2、dashboard整合
      • 2-1、非starter整合
        • 2-1-1、公共
        • 2-1-2、Filter
        • 2-1-3、AOP
        • 2-2、starter 整合
    • 3、总结
  • 二、常见的策略
    • 1、限流
      • 1-1、基于QPS 限流
      • 1-2、基于线程数限流
    • 2、降级
      • 2-1、慢调用比例
      • 2-2、异常数(限流异常不算)
      • 2-3、异常比例(限流异常不算)
    • 3、黑白名单
    • 4、其它
  • 三、全局异常拦截
    • 1、对拦截器方式的全局异常处理
      • 1-2、验证拦截器和AOP的双重拦截
    • 3、对AOP方式的全局异常拦截
  • 四、规则持久化


一、安装


Sentinel 是一个嵌入式的限流框架,所以可以在某个服务中引入它,然后用侵入式的方式去编写限流策略,这当然不是我们想要的,所以它也提供了基于控制台来实时编写限流策略(猜测是基于动态的添加代理和删除代理来实现,后续研究),只需要在代码中引入核心包,然后搭配控制台就可以实时的开启/关闭限流。

  • 资源:在Sentinel的世界里任何想要被限制的【代码块】都可以称之为资源

1、原生使用


所谓原生使用就是不搭配控制台。

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

Demo 代码

import com.alibaba.csp.sentinel.Entry;
import com.alibaba.csp.sentinel.SphU;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.block.RuleConstant;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;

import java.util.ArrayList;
import java.util.List;

public class Main {
    public static void main(String[] args) throws InterruptedException {
        // 配置规则.
        initFlowRules();

        while (true) {
            // 1.5.0 版本开始可以直接利用 try-with-resources 特性
            try (Entry entry = SphU.entry("HelloWorld")) {
                // 被保护的逻辑
                System.out.println("hello world");
            } catch (BlockException ex) {
                // 处理被流控的逻辑
                System.out.println("blocked!");
            }
            // 防止打印太多了
            Thread.sleep(900);
        }
    }

    private static void initFlowRules(){
        List<FlowRule> rules = new ArrayList<>();
        FlowRule rule = new FlowRule();
        rule.setResource("HelloWorld");
        rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
        // 限制QPS 为 1个
        rule.setCount(1);
        rules.add(rule);
        FlowRuleManager.loadRules(rules);
    }
}

2、dashboard整合


正常情况,我们不会使用原生方式,代码侵入性太强了,可以搭配 dashboard来动态的添加/删除规则。

dashboard本身就是一个SpringBoot 项目,jar包下载地址


java -jar 启动

在这里插入图片描述


http://127.0.0.1:8080

默认账号密码:sentinel/sentinel

在这里插入图片描述


2-1、非starter整合


2-1-1、公共

通过上面原生使用方式,得知它的本质其实就和加锁差不多,是有代码侵入性的。在JavaWeb里面如果想实现一个通用的功能并且代码无侵入性的话,Filter和AOP是不错的选择。

在进行Filter和AOP实践之前,先来搭建公共的模块。


pom

<!-- 核心包 -->
<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-core</artifactId>
    <version>1.8.6</version>
</dependency>

<!-- 连接客户端,和dashboard交互 -->
<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-transport-simple-http</artifactId>
    <version>1.8.6</version>
</dependency>

测试类

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class Controller {

    @GetMapping("/one")
    public String one() {
        return "ok";
    }
}

启动的时候加上配置sentinel 的地址 -Dcsp.sentinel.dashboard.server=127.0.0.1:8080


配置入口

在这里插入图片描述


Idea 旧版

在这里插入图片描述


Idea 新版

在这里插入图片描述


Sentinel 是懒加载的,不管使用什么方式,服务启动之后都必须访问 /one 才可以被dashboard监控到


2-1-2、Filter

1、pom文件引入

<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-web-servlet</artifactId>
    <version>1.8.6</version>
</dependency>

2、引入过滤器

在Filter里面加一个优先级很高的 CommonFilter

import com.alibaba.csp.sentinel.adapter.servlet.CommonFilter;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.servlet.Filter;

@Configuration
public class FilterConfig {

    @Bean
    public FilterRegistrationBean sentinelFilterRegistration() {
        FilterRegistrationBean<Filter> registration = new FilterRegistrationBean<>();
        registration.setFilter(new CommonFilter());
        registration.addUrlPatterns("/*");
        registration.setName("sentinelFilter");
        registration.setOrder(1);

        return registration;
    }
}

通过源码发现,其实它就是在执行之前调用了 entry 方法

在这里插入图片描述


2-1-3、AOP

1、pom文件引入

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

2、开启代理

@Configuration
public class SentinelAspectConfiguration {
    @Bean
    public SentinelResourceAspect sentinelResourceAspect() {
        return new SentinelResourceAspect();
    }
}

3、定义资源

加上 @SentinelResource

@GetMapping("/one")
@SentinelResource("one")
public String fun() {
    return "one";
}

通过源码发现代理的方式其实也是一样的

在这里插入图片描述


2-2、starter 整合

1、pom文件引入

<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
    <version>2021.0.1.0</version>
</dependency>

和SpringBoot对应的版本


2、yaml 文件

spring:
  application:
    name: version_11
  cloud:
    sentinel:
      transport:
        dashboard: 127.0.0.1:8080
      eager: true

3、测试代码

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class Controller {

    @GetMapping("/two")
    public String fun2() {

        return "ok";
    }
}

可以看到使用Starter的方式极其简单,它会把所有的请求都映射成资源。限流结果:

在这里插入图片描述


按照以往的经验,使用stater增强功能的时候,只需要大致看看stater中的 spring.factory 注入了什么,然后依次去看看每个注入带来什么功能

在这里插入图片描述


在SentinelWebAutoConfiguration中注入了一个SentinelWebInterceptor,它里面的 preHandle 方法如下:
在这里插入图片描述


3、总结


Sentinel提出了资源的概念,不管是如何使用本质都是在访问某个“资源”之前,先进行 SphU.entry 。所以这个资源并不一定是接口,可以是我们想要限制的任何代码。

可能有人好奇为啥dashboard 可以实时的添加/删除规则,如果熟悉代理的朋友应该知道,代理是可以动态的添加和删除的。

基于上面实践发现使用Sentinel的限流可以有四种方式

  1. 原生方式
  2. Filter
  3. Interceptor
  4. AOP

二、常见的策略


1、限流

1-1、基于QPS 限流

在这里插入图片描述


多次点击接口,会出现正常和500错误,500就说明被限制了

在这里插入图片描述


1-2、基于线程数限流

在这里插入图片描述

因为测试的demo响应时间在2ms,所以不好测试,在代码里面加上让线程睡眠 1s,就会看到限流异常

在这里插入图片描述


2、降级


当服务出现异常的时候(大部分是并发异常,业务异常基本是必现的),系统可能接受不了那么大的请求,这时候为了避免整个服务被击垮,需要有一个限制瓶颈,当触发这个瓶颈的时候,快速失败。


2-1、慢调用比例

在这里插入图片描述


2-2、异常数(限流异常不算)

在这里插入图片描述


2-3、异常比例(限流异常不算)

在这里插入图片描述


3、黑白名单


Sentinel 提供了一个方法来判断当前请求的服务方,可以基于这个方法去进行黑白名单的限制。

注:建议使用stater的方式这样就不需要单独引入很多包


加入判断请求来源的代码

@Component
public class MyRequestOriginParser implements RequestOriginParser {

        /**
         * 通过request获取来源标识,交给授权规则进行匹配
         * @param request
         * @return
         */
        @Override
        public String parseOrigin(HttpServletRequest request) {

            if (request.getHeader("x-forwarded-for") == null) {
                return request.getRemoteAddr();
            }

            return request.getHeader("x-forwarded-for");
        }
}

在这里插入图片描述

上面的配置就可以限制 127.0.0.1 的请求了。


4、其它


Sentinel的使用还有很多,包括但不限于下面的场景

  1. 可以在网关层面限制请求(可以配置nginx使用) nginx 使用
  2. 可以基于热点参数进行限制,这样就比接口层面更细了
  3. sentinel 官方文档

三、全局异常拦截


为何只是简单配置一个类就可以做到全局拦截?我们要知其然且知其所以然。


1、对拦截器方式的全局异常处理


使用 stater的方式,会同时开启 Interceptor、和AOP,上面已经知道AOP是基于自定义注解实现的,所以没有使用 @SentinelResource 的时候是不会有AOP的,就只有Interceptor。

熟悉SpringMVC流程的朋友应该知道,Filter > Interceptor > AOP,如果使用了@SentinelResource那就相当于两次限流了,相当于两道门。


通过Interceptor的前置拦截方法可以看到它把异常吞掉了,转而用 handleBlockException 去处理了
在这里插入图片描述


handleBlockException它里面是调用了一个 BlockExceptionHandler,实现它然后重写里面的 handle 方法,就可以做到全局自定义异常处理

@Component
public class MyBlockExceptionHandler implements BlockExceptionHandler {
    
    public MyBlockExceptionHandler() {
    }
    
    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response, BlockException e) throws Exception {
        response.setStatus(429);
        PrintWriter out = response.getWriter();
        out.print("My Limiting");
        out.flush();
        out.close();
    }
}

1-2、验证拦截器和AOP的双重拦截


为了更好的帮助大家理解拦截器和AOP的双重拦截,在使用 stater的方式中,我在Controller上面加一个@SentinelResource注解,去Sentinel控制台看看资源情况

  1. /one 是拦截器定义的
  2. org.example.Controller:fun() 就是AOP定义的

在这里插入图片描述


对 org.example.Controller:fun() 限流错误提示为

在这里插入图片描述


对 /one 限流错误提示为

在这里插入图片描述


且当对两个资源同时限流,限流规则一样的时候,org.example.Controller:fun() 的限流不会触发,因为拦截器是在AOP的前面呀

为什么AOP拦截给资源取的名字是这个呢?通过源码可以看到,使用AOP的时候
会先获取注解上的 value做资源名,如果没有就会用方法的权限定名。

# com.alibaba.csp.sentinel.annotation.aspectj.SentinelResourceAspect#invokeResourceWithSentinel

String resourceName = this.getResourceName(annotation.value(), originMethod);
protected String getResourceName(String resourceName, Method method) {
    return StringUtil.isNotBlank(resourceName) ? resourceName : MethodUtil.resolveMethodName(method);
}

3、对AOP方式的全局异常拦截


使用@SentinelResource 的时候可以配置blockHandler和fallback 限流处理和失败处理,但如果我们没有配置的话,最后就会将异常抛出来。(这个流程可以直接一步步源代码看到,下面只给出入口)

在这里插入图片描述


既然是抛异常,又在Spring里面,那就简单了,搞一个全局异常处理器就好了

@ControllerAdvice
public class MyExceptionHandler {

    @ExceptionHandler(value =BlockException.class)
    @ResponseBody
    public String exceptionHandler(BlockException e){

        return "AOP Limiting";
    }
}

注:如果想对不同的资源进行不同的异常处理,那可以配置@SentinelResource 上面对应的blockHandler和fallback就好了,这个很简单。


拦截器是直接基于访问路径当成资源名的,比如上述demo中就是 /one,如果你很俏皮的设置了这样一个注解 @SentinelResource(“/one”) ,这样在控制台就只能看到一个资源了,但如果你对这个资源进行限流,相当于两道门都给限制了。


前面我们讲到有一个黑白名单的策略,在Filter和Interceptor的源码里都可以看到这一处理,但是在AOP中没有,所以要想使用这个功能的话,进行AOP资源限流是不可以的。


Filter

在这里插入图片描述


Interceptor

在这里插入图片描述


AOP

在这里插入图片描述


四、规则持久化


Sentinel 的持久化还是有些复杂的,单独写一篇文章来讲解

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

C++ 蛇形矩阵的制作

#include <stdio.h>int arr[101][101]; int n; int i,j; int m; int tmp; void Print(){for(i1;i<n;i){for(j1;j<n-i1;j)printf("%d ",arr[i][j]);puts("");} }void fun(){//i j 初值为1i1,j1;//保底用 tmp 1;//计数从1开始m 1;while(1)…

异常—JAVA

文章目录 异常的概念异常的体系结构异常的分类运行时异常 异常的处理防御式编程异常的抛出异常的捕获异常声明throwstry—catch捕获并处理finally 异常的处理流程自定义异常类 异常的概念 首先在学习之前我们要先知道什么是异常&#xff0c;异常简单来说就是不对的地方我们说一…

MySQL DQL 基本查询

一.概念 数据查询不应只是简单返回数据库中存储的数据&#xff0c;还应该根据需要对数据进行筛选以及确定数据以什么样的格式显示。 二.语法格式 select 列名 from 表 where 条件 1.查询所有的商品 select * from product; 2.查询商品名和商品价格 select pname,price from…

Python实现时间序列分析简单指数平滑模型(SimpleExpSmoothing算法)项目实战

说明&#xff1a;这是一个机器学习实战项目&#xff08;附带数据代码文档视频讲解&#xff09;&#xff0c;如需数据代码文档视频讲解可以直接到文章最后获取。 1.项目背景 时间序列分析中的简单指数平滑&#xff08;Simple Exponential Smoothing, SES&#xff09;模型是一种…

哈希表——位图

哈希表——位图 基本概念一道面试题位图实现设置存在或不存在检查存在 解决一开始的问题 之前我们已经了解了哈希表的底层实现&#xff0c;今天我们来了解一下哈希表思想的衍生产物——位图。 基本概念 在了解位图之前&#xff0c;我们先来了解一些简单的概念。 我们都知道&a…

控制程序执行流程

资源 资源下载 【免费】突破密码认证程序&#xff08;修改函数返回地址&#xff09;资源-CSDN文库 资源内容 源码 在上一篇文章里 修改函数返回地址-CSDN博客 流程 对程序进行编译 思路 了解栈的情况&#xff08;函数地址、缓冲区偏移量&#xff09;程序中密码认证的地…

力扣 第 385 场周赛 解题报告 | 珂学家 | 字典树专场

前言 整体评价 这是一场字典树专场&#xff0c;除了t3这个小模拟之外&#xff0c;1&#xff0c;2&#xff0c;4皆可用字典树搞定。 T4感觉做法挺多的&#xff0c;其实&#xff0c;但是字典树应该效率最高的。 T1. 统计前后缀下标对 I 思路: 模拟 O ( n 2 ) O(n^2) O(n2)全遍…

D3842——三极管驱动,专为脱线和Dc-Dc开关电源应用设计的,起动电流小

D3842/43/44是专为脱线和Dc-Dc开关电源应用设计的恒频电流型Pwd控制器内部包含温度补偿精密基准、供精密占空比调节用的可调振荡器、高增益混放大器、电流传感比较器和适合作功率MOST驱动用的大电流推挽输出颇以及单周期徊滞式限流欠压锁定、死区可调、单脉冲计数拴锁等保护电路…

【RL】Monte Carlo Learning(蒙特卡洛学习)

Lecture 5: Monte Carlo Learning The simplest MC-based RL algorithm: MC Basic 理解MC basic算法的关键是理解如何将policy iteration算法迁移到model-free的条件下。 Policy iteration算法在每次迭代过程中有两步&#xff1a; { Policy evaluation: v π k r π k γ…

山西电力市场日前价格预测【2024-02-16】

日前价格预测 预测说明&#xff1a; 如上图所示&#xff0c;预测明日&#xff08;2024-02-16&#xff09;山西电力市场全天平均日前电价为55.97元/MWh。其中&#xff0c;最高日前电价为314.75元/MWh&#xff0c;预计出现在18:45。最低日前电价为0.00元/MWh&#xff0c;预计出现…

Conda管理Python不同版本教程

Conda管理Python不同版本教程 目录 0.前提 1.conda常用命令 2.conda管理python库 不太推荐 pyenv管理Python不同版本教程&#xff08;本人另一篇博客&#xff0c;姊妹篇&#xff09; 0.前提 ①anaconda、miniconda&#xff08;2个的下载仓库&#xff09;在win上推荐前者&a…

为什么将二维码分解成文字? 二维码在线转文字的方法

将二维码分解成文字的主要目的是为了方便人们获取二维码中的信息便于使用。二维码是一种由黑白方块组成的图案&#xff0c;可以存储大量的数据&#xff0c;如网址、联系方式、产品信息等。然而&#xff0c;对于一些特定的场景或个人需求&#xff0c;无法直接扫描二维码。因此&a…

ubuntu22.04@laptop OpenCV Get Started: 013_contour_detection

ubuntu22.04laptop OpenCV Get Started: 013_contour_detection 1. 源由2. 应用Demo2.1 C应用Demo2.2 Python应用Demo 3. contour_approx应用3.1 读取图像并将其转换为灰度格式3.2 应用二进制阈值过滤算法3.3 查找对象轮廓3.4 绘制对象轮廓3.5 效果3.6 CHAIN_APPROX_SIMPLE v.s…

vue的生命周期图解

vue的生命周期图解 添加链接描述 vue的生命周期函数及过程的简述&#xff1a; vue的生命周期函数&#xff0c;其实就是vm的生命周期&#xff1b; 创建&#xff1a;beforeCreate、created 挂载&#xff1a;beforeMount、mounted 更新&#xff1a;beforeUpdate、updated [ˌʌpˈ…

数字化转型导师坚鹏:数字化思维创新与BLM政府数字化转型战略

数字化思维创新与BLM政府数字化转型战略 ——以BLM模型为核心&#xff0c;践行知行合一思想&#xff0c;实现知行果合一 课程背景&#xff1a; 很多政府存在以下问题&#xff1a; 不知道如何系统地开展数字化转型工作&#xff1f; 不清楚如何高效地执行数字化转型战略&a…

解读OpenAI视频生成模型Sora背后的原理:Diffusion Transformer

Diffusion Models视频生成-博客汇总 前言&#xff1a;OpenAI最近推出的视频生成模型Sora在效果上实现了真正的遥遥领先&#xff0c;很多博主都介绍过Sora&#xff0c;但是深入解读背后原理的博客却非常少。Sora的原理最主要的是核心模型主干《Scalable Diffusion Models with T…

【大厂AI课学习笔记】【2.1 人工智能项目开发规划与目标】(3)数据准备初步

今天来学习数据准备。 一个AI项目要包括构建数据集、数据清理和数据融合、数据采集、特征工程、算法改进和其他步骤。 数据采集和数据清洗&#xff0c;也就是数据准备&#xff0c;要占到人工智能项目一半以上的工作量。 训练的数据量越大&#xff0c;模型越准确。 建立数据标…

php 函数(方法)、日期函数

php 函数、日期函数 1. php函数2. 日期函数 1. php函数 <?php// 创建一个函数 function hello($who) {echo $who.Hello World!; }hello("老张");给参数一个默认值&#xff0c;当然自己有变量走自己的 2. 日期函数 <?php/** date(Y-m-d H:i:s)返回的时间是…

数据库MySQL中出现乱码和表格不对齐怎么解决

MySQL中出现乱码问题及解决办法&#xff1a; 情况类似&#xff1a; 首先进入到数据库中&#xff0c;命令&#xff1a;mysql -h localhost -uroot -p或者mysql -uroot -p;进入数据库后选择一个你的数据库查看表中的中文是否乱码 以上是数据库中表格出现乱码情况&#xff0c;原…

文件上传漏洞--Upload-labs--Pass06--空格绕过

一、什么是空格绕过 在Windows系统中&#xff0c;Windows特性会自动删除文件后缀名后的空格&#xff0c;这使我们看 .php 和 .php 二者没有任何区别&#xff0c;实际上二者是有区别的。若网页源码没有使用 trim()函数 来进行去除空格的操作&#xff0c;就会使网页存在 空格绕…
最新文章