阿里熔断限流框架Sentinel实现流程和动态规则数据源

news2024/11/14 20:49:06

文章目录

  • 1.简单介绍
  • 2.使用示例
  • 3.主要实现原理和组成部分
  • 4.动态规则数据源

本篇文章主要介绍熔断限流框架Sentinel的使用示例、组成原理和动态规则数据源的实现原理。

1.简单介绍

阿里的熔断限流框架Sentinel基于滑动时间窗口实现熔断限流管控的,支持多样的管控场景:

  1. 流量管控;
  2. 熔断降级;
  3. 系统负载管控;
  4. 热点参数限流等。

其中使用最多的就是流量管控和熔断降级两个功能。Sentinel是基于 槽实现规则 来完成具体的管控场景,规则被对应的 Manager管理器静态成员属性 的形式维护在类中,槽实现需要获取规则时则直接根据资源名称去 规则管理器 中获取。下面是官方功能宣传图的简化版:

官方功能特性图

除了绿色部分的功能特性外,Sentinel也支持动态规则配置,目前支持Zookeeper、Nacos和Apollo三个动态数配置源。其中还有个控制台,控制台可以完成数据监控和动态规则配置,但是不可持久化,且不推荐在生产环境使用,介绍意义不大,因此控制台可以忽略。

2.使用示例

下面是实现熔断降级的简单示例:

/** 模拟调用类 */
public class TestService {
    private final Random random = new Random();
    public void test() {
        if (random.nextInt(10) <= 5) {
            throw new RuntimeException("随机数小于等于5");
        }
    }
}
/** 模拟测试类 */
@RunWith(MockitoJUnitRunner.class)
public class TestServiceMockTest {
    @Spy
    private TestService testService;
    @Test
    public void testDegrade() throws InterruptedException {
        DegradeRule degradeRule = new DegradeRule();
        // 设置资源名称
        degradeRule.setResource("test");
        // 设置故障数量
        degradeRule.setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_COUNT);
        // 数量大于5
        degradeRule.setCount(5);
        // 熔断降级时间
        degradeRule.setTimeWindow(1);
        // 统计时间窗口
        degradeRule.setStatIntervalMs(400);
        // 以上规则配置生效场景:
        // 当在400ms内,程序抛故障数量>5,则熔断降级1s,之后半开闭,直到程序正常
        DegradeRuleManager.setRulesForResource("test", Collections.singleton(degradeRule));
        for (int i = 0;i < 30;i ++) {
            Entry entry = null;
            try {
                entry = SphU.entry("test");
                testService.test();
            } catch (Exception e) {
                if (e instanceof BlockException) {
                    System.out.println(i + " blocked,execute degrade method");
                } else {
                    // 抛出异常需要正常追踪
                    Tracer.trace(e);
                    System.out.println(e.getMessage());
                }
            } finally {
                if (entry != null) {
                    entry.exit();
                }
            }
            Thread.sleep(10);
        }
    }
}

流量管控就不做过多介绍了,实现方式和熔断降级类似,只是配置的规则不同。可以从上述例子看到主要内容就三部分:

  1. 制定规则内容并加载到对应的规则管理器中,这部分需要开发者针对不同的资源制定不同的规则;
  2. 使用Sentine开放出来的静态方法完成对被管控方法的监听,熔断降级使用SphU-Entr-Tracer进行监听,Tracer需要追踪异常抛出情况;
  3. 如果Sentinel触发了熔断限流,则会抛出BlockException,熔断降级是DegradeException,开发者可自行编写熔断降级后的逻辑。

从上面这个例子可以看出Sentinel最基本的使用方式是非常简单,很容易接入。

3.主要实现原理和组成部分

仅从最常使用的熔断降级和流量管控两个方面简单的分析一下执行流程和其中的重要部分:

简单执行流程和组成部分

  1. SphU:Sentinel对外提供的静态方法,触发熔断限流后直接抛出异常。与其对应的还有SphO,触发熔断限流后将返回true或false,使用方法在两个类的注解中都有简单案例;
  2. Sph:静态方法实际调用的功能对象,默认使用CtSph实现类,Env类有该实现类的静态常量,平时使用的也都是Env类的静态常量;
  3. Context:Sentinel统计调用方法时的上下文信息,包括当前调用点、统计信息及入口信息;
  4. Entry:入口类,每次调用静态方法都会返回Entry类,保存了当前资源调用的信息;
  5. ProcessorSlotChain:Sentinel使用不同的槽来实现不同的处理逻辑,最外层便使用了槽列表来管理不同的槽实现,并对其排序控制调用顺序;
  6. FlowSlot:流量管控的槽实现,会直接从FlowRuleManager中获取资源名称对应的流量规则FlowRule,使用FlowRule进行规则判断;
  7. DegradeSlot:熔断降级的槽实现,会从DegradeRuleManager中获取资源对应的断路器CircuitBreaker列表,CircuitBreaker由DegradeRule转换生成的。

FlowRuleManager和DegradeRuleManager维护对应的流量规则FlowRule和熔断降级规则DegradeRule使用的是内部静态成员对象,代码如下:

/** 熔断降级规则管理器 */
public final class DegradeRuleManager {
    /** 由熔断限流规则对象生成的断路器对象,key=资源名称,value=对应的断路器列表 */
    private static volatile Map<String, List<CircuitBreaker>> circuitBreakers = new HashMap<>();
    /** 管理器保存的熔断降级规则对象,key=资源名称,value=熔断降级规则列表 */
    private static volatile Map<String, Set<DegradeRule>> ruleMap = new HashMap<>();
}
/** 流量管控规则管理器 */
public class FlowRuleManager {
    /** 管理器保存的流量管控规则对象,key=资源名称,value=流量管控规则列表 */
    private static final Map<String, List<FlowRule>> flowRules = new ConcurrentHashMap<String, List<FlowRule>>();
}

初始化规则和需要更新规则时,则是通过Manager暴露出去的方法新增修改这些静态成员对象,以达到新增规则和更新规则的目的。DegradeRuleManager中使用volatile修饰静态成员对象,是因为由DegradeRule转换成CircuitBreaker需要经过一系列的计算,同时修改两个对象的内容。而FlowRuleManager只需要更新一个静态成员对象,因此无需使用volatile修饰。

4.动态规则数据源

由上面的内容我们可以得知,Sentinel的各种规则是被保存在对应Manger管理器的静态成员属性中的,在Sentinel运行判断时会直接从静态成员属性中获取对应的规则对象。也就是说如果要实现动态规则更改,直接修改对应Manger管理器的静态成员属性即可,动态规则数据源实现原理如下:

动态数据源示意图

动态数据源的实现分为两个部分:

  1. 启动时初始化规则;
  2. 数据源数据修改后的监听更新。

数据转换器: 从动态数据源拉取数据后,需要把数据转换为Sentinel对应的规则对象,如流量管控的规则对象FlowRule;熔断降级的规则对象DegradeRule。动态数据源的格式可自定义,只需要实现对应的数据转换器即可。

以下是不借助Spring容器,使用Sentinel-Zookeeper包的ReadableDataSource实现类,以Zookeeper为数据源的代码示例:

@RunWith(MockitoJUnitRunner.class)
public class ZookeeperDataSourceMockTest {
    @Test
    public void test() {
        // 使用的Zookeeper当远程数据源,确认地址和路径
        String serverAddr = "localhost:2181";
        String path = "xx/sentinelConfig.properties";
        // 获得节点的数据后需要对数据进行解析,具体格式没做强制要求
        // 如果是纯Json格式官方有实现类JsonConverter
        Converter<String, List<DegradeRule>> converter = new LocalConverter();
        // 实例化Zookeeper的数据源,里面会自动连接拉取数据
        ReadableDataSource<String, List<DegradeRule>> zookeeperDataSource =
                new ZookeeperDataSource<>(serverAddr, path, converter);
        // 这一步是为了将数据源的数据注册到规则管理器中
        DegradeRuleManager.register2Property(zookeeperDataSource.getProperty());
        // 测试打印代码
        Thread t = new Thread(() -> {
            while (true) {
                try {
                    System.out.println("rules:" + JSONArray.toJSONString(DegradeRuleManager.getRules()));
                    Thread.sleep(3000);
                    System.out.println("-----------------------------------");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        t.start();
        try {
            Thread.sleep(1000 * 60 * 10);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    public static class LocalConverter implements Converter<String, List<DegradeRule>> {
        @Override
        public List<DegradeRule> convert(String source) {
            // 将返回的string对象转成需要的规则列表,这是省略,可自定义需要的规则属性
            return null;
        }
    }
}

上面是一个以Zookeeper为数据源实现的简单例子,功能及流程如下:

  1. 确定Zookeeper服务器和获取数据节点的路径;
  2. 实现节点数据转换成对应规则对象的转换器,官方支持JSON和XML格式;
  3. 实例化Zookeeper数据源;
  4. 将数据源属性注册到对应的规则管理器中。

完成上面的四步,就可以正常的从远程数据源拉取并监听节点数据,此时就可以在远程动态的修改管理动态规则数据了,十分便捷简。生产推荐使用远程数据源的方式,不推荐使用控制台方式。

上面的代码依赖于下面的maven:

<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-datasource-zookeeper</artifactId>
</dependency>
<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-datasource-extension</artifactId>
</dependency>
<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-core</artifactId>
</dependency>

本篇文章先为深入Sentinel打个基础,先了解Sentinel的大致轮廓及重要组成部分的原理,后续再分析更深入的部分。

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

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

相关文章

PHP 基础入门

目录 1、标记 2、注释 3、输出语句 4、关键字 5、常量的定义与使用 6、预定义常量 7、变量的赋值&#xff08;传参赋值与引用赋值&#xff09; 8、可变变量 9、双引号和单引号的区别 10、heredoc结构和nowdoc结构 11、其他符号 1、标记 <?php 和 ?> 是PHP标…

【MySQL】EXPLAIN 语句 各字段 详解

EXPLAIN 语句 概貌 在连接查询的执行计划中&#xff1a; 每个表都会对应一条记录&#xff0c;这些记录的 id 列的值是相同的&#xff1b; 在包含子查询的执行计划中 &#xff1a;每个 select关键字都会对应一个唯一的 id 值。 驱动表&#xff1a;出现在前面的表&#xff1b; …

Apache ECharts 一个基于 JavaScript 的开源可视化图表库

一&#xff1a; ECharts 特性 ECharts&#xff0c;一个使用 JavaScript 实现的开源可视化库&#xff0c;可以流畅的运行在 PC 和移动设备上&#xff0c;兼容当前绝大部分浏览器&#xff08;IE9/10/11&#xff0c;Chrome&#xff0c;Firefox&#xff0c;Safari等&#xff09;&a…

谷歌正在向所有账户推出密码终止技术

谷歌宣布让其个人帐户持有人使用称为“密码”的密码替代登录的一项重大努力。 该功能面向公司的数十亿帐户推出&#xff0c;用户将能够主动寻找并启用它。谷歌表示&#xff0c;它计划在未来几个月推广密码&#xff0c;并开始推动账户持有人将他们传统的用户名和密码登录转换为…

vscode 远程开发:免密登入设置

文章目录 1. vscode 安装2. vscode 插件安装&#xff08;1&#xff09; 中文界面设置&#xff08;2&#xff09; ssh远程插件安装 3. 免密登入 1. vscode 安装 vscode 官网下载地址&#xff1a;https://code.visualstudio.com/ 安装很简单&#xff1a; 可以默认方式&#xff0…

新建一台VMware虚拟机

文章目录 前言一、问题二、步骤1.确认已安装VMware Workstation&#xff0c;已下载Windows 10 光盘镜像2.新建虚拟机pc13.自定义虚拟机pc1的硬件 总结 前言 新建一台VMware虚拟机。 一、问题 本例要求在VMware Workstation软件中创建一台新虚拟机&#xff0c;相关说明如下。 …

Go语言字符串基础

目录 字符串基础 合并和分割字符串 分割 合并 判断是否包含 strings.Contains() 查找子串出现的位置 strings.Index() strings.LastIndex() 字符串基础 1.字符串是由一串Unicode字符组成的序列&#xff0c;每个Unicode字符都占用一个或多个字节的存储空间。 2.字符串…

【腾讯云 Finops Crane 集训营】老板喜欢降本增效?学会 Crane,让腾讯每月省千万的奇迹在你手中上演

❤️作者主页&#xff1a;小虚竹 ❤️作者简介&#xff1a;大家好,我是小虚竹。2022年度博客之星评选TOP 10&#x1f3c6;&#xff0c;Java领域优质创作者&#x1f3c6;&#xff0c;CSDN博客专家&#x1f3c6;&#xff0c;华为云享专家&#x1f3c6;&#xff0c;掘金年度人气作…

SpringBoot 简单多模块构建

前言 SpringBoot系列到现在虽然代码不多&#xff0c;但是感觉结构很乱&#xff0c;随着项目的复杂性提高&#xff0c;代码会越来越臃肿&#xff0c;耦合性高。 所以SpringBoot多模块很有必要&#xff0c;简单来说就是由以前按包分模块变为jar包分模块。在多模块jar模式下可以将…

【勝讯云 Finops Crane 集训营】之集群优化实战

重要通知 由腾讯云联合 CSDN 推出的“腾讯云 Finops Crane 开发者集训营”活动&#xff0c;主要面向广大开发者&#xff0c;旨在通过线上直播、组织动手实验、有奖征文&#xff0c;开源项目贡献者招募这一系列技术实践活动中既能通过活动对 Finops Crane 开源项目有一个深入的]…

mathtype不激活能用吗 mathtype产品密钥如何取得

在文档中输入数学式子时一般会用到mathtype&#xff0c;虽然mathtype为广大用户提供了一定期限的试用期&#xff0c;但试用期后如果没有成为正式用户&#xff0c;那么部分功能可能就用不了了。有些小伙伴可能会对mathtype不激活能用吗&#xff0c;mathtype产品密钥如何取得这两…

PostGIS五分钟入门【空间数据库】

在本文中&#xff0c;我们将介绍 PostGIS 的一些基础知识及其功能&#xff0c;以及一些可用于简化解决方案或提高性能的提示和技巧。 推荐&#xff1a;用 NSDT设计器 快速搭建可编程3D场景。 简而言之 - PostGIS 是一个 Postgres 扩展&#xff0c;增加了对存储和操作空间数据类…

PyQt5桌面应用开发(11):摸鱼也要讲基本法之桌面精灵

本文目录 PyQt5桌面应用系列鼠标不要钱&#xff0c;手腕还不要钱吗&#xff1f;PyQt5源程序python文件资源定义界面定义文件 技术要素资源文件StyleSheetsQMainWindow设置窗体几何 结论 PyQt5桌面应用系列 PyQt5桌面应用开发&#xff08;1&#xff09;&#xff1a;需求分析 PyQ…

orbslam3 编译时 Thirdparty sophus 库多种错误 redefinition, not declared in this scope

问题 在装了 ROS 的机器人系统里编译 orbslam3 时, 发现 Thirdparty sophus 库密集报错, 导致 orbslam3 无法完成编译 排查 同样的代码在装了 ROS 的笔记本 ubuntu18.04 系统里可以成功通过编译, 但是在装了同版本 ROS 的机器人 ubuntu18.04 系统里无法编译 Sophus 库本身…

探秘力扣之谜:如何轻松解决最长公共前缀问题?

本篇博客我会讲解力扣中的“14. 最长公共前缀”这道题&#xff0c;这是题目链接。 先来审题&#xff1a; 以下是几个输出示例&#xff1a; 提示&#xff1a; 这道题的思路其实并不难&#xff0c;也是一些字符串的常规操作的结合。大家可以先思考一下&#xff0c;再来听我讲…

TCP和UDP数据报文详解(区别及三次握手四次挥手详解)

总结TCP和UDP详解在后文 相同点&#xff1a; 1.都是传输层协议 2.都是全双工通信 区别&#xff1a; TCPUDP面向连接无连接一对一一对一&#xff0c;一对多&#xff0c;多对多&#xff0c;多对一(单播&#xff0c;多播&#xff0c;广播)可靠不保证可靠交付面向字节流面向报…

java变量与方法

方法 构造方法 定义&#xff1a;构造方法是一个特殊的成员方法&#xff0c;名字必须与类相同&#xff0c;在创建对象时由编译器自动调用&#xff0c;并且在生命周期内只调用一次 演示&#xff1a; 特性&#xff1a; 1.构造方法名字必须与类名相同&#xff08;如果不同&#…

Ajax XML

文章目录 AJAX XML 实例AJAX XML 实例实例解析 loadXMLDoc() 函数AJAX 服务器页面 AJAX XML 实例 AJAX 可用来与 XML 文件进行交互式通信。 AJAX XML 实例 下面的例子将演示网页如何使用 AJAX 来读取来自 XML 文件的信息&#xff1a; 代码部分 <!DOCTYPE html> <h…

Oracle—数据恢复

文档结构 1、恢复原理1.1、recyclebin&#xff08;回收站&#xff09;相关操作 2、恢复场景2.1、定义删除2.2、记录删除2.2.1、undo恢复2.2.2、redo恢复2.2.3、dbms_logmnr 场景&#xff1a;在 Oracle数据库使用过程中&#xff0c;误删对象或误删记录的情况时有发生&#xff1b…

07- 算法解读 Faster_R-CNN (目标检测)

要点&#xff1a; Faster_R-CNN RPN Fast R-CNN GitHub地址&#xff1a;vision/torchvision/models/detection at main pytorch/vision GitHub 三 Faster_R-CNN Faster R-CNN 是作者 Ross Girshick 继 Fast R-CNN 后的又一力作。同样使用 VGG16 作为网络的 backbone &am…