Spring Cloud Alibaba快速入门-Sentinel流量控制(FlowRule)

文章目录


什么是流量控制(Flow Control)?

核心思想:流量控制是 Sentinel 的"刹车系统"。它的原理是监控应用流量的 QPS(每秒查询率)或并发线程数等指标,当达到指定的阈值时,就采取预定的控制行为(如直接拒绝、排队等待等),以保证系统不会被突发流量冲垮,从而保障服务的高可用性。

简单来说,其目的就是 "避免让系统处理能力之外的需求涌入系统 "。

新增流控规则

进入Sentinel页面,点击

  • 资源名:需要控制的资源名称
  • 针对来源:一般为default,表示无论从任何地方来的请求
  • 阈值类型:
    • QPS:统计每秒请求数,一般设置QPS
    • 并发线程数:统计并发线程数,统计线程池
  • 单机阈值:每秒数

单机均摊:当均摊阈值为1时,集群中每一个机器每秒最多执行一次

总体阈值:当均摊阈值为1时,整个集群每秒最多执行一次

流控模式

在 Sentinel的流控模式中,直接、关联、链路 是三种核心的流控模式,它们的核心区别在于触发流量控制的条件和场景不同

  • 调用关系包括调用方、被调用方;
  • 一个方法又可能会调用其它方法,形成一个调用链路的层次关系;
  • 有了调用链路的统计信息,我们可以衍生出多种流量控制手段。

直接策略(默认模式)

  • 触发逻辑:当当前资源自身的流量达到阈值时,直接对当前资源的请求进行限流。
  • 场景:最常用的模式,用于保护单个资源不被过度访问。
  • 特点:
    • 只关注当前资源的流量,与其他资源无关;
    • 配置简单,适用于绝大多数基础限流场景。

链路策略

触发逻辑

当从指定入口资源过来的请求 访问当前资源时,若流量达到阈值,对该链路的请求进行限流(其他入口的请求不受影响)。(即:只限制 "特定调用链" 上的流量,允许其他链路正常访问当前资源)

场景

  • 用于精细化控制 "同一资源在不同调用链路下的流量",避免某一条链路的异常流量影响其他链路。如:
    • 同一个Service方法被多个Controller调用。例如,UserService.getUserById() 方法既被 AdminController 调用,也被 AppController 调用。
    • 希望只限制来自 AdminController 这个调用链路的流量,而不影响 AppController 的正常用户访问。

特点

  • 限流范围限定在 "特定入口→当前资源" 的调用链路上;
  • 需通过如@SentinelResource注解明确标记资源和入口(或通过配置指定上下文),实现链路识别。

示例

java 复制代码
@GetMapping("/create")
public Order createOrder(@RequestParam("userId") Long userId,
                         @RequestParam("productId") Long productId) {
    return orderService.createOrder(userId, productId);
}

@GetMapping("/seckill")
public Order seckill(@RequestParam(value = "userId" ) Long userId,
                     @RequestParam(value = "productId") Long productId){
    Order order = orderService.createOrder(productId, userId);
    order.setId(Long.MAX_VALUE);
    return order;
}

配置文件添加web-context-unify: false

yml 复制代码
spring:
  cloud:
    sentinel:
      transport:
        # 指定Sentinel控制台地址
        dashboard: localhost:8080
      # 设置为true,表示启动时立即初始化Sentinel。
      eager: true
      # 关闭Web上下文统一(sentinel_spring_web_context)
      web-context-unify: false

feign:
  sentinel:
    enabled: true

如果web-context-unify使用默认true,则会显示

点击/seckill下的createOrder

注意:启动Sentinel后需要执行一次代码才会显示

设置入口资源只对/seckill限制

访问两个接口时即可发现只有/seckill接口被限制

http://127.0.0.1:8081/create?userId=10\&productId=11

http://127.0.0.1:8081/seckill?userId=10\&productId=11

关联策略

触发逻辑

  • 与当前资源相关联的另一个资源的流量达到阈值时,对当前资源的请求进行限流。(即:B 资源流量过高时,限制 A 资源的请求,防止 A 资源进一步加剧 B 的压力)

场景

用于保护 "有依赖关系的资源",避免因关联资源过载而引发连锁反应。如:

  • 数据库读写分离:当大量的写操作(关联资源A)达到阈值,可能拖慢数据库时,就限制读操作(资源B)的流量,保证写操作能正常完成。
  • 支付与查询:当支付接口(关联资源A)流量激增时,为了保证支付核心流程,可以适当限制订单查询接口(资源B)的流量。

特点

  • 限流的是 "当前资源",但触发条件是 "关联资源" 的流量超标;
  • 适用于需要 "牺牲非核心资源保护核心资源" 的场景(如写操作通常比读操作更核心)。

示例

新增两个接口模拟读写分离场景

java 复制代码
@GetMapping("/writeDb")
public String writeDb(){
    System.out.println("writeDb");
    return "writeDb success....";
}

@GetMapping("/readDb")
public String readDb(){
    System.out.println("readDb");
    return "readDb success....";
}

先快速调用多次http://127.0.0.1:8081/writeDb

在调用http://127.0.0.1:8081/readDb

出现以下情况

注意:这里只有在调用writeDb接口超过阈值时,才会触发readDb接口的限制。只调用readDb接口不会触发

流控效果

流控效果是流量控制的 "执行动作",当某个资源的流量达到预设阈值(如 QPS=100)时,Sentinel 会根据配置的流控效果对超额请求进行处理。其核心目标是:在保护系统不被过载的同时,最大化资源利用率,或保证请求处理的公平性。

注意:只有快速失败支持流控模式(直接、关联、链路)的设置

快速失败

核心思想

流量一旦达到阈值,立即拒绝后续所有请求。并抛出异常,不进行任何等待或缓冲。

适用场景

  • 对响应时间敏感的业务(如支付接口、核心交易链路),快速失败避免请求堆积,防止雪崩
  • 非核心业务,优先保证系统稳定性,牺牲部分请求可用性。

特点

  • 优点:处理速度快,对系统资源消耗低(无需维护队列或计时);
  • 缺点:可能导致短时间内大量请求失败,用户体验较差(如 "瞬间报错")。

示例

设置规则

在代码中设置状态码为429,用于处理Sentinel限流或降级时的异常

java 复制代码
import com.alibaba.csp.sentinel.adapter.spring.webmvc_v6x.callback.BlockExceptionHandler;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.qf.common.R;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Component;

import java.io.PrintWriter;

/**
 * 用于处理Sentinel限流或降级时的异常
 */
@Component
public class MyBlockExceptionHandler implements BlockExceptionHandler {
    private ObjectMapper objectMapper = new ObjectMapper();
    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response,
                       String resourceName, BlockException e) throws Exception {
        response.setStatus(429); //too many requests
        response.setContentType("application/json;charset=utf-8");

        PrintWriter writer = response.getWriter();


        R error = R.error(500, resourceName + " 被Sentinel限制了,原因:" + e.getClass());

        String json = objectMapper.writeValueAsString(error);
        writer.write(json);

        writer.flush();
        writer.close();
    }
}

使用apipost进行压测

断言状态码为200成功

设置10个线程,发送5秒

这里可以看到成功请求数为11个

总结:快速失败会把多余的请求直接抛弃。

Warm Up(预热 / 冷启动)

核心思想

让系统从"冷"状态平滑地过渡到"全速"状态(热身),避免冷启动时瞬间高并发导致系统崩溃

适用场景

  • 系统刚启动(或重启)后,需要时间加载缓存、初始化连接池等资源(冷系统);
  • 流量波动较大的场景(秒杀/抢购系统),避免系统瞬间过载。

特点

  • 优点:保护系统不被突发流量冲击,让系统资源(如 CPU、内存)逐步提升负载;
  • 缺点:预热期间会有部分请求被限流,需要业务允许 "渐进式可用"。

为什么需要Warm Up?

系统在冷启动(如刚启动、长时间低负载后突然扩容)时,各种资源(如数据库连接池、缓存、JVM JIT编译)可能还未完全准备好。如果瞬间施加全部流量,很可能导致系统因负载过高而崩溃。Warm Up 给它一个"热身"的时间。

示例

效果:一开始只处理三分一的请求(1/10),之后每秒会逐步增加,三秒时和之后每秒处理10个请求

进行压测

查看接口日志

js 复制代码
2025-02-25T07:49:36.499+08:00  INFO 34312 --- [qf-service-order] [nio-8081-exec-4] com.qf.controller.OrderController        : ----------readDb----------
2025-02-25T07:49:36.500+08:00  INFO 34312 --- [qf-service-order] [io-8081-exec-17] com.qf.controller.OrderController        : ----------readDb----------
2025-02-25T07:49:36.499+08:00  INFO 34312 --- [qf-service-order] [nio-8081-exec-6] com.qf.controller.OrderController        : ----------readDb----------
2025-02-25T07:49:37.000+08:00  INFO 34312 --- [qf-service-order] [io-8081-exec-20] com.qf.controller.OrderController        : ----------readDb----------
2025-02-25T07:49:37.000+08:00  INFO 34312 --- [qf-service-order] [io-8081-exec-18] com.qf.controller.OrderController        : ----------readDb----------
2025-02-25T07:49:37.000+08:00  INFO 34312 --- [qf-service-order] [io-8081-exec-17] com.qf.controller.OrderController        : ----------readDb----------
2025-02-25T07:49:38.000+08:00  INFO 34312 --- [qf-service-order] [nio-8081-exec-2] com.qf.controller.OrderController        : ----------readDb----------
2025-02-25T07:49:38.000+08:00  INFO 34312 --- [qf-service-order] [nio-8081-exec-8] com.qf.controller.OrderController        : ----------readDb----------
2025-02-25T07:49:38.000+08:00  INFO 34312 --- [qf-service-order] [io-8081-exec-19] com.qf.controller.OrderController        : ----------readDb----------
2025-02-25T07:49:38.000+08:00  INFO 34312 --- [qf-service-order] [io-8081-exec-11] com.qf.controller.OrderController        : ----------readDb----------
2025-02-25T07:49:38.000+08:00  INFO 34312 --- [qf-service-order] [io-8081-exec-14] com.qf.controller.OrderController        : ----------readDb----------
2025-02-25T07:49:38.000+08:00  INFO 34312 --- [qf-service-order] [io-8081-exec-18] com.qf.controller.OrderController        : ----------readDb----------
2025-02-25T07:49:39.000+08:00  INFO 34312 --- [qf-service-order] [nio-8081-exec-9] com.qf.controller.OrderController        : ----------readDb----------
2025-02-25T07:49:39.000+08:00  INFO 34312 --- [qf-service-order] [io-8081-exec-19] com.qf.controller.OrderController        : ----------readDb----------
2025-02-25T07:49:39.000+08:00  INFO 34312 --- [qf-service-order] [io-8081-exec-20] com.qf.controller.OrderController        : ----------readDb----------
2025-02-25T07:49:39.000+08:00  INFO 34312 --- [qf-service-order] [nio-8081-exec-2] com.qf.controller.OrderController        : ----------readDb----------
2025-02-25T07:49:39.000+08:00  INFO 34312 --- [qf-service-order] [nio-8081-exec-8] com.qf.controller.OrderController        : ----------readDb----------
2025-02-25T07:49:39.000+08:00  INFO 34312 --- [qf-service-order] [nio-8081-exec-1] com.qf.controller.OrderController        : ----------readDb----------
2025-02-25T07:49:39.000+08:00  INFO 34312 --- [qf-service-order] [io-8081-exec-14] com.qf.controller.OrderController        : ----------readDb----------
2025-02-25T07:49:39.000+08:00  INFO 34312 --- [qf-service-order] [nio-8081-exec-3] com.qf.controller.OrderController        : ----------readDb----------
2025-02-25T07:49:39.000+08:00  INFO 34312 --- [qf-service-order] [io-8081-exec-16] com.qf.controller.OrderController        : ----------readDb----------
2025-02-25T07:49:39.000+08:00  INFO 34312 --- [qf-service-order] [nio-8081-exec-5] com.qf.controller.OrderController        : ----------readDb----------

可以看到每秒访问接口数量在逐步增加,直到每秒10个

排队等待(Rate Limiting / Queueing)

核心思想

当流量超过阈值时,不立即拒绝请求,而是让超限的请求进入队列排队等待,以固定的速率(等于阈值)处理,使用的是漏桶算法的思想。

适用场景

  • 需要平滑流量的场景(如秒杀、定时任务触发的批量请求),用排队来缓冲流量,避免恢复瞬间被压垮。
  • 对请求延迟不敏感(异步),但要求 "最终处理" 的业务(如日志上报、数据同步)。

示例

当单机阈值设置为2时,表示每隔500ms才允许通过下一个请求。1000ms/2所得。

效果:每秒中处理两个请求,多余的请求进行排队,超过1秒(timeout)丢弃

注意:排队等待不支持流控模式中的关联和链路,配置了也不会起到效果

使用Apipost进行请求发送

js 复制代码
2025-02-26T07:33:46.192+08:00  INFO 34312 --- [qf-service-order] [io-8081-exec-12] com.qf.controller.OrderController        : ----------readDb----------
2025-02-26T07:33:46.192+08:00  INFO 34312 --- [qf-service-order] [nio-8081-exec-5] com.qf.controller.OrderController        : ----------readDb----------
2025-02-26T07:33:46.192+08:00  INFO 34312 --- [qf-service-order] [io-8081-exec-13] com.qf.controller.OrderController        : ----------readDb----------
2025-02-26T07:33:46.193+08:00  INFO 34312 --- [qf-service-order] [io-8081-exec-14] com.qf.controller.OrderController        : ----------readDb----------
2025-02-26T07:33:46.692+08:00  INFO 34312 --- [qf-service-order] [io-8081-exec-10] com.qf.controller.OrderController        : ----------readDb----------
2025-02-26T07:33:47.192+08:00  INFO 34312 --- [qf-service-order] [io-8081-exec-17] com.qf.controller.OrderController        : ----------readDb----------
2025-02-26T07:33:47.692+08:00  INFO 34312 --- [qf-service-order] [io-8081-exec-21] com.qf.controller.OrderController        : ----------readDb----------
2025-02-26T07:33:48.191+08:00  INFO 34312 --- [qf-service-order] [io-8081-exec-13] com.qf.controller.OrderController        : ----------readDb----------
2025-02-26T07:33:48.691+08:00  INFO 34312 --- [qf-service-order] [io-8081-exec-10] com.qf.controller.OrderController        : ----------readDb----------
2025-02-26T07:33:49.191+08:00  INFO 34312 --- [qf-service-order] [io-8081-exec-15] com.qf.controller.OrderController        : ----------readDb----------
2025-02-26T07:33:49.691+08:00  INFO 34312 --- [qf-service-order] [io-8081-exec-12] com.qf.controller.OrderController        : ----------readDb----------
2025-02-26T07:33:50.197+08:00  INFO 34312 --- [qf-service-order] [io-8081-exec-10] com.qf.controller.OrderController        : ----------readDb----------
2025-02-26T07:33:50.695+08:00  INFO 34312 --- [qf-service-order] [nio-8081-exec-7] com.qf.controller.OrderController        : ----------readDb----------
2025-02-26T07:33:51.192+08:00  INFO 34312 --- [qf-service-order] [io-8081-exec-17] com.qf.controller.OrderController        : ----------readDb----------
2025-02-26T07:33:51.691+08:00  INFO 34312 --- [qf-service-order] [io-8081-exec-13] com.qf.controller.OrderController        : ----------readDb----------
2025-02-26T07:33:52.191+08:00  INFO 34312 --- [qf-service-order] [io-8081-exec-25] com.qf.controller.OrderController        : ----------readDb----------
2025-02-26T07:33:52.234+08:00  WARN 34312 --- [qf-service-order] [io-8081-exec-25] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.web.context.request.async.AsyncRequestNotUsableException: ServletOutputStream failed to flush: java.io.IOException: Connection reset by peer]
2025-02-26T07:33:52.692+08:00  INFO 34312 --- [qf-service-order] [io-8081-exec-17] com.qf.controller.OrderController        : ----------readDb----------
2025-02-26T07:33:52.692+08:00  WARN 34312 --- [qf-service-order] [io-8081-exec-17] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.web.context.request.async.AsyncRequestNotUsableException: ServletOutputStream failed to flush: java.io.IOException: Connection reset by peer]

开头的情况属于正常,统计时需要有时间起点。开始统计后发现是每秒处理两个请求。

最后有两条WARN级别的日志,表示客户端提前终止了与服务器的连接,导致服务器无法完成响应的发送。新来的请求因为排不上队(集合满了)而被丢弃,导致客户端等待超时后断开连接。


相关文章:
Spring Cloud Alibaba快速入门
Spring Cloud Alibaba快速入门-Nacos注册中心(上)
Spring Cloud Alibaba快速入门-Nacos注册中心(下)
Spring Cloud Alibaba快速入门-Nacos配置中心(上)
Spring Cloud Alibaba快速入门-Nacos配置中心(下)
Spring Cloud Alibaba快速入门-OpenFeign
Spring Cloud Alibaba快速入门-OpenFeign进阶用法
Spring Cloud Alibaba快速入门-Sentinel
Spring Cloud Alibaba快速入门-Sentinel流量控制(FlowRule)
Spring Cloud Alibaba快速入门-Sentinel熔断规则

Spring Cloud Netflix快速入门

相关推荐
echoyu.4 小时前
微服务-网络模型与服务通信方式openfein
网络·spring cloud·微服务·架构·openfein
喂完待续4 小时前
【序列晋升】38 Spring Data MongoDB 的统一数据访问范式与实践
java·spring·spring cloud·big data·序列晋升
Jabes.yang4 小时前
互联网大厂Java面试:从Spring到Kafka的技术挑战
spring boot·spring cloud·eureka·kafka·mybatis·jpa·java面试
承悦赋9 小时前
微服务通信:5大消息队列横向对比
微服务·架构·kafka·rabbitmq·rocketmq
我就要用Cx3309 小时前
微服务配置管理
java·运维·微服务
qq_3168377510 小时前
spring cloud 同一服务多实例 websocket跨实例无法共享Session 的解决
java·websocket·spring cloud
boonya10 小时前
云原生微服务中间件选型
微服务·云原生·架构
whltaoin12 小时前
SpringCloud项目阶段八:利用redis分布式锁解决集群状态下任务抢占以及实现延迟队列异步审核文章
redis·分布式·spring cloud
Zfox_13 小时前
【C++项目】微服务即时通讯系统:服务端
数据库·c++·微服务·中间件·rpc·架构·即时通讯