使用Sentinel滑动窗口实现限流和降级

 更新时间:2023年09月04日 08:25:06   作者:小威要向诸佬学习呀  
Sentinel 是一个开源的高可用性、高扩展性的实时流量控制框架,它可以用于保护服务稳定性,防止系统因为流量过大而崩溃,这篇文章我们所介绍的是滑动窗口,它是 Sentinel 实现限流和降级的重要组件之一,感兴趣的同学跟着小编来看看吧

Sentinel滑动窗口前言

Sentinel 是一个开源的高可用性、高扩展性的实时流量控制框架,它可以用于保护服务稳定性,防止系统因为流量过大而崩溃。今天我们所介绍的,是滑动窗口,它是 Sentinel 实现限流和降级的重要组件之一。

Sentinel滑动窗口原理

滑动窗口通常由一个固定大小的时间窗口和一个可滑动的数据结构组成,例如队列或滑动块。在 Sentinel 中,滑动窗口被分为计数器类型和预算类型

计数器滑动窗口:计数器滑动窗口维护一个周期内请求的总数,当周期结束后,滑动窗口会被清空,开始下一个周期的计数。在 Sentinel 中,计数器滑动窗口通过 AtomicLong 数组实现,数组的长度代表时间窗口的大小,每个元素代表该时间片保存的请求次数。

预算滑动窗口:预算滑动窗口维护周期内预算资源的使用情况,以便根据实际资源需要进行限流或降级。预算类型的滑动窗口可以设置阈值,并支持动态调整。在 Sentinel 中,预算滑动窗口通常用于 CPU 使用率、线程池等容量资源的控制

除此之外,Sentinel 还提供了基于单机、集群和分布式三种模式的滑动窗口实现。其中,单机模式下将使用本地内存来维护滑动窗口数据结构;集群模式下,各节点会通过多播或 Redis 等方式共享相同的计数器数据;分布式模式下,则允许多个服务节点公用同一组滑动窗口数据。

在使用 Sentinel 进行限流和降级时,用户可以通过配置规则来指定需要监控的目标资源,并设置相应的阈值和处理策略。例如,在限流场景下,用户可以设置最大 QPS,并指定超过该阈值的请求将会被丢弃或返回特定的错误码。在降级场景下,用户可以设置响应时间、异常比例等阈值,并指定相应的降级策略,例如返回默认值或者直接抛出异常。

如何在项目中使用滑动窗口

以实际的项目为例子,我们有一个服务用于提供用户信息查询接口,每秒钟最多只能处理 10 次查询请求,并且如果连续 5 秒内的请求次数超过 50 次,则触发限流或降级操作

在 Sentinel 中,我们首先需要定义一个 FlowRule 数组用于配置针对该服务的限流规则,在这块项目例子中,它们是每秒钟限流到 10 个请求和 5 秒内超过 50 次请求两种限制:

FlowRule rule1 = new FlowRule();
rule1.setResource("queryUser");
rule1.setCount(10);
rule1.setGrade(RuleConstant.FLOW_GRADE_QPS);
FlowRule rule2 = new FlowRule();
rule2.setResource("queryUser");
rule2.setCount(50);
rule2.setGrade(RuleConstant.FLOW_GRADE_QPS);
rule2.setStrategy(RuleConstant.STRATEGY_CHAIN);
rule2.setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_WARM_UP);

我们先对以上代码进行解释,“queryUser” 代表资源名称,这个可以自己定义,然后设置了resource、count、grade以及对于第二个规则还增加了三个属性stratety, controlBehavior和controlBehavior。其中 count 表示限流阈值,即每秒钟最多可以处理多少个请求;grade 表示限流模式,QPS(每秒钟最多允许通过的请求数量);strategy 表示限流策略;controlBehavior 表示流量控制的行为。

接下来,我们需要通过执行如下代码初始化 Sentinel:

List<FlowRule> rules = new ArrayList<>();
rules.add(rule1);
rules.add(rule2);
FlowRuleManager.loadRules(rules);

我们这里定义了一个 FlowRule 数组,将前面定义好的两个规则加入到列表中,然后通过 FlowRuleManager.loadRules() 方法加载这些规则。

现在,我们可以在查询用户信息的方法上增加 @SentinelResource 注解,并在该注解中设置 blockHandler 和 fallback 属性来处理限流和降级异常:

@SentinelResource(value = "queryUser", blockHandler = "queryUserBlockHandler",
    fallback = "queryUserFallback")
public UserInfo queryUser(String userId) {
    // 查找用户信息的实现
}
// 限流/降级处理函数
public UserInfo queryUserBlockHandler(String userId, BlockException ex) {
    // 返回具体的错误信息
}
// 降级处理
public UserInfo queryUserFallback(String userId, Throwable ex) {
    // 返回降级后的响应
}

以上代码中我们定义了一个名为“queryUser”的资源,它被 @SentinelResource 注解所修饰,blockHandler 属性表示当该服务触发限流或降级时调用的函数,fallback 属性表示服务出现异常时的回退函数。

最后,我们可以通过对定时任务进行调度,模拟10秒内对同一个 API 请求用户数据的场景,例如代码如下:

public class QueryUserTask implements Runnable {
    private static final Random random = new Random();
    @Override
    public void run() {
        // 模拟 10 秒内对同一个 API 请求用户数据
        for (int i = 0; i < 20; i++) {
            String userId = "user-" + (i % 5);
            queryUser(userId);
            try {
                Thread.sleep(random.nextInt(500));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

我们可以在 QueryUserTask 内部实现每隔一秒获取一次用户信息,检测系统是否触发限流或降级保护。如果触发了规则中配置的限流规则,那么 Sentinel 将执行相应的措施进行处理。

好了,本篇文章就先分享到这里了,后续将会继续介绍sentinel详细的其他方面的知识。

到此这篇关于使用Sentinel滑动窗口实现限流和降级的文章就介绍到这了,更多相关Sentinel限流和降级内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Spring Boot3 集成 Spring AI 实现 Advisor 增强机制的完整流程

    Spring Boot3 集成 Spring AI 实现 A

    Spring AI的Advisor API是一种声明式的拦截机制,借鉴了 Spring AOP 的设计理念,允许开发者在AI交互的生命周期关键节点插入自定义逻辑,本文全面介绍了Spring Boot集成Spring AI 1.0.0 实现 Advisor 增强机制的完整流程,感兴趣的朋友跟随小编一起看看吧
    2026-03-03
  • 定时任务@Scheduled用法及其参数使用

    定时任务@Scheduled用法及其参数使用

    这篇文章主要介绍了定时任务@Scheduled用法及其参数使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-08-08
  • 详解Java串行化接口的用法和原理

    详解Java串行化接口的用法和原理

    在Java开发中,我们经常需要将对象进行序列化和反序列化,以便在网络传输或存储到持久化介质中,Java提供了一种机制,即通过实现Serializable接口来实现对象的串行化,本文将详细介绍Java串行化接口的用法和原理,以及一些相关的注意事项,需要的朋友可以参考下
    2023-11-11
  • SpringBoot中事务失效的原因详解

    SpringBoot中事务失效的原因详解

    这篇文章主要介绍了SpringBoot中事务失效的原因详解,spring中的事务是依赖AOP的,AOP是通过动态代理实现的,只有通过代理类访问的方法才能被拦截,需要的朋友可以参考下
    2023-10-10
  • 用java实现斗地主发牌过程

    用java实现斗地主发牌过程

    这篇文章主要为大家详细介绍了用java实现斗地主发牌过程,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-11-11
  • java中构造器内部调用构造器实例详解

    java中构造器内部调用构造器实例详解

    在本篇文章里小编给大家分享的是关于java中构造器内部调用构造器实例内容,需要的朋友们可以学习下。
    2020-05-05
  • Spring component-scan XML配置与@ComponentScan注解配置

    Spring component-scan XML配置与@ComponentScan注解配置

    这篇文章主要介绍了Spring component-scan XML配置与@ComponentScan注解配置,文章围绕主题展开详细的内容介绍,具有一定的参考价值,需要的小伙伴可以参考一下
    2022-09-09
  • 如何使用GSON解析JSON数据

    如何使用GSON解析JSON数据

    这篇文章主要介绍了如何使用GSON解析JSON数据,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-08-08
  • PostMan传@RequestParam修饰的数组方式

    PostMan传@RequestParam修饰的数组方式

    这篇文章主要介绍了PostMan传@RequestParam修饰的数组方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-08-08
  • 从千千静听歌词服务器获取lrc歌词示例分享

    从千千静听歌词服务器获取lrc歌词示例分享

    这篇文章主要介绍了使用PHP从千千静听歌词服务器获取lrc歌词的方法,大家参考使用吧
    2014-01-01

最新评论