Sentinel

技术栈
工具链
微服务熔断降级限流流量控制系统保护阿里云

概览

Sentinel

Sentinel 是阿里巴巴开源的流量治理组件,以"流量"为切入点,提供流量控制、熔断降级、系统自适应保护等能力,是微服务架构的"断路器"。

是什么

Sentinel = 限流 + 熔断降级 + 系统保护 + 热点参数限流 + 集群流控。它可以作为独立 Dashboard 运行,与 Spring Cloud、Dubbo、gRPC 等框架无缝集成。

解决什么问题

  • 流量突刺:秒杀/大促时 QPS 暴涨 → 限流保护
  • 级联故障:下游服务慢/挂了 → 熔断快速失败,防止雪崩
  • 系统过载:CPU/LOAD 飙升 → 系统自适应保护
  • 热点击穿:单个热点 key 被打满 → 热点参数限流
  • 集群流控:分布式环境下精确控制总 QPS

关键特性

  • 9 种流控效果:直接拒绝、Warm Up(预热)、匀速排队、冷启动+排队
  • 3 种熔断策略:慢调用比例、异常比例、异常数
  • Dashboard 控制台:实时监控 + 规则推送(Pull/Push 模式)
  • @SentinelResource 注解:声明式定义资源和 fallback
  • 规则持久化:支持推送到 Nacos/ZooKeeper/Apollo
  • 自适应保护:根据系统 Load/CPU/RT 自动调整阈值

安装

Sentinel 安装与初始化

1. 环境准备

要求 说明
JDK JDK 8+(推荐 JDK 11 或 17)
Maven 3.5+(源码编译时需要)
端口 默认 8080(Dashboard)、8719(客户端通信)
存储 内存模式(默认)/ Nacos / ZooKeeper / Apollo(持久化规则)

2. 安装命令

方式一:二进制包(快速启动 Dashboard)

# 下载 Sentinel Dashboard
wget https://github.com/alibaba/Sentinel/releases/download/1.8.7/sentinel-dashboard-1.8.7.jar

# 启动(默认端口 8080)
java -Dserver.port=8080 \
     -Dcsp.sentinel.dashboard.server=localhost:8080 \
     -Dproject.name=sentinel-dashboard \
     -jar sentinel-dashboard-1.8.7.jar

# 访问控制台
# http://localhost:8080
# 默认账号密码:sentinel/sentinel

方式二:Docker

docker run -d --name sentinel \
  -p 8080:8080 \
  -p 8719:8719 \
  bladex/sentinel-dashboard:1.8.7

Spring Cloud Alibaba 集成

在业务应用中添加依赖:

<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
    <version>2023.0.1.0</version>
</dependency>

配置:

spring:
  cloud:
    sentinel:
      transport:
        dashboard: localhost:8080  # Dashboard 地址
        port: 8719                 # 客户端通信端口
      eager: true                  # 启动时立即注册

规则持久化(推荐 Nacos)

<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
spring:
  cloud:
    sentinel:
      datasource:
        flow:
          nacos:
            server-addr: localhost:8848
            data-id: ${spring.application.name}-flow-rules
            group-id: DEFAULT_GROUP
            data-type: json
            rule-type: flow

3. 常见安装问题

问题 解决方案
Dashboard 启动后无应用显示 Sentinel 采用懒加载,需先触发一次请求,应用才会出现在列表
8719 端口冲突 Sentinel 会自动尝试 +1 端口(8720、8721…),查看日志确认实际端口
Dashboard 无法访问 确认 server.port 参数和防火墙规则;默认账号密码是 sentinel/sentinel
规则重启丢失 默认规则存内存,需配置 Nacos/ZooKeeper 持久化
Dashboard 内存溢出 生产环境建议 java -Xms512m -Xmx512m -jar ...
Spring Boot 3 / JDK 17 兼容性 使用 Spring Cloud Alibaba 2023.x 版本,支持 Spring Boot 3.x

示例

目标

演示 Spring Boot 应用接入 Sentinel,实现 QPS 限流 + 熔断降级 + 自定义 fallback,通过控制台实时下发规则。

完整代码

1. pom.xml

<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
    <version>2023.0.1.0</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

2. application.yml

server:
  port: 8080
spring:
  application:
    name: sentinel-demo
  cloud:
    sentinel:
      transport:
        dashboard: localhost:8080
        port: 8719
      eager: true
      # 规则持久化(Nacos)
      datasource:
        flow:
          nacos:
            server-addr: localhost:8848
            data-id: ${spring.application.name}-flow-rules
            group-id: DEFAULT_GROUP
            data-type: json
            rule-type: flow

3. 控制器(限流 + 熔断)

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class DemoController {

    // ===== QPS 限流 =====
    @GetMapping("/hello")
    @SentinelResource(value = "hello", blockHandler = "helloBlock")
    public String hello() {
        return "Hello, Sentinel!";
    }

    public String helloBlock(BlockException ex) {
        return "Too many requests! Please try later. " + ex.getClass().getSimpleName();
    }

    // ===== 热点参数限流 =====
    @GetMapping("/item/{id}")
    @SentinelResource(value = "getItem", blockHandler = "itemBlock")
    public String getItem(@PathVariable Long id) {
        return "Item detail for ID: " + id;
    }

    public String itemBlock(@PathVariable Long id, BlockException ex) {
        return "Item " + id + " is hot! Rate limited.";
    }

    // ===== 熔断降级 =====
    @GetMapping("/risky")
    @SentinelResource(value = "risky", fallback = "riskyFallback")
    public String risky() {
        // 模拟 >50% 异常率触发熔断
        if (System.currentTimeMillis() % 3 == 0) {
            throw new RuntimeException("Simulated error");
        }
        return "OK from risky API";
    }

    public String riskyFallback(Throwable t) {
        return "Fallback: Service degraded. " + t.getMessage();
    }

    // ===== 系统自适应保护 =====
    @GetMapping("/heavy")
    public String heavy() {
        // 模拟 CPU 密集型操作
        for (int i = 0; i < 1000000; i++) {
            Math.sqrt(i);
        }
        return "Heavy computation done!";
    }
}

4. 流控规则定义(Nacos 持久化)

[
  {
    "resource": "hello",
    "grade": 1,
    "count": 5,
    "strategy": 0,
    "controlBehavior": 0
  },
  {
    "resource": "getItem",
    "grade": 1,
    "count": 10,
    "strategy": 0,
    "controlBehavior": 1,
    "paramIdx": 0
  }
]

运行步骤

# 1. 启动 Sentinel Dashboard
java -jar sentinel-dashboard-1.8.7.jar

# 2. 启动应用
mvn spring-boot:run

# 3. 触发请求(让应用出现在 Dashboard)
curl http://localhost:8080/hello

# 4. 打开 Sentinel Dashboard → 簇点链路
# 设置 hello 资源的 QPS 限流为 5

# 5. 压测验证限流
ab -n 100 -c 10 http://localhost:8080/hello
# 部分请求返回: Too many requests! Please try later. FlowException

# 6. 验证热点参数限流
for i in {1..20}; do curl http://localhost:8080/item/42; done
# 热点 key=42 被限流

# 7. 验证熔断降级
# 在 Dashboard 配置 risky 资源:
#   熔断策略: 异常比例
#   比例阈值: 0.5
#   最小请求数: 5
#   统计时长: 1000ms
#   熔断时长: 10s
for i in {1..20}; do curl http://localhost:8080/risky; done

预期输出

# 限流后
Too many requests! Please try later. FlowException

# 热点参数限流
Item 42 is hot! Rate limited.

# 熔断降级
Fallback: Service degraded. RuntimeException: Simulated error
# 连续触发后直接快速失败(不再调用原方法)

关键点

  • blockHandler 处理限流/熔断异常(BlockException)
  • fallback 处理业务异常(Throwable)
  • Sentinel Dashboard 实时推送规则,无需重启
  • 熔断半开状态:一段时间后尝试放行少量请求探测恢复

教程

前言

想象一个秒杀场景:每秒 10 万请求涌入,任何一个下游服务的"慢"都可能像多米诺骨牌一样拖垮整个系统。Sentinel 就是在这个时刻保护你的"电路开关"。


第一章:理解流量治理的三个层次

1.1 限流(Rate Limiting)

"老子只能处理这么多,多的请排队或滚蛋"

场景:你的服务设计 QPS 是 1000
      突然来了 5000 QPS
      → 限流拦截 4000,放行 1000
      → 保证服务不崩溃

1.2 熔断降级(Circuit Breaking)

"下游已经不行了,我先不调了,直接返回 fallback"

场景:支付服务调用库存服务
      库存服务响应时间从 50ms → 5000ms
      → 熔断器打开 → 快速失败
      → 支付服务线程池不会被打满
      → 10s 后半开探测 → 恢复则关闭

1.3 系统自适应保护

"系统 Load 已经很高了,拒绝新请求,保护当前处理中的"

不是按 QPS 限流,而是按系统指标:
  - CPU 使用率 > 80%
  - 系统 Load > 阈值
  - RT > 阈值
  → 自动拒绝入口流量

第二章:Sentinel 核心概念

2.1 资源(Resource)

资源是 Sentinel 的保护对象。任何想要保护的代码块都可以是一个资源:

// 方式1:注解(推荐)
@SentinelResource("myResource")
public String doSomething() { ... }

// 方式2:API(代码中埋点)
try (Entry entry = SphU.entry("myResource")) {
    // 被保护的代码
} catch (BlockException e) {
    // 被限流后的处理
}

2.2 规则(Rule)

每条规则定义了"如何保护资源":

规则类型:
├── FlowRule(流控规则)—— QPS/并发线程数
├── DegradeRule(熔断降级)—— 慢调用/异常比例/异常数
├── SystemRule(系统规则)—— CPU/Load/RT/QPS
├── AuthorityRule(授权规则)—— 黑白名单
└── ParamFlowRule(热点规则)—— 针对特定参数

2.3 Slot Chain(责任链)

Sentinel 内部通过责任链模式处理请求:

请求 → NodeSelectorSlot → ClusterBuilderSlot → StatisticSlot
    → AuthoritySlot → SystemSlot → FlowSlot → DegradeSlot
    → 业务方法

第三章:限流算法详解

3.1 滑动窗口

Sentinel 默认使用滑动窗口算法做统计:

时间轴:[0--1--2--3--4--5--6--7--8--9--10] 秒
窗口大小:1 秒
滑动步长:200ms(5 个桶)
每个桶统计:通过 / 阻塞 / 异常 / RT

效果:1 秒维度精确 QPS 控制

3.2 四种流控效果

效果 行为 适用场景
直接拒绝 超出 QPS 立即抛异常 一般 API 保护
Warm Up 阈值从低到高逐渐提升 冷启动保护(连接池预热)
匀速排队 请求排队,恒定间隔通过 消息队列削峰
Warm Up + 排队 预热 + 排队混合 突发流量 + 冷启动

3.3 三种流控模式

// 直接模式:针对当前资源
FlowRule rule = new FlowRule("resourceName")
    .setCount(10)
    .setGrade(RuleConstant.FLOW_GRADE_QPS);

// 关联模式:关联资源触发时限制自己
// 例如:写操作 QPS 大时限制读操作
rule.setStrategy(RuleConstant.STRATEGY_RELATE);
rule.setRefResource("writeResource");

// 链路模式:只限制入口链路
rule.setStrategy(RuleConstant.STRATEGY_CHAIN);
rule.setRefResource("entryPointA");

第四章:熔断降级深入

4.1 熔断器状态机

        ┌──────────┐
        │  CLOSED  │ (正常)
        └─────┬────┘
              │ 失败达到阈值
        ┌─────┴────┐
        │   OPEN   │ (熔断)
        └─────┬────┘
              │ 休眠时间到
        ┌─────┴────────┐
        │  HALF-OPEN   │ (探测)
        └──────┬───────┘
        成功 ↓  ↑ 失败
      CLOSED     OPEN

4.2 三种熔断策略

// 慢调用比例
new DegradeRule("resource")
    .setGrade(RuleConstant.DEGRADE_GRADE_RT)
    .setCount(500)       // RT > 500ms 算慢调用
    .setTimeWindow(10)   // 熔断时长 10s
    .setMinRequestAmount(5)
    .setSlowRatioThreshold(0.5);  // 50% 慢调用触发

// 异常比例
new DegradeRule("resource")
    .setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_RATIO)
    .setCount(0.5);      // 异常比例 > 50% 触发

// 异常数
new DegradeRule("resource")
    .setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_COUNT)
    .setCount(20);       // 1 分钟内 > 20 个异常触发

第五章:Sentinel vs Hystrix vs Resilience4j

特性 Sentinel Hystrix Resilience4j
状态 ✅ 活跃维护 ❌ 停止维护 ✅ 活跃
限流 ✅ 丰富 ❌ 只有信号量 ✅ RateLimiter
熔断
Dashboard ✅ 强大 ✅ 基础 ❌ 无内置
热点限流
系统保护
规则动态下发
Spring 集成 Spring Cloud Alibaba Spring Cloud Netflix 独立

思考题

  1. Sentinel 的滑动窗口和常见的固定窗口、令牌桶有什么区别?各有什么优劣?
  2. 熔断器的「半开」状态为什么要只放行少量请求?如果放行大量请求会怎样?
  3. 热点参数限流和普通 QPS 限流的底层实现有什么不同?
  4. 如果 Sentinel Dashboard 挂了,规则还会生效吗?服务会怎样?

下一步

  • 学习 Sentinel + Gateway 实现网关层限流
  • 学习 Sentinel 集群流控
  • 学习 Sentinel + Nacos 规则持久化

参考资料

暂无参考文献