Spring Boot4使用Sentinel进行限流的操作方法

 更新时间:2025年12月27日 14:35:48   作者:enjoy编程  
Sentinel是阿里巴巴开源的流量控制组件,用于保障微服务架构的稳定性,它提供了多种规则类型,本文还介绍了如何在Spring Boot 4中集成Sentinel,以及Sentinel在不同版本的Spring Boot和Spring Cloud中的兼容性情况,感兴趣的朋友跟随小编一起看看吧

Sentinel介绍

随着微服务的流行,服务和服务之间的稳定性变得越来越重要。Sentinel 是面向分布式、多语言异构化服务架构的流量治理组件,主要以流量为切入点,从流量路由、流量控制、流量整形、熔断降级、系统自适应过载保护、热点流量防护等多个维度来帮助开发者保障微服务的稳定性。

Sentinel 社区正在将流量治理相关标准抽出到 OpenSergo spec 中,Sentinel 作为流量治理标准实现

Sentinel规则类型

针对Sentinel的规则重新学习下,详细使用文档参见 官方文档

规则类型核心作用维度典型应用场景触发后果作用
流控规则 (Flow)限制流量 (QPS/线程数)秒杀限流、防止突发流量冲垮系统请求被拒绝/排队等待防刷、防过载
熔断规则 (Degrade)依赖稳定性 (响应时间/异常)调用第三方接口超时、数据库慢查询暂停请求,快速失败(熔断)防雪崩、防依赖故障
热点规则 (Param)参数粒度 (特定参数值)某个热门商品被疯狂刷,其他商品正常访问限制特定参数的访问频率防热点数据击穿
系统规则 (System)整体负载 (CPU/Load/RT)大促期间防止机器过载,保护系统基线拒绝部分请求,保护机器不挂防机器挂掉
授权规则 (Auth)来源控制 (黑白名单)防止某个恶意 IP 或非法应用调用接口允许或拒绝请求防非法调用

流控规则(Flow Control)

最常用的规则,主要用于限流,有如下2种模式

  • QPS 模式:每秒允许多少个请求通过。超过阈值则拦截。
  • 线程数模式:限制同时处理该资源的线程数量。

除了简单的直接拒绝,它还有两种高级策略:

  • Warm Up (预热):比如系统刚启动,像冷车一样,不能直接拉满油门。预热模式会在一定时间内逐渐将阈值从低升到高,防止瞬间流量把刚启动的服务打挂。
  • 排队等待 (Queueing):不直接拒绝请求,而是让请求按照设定的时间间隔匀速通过(像检票口一样),用于处理突发的脉冲流量。

熔断规则 (Circuit Breaker)

关注服务的质量。当它发现某个服务调用“不健康”时,会直接切断连接,防止连锁故障(雪崩)。
Sentinel 支持三种策略:

  • 慢调用比例:如果一个接口的平均响应时间(RT)太长(比如超过 1 秒),且比例达到阈值,就熔断。适用于对响应速度敏感的场景。
  • 异常比例:如果请求中出现的异常(如抛出 RuntimeException)比例过高,就熔断。
  • 异常数:统计时间内出现的异常总数超过阈值,直接熔断。

熔断是“宁可错杀一百,不可放过一个”的保护机制。触发后,所有请求直接走“降级逻辑”(fallback),不再调用下游真实服务,直到经过一段“冷却时间”后尝试恢复

热点规则 (Hotspot Param)

流控规则的高级版,它能把限流的粒度细化到方法参数级别。
通常情况下,流控是对整个接口(如 /getProduct)限流。但热点规则可以做到:当参数 id=1 的时候限流 100 QPS,而 id=2 的时候不限流

关注的是“不均匀”。在实际场景中,可能只有某个特定的“爆款”商品(热点 key)流量巨大,导致数据库压力大。如果对整个接口限流,会误伤其他正常的商品查询。热点规则就是为了解决这种“贫富不均”的问题

系统规则 (System Protection)

全局视角的规则,它不针对某个具体的接口,而是针对整个应用实例的系统指标。
它监控的指标包括:

  • Load(仅 Linux/Unix):系统平均负载。
  • CPU 使用率
  • 入口 QPS
  • 线程数
  • 平均 RT
    保底”机制。通常在单机的 QPS 或负载过高时触发,目的是让系统整体保持在一个稳定的水位,防止机器直接死机。它是一种兜底的保护,通常配置的阈值会比机器的极限处理能力稍微保守一点

授权规则 (Authority Rule)

黑白名单机制,用于控制“谁可以调用”。
它通过 SentinelContext 中的 origin(来源标识)来判断。通常用来识别调用方的服务名、IP 地址等。 关注的是“身份”,可以使用黑名单 或白名单限制

Spring boot 4如何集成Sentinel?

本次采用@SentinelResource + AOP 方式集成 Sentinel

添加依赖

 <dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-core</artifactId>
            <version>1.8.9</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-parameter-flow-control</artifactId>
            <version>1.8.9</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-annotation-aspectj</artifactId>
            <version>1.8.9</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-transport-simple-http</artifactId>
            <version>1.8.9</version>
        </dependency>

编写相关的测试代码

SentinelConfig类

@Configuration
public class SentinelConfig {
    @PostConstruct
    public void initFlowRules(){
        List<FlowRule> rules = new ArrayList<>();
        FlowRule rule = new FlowRule();
        rule.setResource("HelloWorld");
        rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
        // Set limit QPS to 20.
        rule.setCount(10);
        rules.add(rule);
        FlowRuleManager.loadRules(rules);
    }
    @PostConstruct
    public void initDegradeRules() {
        List<DegradeRule> rules = new ArrayList<>();
        DegradeRule rule = new DegradeRule();
        rule.setResource("HelloWorld");
        rule.setGrade(RuleConstant.DEGRADE_GRADE_RT); // RT threshold degrade strategy
        rule.setCount(200); // Max response time (ms)
        rule.setTimeWindow(10); // Recovery timeout period in seconds
        rules.add(rule);
        DegradeRuleManager.loadRules(rules);
    }
    @Bean
    public SentinelResourceAspect sentinelResourceAspect() {
        return new SentinelResourceAspect();
    }
}

HelloWorldService

@Service
public class HelloWorldService {
    @SentinelResource(value = "HelloWorld",
        entryType = EntryType.IN,
        exceptionsToIgnore = {IllegalStateException.class},
        blockHandler = "handleBlock",
        fallback = "handleFallback")
    public String sayHello(String name) {
        return "Hello, " + name;
    }
    public String handleBlock(String name, BlockException ex) {
        return "Request blocked by Sentinel: " + ex.getClass().getSimpleName();
    }
    public String handleFallback(String name, Throwable t) {
        return "Request failed and handled by fallback: " + t.getClass().getSimpleName();
    }
}

HelloWorldController

@RestController
@RequestMapping("/api")
@Tag(name = "登录接口")
public class HelloWorldController {
    @Autowired
    private HelloWorldService helloWorldService;
    @GetMapping("/hello")
    @Operation(summary = "hello")
    public String sayHello(@RequestParam(value = "name", defaultValue = "World") String name) {
        return helloWorldService.sayHello(name);
    }
}
@SpringBootTest
@Slf4j
public class SentinelTest {
    @Autowired
    HelloWorldService helloWorldService;
    private AtomicInteger successCount = new AtomicInteger(0);
    private AtomicInteger blockCount = new AtomicInteger(0);
    private AtomicInteger fallbackCount = new AtomicInteger(0);
    @BeforeEach
    public void setUp() throws Exception {
        // Reset counters before each test
        successCount.set(0);
        blockCount.set(0);
        fallbackCount.set(0);
    }
    @Test
    public void testRateLimitingAndDegradation() throws InterruptedException {
        log.info("准备测试...............");
        TimeUnit.SECONDS.sleep(5);
        log.info("开始测试...............");
        int numberOfThreads = 30; // Number of concurrent threads
        ExecutorService executorService = Executors.newFixedThreadPool(numberOfThreads);
        CountDownLatch latch = new CountDownLatch(numberOfThreads);
        for (int i = 0; i < numberOfThreads; i++) {
            executorService.submit(() -> {
                try {
                    String result = helloWorldService.sayHello("TestUser");
                    if (result.contains("blocked")) {
                        blockCount.incrementAndGet();
                    } else if (result.contains("failed")) {
                        fallbackCount.incrementAndGet();
                    } else {
                        successCount.incrementAndGet();
                    }
                } catch (Exception ex) {
                    System.out.println(ex.getMessage());
                    fallbackCount.incrementAndGet();
                } finally {
                    latch.countDown();
                }
            });
        }
        latch.await(); // Wait until all threads have completed
        log.info("Success count: " + successCount.get());
        log.info("Blocked count: " + blockCount.get());
        log.info("Fallback count: " + fallbackCount.get());
        // Assuming the flow rule is set to allow up to 20 requests per second
        assert successCount.get() <= 20 : "Number of successful requests should not exceed 20";
        assert blockCount.get() > 0 : "Some requests should be blocked due to rate limiting";
        assert fallbackCount.get() == 0 : "No requests should go to fallback under normal conditions";
        executorService.shutdown();
    }
}

启动程序

启动sentinel-dashboard

java -Dserver.port=8858 -Dcsp.sentinel.dashboard.server=localhost:8858 -Dproject.name=sentinel-dashboard -Dsentinel.dashboard.auth.username=sentinel -Dsentinel.dashboard.auth.password=123456  -Dserver.servlet.session.timeout=7200 -jar sentinel-dashboard-1.8.9.jar

启动Springboot

注意在启动时需要添加VM参数

-Dcsp.sentinel.dashboard.server=localhost:8858

界面展示

通过界面可以针对规则进行修改,保存后可以立即生效

附录

限流常见配置参数速查表

概念说明适用场景
QPS每秒查询率大促抢购、防止刷单
线程数并发占用线程数保护慢接口不占用所有线程池
快速失败超过阈值直接报错默认策略,简单粗暴
Warm Up预热模式,阈值缓慢升高系统刚启动,防止瞬间高流量压垮
排队等待请求匀速通过,处理不急的请求订单创建等需要削峰填谷的场景

Token Server Cluster 部署方式对比

特性嵌入模式 (Embedded)独立模式 (Alone)
部署成本 (利用现有资源) (需要独立机器)
隔离性差 (与业务争抢资源) (完全隔离)
适用场景中小规模集群、对成本敏感超大规模集群、核心中间件、全局限流
容灾能力依赖应用集群的稳定性 (通常有主从热备)
运维难度简单较复杂 (需维护 Server 集群)

与springboot及springcloud版本对应关系

Spring Boot 版本对应的 Spring Cloud Alibaba (SCA) 版本对应的 Sentinel 版本状态
2.3.x2.2.x.RELEASE1.7.x / 1.8.0旧版,已不再主推
2.4.x, 2.5.x, 2.6.x, 2.7.x2021.x (如 2021.0.5.0)1.8.5 / 1.8.6目前最主流的生产环境组合
3.0.x, 3.1.x2022.0.0.0 (or 2022.0.0.0-RC2)1.8.6 (有限支持)注意:原生 Web 适配器不支持,需用 Gateway 或特定适配
  • Sentinel(通过 Spring Cloud Alibaba)实际上支持 Spring Boot 2.x 的全系版本
  • Spring Boot 3.0 的变化:Spring Boot 3.0 强制要求 Java 17+,并且将底层的 javax.servlet (Java EE) 迁移为了 jakarta.servlet (Jakarta EE)。
  • Sentinel 对 Spring Boot 的支持在 3.0 上遇到了“断层”,这才是目前版本选择的核心痛点
  • Sentinel 的现状
    • Sentinel-core / sentinel-web-servlet:目前的主流稳定版本(如 1.8.x)底层依然使用的是 javax.servlet.Filter
    • sentinel-spring-webmvc-adapter 目前使用的 springboot 2.5.x版本,servlet.api版本是3.1.0
    • 不兼容:这意味着,如果你直接使用原生的 sentinel-web-servlet 依赖,它是无法运行在 Spring Boot 3.0 环境下的,会报 ClassNotFoundException(找不到 javax 包)

到此这篇关于Spring Boot4使用Sentinel进行限流的操作方法的文章就介绍到这了,更多相关springboot sentinel限流内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Springboot 中的 Filter 实现超大响应 JSON 数据压缩的方法

    Springboot 中的 Filter 实现超大响应 JSON 数据压缩的方法

    这篇文章主要介绍了Springboot 中的 Filter 实现超大响应 JSON 数据压缩,定义GzipFilter对输出进行拦截,定义 Controller该 Controller 非常简单,主要读取一个大文本文件,作为输出的内容,本文通过实例代码给大家介绍的非常详细,需要的朋友可以参考下
    2022-10-10
  • java字节流、字符流与转换流过程

    java字节流、字符流与转换流过程

    输入输出流(IO流)是数据传输的抽象概念,用于表示数据在设备间的传输过程,IO流按数据类型分为字符流和字节流,按数据流向分为输入流和输出流,字节流操作单个字节,字符流操作字符,在实际应用中,非文本文件多用字节流操作
    2024-10-10
  • 使用Spring底层组件实现Aware接口

    使用Spring底层组件实现Aware接口

    这篇文章主要介绍了使用Spring底层组件实现Aware接口,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-07-07
  • java ArrayList和Vector的区别详解

    java ArrayList和Vector的区别详解

    这篇文章主要介绍了java ArrayList和Vector的区别详解的相关资料,并附简单实例代码,需要的朋友可以参考下
    2016-11-11
  • 图解Java经典算法快速排序的原理与实现

    图解Java经典算法快速排序的原理与实现

    快速排序是基于二分的思想,对冒泡排序的一种改进。主要思想是确立一个基数,将小于基数的数放到基数左边,大于基数的数字放到基数的右边,然后在对这两部分进一步排序,从而实现对数组的排序
    2022-09-09
  • sublime编译器怎么运行java程序

    sublime编译器怎么运行java程序

    Sublime是一款强大的代码编辑器,它提供了丰富的功能和插件,可以帮助开发者提高代码的编写效率和质量,通过安装相关插件和进行简单配置,我们可以轻松地在Sublime中编译和运行Java代码,下面我们将详细介绍如何配置Sublime,使其能够高效地运行Java代码
    2024-06-06
  • Mybatis SQL日志如何转换为可执行sql

    Mybatis SQL日志如何转换为可执行sql

    这篇文章主要介绍了Mybatis SQL日志如何转换为可执行sql问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-09-09
  • 微信跳一跳辅助Java代码实现

    微信跳一跳辅助Java代码实现

    这篇文章主要为大家详细介绍了微信跳一跳辅助的Java代码实现资料,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-01-01
  • jar包加密方案分享

    jar包加密方案分享

    如何对jar包进行加密呢?其实没有想象中的那么困难,有一款开源工具已经提供了较为完善的加密方案,这款开源工具的名字叫做xjar。接下来我们就看一下使用xjar工具给jar包加密有多么的容易。
    2021-06-06
  • java 数据类型有哪些取值范围多少

    java 数据类型有哪些取值范围多少

    这篇文章主要介绍了java 数据类型有哪些取值范围多少的相关资料,网上关于java 数据类型的资料有很多,不够全面,这里就整理下,需要的朋友可以参考下
    2017-01-01

最新评论