Sentinel:入门到实战详细教程

一、为什么需要限流组件?

在分布式系统和微服务架构日益普及的今天,流量控制已经成为保障系统稳定性的核心手段。让我们先看一个真实的生产案例:

1.1 真实案例:某电商平台崩溃事故

2023年双11大促期间,某中型电商平台在秒杀活动开启后5分钟内系统全面崩溃。事后分析发现:

流量峰值:正常QPS约500,秒杀开始瞬间飙升至50000+

系统表现:所有服务实例CPU 100%,内存溢出,数据库连接池耗尽

影响范围:不仅秒杀服务崩溃,连带影响首页、浏览、下单等所有核心功能

直接损失:约300万交易额无法完成,品牌声誉受损

图1:无限流保护的系统架构 - 流量冲击场景

如上图所示,没有限流保护的系统面临多重问题:

① 资源耗尽问题当突发流量到来时,系统会按照"先来先服务"的原则处理请求。流量超出系统承载能力后:

CPU持续高负载,上下文切换频繁

内存快速分配导致GC压力增大,最终OOM

数据库连接池被占满,新请求无法获取连接

② 雪崩效应微服务架构中,服务间存在依赖关系。当下游服务因流量过大而响应缓慢或失败时:

上游服务持有的连接/线程无法释放,资源逐渐耗尽

故障会沿着调用链向上传播,最终导致整个系统崩溃

一个服务的故障可能影响整个业务链路

③ 用户体验恶化

正常用户的请求无法得到及时响应

页面长时间加载或直接报错

用户流失,信任度下降

1.2 传统解决方案的局限性

面对流量冲击,传统方案通常包括:

这些方案要么成本过高,要么效果有限,要么需要大量人力投入。我们需要一个更加智能化、自动化的流量控制解决方案。

二、Sentinel简介

2.1 Sentinel是什么?

Sentinel是阿里巴巴开源的一款面向分布式服务架构的流量控制组件,主要以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度来帮助您保障微服务的稳定性。

2.2 核心特性

① 丰富的应用场景

秒杀系统:瞬间大流量限流

消息削峰:平滑处理突发流量

熔断降级:保护核心服务不被拖垮

实时监控:全方位流量监控大盘

② 完备的实时监控Sentinel提供实时的监控功能,可以监控:

QPS(每秒查询数)

RT(响应时间)

成功率

拒绝数

③ 广泛的开源生态Sentinel提供与主流框架的整合:

Spring Cloud / Spring Boot

Dubbo

gRPC

RocketMQ

④ 完善的SPI扩展点Sentinel提供简单易用、完善的SPI扩展接口,可以通过实现扩展接口来快速定制逻辑。

三、Sentinel核心原理

3.1 责任链模式设计

Sentinel的核心工作原理基于责任链模式,通过一系列的Slot(槽位)串联成一个处理链。

图3:Sentinel核心工作原理

当请求进入时,会依次经过以下Slot:

① NodeSelectorSlot

负责收集资源的调用路径

构建树状结构的调用链路

为每个资源创建DefaultNode

② ClusterBuilderSlot

构建ClusterNode

统计集群维度某个资源的调用情况

用于存储聚合后的统计信息

③ LogSlot

记录异常日志

便于问题排查和定位

④ StatisticSlot

实时统计指标的Slot

记录秒级、分钟级的指标数据

为后续的规则判断提供数据支撑

⑤ AuthoritySlot

黑白名单控制

基于来源的流量控制

⑥ FlowSlot

流量控制Slot

根据配置的限流规则进行判断

超出阈值则抛出FlowException

⑦ DegradeSlot

熔断降级Slot

根据熔断规则判断是否需要熔断

触发熔断则抛出DegradeException

3.2 核心概念

① 资源(Resource)资源是Sentinel的核心概念,可以是:

Java代码中的一段代码

一个接口

一个方法

java 复制代码
// 定义资源方式一:使用@SentinelResource注解
@SentinelResource(value = "getUserInfo", blockHandler = "handleBlock")
public User getUserInfo(Long id) {
    return userService.getUser(id);
}

// 定义资源方式二:使用try-catch
try (Entry entry = SphU.entry("getUserInfo")) {
    return userService.getUser(id);
} catch (BlockException e) {
    return handleBlock(e);
}

② 规则(Rule)Sentinel支持多种规则类型:

③ 上下文(Context)Context保存了调用链路的元数据,包括:

入口节点(EntranceNode)

当前节点(CurrentNode)

调用来源(Origin)

四、流量控制详解

4.1 限流流程

Sentinel的限流处理流程如下图所示:

图4:Sentinel限流处理流程

4.2 限流维度

① QPS限流每秒查询数限流,适用于:

API接口限流

防止接口被刷

保护下游服务

java 复制代码
// QPS限流配置
List<FlowRule> rules = new ArrayList<>();
FlowRule rule = new FlowRule();
rule.setResource("getUserInfo");
rule.setGrade(RuleConstant.FLOW_GRADE_QPS); // QPS维度
rule.setCount(100); // 每秒最多100个请求
rule.setStrategy(RuleConstant.STRATEGY_DIRECT); // 直接拒绝
rule.setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_DEFAULT); // 默认行为
rules.add(rule);
FlowRuleManager.loadRules(rules);

② 线程数限流并发线程数限流,适用于:

业务处理时间长

需要限制并发量的场景

java 复制代码
// 线程数限流配置
FlowRule rule = new FlowRule();
rule.setResource("processOrder");
rule.setGrade(RuleConstant.FLOW_GRADE_THREAD); // 线程数维度
rule.setCount(10); // 最多10个线程并发处理

4.3 限流策略

① 直接拒绝(Default)默认策略,超出阈值直接拒绝请求:

java 复制代码
rule.setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_DEFAULT);
// 抛出FlowException: Blocked by Sentinel (flow limiting)

② Warm Up(预热)从初始阈值缓慢上升到最大阈值:

java 复制代码
rule.setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_WARM_UP);
rule.setCount(100); // 最大阈值
rule.setWarmUpPeriodSec(10); // 预热时长10秒
// 实际效果:前10秒从 100/3 ≈ 33 逐渐增加到100

适用于:

秒杀系统预热

缓存预热

系统启动阶段流量控制

③ 排队等待(Throttling)请求在队列中排队,超时则拒绝:

java 复制代码
rule.setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_RATE_LIMITER);
rule.setCount(100); // 每秒100个请求
rule.setMaxQueueingTimeMs(500); // 最大排队等待时间500ms

适用于:

消息削峰填谷

请求可以适当延迟处理的场景

4.4 关联限流

当关联的资源达到阈值时,对当前资源限流:

java 复制代码
// 当userLogin资源QPS超过50时,限制getUserInfo
rule.setStrategy(RuleConstant.STRATEGY_RELATE);
rule.setRefResource("userLogin");
rule.setCount(50);

适用场景:

登录接口压力大时,限制其他非核心接口

支付接口压力大时,限制下单接口

五、熔断降级详解

5.1 熔断机制

熔断器模式(Circuit Breaker Pattern)是一种保护性设计模式,Sentinel实现了完整的熔断降级机制。

图5:Sentinel熔断降级机制

熔断器有三种状态:

① Closed(关闭状态)

正常状态,请求正常通过

监控失败率和响应时间

异常达到阈值时,转换为Open状态

② Open(开启状态)

熔断状态,直接拒绝所有请求

持续熔断时长(timeWindow)结束后进入Half-Open状态

③ Half-Open(半开状态)

探测状态,允许部分请求通过

如果请求成功,说明服务已恢复,转为Closed状态

如果请求失败,说明服务仍未恢复,转回Open状态

5.2 熔断策略

① 慢调用比例(SLOW_REQUEST_RATIO)

当资源的响应时间超过最大RT时,被标记为慢调用。慢调用比例超过阈值时触发熔断:

java 复制代码
List<DegradeRule> rules = new ArrayList<>();
DegradeRule rule = new DegradeRule();
rule.setResource("orderService");
rule.setGrade(RuleConstant.DEGRADE_GRADE_SLOW_REQUEST_RATIO);
rule.setCount(500); // 慢调用阈值:RT > 500ms
rule.setSlowRatioThreshold(0.5); // 慢调用比例阈值:50%
rule.setTimeWindow(10); // 熔断时长:10秒
rule.setMinRequestAmount(5); // 最小请求数:5
rule.setStatIntervalMs(1000); // 统计时长:1秒
rules.add(rule);
DegradeRuleManager.loadRules(rules);

② 异常比例(EXCEPTION_RATIO)

当资源的异常比例超过阈值时触发熔断:

java 复制代码
DegradeRule rule = new DegradeRule();
rule.setResource("paymentService");
rule.setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_RATIO);
rule.setCount(0.5); // 异常比例阈值:50%
rule.setTimeWindow(10); // 熔断时长:10秒
rule.setMinRequestAmount(5); // 最小请求数:5

③ 异常数(EXCEPTION_COUNT)

当资源的异常数超过阈值时触发熔断:

java 复制代码
DegradeRule rule = new DegradeRule();
rule.setResource("smsService");
rule.setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_COUNT);
rule.setCount(10); // 异常数阈值:10个
rule.setTimeWindow(10); // 熔断时长:10秒
rule.setMinRequestAmount(5); // 最小请求数:5

5.3 降级处理

当请求被限流或熔断时,需要进行降级处理:

java 复制代码
@SentinelResource(
    value = "getUserInfo",
    blockHandler = "handleBlock",     // 限流/熔断时的处理
    fallback = "handleFallback"        // 异常时的处理
)
public User getUserInfo(Long id) {
    return userService.getUser(id);
}

// 限流/熔断处理
public User handleBlock(Long id, BlockException e) {
    // 返回默认值或缓存数据
    return User.getDefaultUser();
}

// 异常处理
public User handleFallback(Long id, Throwable e) {
    log.error("获取用户信息异常", e);
    return User.getDefaultUser();
}

六、生产实战案例

6.1 电商秒杀系统

以下是一个电商秒杀系统使用Sentinel的完整案例:

图6:生产实战:电商秒杀系统Sentinel应用架构

场景描述:

正常流量:约2000 QPS

秒杀流量:峰值可达50000+ QPS

核心需求:保护库存服务不被击垮

配置方案:

java 复制代码
@Configuration
publicclass SentinelConfig {

    @PostConstruct
    public void initRules() {
        initSeckillFlowRules();
        initOrderDegradeRules();
        initStockFlowRules();
    }

    /**
     * 秒杀接口限流规则
     */
    private void initSeckillFlowRules() {
        List<FlowRule> rules = new ArrayList<>();

        // 用户维度限流
        FlowRule userRule = new FlowRule();
        userRule.setResource("seckill:userId");
        userRule.setGrade(RuleConstant.FLOW_GRADE_QPS);
        userRule.setCount(5); // 单用户每秒最多5次请求
        userRule.setParamIdx(0); // 第一个参数作为userId
        rules.add(userRule);

        // 接口维度限流
        FlowRule apiRule = new FlowRule();
        apiRule.setResource("/api/seckill/doSeckill");
        apiRule.setGrade(RuleConstant.FLOW_GRADE_QPS);
        apiRule.setCount(10000); // 接口整体限制10000 QPS
        apiRule.setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_WARM_UP);
        apiRule.setWarmUpPeriodSec(10); // 10秒预热
        rules.add(apiRule);

        FlowRuleManager.loadRules(rules);
    }

    /**
     * 订单服务熔断规则
     */
    private void initOrderDegradeRules() {
        List<DegradeRule> rules = new ArrayList<>();

        DegradeRule rule = new DegradeRule();
        rule.setResource("orderService:createOrder");
        rule.setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_RATIO);
        rule.setCount(0.3); // 异常比例30%
        rule.setTimeWindow(10); // 熔断10秒
        rule.setMinRequestAmount(10);
        rules.add(rule);

        DegradeRuleManager.loadRules(rules);
    }

    /**
     * 库存服务限流规则
     */
    private void initStockFlowRules() {
        List<FlowRule> rules = new ArrayList<>();

        // 线程数限流,保护数据库
        FlowRule rule = new FlowRule();
        rule.setResource("stockService:decreaseStock");
        rule.setGrade(RuleConstant.FLOW_GRADE_THREAD);
        rule.setCount(100); // 最多100个线程同时操作
        rules.add(rule);

        FlowRuleManager.loadRules(rules);
    }
}

核心接口实现:

java 复制代码
@RestController
@RequestMapping("/api/seckill")
publicclass SeckillController {

    @Autowired
    private SeckillService seckillService;

    /**
     * 秒杀接口
     */
    @PostMapping("/doSeckill")
    @SentinelResource(
        value = "seckill:doSeckill",
        blockHandler = "handleBlock",
        fallback = "handleFallback"
    )
    public Result doSeckill(@RequestParam Long userId,
                           @RequestParam Long goodsId) {
        try {
            boolean success = seckillService.doSeckill(userId, goodsId);
            return success ? Result.success("秒杀成功") : Result.error("秒杀失败");
        } catch (Exception e) {
            log.error("秒杀异常", e);
            return Result.error("系统繁忙,请稍后重试");
        }
    }

    /**
     * 限流处理
     */
    public Result handleBlock(Long userId, Long goodsId, BlockException e) {
        if (e instanceof FlowException) {
            return Result.error("当前请求过多,请稍后再试");
        } elseif (e instanceof DegradeException) {
            return Result.error("服务暂时不可用,请稍后再试");
        }
        return Result.error("系统繁忙");
    }

    /**
     * 异常处理
     */
    public Result handleFallback(Long userId, Long goodsId, Throwable e) {
        log.error("秒杀异常: userId={}, goodsId={}", userId, goodsId, e);
        return Result.error("系统异常,请稍后重试");
    }
}

@Service
publicclass SeckillServiceImpl implements SeckillService {

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private StockService stockService;

    @Autowired
    private OrderService orderService;

    @Override
    @SentinelResource(
        value = "seckill:doSeckill:inner",
        blockHandler = "handleBlock"
    )
    public boolean doSeckill(Long userId, Long goodsId) {
        // 1. 校验用户是否重复购买
        String key = "seckill:user:" + userId + ":goods:" + goodsId;
        Boolean isBought = redisTemplate.hasKey(key);
        if (Boolean.TRUE.equals(isBought)) {
            thrownew BusinessException("您已经参与过此秒杀活动");
        }

        // 2. 预扣减库存
        Long stock = redisTemplate.opsForValue().decrement("seckill:stock:" + goodsId);
        if (stock == null || stock < 0) {
            redisTemplate.opsForValue().increment("seckill:stock:" + goodsId);
            thrownew BusinessException("库存不足");
        }

        // 3. 创建订单(可能触发熔断)
        try {
            Order order = orderService.createOrder(userId, goodsId);
            // 标记用户已购买
            redisTemplate.opsForValue().set(key, "1", 24, TimeUnit.HOURS);
            returntrue;
        } catch (DegradeException e) {
            // 订单服务熔断,回滚库存
            redisTemplate.opsForValue().increment("seckill:stock:" + goodsId);
            returnfalse;
        }
    }

    public boolean handleBlock(Long userId, Long goodsId, BlockException e) {
        log.warn("秒杀请求被限流: userId={}, goodsId={}", userId, goodsId);
        returnfalse;
    }
}

监控效果:

接口QPS被控制在10000左右

库存服务线程数不超过100

订单服务异常时自动熔断,不影响其他服务

系统整体可用性达到99.95%

6.2 第三方API调用保护

调用外部接口时,使用Sentinel进行保护:

java 复制代码
@Service
publicclass ThirdPartyServiceImpl {

    /**
     * 调用第三方支付接口
     */
    @SentinelResource(
        value = "thirdParty:payment",
        blockHandler = "handleBlock",
        fallback = "handleFallback",
        fallbackClass = ThirdPartyFallback.class
    )
    public PaymentResult payment(PaymentRequest request) {
        try {
            // 调用第三方支付接口
            return thirdPartyClient.payment(request);
        } catch (Exception e) {
            thrownew ThirdPartyException("支付接口调用失败", e);
        }
    }

    public PaymentResult handleBlock(PaymentRequest request, BlockException e) {
        // 返回默认结果,后续异步重试
        return PaymentResult.pending();
    }
}

/**
 * 降级处理类
 */
publicclass ThirdPartyFallback {

    public static PaymentResult handleFallback(PaymentRequest request, Throwable e) {
        log.error("支付接口异常,使用降级逻辑", e);
        // 返回降级结果,走人工处理流程
        return PaymentResult.manual();
    }
}

@Configuration
publicclass ThirdPartySentinelConfig {

    @PostConstruct
    public void initRules() {
        // 慢调用熔断
        DegradeRule slowRule = new DegradeRule();
        slowRule.setResource("thirdParty:payment");
        slowRule.setGrade(RuleConstant.DEGRADE_GRADE_SLOW_REQUEST_RATIO);
        slowRule.setCount(1000); // RT > 1秒
        slowRule.setSlowRatioThreshold(0.5); // 50%慢调用
        slowRule.setTimeWindow(30); // 熔断30秒
        slowRule.setMinRequestAmount(5);

        // 异常比例熔断
        DegradeRule exceptionRule = new DegradeRule();
        exceptionRule.setResource("thirdParty:payment");
        exceptionRule.setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_RATIO);
        exceptionRule.setCount(0.3); // 30%异常
        exceptionRule.setTimeWindow(30);
        exceptionRule.setMinRequestAmount(5);

        DegradeRuleManager.loadRules(Arrays.asList(slowRule, exceptionRule));
    }
}

6.3 系统自适应保护

Sentinel提供了系统自适应保护规则,根据系统的负载情况自动调整:

java 复制代码
@Configuration
publicclass SystemProtectConfig {

    @PostConstruct
    public void initSystemRules() {
        List<SystemRule> rules = new ArrayList<>();

        // CPU使用率保护
        SystemRule cpuRule = new SystemRule();
        cpuRule.setHighestSystemLoad(0.8); // CPU使用率超过80%时触发
        rules.add(cpuRule);

        // 平均RT保护
        SystemRule rtRule = new SystemRule();
        rtRule.setAvgRt(1000); // 平均RT超过1000ms时触发
        rules.add(rtRule);

        // 并发线程数保护
        SystemRule threadRule = new SystemRule();
        threadRule.setMaxThread(500); // 并发线程超过500时触发
        rules.add(threadRule);

        // 入口QPS保护
        SystemRule qpsRule = new SystemRule();
        qpsRule.setQps(10000); // QPS超过10000时触发
        rules.add(qpsRule);

        SystemRuleManager.loadRules(rules);
    }
}

七、Sentinel Dashboard使用

7.1 Dashboard部署

java 复制代码
# 下载Dashboard
wget https://github.com/alibaba/Sentinel/releases/download/1.8.6/sentinel-dashboard-1.8.6.jar

# 启动Dashboard
java -Dserver.port=8080 -Dcsp.sentinel.dashboard.server=localhost:8080 \
     -Dproject.name=sentinel-dashboard \
     -jar sentinel-dashboard-1.8.6.jar

7.2 客户端配置

java 复制代码
# application.yml
spring:
application:
    name:sentinel-demo
cloud:
    sentinel:
      transport:
        dashboard:localhost:8080
        port:8719
      eager:true
      datasource:
        flow:
          type:file
          file:classpath:sentinel-flow.json
        degrade:
          type:file
          file:classpath:sentinel-degrade.json

7.3 Dashboard功能

Dashboard提供了以下功能:

实时监控:查看QPS、RT、成功率等指标

规则配置:动态配置流控规则、熔断规则等

集群流控:配置集群限流

机器列表:查看连接到Dashboard的所有机器

八、总结

Sentinel作为一款成熟的流量控制组件,在微服务架构中发挥着重要作用:

核心价值

流量整形:平滑处理突发流量

服务保障:保护核心服务稳定

实时监控:全方位流量监控

快速失败:避免资源耗尽

适用场景

秒杀/抢购场景

第三方API调用

微服务链路保护

系统自适应保护

通过合理使用Sentinel,可以有效提升系统的稳定性和可用性,让微服务架构更加健壮。

图解














相关推荐
小马爱打代码1 天前
Spring Boot:Sentinel 企业级熔断、降级与限流实战
spring boot·后端·sentinel
没有bug.的程序员1 天前
Spring Cloud Sentinel:熔断降级规则配置与分布式流量防线实战终极指南
java·分布式·后端·spring cloud·sentinel·熔断规则·分布式流量防线
u0104058364 天前
Java中的服务熔断机制:Hystrix与Sentinel的比较
java·hystrix·sentinel
what丶k4 天前
微服务稳定性守护者:Sentinel 全面使用指南(从入门到企业级落地)
微服务·架构·sentinel
鸽鸽程序猿4 天前
【JavaEE】【SpringCloud】 熔断和限流 Alibaba Sentinel
spring cloud·java-ee·sentinel
小楼v5 天前
如何使用Sentinel进行流量控制和熔断
java·后端·sentinel
MediaTea8 天前
Python:_sentinel 命名约定
开发语言·python·sentinel
短剑重铸之日8 天前
《SpringCloud实用版》Feign + LoadBalancer + Sentinel 微服务调用链路
spring cloud·微服务·sentinel·feign·loadbalancer
短剑重铸之日8 天前
《SpringCloud实用版》告别 Hystrix!Sentinel vs Resilience4j 深度对比 & 选型
spring cloud·hystrix·sentinel·熔断限流降级