SpringCloudAlibaba_Sentinel详解

O泡李华 9

Spring Cloud Alibaba:Sentinel 详解

课程位置:第四阶段「微服务项目 + AI 应用」第 3 课
前置知识:微服务体系架构、Nacos、Feign、LoadBalancer、Spring Boot 3
本课主题:Spring Cloud Alibaba——Sentinel
下一课:Spring Cloud Alibaba——Gateway
学习目标:从“下游服务变慢导致上游被拖住”开始,理解 Sentinel 为什么存在,掌握资源、规则、QPS 限流、并发线程数限流、流控效果、熔断器状态机、慢调用比例、异常比例、异常数、@SentinelResource、blockHandler、fallback、Feign + Sentinel、热点参数限流、系统保护、Dashboard、规则持久化与常见错误排查。


一、这一课先不要背配置

上一课我们已经实现:

order-service
↓ Feign
user-service

现在调用:

userClient.getById(id);

能够成功。

但是:

能调用
≠
调用一定稳定

这就是 Sentinel 要解决的问题。


二、先制造一个故障

在 user-service 中添加:

@GetMapping("/users/slow/{id}")
public UserRemoteDTO slow(
        @PathVariable Long id
)
        throws InterruptedException {

    Thread.sleep(5000);

    return new UserRemoteDTO(
        id,
        "slow-user-" + id
    );
}

这个接口每次:

等待 5 秒

三、order-service 调它

Feign:

@FeignClient(
    name = "user-service"
)
public interface UserClient {

    @GetMapping(
        "/users/slow/{id}"
    )
    UserRemoteDTO slow(
        @PathVariable("id")
        Long id
    );
}

然后:

userClient.slow(1L);

四、一个请求慢 5 秒有什么问题

如果只有:

1 个请求

可能感觉还好。

但如果同时:

1000 个请求

都进入 order-service,

order-service 会:

大量线程等待 user-service

五、资源会被占用

例如:

Web 线程
HTTP 连接
内存
连接池

都会持续被占。

如果请求继续增加:

order-service 自己也会被拖垮

六、这就是雪崩传播

user-service 变慢
↓
order-service 线程堆积
↓
order-service 变慢
↓
Gateway 等待
↓
前端大量超时

一个下游问题:

逐层向上传播

七、Sentinel 是什么

Sentinel 是:

面向分布式服务架构的流量治理组件

Spring Cloud Alibaba 把它集成进 Spring Cloud 项目。

核心能力包括:

流量控制

熔断降级

系统保护

热点参数限流

实时监控

八、Sentinel 的核心思想

可以先记一句:

把系统能承受的流量
控制在安全范围内

并且:

下游不稳定时
及时切断调用

九、Sentinel 主要解决两类问题

第一类:

流量太大

例如:

突然 10000 QPS

解决:

限流

第二类:

下游不稳定

例如:

响应慢
大量异常

解决:

熔断降级

十、限流和熔断不是一回事

限流关注:

进入系统的流量

熔断关注:

依赖服务的健康程度

可以理解:

限流:
别让太多人进来

熔断:
这个下游已经不行了,暂时别再调

十一、当前版本基线

上一课使用:

Spring Cloud Alibaba 2025.0.0.0
Spring Cloud 2025.0.0
Spring Boot 3.5.0
JDK17

官方组件关系表中:

Sentinel = 1.8.9

所以课程:

优先跟 BOM

不要自己手工把 Sentinel Client:

强行升级成别的版本

十二、上游 Sentinel 当前还有更新版本

Sentinel GitHub 当前最新稳定 Release:

1.8.10

但是:

SCA 2025.0.0.0
官方对应 1.8.9

因此项目中最重要的是:

兼容关系

不是:

组件单独越新越好

十三、加入 Sentinel Starter

在 order-service 中:

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

因为父工程 BOM 已经管理版本:

不要再写 version

十四、为什么先加在 order-service

因为当前场景:

order-service
是 user-service 的消费者

我们首先要保护:

order-service
不要被 user-service 拖垮

十五、Sentinel 中最重要的概念:资源

Resource:

资源

可以是:

一个 URL

一个 Java 方法

一次远程调用

一段代码

十六、为什么先定义资源

Sentinel 所有规则都要作用于:

某个资源

例如:

资源名:
queryOrder

然后才能说:

queryOrder 最大 QPS=10

十七、最简单资源注解

@SentinelResource(
    value = "queryOrder"
)
public OrderVO queryOrder(
        Long id
) {
    ...
}

十八、@SentinelResource 的 value

就是:

资源名

例如:

queryOrder

十九、一个资源可以有多个规则

例如:

queryOrder

可以同时配置:

QPS 限流

熔断

热点参数限流

Sentinel 会分别判断。


二十、Web 接口本身也可以成为资源

Spring Cloud Alibaba Sentinel:

会对 Web 请求进行适配

例如:

GET /orders/1

可以在 Sentinel 中形成 URL 资源。


二十一、什么时候还需要 @SentinelResource

当你想对:

业务方法

特定逻辑

非 Controller 方法

定义资源时,

@SentinelResource 很方便。


二十二、Sentinel Dashboard

Sentinel 提供:

控制台

用于:

实时监控

查看资源

配置规则

二十三、课程版本建议

为了和 SCA 2025.0.0.0 的:

Sentinel 1.8.9

保持一致,

课程可以使用:

sentinel-dashboard-1.8.9.jar

二十四、启动 Dashboard

java \
  -Dserver.port=8080 \
  -Dcsp.sentinel.dashboard.server=localhost:8080 \
  -Dproject.name=sentinel-dashboard \
  -jar sentinel-dashboard-1.8.9.jar

Windows PowerShell 可以写成一行:

java -Dserver.port=8080 -Dcsp.sentinel.dashboard.server=localhost:8080 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard-1.8.9.jar

二十五、如果 8080 被占用

例如改:

8858
java -Dserver.port=8858 -Dcsp.sentinel.dashboard.server=localhost:8858 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard-1.8.9.jar

二十六、为什么你很可能遇到 8080 冲突

因为:

Gateway
Tomcat
普通 Spring Boot

很多教程都喜欢:

8080

所以建议本地:

Sentinel Dashboard = 8858

更清楚。


二十七、Dashboard 默认登录

Sentinel 官方文档说明:

默认用户名:
sentinel

默认密码:
sentinel

这是:

测试控制台默认值

生产环境:

不能直接这样用

二十八、Dashboard 官方定位

Sentinel Dashboard:

主要是功能演示和基础管理控制台

官方明确提醒:

并不是直接拿来就能当企业生产平台

生产通常需要:

权限
认证
持久化
高可用
二次改造

二十九、应用连接 Dashboard

order-service:

spring:
  cloud:
    sentinel:
      transport:
        dashboard: localhost:8858
        port: 8719

如果 Dashboard 使用 8080:

dashboard: localhost:8080

三十、8719 是什么

transport.port:

Sentinel Client 对外通讯端口

Dashboard:

通过这个端口和客户端交互

三十一、如果 8719 被占

Sentinel:

可能尝试寻找后续可用端口

本地多个服务时:

不要所有服务都死盯 8719

但课程阶段可以:

先理解它的用途

三十二、为什么 Dashboard 看不到应用

很多人启动:

order-service

然后马上看 Dashboard:

没有应用

三十三、一个常见原因

Sentinel 通常需要:

资源产生访问

才会出现相关监控数据。

所以启动后:

先访问一次接口

例如:

/orders/1

再刷新控制台。


三十四、接入检查顺序

1. Sentinel Starter

2. Dashboard 是否启动

3. dashboard 地址是否正确

4. 应用是否启动

5. 请求资源是否被访问

6. transport 是否有异常

三十五、限流第一种:QPS

QPS:

Queries Per Second

简单理解:

每秒请求数

三十六、QPS=10 是什么意思

资源:

每秒允许大约 10 个请求通过

超过:

触发流量控制

三十七、Sentinel 官方流控维度

核心有:

QPS

并发线程数

三十八、为什么两种都需要

有些问题:

请求数量太多

适合:

QPS

有些问题:

每个请求都很慢

适合:

并发数

三十九、QPS 限流实验

Controller:

@GetMapping("/orders/limit")
@SentinelResource(
    value = "orderLimit"
)
public String limit() {
    return "success";
}

四十、在 Dashboard 配规则

资源:

orderLimit

规则:

阈值类型:
QPS

单机阈值:
2

四十一、效果

1 秒内:

第1个
通过

第2个
通过

后面超过阈值
被 Sentinel 拦截

四十二、这是不是说精确永远两个

不要用:

绝对秒表思维

Sentinel:

按运行统计窗口执行规则

你只需要理解:

QPS 超过阈值
会触发控制

四十三、QPS 限流适合什么

例如:

短信验证码

搜索接口

热门商品详情

AI 请求

第三方接口入口

四十四、为什么短信接口很适合

如果不控制:

恶意用户每秒几千次请求

可能:

短信费用爆炸

四十五、第二种:并发线程数限流

Sentinel 官方还支持:

并发线程数

四十六、什么叫并发线程数

当前正在处理资源的:

线程数量

例如一个接口每次:

sleep 5 秒

请求进入后:

线程长期占用

四十七、这种情况 QPS 不一定很高

假设:

每秒只来 20 个请求

但每个:

处理 10 秒

积累起来:

正在处理的线程会越来越多

四十八、所以线程数规则特别适合

慢资源

保护:

Web 线程不要被占光

四十九、线程数限流本质

Sentinel 官方把它描述为:

轻量级的信号量隔离

意思:

当前同时允许 N 个线程进入
超过就拒绝

五十、实验

资源:

slowOrder

方法:

@GetMapping("/orders/slow")
@SentinelResource(
    value = "slowOrder"
)
public String slow()
        throws InterruptedException {

    Thread.sleep(5000);

    return "ok";
}

五十一、配置

阈值类型:
线程数

单机阈值:
2

五十二、效果

前两个请求:

正在执行

第三个同时进来:

直接被 Sentinel 拒绝

五十三、QPS 和线程数怎么选

可以记:

限制请求速度
→ QPS

限制正在占用的并发资源
→ 线程数

五十四、最典型慢接口

例如:

AI 大模型调用
文件生成
第三方支付查询
慢数据库报表

这些特别要考虑:

并发资源保护

五十五、Sentinel 默认流控效果:快速失败

超过阈值:

直接拒绝

不会:

无限排队

五十六、为什么快速失败有价值

系统已经:

到容量上限

继续接受请求:

可能全部一起变慢

快速失败:

至少保护已有请求

五十七、流控效果还有 Warm Up

Warm Up:

预热

适合:

系统长期低流量
突然瞬间大流量

五十八、为什么需要预热

例如:

JVM
缓存
连接池

长期空闲后,

突然:

大流量一下全部打进来

可能不稳定。

Warm Up:

逐步提高允许流量

五十九、另一种流控效果:匀速排队

Sentinel 官方支持:

匀速通过 / Rate Limiter

核心:

把突发请求整形成较稳定速度

六十、适合什么

例如:

消息处理

削峰填谷

不是所有 Web 请求都适合:

长时间排队

六十一、为什么 Web 请求通常更关心快速失败

用户请求:

等待几十秒

体验很差。

很多在线接口宁愿:

快速告诉用户“系统繁忙”

也不要:

一直卡住

六十二、限流触发的异常

Sentinel 规则触发后:

不是普通业务异常

而是:

BlockException 体系

六十三、BlockException 代表什么

可以理解:

Sentinel 主动阻止了这次访问

原因可能:

限流
熔断
热点参数
系统保护

六十四、为什么要区分业务异常

例如:

用户不存在

是业务异常。

QPS 超过

是 Sentinel Block。

两者:

处理逻辑不同

六十五、@SentinelResource 的 blockHandler

@SentinelResource(
    value = "queryOrder",
    blockHandler = "handleBlock"
)
public OrderVO queryOrder(
        Long id
) {
    ...
}

处理函数:

public OrderVO handleBlock(
        Long id,
        BlockException ex
) {

    OrderVO vo =
            new OrderVO();

    vo.setOrderId(id);
    vo.setMessage(
        "系统繁忙,请稍后再试"
    );

    return vo;
}

六十六、blockHandler 方法签名

Sentinel 官方要求:

返回类型
与原方法一致

参数
与原方法一致
+
最后追加 BlockException

六十七、而且 blockHandler 必须可访问

一般写:

public

六十八、@SentinelResource 不支持 private 方法埋点

官方文档明确说明:

private 方法不支持

所以不要:

@SentinelResource(...)
private void xxx() {
}

六十九、blockHandlerClass

如果不想把处理函数都放当前类,

可以:

blockHandlerClass =
    SentinelBlockHandlers.class

七十、外部 blockHandler 一般要求 static

例如:

public class SentinelBlockHandlers {

    public static OrderVO handleOrder(
            Long id,
            BlockException ex
    ) {
        ...
    }
}

七十一、为什么推荐集中处理

如果几十个 Controller:

每个都写一套“系统繁忙”

会:

重复

可以集中:

BlockHandler

七十二、fallback 是什么

fallback:

业务执行异常时的降级处理

例如:

@SentinelResource(
    value = "queryOrder",
    blockHandler = "handleBlock",
    fallback = "fallback"
)
public OrderVO queryOrder(
        Long id
) {
    ...
}

七十三、blockHandler 和 fallback 最容易混淆

记住:

blockHandler
处理 Sentinel 主动拦截

fallback
处理业务执行异常

七十四、例如

限流:

QPS 超过

走:

blockHandler

数据库抛异常:

RuntimeException

可以走:

fallback

七十五、fallback 示例

public OrderVO fallback(
        Long id,
        Throwable ex
) {

    OrderVO vo =
            new OrderVO();

    vo.setOrderId(id);
    vo.setMessage(
        "订单服务暂时不可用"
    );

    return vo;
}

七十六、fallback 最后参数

可以:

Throwable

用于获取原异常。


七十七、不要把所有异常都静默降级

例如:

金额计算 Bug
数据库字段错误
代码 NullPointerException

如果全部返回:

“系统繁忙”

开发人员:

根本发现不了真实问题

七十八、正确

降级时:

用户得到可理解响应

同时:

日志仍然记录真实异常

七十九、什么叫熔断

如果某个资源:

持续变慢

或者:

持续大量异常

Sentinel 可以:

暂时停止继续调用

八十、为什么要熔断

下游已经:

明显不健康

继续打请求:

只会雪上加霜

八十一、熔断器状态机

最重要三个状态:

CLOSED

OPEN

HALF_OPEN

八十二、CLOSED

关闭状态:

正常放行请求

并统计:

慢调用
异常

八十三、触发规则后

进入:

OPEN

八十四、OPEN

熔断打开:

后续请求直接拒绝

不会再真正调用:

下游

八十五、经过熔断时间

进入:

HALF_OPEN

八十六、HALF_OPEN

半开状态:

放一个探测请求

如果成功:

恢复 CLOSED

如果失败:

重新 OPEN

八十七、状态机记忆图

CLOSED
正常调用
↓
达到熔断条件
↓
OPEN
快速失败
↓
等待 timeWindow
↓
HALF_OPEN
探测
├─ 成功 → CLOSED
└─ 失败 → OPEN

八十八、Sentinel 三种熔断策略

官方 1.8.x:

慢调用比例

异常比例

异常数

八十九、第一种:慢调用比例

Slow Request Ratio:

大量请求虽然没有报错
但响应特别慢

也需要熔断。


九十、为什么“没报错”也可能很危险

例如 user-service:

每个请求都最终成功

但是:

平均 20 秒

这已经足以:

拖垮整个调用链

九十一、慢调用判断

你要设:

最大允许 RT

例如:

500ms

超过:

500ms

就统计为:

慢调用

九十二、再设慢调用比例

例如:

0.5

表示:

50%

九十三、还需要最小请求数

例如:

minRequestAmount = 5

为什么?

如果只有第一个请求:

恰好慢

慢调用比例:

100%

立刻熔断:

很容易误判

所以需要:

最小样本数

九十四、还需要统计窗口

例如:

1 秒

在这个窗口内:

统计请求表现

九十五、再需要熔断时间

例如:

10 秒

进入 OPEN 后:

10 秒内快速失败

九十六、慢调用熔断实验

Provider:

Thread.sleep(2000);

配置资源:

UserClient slow resource

最大 RT:

500ms

慢调用比例:

0.5

最小请求数:

5

熔断时长:

10s

九十七、预期

连续访问:

前几个真实调用 2 秒

达到规则后:

后续请求快速失败

而不是:

每次继续等 2 秒

九十八、第二种:异常比例

Error Ratio:

异常请求数量 / 完成请求数量

达到阈值:

熔断

九十九、例如

统计 100 个请求:

60 个抛异常

异常比例:

60%

如果阈值:

50%

满足熔断条件。


一百、异常比例阈值范围

Sentinel 官方:

0.0 ~ 1.0

例如:

0.2 = 20%

0.5 = 50%

1.0 = 100%

一百零一、异常比例适合什么

例如:

第三方 API 大面积报错

数据库依赖异常

下游服务大量 500

一百零二、第三种:异常数

Error Count:

统计窗口内异常数量

超过阈值:

熔断

一百零三、异常数与异常比例区别

异常比例:

看占比

异常数:

看绝对数量

一百零四、例如

10 请求:

5 个错

比例:

50%

数量:

5

不同业务:

适合不同规则

一百零五、BlockException 会不会计入业务异常熔断

官方说明:

Sentinel 自己的 BlockException
不作为业务异常计入异常比例/异常数

因为:

它是保护行为
不是业务执行失败

一百零六、为什么这个设计合理

否则:

已经被限流的请求

又被当成:

业务失败

可能导致:

规则互相放大

一百零七、Feign + Sentinel

上一课:

order-service
↓ Feign
user-service

这正是 Sentinel 很重要的使用场景。


一百零八、开启 Feign Sentinel 支持

SCA 2025.x 官方文档要求:

feign.sentinel.enabled=true

配置:

feign:
  sentinel:
    enabled: true

一百零九、为什么要显式开启

虽然已经有:

Sentinel Starter
+
OpenFeign

但:

Feign Sentinel 适配需要开启

一百一十、Feign Fallback

@FeignClient(
    name = "user-service",
    fallback = UserClientFallback.class
)
public interface UserClient {

    @GetMapping("/users/{id}")
    UserRemoteDTO getById(
        @PathVariable("id")
        Long id
    );
}

一百一十一、Fallback 实现

@Component
public class UserClientFallback
        implements UserClient {

    @Override
    public UserRemoteDTO getById(
            Long id
    ) {

        UserRemoteDTO dto =
                new UserRemoteDTO();

        dto.setId(id);
        dto.setName(
            "用户服务暂不可用"
        );

        return dto;
    }
}

一百一十二、Feign Fallback 什么时候生效

例如:

下游调用异常

Sentinel 熔断

可以进入:

Fallback

具体异常暴露方式:

取决于当前 Feign/Sentinel 适配

一百一十三、FallbackFactory

如果你想知道:

为什么降级

比单纯 Fallback 更常用的是:

FallbackFactory

一百一十四、为什么 FallbackFactory 更好

普通 fallback:

只知道进入了降级

FallbackFactory:

能拿到 cause

方便:

日志排查

一百一十五、示意

@Component
public class UserClientFallbackFactory
        implements FallbackFactory<UserClient> {

    @Override
    public UserClient create(
            Throwable cause
    ) {

        return id -> {

            log.warn(
                "调用 user-service 失败, id={}",
                id,
                cause
            );

            UserRemoteDTO dto =
                    new UserRemoteDTO();

            dto.setId(id);
            dto.setName(
                "用户服务暂不可用"
            );

            return dto;
        };
    }
}

一百一十六、Feign Client

@FeignClient(
    name = "user-service",
    fallbackFactory =
        UserClientFallbackFactory.class
)
public interface UserClient {
    ...
}

一百一十七、课程推荐

企业排错:

优先理解 FallbackFactory

因为可以保留:

原始异常原因

一百一十八、不要在 Fallback 中做重业务

Fallback 应该:

简单
稳定
快速

不要:

再调用 5 个远程服务

否则:

降级链又可能失败

一百一十九、Fallback 示例原则

用户服务不可用:

返回最小必要信息

或者:

明确业务错误

取决于:

业务是否允许继续

一百二十、什么业务不能乱降级

例如:

支付

权限校验

库存扣减

如果失败:

不能假装成功

一百二十一、错误降级

权限服务挂了:

默认所有人都有权限

绝对危险。


一百二十二、正确

权限关键服务异常:

拒绝敏感操作

也就是:

Fail Closed

一百二十三、哪些业务可以优雅降级

例如:

推荐列表

用户头像

非核心标签

AI 说明

这些失败后:

核心流程仍可继续

一百二十四、限流返回什么

推荐:

明确错误码
+
可理解消息

例如:

{
  "code": 429,
  "message": "请求过于频繁,请稍后再试"
}

一百二十五、为什么常用 429

HTTP:

Too Many Requests

非常适合:

客户端流量过多

不过具体统一错误码:

按项目规范

一百二十六、熔断返回什么

可以:

503 Service Unavailable

或者:

业务统一错误码

关键:

调用方必须能区分

一百二十七、不要所有异常统一 200

例如:

{
  "code": 200,
  "message": "系统繁忙"
}

很混乱。

HTTP 语义和业务 code:

要有统一约定

一百二十八、Sentinel 热点参数限流

热点参数:

某个参数值特别热门

例如:

商品 id=1001

突然:

每秒几万次访问

一百二十九、普通 QPS 限流的问题

如果接口整体:

QPS 不算特别高

但是某一个商品:

特别热

我们可能只想:

限制这个参数

一百三十、热点参数限流

Sentinel 可以:

按参数值统计并限流

例如:

productId=1001
QPS ≤ 100

其他 productId
QPS ≤ 10

一百三十一、热点限流适合

热门商品

热门景点

用户 ID

热点搜索词

一百三十二、官方实现思想

Sentinel 会:

统计热点参数

并结合:

参数索引

阈值

例外项

执行限流。


一百三十三、参数索引

例如方法:

queryProduct(
    Long productId,
    String source
)

productId:

第 0 个参数

所以:

paramIdx = 0

一百三十四、热点参数规则还支持例外项

默认:

所有 productId QPS=5

但是:

productId=1001
QPS=20

可以单独配置。


一百三十五、热点参数是不是万能防刷

不是。

针对用户恶意访问:

还可能需要 Gateway 限流
Redis 计数
验证码
账号策略

Sentinel 是:

流量治理工具之一

一百三十六、系统保护

除了针对某一个资源,

Sentinel 还支持:

系统级保护

一百三十七、官方系统保护指标包括

系统 Load

CPU 使用率

入口 QPS

平均 RT

最大并发

一百三十八、系统规则只针对入口流量

官方说明:

System Rule
主要对 EntryType.IN 生效

也就是:

进入系统的流量

一百三十九、为什么系统保护存在

某一个接口:

可能都没超过自己阈值

但是整个 JVM:

CPU 95%

这时还继续全部放行:

也可能崩

一百四十、系统保护目标

不是:

让 CPU 永远很低

而是:

在系统稳定前提下保持合理吞吐

一百四十一、系统规则使用要谨慎

例如:

CPU 80%

是否应该限流,

不能:

完全拍脑袋

要结合:

机器规格
GC
业务延迟
压测数据

一百四十二、Sentinel 规则在 Dashboard 配好后会永久保存吗

默认:

不会

一百四十三、Dashboard 默认规则存哪里

Sentinel 官方 FAQ:

控制台配置规则默认存在客户端内存

所以:

应用重启
规则可能丢失

一百四十四、这就是规则持久化问题

本地学习:

Dashboard 临时规则

够用。

生产:

必须考虑持久化

一百四十五、常见持久化方式

Sentinel 支持动态数据源。

例如:

Nacos

文件

ZooKeeper

Apollo

一百四十六、我们课程最自然的方式

因为已经学了:

Nacos

所以:

Sentinel Rules
↓
Nacos

一百四十七、加入 Nacos 数据源依赖

如果当前 Starter 没有直接满足持久化适配,可以明确加入:

<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>
        sentinel-datasource-nacos
    </artifactId>
</dependency>

具体版本:

跟 Sentinel BOM/依赖树一致

不要:

自己随便指定 1.8.x

一百四十八、Spring Cloud Alibaba 数据源配置

官方 2025.x 高级指南仍支持:

spring.cloud.sentinel.datasource

例如 Nacos:

spring:
  cloud:
    sentinel:
      datasource:
        flow:
          nacos:
            server-addr: 127.0.0.1:8848
            data-id: order-service-flow-rules
            group-id: SENTINEL_GROUP
            data-type: json
            rule-type: flow

一百四十九、rule-type

官方支持的类型包括:

flow

degrade

authority

system

param-flow

gw-flow

gw-api-group

一百五十、流控规则 JSON 示例

[
  {
    "resource": "orderLimit",
    "grade": 1,
    "count": 2,
    "strategy": 0,
    "controlBehavior": 0,
    "limitApp": "default"
  }
]

一百五十一、grade 常见理解

流控:

0
并发线程数

1
QPS

一百五十二、为什么持久化后更可靠

应用启动:

主动/订阅读取 Nacos 规则

而不是:

依赖 Dashboard 内存

一百五十三、生产推模式思想

Sentinel 官方推荐配置中心场景:

配置中心
↓
Sentinel DataSource
↓
Sentinel Client

而不是只:

Dashboard
↓
Client 内存

一百五十四、为什么直接 Dashboard 改规则不够

因为默认 Dashboard:

推到客户端内存

重启:

没了

所以生产要:

改造为持久化规则源

一百五十五、课程不要现在改 Sentinel Dashboard 源码

当前阶段目标:

理解规则持久化机制

实际课程项目:

Nacos 中维护规则

已经能理解核心思想。


一百五十六、流控规则与熔断规则不要放一个 DataId 乱混

推荐:

order-service-flow-rules

order-service-degrade-rules

职责清楚。


一百五十七、例如熔断配置

spring:
  cloud:
    sentinel:
      datasource:
        degrade:
          nacos:
            server-addr: 127.0.0.1:8848
            data-id: order-service-degrade-rules
            group-id: SENTINEL_GROUP
            data-type: json
            rule-type: degrade

一百五十八、规则持久化的环境隔离

开发:

DEV_SENTINEL_GROUP

生产:

PROD_SENTINEL_GROUP

或者:

Nacos Namespace

隔离。


一百五十九、不要让开发规则打到生产

例如开发设置:

QPS=1

如果误加载到生产:

直接事故

一百六十、规则也是配置

需要:

环境隔离
权限
审计
Review

一百六十一、限流规则参数怎么理解

控制台中常见字段:

资源名

阈值类型

单机阈值

流控模式

流控效果

学习顺序:

先只学:
资源名
QPS/线程数
阈值

再学:
调用关系
Warm Up
排队等待

一百六十二、直接拒绝

默认:

超过阈值
立即拒绝

适合:

绝大多数在线接口保护

优点:

简单

响应快

不会大量堆积

一百六十三、Warm Up 冷启动

假设最终允许:

100 QPS

但是系统刚启动:

缓存还没热

JIT 还没充分优化

连接池刚建立

如果瞬间:

直接 100 QPS

可能压力很大。


一百六十四、Warm Up 的思想

刚开始
允许较少流量
↓
逐渐增加
↓
达到目标阈值

一百六十五、什么时候适合 Warm Up

例如:

秒杀开始

大促活动开始

服务刚恢复

缓存刚重建

一百六十六、匀速排队

突发:

1000 个请求

不是立即全部执行,

而是:

按较平滑速度放行

一百六十七、匀速排队的思想类似削峰

尖峰
████████████████

变成:

██
██
██
██
██

一百六十八、什么时候适合

例如:

异步任务入口

日志处理

消息消费前置整形

一百六十九、为什么不适合所有 HTTP 请求

因为排队意味着:

用户等待

如果请求时延要求很高:

快速失败

往往更合理。


一百七十、流控模式:直接

最基础:

直接根据当前资源自身统计

例如:

/order/query
QPS ≤ 100

一百七十一、关联流控

Sentinel 还支持根据:

关联资源

进行控制。

例如:

查询

和:

写入

竞争数据库资源。

如果写入压力很高:

限制查询

保护写入。


一百七十二、为什么关联流控要谨慎

它依赖:

真实资源关系

配置错:

可能无缘无故限制另一个接口

课程第一阶段:

了解即可

一百七十三、链路流控

Sentinel 能根据:

调用链入口

区分同一个资源。

例如:

入口 A
↓
commonResource

入口 B
↓
commonResource

你可能只想限制:

从 A 过来的调用

一百七十四、为什么微服务里“调用来源”重要

同一个核心服务:

可能被很多业务调用

例如用户服务:

订单服务调用

支付服务调用

后台管理调用

不同来源:

重要程度不同

一百七十五、课程先掌握直接流控

对于初学阶段:

QPS
线程数
直接流控
快速失败

已经是最重要部分。


一百七十六、三种熔断策略对比

慢调用比例
→ 没报错但太慢

异常比例
→ 错误占比太高

异常数
→ 错误绝对数量太高

一百七十七、慢调用比例参数

控制台通常需要理解:

最大 RT

比例阈值

熔断时长

最小请求数

统计时长

一百七十八、最大 RT 示例

最大 RT = 500ms

意味着:

> 500ms
算慢调用

一百七十九、比例阈值

0.5

表示:

50%

如果统计窗口中:

超过一半请求是慢调用

达到条件。


一百八十、最小请求数

5

表示:

至少先积累 5 个请求

样本数量不足:

不轻易熔断

一百八十一、统计时长

例如:

1000 ms

Sentinel 在:

这个统计窗口

观察资源表现。


一百八十二、熔断时长

例如:

10 秒

一旦 OPEN:

10 秒内快速失败

之后:

进入 HALF_OPEN 探测

一百八十三、慢调用完整例子

最大 RT:
500ms

慢调用比例:
0.5

最小请求数:
5

统计时长:
1000ms

熔断时长:
10s

如果:

1 秒内至少 5 个请求
且其中超过 50% 的 RT > 500ms

就可能:

触发熔断

一百八十四、为什么慢调用比“平均 RT”更合理

平均值可能:

被少量极端数据影响

慢调用比例:

直接关注多少请求已经超过业务可接受时间

一百八十五、异常比例完整例子

比例阈值:
0.5

最小请求数:
5

统计时长:
1000ms

熔断时长:
10s

如果:

至少 5 个请求
且业务异常比例超过 50%

触发熔断。


一百八十六、异常数完整例子

异常数:
5

最小请求数:
5

统计时长:
10000ms

熔断时长:
10s

统计窗口内:

异常数量超过阈值

触发。


一百八十七、三种策略怎么选

下游:

经常很慢

优先考虑:

慢调用比例

一百八十八、下游响应速度正常但大量报错

优先:

异常比例

一百八十九、业务需要对固定错误次数敏感

可以:

异常数

一百九十、不要同时乱配 10 条熔断规则

规则越多:

越难解释

课程建议:

一次只实验一种

看清行为后再组合。


一百九十一、HALF_OPEN 为什么重要

如果熔断后:

永远不再尝试下游

那么下游即使恢复:

也永远用不了

所以需要:

探测请求

一百九十二、探测成功

OPEN
↓
HALF_OPEN
↓
成功
↓
CLOSED

恢复正常。


一百九十三、探测失败

OPEN
↓
HALF_OPEN
↓
失败
↓
OPEN

继续保护。


一百九十四、熔断不是把服务下线

Nacos:

可能仍认为 Provider 健康

但是 Sentinel:

Consumer 这边暂时不调用这个资源

一百九十五、为什么 Nacos 健康和 Sentinel 熔断不同

Provider 进程:

活着

所以 Nacos:

健康

但业务接口:

响应 10 秒

从 Consumer 看:

不可接受

于是 Sentinel:

熔断

一百九十六、所以两者职责不同

Nacos Health
→ 实例活不活

Sentinel Circuit Breaker
→ 这个资源当前值不值得继续调用

一百九十七、BlockHandler 示例完整版

@RestController
@RequestMapping("/demo")
public class SentinelDemoController {

    @GetMapping("/order/{id}")
    @SentinelResource(
        value = "queryOrder",
        blockHandler = "queryOrderBlock"
    )
    public String queryOrder(
            @PathVariable Long id
    ) {
        return "order-" + id;
    }

    public String queryOrderBlock(
            Long id,
            BlockException ex
    ) {
        return "请求过于频繁,id="
               + id;
    }
}

一百九十八、为什么签名必须匹配

原方法:

String queryOrder(Long id)

handler:

String queryOrderBlock(
    Long id,
    BlockException ex
)

即:

原参数全部保留
+
最后 BlockException

一百九十九、错误签名

public void queryOrderBlock(
    BlockException ex
)

如果原方法返回 String:

返回类型不匹配

会出现:

Handler 找不到/调用失败

二百、外部 Block Handler

public final class GlobalSentinelHandler {

    private GlobalSentinelHandler() {
    }

    public static String handleOrder(
            Long id,
            BlockException ex
    ) {
        return "系统繁忙";
    }
}

二百零一、注解

@SentinelResource(
    value = "queryOrder",
    blockHandler = "handleOrder",
    blockHandlerClass =
        GlobalSentinelHandler.class
)

二百零二、为什么外部类方法一般 static

官方注解规范:

blockHandlerClass 指定外部类时
对应处理方法需要是 static

二百零三、Fallback 完整例子

@GetMapping("/business/{id}")
@SentinelResource(
    value = "businessQuery",
    fallback = "businessFallback"
)
public String business(
        @PathVariable Long id
) {

    if (id < 0) {
        throw new IllegalArgumentException(
            "id 非法"
        );
    }

    return "success";
}

二百零四、Fallback 方法

public String businessFallback(
        Long id,
        Throwable throwable
) {

    log.error(
        "业务异常, id={}",
        id,
        throwable
    );

    return "服务暂时不可用";
}

二百零五、哪些异常不想进入 fallback

@SentinelResource 还可以:

配置需要忽略的异常类型

例如:

exceptionsToIgnore

二百零六、为什么有用

例如:

参数校验异常

你希望:

正常返回参数错误

而不是:

统一变成降级

二百零七、不要用 fallback 掩盖程序 Bug

错误:

NullPointerException
SQLException
所有都吞掉

然后:

用户永远只看到“系统繁忙”

这会严重降低:

可观测性

二百零八、正确降级的三个目标

1. 用户获得可理解结果

2. 核心系统继续可用

3. 开发人员仍能看到真实异常

二百零九、Feign + Sentinel 实战结构

order-service
├─ controller
├─ service
├─ client
│  └─ UserClient
└─ fallback
   └─ UserClientFallbackFactory

二百一十、配置

feign:
  sentinel:
    enabled: true

二百一十一、UserClient

@FeignClient(
    name = "user-service",
    fallbackFactory =
        UserClientFallbackFactory.class
)
public interface UserClient {

    @GetMapping("/users/{id}")
    UserRemoteDTO getById(
        @PathVariable("id")
        Long id
    );
}

二百一十二、FallbackFactory

@Component
public class UserClientFallbackFactory
        implements FallbackFactory<UserClient> {

    private static final Logger log =
            LoggerFactory.getLogger(
                UserClientFallbackFactory.class
            );

    @Override
    public UserClient create(
            Throwable cause
    ) {

        return id -> {

            log.warn(
                "user-service 调用失败, id={}",
                id,
                cause
            );

            UserRemoteDTO dto =
                    new UserRemoteDTO();

            dto.setId(id);
            dto.setName(
                "未知用户"
            );

            return dto;
        };
    }
}

二百一十三、FallbackFactory 必须是 Spring Bean

所以:

@Component

或者:

@Configuration + @Bean

二百一十四、如果忘记注册

可能:

FallbackFactory 无法使用

二百一十五、什么时候返回“未知用户”是合理的

比如:

订单历史页面

用户名只是:

附加展示信息

即使用户服务暂时异常:

订单主体还能展示

二百一十六、什么时候不合理

创建订单前必须确认:

用户是否合法

如果用户服务挂了却返回:

未知用户

然后继续创建:

业务可能错误

二百一十七、所以 Fallback 必须看业务语义

不要:

看到 Feign 就全部写默认对象

二百一十八、关键校验服务的原则

如果无法确认:

权限
资金
库存
身份

通常:

宁可失败
也不要假装成功

二百一十九、热点参数实战思路

例如景点详情:

/travel/attraction/{id}

某个景点:

id=1001

突然爆火。


二百二十、我们想实现

普通景点:
每个 id QPS ≤ 5

热门 id=1001:
允许 QPS ≤ 20

这就是:

热点参数例外项

二百二十一、为什么热点限流和接口总 QPS 不冲突

接口总限流:

保护整个资源

热点限流:

保护某些参数值

可以根据实际业务:

组合

二百二十二、参数必须真正进入 Sentinel 资源上下文

热点参数限流依赖:

Sentinel 能看到资源参数

如果只配置规则但资源埋点:

没有参数

规则不会按预期工作。


二百二十三、@SentinelResource 热点规则测试

不同 Web 自动资源和:

@SentinelResource

参数传递行为需要区分。

课程建议热点参数实验:

明确使用 @SentinelResource

然后在 Dashboard:

观察资源

不要凭空猜资源名。


二百二十四、为什么强调“看 Dashboard 实际资源名”

Sentinel 集成不同组件:

Web

Feign

RestTemplate

生成的资源命名:

可能不同

规则一定要:

绑到真实资源名

二百二十五、不要在网上抄某个资源名格式

更可靠:

启动应用
访问一次
打开 Dashboard
看实际资源

二百二十六、系统规则实战

如果只是本地学习:

不要一开始改 CPU 规则

可以先理解:

全局入口 QPS

二百二十七、为什么系统规则风险更大

它不是:

保护单一接口

而是可能影响:

整个应用入口

配置错误:

整个服务都被限

二百二十八、规则上线顺序

企业里建议:

先压测

找容量

小阈值灰度验证

观察指标

再正式应用

二百二十九、限流阈值不能拍脑袋

错误:

我觉得 100 QPS 差不多

正确:

压测得到系统容量

二百三十、容量评估至少看

CPU

内存

GC

P95 RT

P99 RT

错误率

线程池

数据库连接

下游能力

二百三十一、为什么限流阈值要低于极限容量

系统压测极限:

1000 QPS

生产阈值直接:

1000

几乎没有:

安全余量

二百三十二、应该保留安全边际

具体比例:

根据业务和压测

而不是死记:

80%

二百三十三、Sentinel 与线程池隔离

Sentinel 的线程数流控:

更接近信号量隔离

不会自动为每个资源:

创建独立线程池

二百三十四、为什么这样更轻量

独立线程池:

需要更多线程

上下文切换成本更高

并发数流控:

直接限制同时进入资源的线程数

二百三十五、Sentinel 和线程池并不互斥

有些系统:

仍然会用专用线程池做隔离

Sentinel:

负责流控/熔断

根据架构:

可以组合

二百三十六、Sentinel 和超时的关系

熔断不能替代:

HTTP 超时

二百三十七、为什么

熔断器需要:

先观察慢调用/异常

如果一个请求完全卡住且:

没有超时

它自己仍会一直占资源。


二百三十八、正确组合

Feign Timeout
+
Sentinel Circuit Breaker

二百三十九、Timeout 解决

单次调用最多等多久

二百四十、Circuit Breaker 解决

下游持续不好时
未来一段时间别再继续试

二百四十一、限流、超时、熔断完整关系

限流
→ 控制进来多少请求

超时
→ 单次最多等多久

熔断
→ 持续不健康时暂时切断

三者:

互相补充

二百四十二、重试也要放进这个关系

失败
↓
是否重试

重试会:

增加下游压力

所以和熔断:

必须一起考虑

二百四十三、错误做法

readTimeout = 30s
重试 5 次
无熔断

一个请求最坏:

可能等待非常久

二百四十四、正确思维

合理 timeout

少量且有条件 retry

Sentinel 熔断

业务 fallback

二百四十五、规则持久化的两个方向

简单理解:

Dashboard → Client

是:

临时内存规则

而:

Config Center → Client

更适合:

持久规则

二百四十六、官方对 push 模式的建议

对于 Nacos 这种配置中心:

规则应由配置中心作为真实数据源

客户端:

订阅变化

二百四十七、为什么不是“客户端再写回 Nacos”

Nacos DataSource 对这类 push 模式:

主要是读取/订阅

生产控制台如果要:

直接编辑 Nacos

需要:

对 Dashboard 做相应改造

二百四十八、课程阶段怎么做最合理

Dashboard
→ 用于观察、临时实验

Nacos
→ 用于理解/保存规则

不用现在:

二次开发 Sentinel Dashboard

二百四十九、Nacos 持久化 Flow Rule

spring:
  cloud:
    sentinel:
      datasource:
        flow:
          nacos:
            server-addr: 127.0.0.1:8848
            group-id: SENTINEL_GROUP
            data-id: order-service-flow-rules
            data-type: json
            rule-type: flow

二百五十、Nacos JSON

[
  {
    "resource": "orderLimit",
    "limitApp": "default",
    "grade": 1,
    "count": 5,
    "strategy": 0,
    "controlBehavior": 0,
    "clusterMode": false
  }
]

二百五十一、为什么 resource 必须完全一致

如果代码:

orderLimit

配置:

order-limit

那么:

规则不会命中

二百五十二、规则变化后

Nacos:

发布新配置

客户端数据源:

接收变化

然后:

更新 Sentinel 规则

二百五十三、怎么确认规则生效

不要只:

看 Nacos 有 JSON

还要:

实际请求压测

或者:

查看 Sentinel Endpoint / Dashboard

确认客户端:

真的加载

二百五十四、Sentinel Endpoint

SCA 提供:

sentinel Endpoint

可以暴露:

当前规则

日志目录

Dashboard 地址

客户端端口

Datasource

二百五十五、通常需要 Actuator

例如:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>
        spring-boot-starter-actuator
    </artifactId>
</dependency>

二百五十六、暴露 Endpoint 要注意安全

生产:

不要无脑 management.endpoints.web.exposure.include=*

因为会:

暴露过多运行信息

二百五十七、本地调试可以临时开放

生产:

最小暴露
+
网络/认证保护

二百五十八、Dashboard 规则为什么应用重启丢

流程:

Dashboard
↓
推送到 Client
↓
Client 内存 RuleManager

没有:

持久存储

所以重启:

内存清空

二百五十九、这道面试题很常见

问:

Sentinel Dashboard 配的规则为什么重启丢?

答:

默认规则存于客户端内存,
Dashboard 默认不提供持久化规则源。
生产需要配置 Nacos 等动态数据源。

二百六十、Sentinel Dashboard 是否适合直接生产

官方明确提醒:

默认 Dashboard 更偏功能全集示例

生产需要:

定制与改造

尤其:

认证
规则持久化
权限
高可用

二百六十一、为什么 Dashboard 本身也是单点

官方 Dashboard:

默认仅支持单机部署

所以不能:

把它当成天然高可用控制中心

二百六十二、但 Client 规则执行不依赖每次请求都访问 Dashboard

规则加载到:

本地 Client

请求判断:

在本地执行

这点很重要。


二百六十三、为什么本地执行性能好

每一个请求如果都:

远程问 Dashboard

性能:

会很差

Sentinel:

统计和规则判断主要在应用进程内完成

二百六十四、这也是为什么 Dashboard 短暂不可用

已经加载的规则:

通常仍可在客户端继续执行

二百六十五、Sentinel 日志

遇到问题:

不要只看业务日志

还可以检查 Sentinel 日志目录。


二百六十六、常见问题 1:Dashboard 看不到应用

排查:

Starter 是否加入

Dashboard 地址

应用有没有实际流量

客户端和 Dashboard 网络

transport port

应用日志

二百六十七、常见问题 2:看得到应用但没有资源

先:

访问目标接口

Sentinel:

只有被访问/埋点的资源
才会产生统计

二百六十八、问题 3:配置了 QPS=1 但没限流

检查:

资源名是否一致

请求频率是否真的超过

规则是否下发到正确机器

是否在正确应用

是否规则已经丢失

二百六十九、问题 4:@SentinelResource 不生效

检查:

Sentinel Starter

注解切面是否正常

方法是否 private

是否通过 Spring Bean 调用

资源是否真的访问

二百七十、AOP 自调用问题要警惕

如果某些代理能力依赖:

Spring AOP

同类:

this.someMethod();

可能绕过代理。

课程里你已经学过:

Spring AOP 自调用

这里继续保持警惕。


二百七十一、问题 5:blockHandler 找不到

检查:

方法名

返回类型

原参数

最后 BlockException

public

外部类是否 static

二百七十二、问题 6:fallback 不执行

检查:

异常是否被代码自己 catch 掉

exceptionsToIgnore

方法签名

异常类型

二百七十三、错误示例

try {
    throw new RuntimeException();
} catch (Exception e) {
    return "error";
}

对于 Sentinel 来说:

方法正常 return

可能根本:

看不到这个业务异常

二百七十四、为什么异常不要乱吞

熔断器需要:

真实异常统计

如果你全部:

catch 后当成功返回

监控就:

失真

二百七十五、问题 7:异常比例一直是 0

重点检查:

业务异常是否真正传播/被 Sentinel 记录

不要:

所有异常都在最里面 catch 掉

二百七十六、问题 8:Feign Fallback 不生效

检查:

feign.sentinel.enabled=true

Sentinel Starter

Fallback Bean

@FeignClient fallback/fallbackFactory

OpenFeign Starter

二百七十七、问题 9:Feign 还是等待很久

因为:

Sentinel 熔断
不能替代超时

检查:

connectTimeout

readTimeout

二百七十八、问题 10:Nacos 规则不加载

检查:

sentinel datasource Nacos 依赖

server-addr

data-id

group-id

rule-type

JSON 格式

resource

二百七十九、问题 11:Dashboard 改规则后 Nacos 没变化

这在默认模式:

是正常现象

因为:

Dashboard → Client 内存

不会自动:

反向写入 Nacos

二百八十、问题 12:应用重启规则没了

如果规则只是:

Dashboard 临时创建

这是:

默认行为

要:

配置动态数据源持久化

二百八十一、问题 13:系统规则一配整个服务都访问不了

系统规则:

影响范围大

检查:

阈值是否过低

测试环境机器指标

入口规则

二百八十二、问题 14:热点参数规则不生效

检查:

资源埋点是否携带参数

paramIdx 是否正确

参数类型

资源名

热点规则依赖

二百八十三、问题 15:多个实例规则不一致

Dashboard:

可能按机器看到规则

如果没有统一数据源:

实例之间可能状态不一致

生产:

用统一配置中心

更合理。


二百八十四、Sentinel 和 Nacos 配合图

                  Nacos
                    │
          Sentinel Rule JSON
                    │
                    ▼
              DataSource
                    │
                    ▼
          Sentinel RuleManager
                    │
                    ▼
             order-service
                    │
      ┌─────────────┴─────────────┐
      ▼                           ▼
   FlowRule                  DegradeRule
   限流                         熔断

二百八十五、完整微服务调用保护图

Client
↓
Gateway
↓
order-service
│
├─ Sentinel:
│  限流
│  熔断
│  降级
│
↓
Feign
↓
LoadBalancer
↓
Nacos
↓
user-service

二百八十六、为什么下一课 Gateway 也会用 Sentinel

因为 Gateway 是:

统一入口

特别适合:

入口流量控制

下一课会先学 Gateway 本身。

后续你会看到:

Sentinel Gateway Adapter

二百八十七、Sentinel 与 Gateway 限流的区别

业务服务 Sentinel:

保护具体服务/资源

Gateway 限流:

在统一入口更早挡掉流量

二百八十八、为什么最好多层防护

恶意流量如果已经:

进入所有内部服务

才限流,

成本:

已经发生

Gateway:

可提前挡

业务服务:

再做第二层保护

二百八十九、但是不要所有层设置互相矛盾阈值

例如:

Gateway 100 QPS

Service 1000 QPS

可能合理。

但如果:

Gateway 1000

Service 10

真实业务可能:

大量请求在内部才被拒

需要:

统一容量设计

二百九十、AI 服务为什么特别适合 Sentinel

AI 调用通常:

响应慢

成本高

并发有限

第三方容易抖动

二百九十一、AI 限流

例如模型账户:

最大 20 QPS

Java AI Service:

必须保护

否则:

大量 429

费用不可控

二百九十二、AI 并发限制

每个 AI 请求:

可能 10 秒

即使 QPS 不高:

并发连接也可能很高

因此:

并发数保护

很重要。


二百九十三、AI 熔断

第三方模型:

连续 timeout

继续每次等待 10 秒:

没有意义

可以:

熔断

二百九十四、AI Fallback

模型不可用:

返回普通搜索结果

而不是:

整个旅行搜索失败

二百九十五、但 AI Fallback 不能伪造核心事实

例如:

酒店价格

AI 服务挂了:

不能随便生成一个价格

应该:

查数据库/真实 API
或者明确暂不可用

二百九十六、限流不是为了“拒绝用户”

真正目的:

牺牲少量请求
保护整体系统

二百九十七、为什么 100% 接受请求反而可能更差

系统最大:

1000 QPS

来了:

5000 QPS

如果全部接受:

可能 5000 个都超时

二百九十八、如果限流到 900

可能:

900 个稳定成功

其余快速失败

整体:

反而更可控

二百九十九、这是稳定性工程重要思维

不是保证每个请求成功
而是保证系统持续可用

三百、Sentinel 和缓存关系

如果热点查询:

非常多

Sentinel 可以:

限流

Redis 可以:

降低数据库压力

两者:

不是替代关系

三百零一、Sentinel 和 MQ 关系

Sentinel:

控制实时流量

MQ:

异步削峰

如果业务允许异步:

MQ 可能比直接拒绝更好

三百零二、例如日志任务

瞬间:

10 万任务

不是:

全部拒绝

而是:

进入 MQ
慢慢消费

三百零三、架构选择要看业务

实时 API:

限流快速失败

异步任务:

MQ 削峰

三百零四、Sentinel 和 Redis 分布式限流

Redis 可以实现:

全局分布式计数

Sentinel 单机规则:

通常以实例维度统计

三百零五、为什么多实例需要理解“单机阈值”

假设:

3 个实例

每个:

QPS 100

整体理论可通过:

约 300 QPS

前提:

流量较均匀

三百零六、如果业务需要整个集群统一限流

这属于:

集群流控/网关全局限流

比单机流控:

更复杂

三百零七、课程先掌握单机规则

因为:

理解资源和规则

是后续集群流控基础。


三百零八、压测工具

本地可以使用:

JMeter

Apache Bench

wrk

Postman Runner

三百零九、最简单也可以写脚本

例如 PowerShell 并发请求。

但学习阶段:

JMeter

更直观。


三百一十、QPS 限流测试要注意

如果你:

手点浏览器

通常:

根本达不到 QPS 阈值

然后误以为:

Sentinel 不生效

三百一十一、所以要真正产生并发/频率

例如:

JMeter 20 线程

或快速请求。


三百一十二、慢调用测试同样要满足最小请求数

你只请求:

1 次

可能:

不会触发熔断

因为:

minRequestAmount

还没达到。


三百一十三、为什么学习 Sentinel 必须看规则参数

如果只会:

点控制台

不知道:

统计窗口
最小请求数
比例

就很难解释:

为什么没触发

三百一十四、Cursor 提示词:接入 Sentinel

当前项目:
Spring Boot 3.5.x
Spring Cloud 2025.0.x
Spring Cloud Alibaba 2025.0.x
JDK17

order-service 通过 OpenFeign 调用 user-service。

请先分析 pom.xml,不修改。

然后给出最小 Sentinel 接入方案:
1. 使用 spring-cloud-starter-alibaba-sentinel
2. 版本交给 SCA BOM
3. 配置 Sentinel Dashboard
4. 保留当前 Nacos/Feign 配置
5. 不引入旧 Hystrix
6. 不手工覆盖 Sentinel Client 版本

三百一十五、Cursor 提示词:制造慢调用

请在 user-service 增加一个只用于学习的慢接口:

GET /users/slow/{id}

要求:
1. sleep 2000ms
2. 返回当前实例端口
3. order-service 用 Feign 调用
4. 不加 Sentinel 规则
5. 先让我观察并发请求时上游等待现象

三百一十六、Cursor 提示词:QPS 限流

请为 order-service 创建一个明确的 Sentinel 资源:

orderLimit

要求:
1. 使用 @SentinelResource
2. 提供 blockHandler
3. blockHandler 返回明确的“请求过于频繁”
4. 方法签名严格符合 Sentinel 规范
5. 告诉我在 Dashboard 中如何配置 QPS=2
6. 给出 JMeter 验证步骤

三百一十七、Cursor 提示词:线程数限流

请创建 slowOrder 资源。

要求:
1. 每个请求 sleep 3000ms
2. Sentinel 使用并发线程数限流
3. 并发阈值设置为 2
4. 同时发起 5 个请求
5. 解释为什么线程数限流比 QPS 更适合这个实验

三百一十八、Cursor 提示词:熔断

请为 user-service 的慢调用设计 Sentinel 熔断实验。

分别给我三套独立实验:
1. 慢调用比例
2. 异常比例
3. 异常数

每次只启用一套规则。

请解释:
最大 RT
比例阈值
最小请求数
统计时长
熔断时长
CLOSED / OPEN / HALF_OPEN

不要一次创建很多互相影响的规则。

三百一十九、Cursor 提示词:Feign + Sentinel

请检查 order-service 的 OpenFeign + Sentinel 集成。

要求:
1. 检查 Sentinel Starter
2. 检查 feign.sentinel.enabled=true
3. UserClient 使用 fallbackFactory
4. FallbackFactory 是 Spring Bean
5. 记录原始 cause
6. 降级函数不能再调用其他复杂远程服务
7. 关键权限/支付类调用失败时不要返回假成功

三百二十、Cursor 提示词:blockHandler/fallback 审查

请审查所有 @SentinelResource。

重点检查:
1. blockHandler 与 fallback 是否混淆
2. blockHandler 参数是否为原参数 + BlockException
3. 返回类型是否一致
4. 外部 Handler 是否 static
5. 方法是否 private
6. fallback 是否吞掉严重程序 Bug
7. 是否保留异常日志
8. exceptionsToIgnore 是否合理

三百二十一、Cursor 提示词:规则持久化

请给当前 Spring Cloud Alibaba 项目设计 Sentinel + Nacos 规则持久化。

要求:
1. 使用 spring.cloud.sentinel.datasource
2. 流控规则和熔断规则分不同 DataId
3. data-type=json
4. rule-type 正确
5. 使用 Nacos Group/Namespace 隔离环境
6. 说明 Dashboard 默认规则为什么重启丢失
7. 不声称默认 Dashboard 会自动把规则写入 Nacos
8. 不修改 Sentinel Dashboard 源码

三百二十二、Cursor 提示词:Sentinel 不生效排查

Sentinel 规则看起来没有生效。

请按下面顺序检查:
1. Starter
2. Dashboard 地址
3. 应用是否产生资源访问
4. 实际 resource 名称
5. Dashboard 规则是否作用到正确应用/机器
6. @SentinelResource 方法是否 private
7. blockHandler 签名
8. Feign 是否开启 sentinel
9. 熔断最小请求数是否达到
10. Nacos DataId/Group/rule-type
11. 是否有异常被 catch 吞掉

先定位,不改代码。

三百二十三、面试题 1:Sentinel 是什么

答:

Sentinel 是面向分布式系统的流量治理组件。

它以资源为核心,通过运行时统计和规则判断,
提供流量控制、熔断降级、系统保护和热点参数限流等能力,
用于避免突发流量或下游不稳定导致系统雪崩。

三百二十四、面试题 2:Sentinel 的资源是什么

答:

资源是 Sentinel 保护和统计的基本单位。

一个 URL、Java 方法、远程调用或一段代码都可以定义为资源。

流控、熔断等规则最终都必须作用于具体资源。

三百二十五、面试题 3:QPS 限流与线程数限流区别

答:

QPS 限流关注单位时间进入资源的请求数量,
适合控制请求速率。

线程数限流关注当前正在处理资源的并发线程数量,
适合保护耗时较长的慢资源,防止线程大量占用。

三百二十六、面试题 4:什么是熔断

答:

当下游资源持续变慢或大量异常时,
熔断器会暂时阻止后续请求继续访问该资源,
让调用快速失败。

这样可以避免上游线程持续等待,
防止故障沿调用链扩大。

三百二十七、面试题 5:熔断器三个状态

答:

CLOSED 状态正常调用并统计资源。

满足熔断条件后进入 OPEN,
一段时间内快速拒绝请求。

熔断时间结束后进入 HALF_OPEN,
放入探测请求。

探测成功恢复 CLOSED,
失败则重新 OPEN。

三百二十八、面试题 6:Sentinel 有哪些熔断策略

答:

Sentinel 1.8.x 主要支持:

慢调用比例、
异常比例、
异常数。

慢调用比例关注超过最大 RT 的请求占比,
异常比例关注业务异常占比,
异常数关注统计窗口中的异常绝对数量。

三百二十九、面试题 7:为什么需要最小请求数

答:

如果样本太少,
例如第一个请求刚好失败,
异常比例就可能达到 100%。

直接熔断容易误判。

最小请求数用于保证达到一定统计样本后,
才根据慢调用或异常情况判断是否熔断。

三百三十、面试题 8:blockHandler 和 fallback 区别

答:

blockHandler 用来处理 Sentinel 规则主动阻止的请求,
例如限流、熔断等产生的 BlockException。

fallback 主要用于业务方法执行过程中产生的异常降级。

两者处理的异常来源不同。

三百三十一、面试题 9:为什么 BlockException 不算业务异常

答:

BlockException 表示 Sentinel 为保护系统主动拦截请求,
并不是业务代码自身执行失败。

如果把这种保护行为再次统计为业务异常,
可能干扰异常比例和异常数熔断判断。

三百三十二、面试题 10:Sentinel 与 Feign 怎么配合

答:

Spring Cloud Alibaba Sentinel 可以适配 OpenFeign。

开启 feign.sentinel.enabled=true 后,
Feign 调用可以纳入 Sentinel 保护,
并通过 fallback 或 fallbackFactory 提供降级处理。

fallbackFactory 还能保留原始异常原因,方便排查。

三百三十三、面试题 11:Fallback 是否越多越好

答:

不是。

Fallback 应该根据业务语义设计。

推荐、头像等非核心能力失败可以提供默认结果,
但支付、权限、库存等关键校验失败时不能返回假成功。

降级的目标是保证核心业务正确,而不是把所有异常隐藏。

三百三十四、面试题 12:Sentinel 和超时什么关系

答:

超时控制的是一次远程调用最多等待多久。

Sentinel 熔断控制的是下游持续不健康时,
未来一段时间是否继续调用。

两者不能互相替代,
实际项目通常需要组合使用。

三百三十五、面试题 13:Sentinel 和 Nacos 区别

答:

Nacos 主要负责服务注册发现和配置管理。

Sentinel 主要负责限流、熔断降级和系统保护。

可以理解为:
Nacos 解决“服务在哪里”,
Sentinel 解决“服务怎么安全稳定地被调用”。

三百三十六、面试题 14:Dashboard 规则为什么重启丢

答:

Sentinel Dashboard 默认把规则推送到客户端内存。

客户端重启后内存规则会丢失。

生产需要使用 Nacos 等动态数据源作为规则配置中心,
让应用启动后重新加载持久规则。

三百三十七、面试题 15:Nacos 规则数据源是什么模式

答:

Nacos 这类配置中心一般作为 push 模式的规则数据源。

客户端订阅配置中心的规则变化,
再更新本地 Sentinel RuleManager。

配置中心应该成为规则真实来源,
而不是依赖客户端内存保存。

三百三十八、面试题 16:什么是热点参数限流

答:

热点参数限流是针对资源中的某个参数值进行流量控制。

例如商品详情接口中,
商品 id=1001 特别热门,
可以只针对该热点 id 设置单独 QPS 阈值,
而不必完全限制整个接口。

三百三十九、面试题 17:什么是系统保护

答:

系统保护不是只看单个业务资源,
而是根据系统整体指标保护入口流量。

Sentinel 可根据系统 Load、CPU 使用率、
入口 QPS、平均 RT、最大并发等指标执行系统级保护。

三百四十、面试题 18:为什么限流阈值不能拍脑袋

答:

真正安全阈值应该通过压测和生产指标确定。

需要观察 CPU、内存、GC、P95/P99 响应时间、
错误率、线程池、数据库和下游容量。

如果只凭感觉配置,
可能过低浪费能力,也可能过高导致系统失稳。

三百四十一、面试题 19:Sentinel 与 Redis 限流区别

答:

Sentinel 更偏应用资源级流量治理,
可以在本地快速完成 QPS、并发和熔断判断。

Redis 可以实现基于共享存储的分布式计数和业务级限流。

实际项目需要根据是否要求集群全局一致限流、
限流维度和架构成本选择。

三百四十二、面试题 20:Sentinel 最大价值是什么

答:

Sentinel 的核心价值不是简单“拒绝请求”,
而是在流量过大或依赖不稳定时主动牺牲部分非必要请求,
保护线程、连接和系统整体容量,
避免局部问题演变成全链路雪崩。

三百四十三、本章知识树

Sentinel
│
├─ Resource
│  ├─ URL
│  ├─ Method
│  ├─ Feign
│  └─ @SentinelResource
│
├─ Flow Control
│  ├─ QPS
│  ├─ Thread Count
│  ├─ Direct Reject
│  ├─ Warm Up
│  └─ Rate Limiter
│
├─ Circuit Breaker
│  ├─ CLOSED
│  ├─ OPEN
│  ├─ HALF_OPEN
│  ├─ Slow Request Ratio
│  ├─ Error Ratio
│  └─ Error Count
│
├─ Handler
│  ├─ BlockException
│  ├─ blockHandler
│  ├─ blockHandlerClass
│  ├─ fallback
│  └─ FallbackFactory
│
├─ Feign
│  ├─ feign.sentinel.enabled
│  ├─ fallback
│  └─ fallbackFactory
│
├─ Advanced
│  ├─ Hot Parameter
│  ├─ System Rule
│  └─ Call Path
│
├─ Dashboard
│  ├─ Metrics
│  ├─ Rule
│  ├─ Port 8719
│  └─ Authentication
│
├─ Persistence
│  ├─ Nacos DataSource
│  ├─ flow
│  ├─ degrade
│  └─ param-flow
│
└─ Reliability
   ├─ Timeout
   ├─ Retry
   ├─ Idempotency
   ├─ Rate Limit
   ├─ Circuit Breaker
   └─ Fallback

三百四十四、最重要关系图

请求太多
↓
Flow Control
↓
限流

请求太慢 / 错太多
↓
Circuit Breaker
↓
熔断

被 Sentinel 拦截
↓
BlockException
↓
blockHandler

业务代码异常
↓
fallback

Feign 下游失败
↓
fallbackFactory

三百四十五、最重要的 20 条原则

1. Sentinel 保护的是资源,不是抽象概念

2. 限流和熔断不是一回事

3. QPS 控制请求速率

4. 线程数控制资源并发占用

5. 慢接口不能只看 QPS

6. 熔断器有 CLOSED、OPEN、HALF_OPEN

7. 慢调用比例关注 RT 超标占比

8. 异常比例关注业务错误占比

9. 异常数关注错误绝对数量

10. 最小请求数用于减少小样本误判

11. BlockException 是保护异常,不是普通业务异常

12. blockHandler 专门处理 Sentinel Block

13. fallback 处理业务执行异常

14. Fallback 不能把关键业务伪装成成功

15. Feign Sentinel 要显式检查是否开启

16. Timeout、Retry、Circuit Breaker 必须组合思考

17. Dashboard 默认规则不是持久化规则

18. 生产规则应该有统一配置源和环境隔离

19. 阈值必须由压测和指标支撑

20. Sentinel 的目标是保护整体可用性,不是追求所有请求都被接受

三百四十六、本章最终验收

学完以后,你应该可以独立回答和完成:

1. Sentinel 是什么

2. Sentinel 为什么存在

3. 什么叫资源

4. @SentinelResource 怎么用

5. Dashboard 怎么启动

6. Client 怎么连接 Dashboard

7. 8719 是什么

8. 为什么 Dashboard 看不到应用

9. 什么是 QPS 限流

10. 什么是线程数限流

11. QPS 和线程数怎么选

12. 什么是快速失败

13. 什么是 Warm Up

14. 什么是匀速排队

15. 什么是 BlockException

16. blockHandler 怎么写

17. blockHandlerClass 怎么写

18. fallback 怎么写

19. blockHandler 和 fallback 区别

20. 什么是熔断

21. CLOSED / OPEN / HALF_OPEN

22. 什么是慢调用比例

23. 什么是最大 RT

24. 什么是异常比例

25. 什么是异常数

26. 什么是最小请求数

27. 什么是统计时长

28. 什么是熔断时长

29. Feign 怎么接 Sentinel

30. feign.sentinel.enabled 是什么

31. fallback 和 fallbackFactory 区别

32. 什么业务可以降级

33. 什么业务不能假成功

34. 什么是热点参数限流

35. paramIdx 是什么

36. 什么是系统保护

37. Dashboard 规则为什么重启丢

38. Nacos DataSource 怎么做规则持久化

39. rule-type 有哪些

40. Sentinel 与 Nacos、Feign、Timeout 的关系

三百四十七、下一课

按照课程表,下一篇进入:

《Spring Cloud Alibaba:Gateway 详解》

下一课会解决:

现在已经有:
user-service
order-service

前端到底该访问谁?

我们会从:

前端直接访问多个服务

开始,

一步一步改造成:

Client
↓
Spring Cloud Gateway
├─ /user/**  → user-service
└─ /order/** → order-service

继续学习:

Route

Predicate

Filter

lb:// 服务名

Nacos Discovery

Path Predicate

Method Predicate

Header Predicate

Query Predicate

StripPrefix

AddRequestHeader

GlobalFilter

自定义 Filter

Filter 顺序

CORS

统一鉴权

JWT

白名单

限流入口

Gateway + Sentinel

也就是从:

服务内部治理

正式进入:

微服务统一入口治理

阶段。