SpringCloud Alibaba 核心组件解析:服务熔断和降级

SpringCloud Alibaba 核心组件解析:服务熔断与降级(Sentinel)

技术栈 :Spring Boot 3.2.0 + Spring Cloud Alibaba 2023.0.0.0-RC1 + Sentinel + Nacos


4.1 是什么 --- Sentinel 定位与核心能力

4.1.1 一句话定义

Sentinel = 流量控制 + 熔断降级 + 系统负载保护 的高可用防护组件。阿里双十一核心链路验证。

4.1.2 生活化类比:景区限流

复制代码
景区最大承载 5000 人:
  → 到达 4500 人:预警,减缓入园
  → 到达 5000 人:停止售票(限流)
  → 某个游乐设施排队超过 2 小时:引导去别的项目(降级)
  → VIP 通道:特殊游客不受限制(授权规则)

4.1.3 四大核心能力

能力 说明 类比
流量控制 QPS/并发线程数超阈值时拒绝 景区限流
熔断降级 慢调用/异常比例过高时快速失败 游乐设施排队太久关闭
热点参数 对某个参数值精细化限流 热门项目单独限流
授权规则 白名单/黑名单控制来源 VIP 通道

4.2 为什么 --- Sentinel vs Hystrix vs Resilience4J

4.2.1 控制台对比

能力 Sentinel Hystrix Resilience4J
实时监控 ✅ 秒级 Dashboard(废弃)
规则热更新 ✅ 控制台实时下发 ❌(需重启)
规则持久化 ✅ Nacos/Apollo/Redis
链路追踪 ✅ 自带
Spring Cloud @SentinelResource @HystrixCommand @CircuitBreaker

4.2.2 选择建议

复制代码
小项目:Resilience4J(够用,零运维)
中等规模:Sentinel(有控制台,好排查)
阿里生态/大流量:Sentinel(唯一选择)

4.3 怎么做 --- Sentinel 完整实战

4.3.0 启动控制台

bash 复制代码
java -Dserver.port=8080 -jar sentinel-dashboard-1.8.6.jar
# 访问 http://localhost:8080  账号/密码:sentinel/sentinel

4.3.1 项目模块

模块 端口 说明
cloudalibaba-sentinel-service8401 8401 Sentinel 完整功能演示
clooudalibaba-sentinel-gateway9528 9528 Sentinel + Gateway 整合(见第 6 章)

4.3.2 步骤 ①:依赖与配置

xml 复制代码
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
yaml 复制代码
server:
  port: 8401

spring:
  application:
    name: cloudalibaba-sentinel-service
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
    sentinel:
      transport:
        dashboard: localhost:8080
        port: 8719
      web-context-unify: false   # 关闭 URL 收敛
      datasource:                # 规则持久化到 Nacos
        ds1:
          nacos:
            server-addr: localhost:8848
            dataId: ${spring.application.name}
            groupId: DEFAULT_GROUP
            data-type: json
            rule-type: flow

4.3.3 步骤 ②:流控 --- 直接模式

java 复制代码
@RestController
public class FlowLimitController {

    @GetMapping("/testA")
    public String testA() {
        return "------testA";
    }

    @GetMapping("/testB")
    public String testB() {
        return "------testB";
    }
}

控制台 → 簇点链路 → 对 /testA 新增流控规则 → QPS=1 → 快速刷新 → 触发限流返回 Blocked by Sentinel

三种流控效果

效果 说明 场景
快速失败 直接拒绝(默认) 保护系统不被冲垮
Warm Up 预热/冷启动,逐步放开 QPS 缓存预热、新实例上线
排队等待 匀速排队,超时才拒绝 消息队列削峰填谷

4.3.4 步骤 ③:流控 --- 链路模式

java 复制代码
// 公共 Service
@Service
public class FlowLimitService {
    @SentinelResource(value = "common")
    public void common() {
        System.out.println("------FlowLimitService come in");
    }
}

// Controller
@RestController
public class FlowLimitController {
    @Resource
    private FlowLimitService flowLimitService;

    @GetMapping("/testC")
    public String testC() {
        flowLimitService.common();
        return "------testC";
    }

    @GetMapping("/testD")
    public String testD() {
        flowLimitService.common();
        return "------testD";
    }
}

common 资源设链路流控,入口资源填 testC → 则 /testC 限流,/testD 不受影响。

4.3.5 步骤 ④:熔断 --- 三种策略

java 复制代码
// 慢调用比例
@GetMapping("/testF")
public String testF() {
    try { TimeUnit.SECONDS.sleep(1); }
    catch (InterruptedException e) { e.printStackTrace(); }
    return "------testF 慢调用比例";
}

// 异常比例
@GetMapping("/testG")
public String testG() {
    int age = 10 / 0;  // ← 触达异常
    return "------testG";
}

// 异常数
@GetMapping("/testH")
public String testH() {
    int age = 10 / 0;  // ← 触达异常
    return "------testH";
}

4.3.6 步骤 ⑤:@SentinelResource --- blockHandler vs fallback

java 复制代码
@RestController
@Slf4j
public class RateLimitController {

    // 按资源名限流
    @GetMapping("/rateLimit/byResource")
    @SentinelResource(value = "byResourceSentinelResource",
                      blockHandler = "handleException")
    public String byResource() {
        return "按资源名称SentinelResource限流测试OK";
    }
    public String handleException(BlockException exception) {
        return "服务不可用@SentinelResource启动 o(╥﹏╥)o";
    }

    // blockHandler + fallback 同时使用
    @GetMapping("/rateLimit/doAction/{p1}")
    @SentinelResource(value = "doActionSentinelResource",
            blockHandler = "doActionBlockHandler",
            fallback = "doActionFallback")
    public String doAction(@PathVariable("p1") Integer p1) {
        if (p1 == 0) throw new RuntimeException("p1等于零直接异常");
        return "doAction";
    }

    public String doActionBlockHandler(@PathVariable("p1") Integer p1,
                                        BlockException e) {
        log.error("sentinel配置自定义限流了:{}", e);
        return "sentinel配置自定义限流了";
    }
    public String doActionFallback(@PathVariable("p1") Integer p1,
                                    Throwable e) {
        log.error("程序逻辑异常了:{}", e);
        return "程序逻辑异常了" + "\t" + e.getMessage();
    }

    // 热点参数限流
    @GetMapping("/testHotKey")
    @SentinelResource(value = "testHotKey",
                      blockHandler = "dealHandler_testHotKey")
    public String testHotKey(
            @RequestParam(value = "p1", required = false) String p1,
            @RequestParam(value = "p2", required = false) String p2) {
        return "------testHotKey";
    }
    public String dealHandler_testHotKey(String p1, String p2,
                                          BlockException exception) {
        return "-----dealHandler_testHotKey";
    }
}

blockHandler vs fallback 对比

blockHandler fallback
触发条件 Sentinel 规则(流控/降级/热点) 业务运行时异常
方法签名 (参数, BlockException) (参数, Throwable)
谁调用 Sentinel 框架 你的代码

4.3.7 步骤 ⑥:授权规则 + 来源解析

java 复制代码
// 自定义来源解析器
@Component
public class MyRequestOriginParser implements RequestOriginParser {
    @Override
    public String parseOrigin(HttpServletRequest request) {
        return request.getParameter("serverName");
    }
}

// Controller
@RestController
@Slf4j
public class EmpowerController {
    @GetMapping(value = "/empower")
    public String requestSentinel4() {
        log.info("测试Sentinel授权规则empower");
        return "Sentinel授权规则";
    }
}

控制台为 /empower 配置授权规则 → 流控应用填 serverName=test → 只有带 ?serverName=test 的请求才能访问。

4.3.8 步骤 ⑦:规则持久化到 Nacos

yaml 复制代码
spring:
  cloud:
    sentinel:
      datasource:
        ds1:
          nacos:
            server-addr: localhost:8848
            dataId: ${spring.application.name}
            groupId: DEFAULT_GROUP
            data-type: json
            rule-type: flow

在 Nacos 中创建配置(JSON 格式):

json 复制代码
[
    {
        "resource": "/testA",
        "limitApp": "default",
        "grade": 1,
        "count": 1,
        "strategy": 0,
        "controlBehavior": 0
    }
]

4.4 深入原理 --- Sentinel 滑动窗口

复制代码
时间轴 →
├──── 窗口1 ────┼──── 窗口2 ────┤
│ QPS=10       │ QPS=3         │ → 滑动窗口总 QPS=13
└──────────────┴───────────────┘

Sentinel 使用滑动窗口统计 QPS,比固定窗口更平滑,避免临界突发流量。


4.5 面试题

Q1:Sentinel 的 blockHandler 和 fallback 有什么区别?

blockHandler 处理 Sentinel 规则触发的异常(流控、降级、热点),fallback 处理业务代码的运行时异常。前者由框架调用,后者是开发者兜底。

Q2:Sentinel 规则持久化怎么做?为什么需要?

:默认规则存在内存中,应用重启即丢失。通过配置 datasource 将规则同步到 Nacos/Apollo/Redis 中实现持久化。生产环境必须持久化,否则每次发版都要重新配置。


4.6 踩坑指南

现象 原因 解决
🔴 控制台不显示应用 簇点链路为空 Sentinel 是懒加载,需先访问一次接口 先 curl 一次被保护的接口
🔴 web-context-unify 多个接口共享一个限流阈值 默认将所有 /foo/{id} 收敛为 /foo/* 配置 web-context-unify: false
🔴 规则重启丢失 应用重启后规则没了 默认内存存储 配置 datasource 持久化到 Nacos
🔴 @SentinelResource 不生效 限流了但返回默认错误页 未配 blockHandler 加上 blockHandler 指定兜底方法

4.7 章节总结

要点 说明
四大能力 流控 + 熔断 + 热点 + 授权
核心注解 @SentinelResource(value, blockHandler, fallback)
流控三种效果 快速失败 / Warm Up / 排队等待
熔断三种策略 慢调用比例 / 异常比例 / 异常数
规则持久化 配置 datasource → Nacos,应用重启不丢失
控制台 sentinel-dashboard-1.8.6.jar,实时监控 + 规则热更新
相关推荐
我命由我123451 小时前
Android 开发问题:EditText 控件的 android:imeOptions=“actionDone“ 属性不生效
android·java·java-ee·android studio·android jetpack·android-studio·android runtime
z_鑫1 小时前
深入理解MyBatis:collection集合封装的底层原理与实现细节
java·开发语言·数据库·spring boot·mybatis
aramae1 小时前
《计算机网络(第5版)》第二章 物理层
服务器·网络·后端·计算机网络
我命由我123451 小时前
Android 开发问题:获取到的 Android ID 发生了变化
android·java·开发语言·java-ee·android studio·android jetpack·android runtime
lazy H1 小时前
Spring Boot 连接 MySQL 失败怎么办?常见报错原因和解决方法总结
spring boot·后端·学习·mysql·spring
Solis程序员1 小时前
Raft:分布式系统的定海神针
java·分布式·kafka·rabbitmq·agent·raft
我登哥MVP1 小时前
SpringCloud Alibaba 核心组件解析:服务调用和负载均衡
java·spring boot·后端·spring·spring cloud·java-ee·负载均衡
云烟成雨TD1 小时前
Agent Scope Java 2.x 系列【13】权限系统
java·人工智能·agent
倔强的石头1061 小时前
《Kingbase护城河》——深度解密数据库行锁冲突与等待事件架构
java·数据库·架构