SpringCloud Alibaba Sentinel 从入门到精通

前言

在微服务架构中,服务间的依赖关系复杂,一个服务的故障可能引发连锁反应,导致整个系统雪崩。Sentinel 作为阿里巴巴开源的流量控制框架,能从流量控制、熔断降级等维度保护服务稳定性。本文将从实战角度,完整讲解 Sentinel 的核心概念、使用方式及各类规则配置。

一、Sentinel 核心概念

1.1 什么是 Sentinel

Sentinel(分布式系统的流量防卫兵)以流量为切入点,提供流量控制熔断降级系统负载保护等能力,保障微服务高可用。

1.2 核心概念

  • 资源:Sentinel 要保护的对象,可是一个接口、方法、服务等。
  • 规则:定义保护资源的策略,包括流量控制、熔断降级、热点参数、系统规则、授权规则等。
  • 核心功能
    • 流量控制:限制接口 QPS / 线程数,避免服务被压垮。
    • 熔断降级:当下游服务异常时,暂时切断调用,防止级联故障。

二、环境准备

2.1 搭建基础微服务

2.1.1 服务提供者(sentinel-provider)

application.yml

复制代码
server:
  port: 9090
spring:
  cloud:
    nacos:
      discovery:
        server-addr: 192.168.209.129:8848
  application:
    name: sentinel-provider

核心服务类

java 复制代码
@Service
public class UserServiceImpl implements UserService {
    @Override
    public User getUserById(Integer id) {
        // 模拟网络延时
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return new User(id,"王粪堆-provider",18);
    }
}
2.1.2 Feign 接口(sentinel_feign)
java 复制代码
@FeignClient("sentinel-provider")
public interface UserFeign {
    @RequestMapping(value = "/provider/getUserById/{id}")
    public User getUserById(@PathVariable Integer id);
}
2.1.3 服务消费者(sentinel_consumer)

pom.xml

XML 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>springcloud_parent</artifactId>
        <groupId>com.hg</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>sentinel_consumer</artifactId>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>com.hg</groupId>
            <artifactId>springcloud_common</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <!--feign接口-->
        <dependency>
            <groupId>com.hg</groupId>
            <artifactId>sentinel_feign</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <!--Sentinel核心依赖-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
        </dependency>
    </dependencies>
</project>

application.yml

复制代码
server:
  port: 8080
  tomcat:
    max-threads: 10 # 降低tomcat并发,便于测试雪崩
spring:
  cloud:
    nacos:
      discovery:
        server-addr: 192.168.209.129:8848
    sentinel:
      transport:
        dashboard: 127.0.0.1:8080 # Sentinel控制台地址
feign:
  client:
    config:
      default:
        connectionTimeout: 5000
        readTimeout: 5000
  sentinel:
    enabled: true # 开启Feign整合Sentinel

三、Sentinel 快速入门

3.1 方式 1:硬编码(抛异常方式)

java 复制代码
@RestController
@RequestMapping("/consumer")
public class ConsumerController {
    @RequestMapping(value = "/hello")
    public String hello() {
        Entry entry = null;
        try {
            // 定义资源
            entry = SphU.entry("/consumer/hello");
            return "Hello Sentinel!!!";
        } catch (BlockException e) {
            // 限流兜底逻辑
            return "接口被限流了, exception: " + e;
        }finally {
            if (entry != null) {
                entry.exit();
            }
        }
    }

    // 初始化限流规则
    @PostConstruct
    public void initFlowQpsRule() {
        List<FlowRule> rules = new ArrayList<>();
        FlowRule rule1 = new FlowRule();
        rule1.setResource("/consumer/hello"); // 资源名
        rule1.setGrade(RuleConstant.FLOW_GRADE_QPS); // 按QPS限流
        rule1.setCount(2); // QPS阈值2
        rules.add(rule1);
        FlowRuleManager.loadRules(rules);
    }
}

3.2 方式 2:注解方式(推荐)

java 复制代码
@RestController
@RequestMapping("/consumer")
public class ConsumerController {
    // 开启Sentinel注解支持
    @Bean
    public SentinelResourceAspect sentinelResourceAspect(){
        return new SentinelResourceAspect();
    }

    @RequestMapping(value = "/hello2")
    @SentinelResource(value="/consumer/hello2",blockHandler = "blockHandlerMethod")
    public String hello2() {
        return "Hello Sentinel2!!!";
    }

    // 限流兜底方法
    public String blockHandlerMethod(BlockException e){
        return "接口被限流了, exception: " + e;
    }

    @PostConstruct
    public void initFlowQpsRule() {
        List<FlowRule> rules = new ArrayList<>();
        FlowRule rule1 = new FlowRule();
        rule1.setResource("/consumer/hello2");
        rule1.setGrade(RuleConstant.FLOW_GRADE_QPS);
        rule1.setCount(2);
        rules.add(rule1);
        FlowRuleManager.loadRules(rules);
    }
}

3.3 Sentinel 控制台使用

3.3.1 启动控制台

bash

复制代码
# 下载地址:https://github.com/alibaba/Sentinel/releases
java -jar sentinel-dashboard-1.8.1.jar

访问 http://localhost:8080,默认账号 / 密码:sentinel/sentinel。

3.3.2 接入控制台

消费者配置文件中添加:

yaml:

复制代码
spring:
  cloud:
    sentinel:
      transport:
        dashboard: 127.0.0.1:8080

访问任意接口(如 http://127.0.0.1:8080/consumer/hello3),控制台即可识别服务。

四、Sentinel 核心规则配置

4.1 流量控制规则

流量控制是 Sentinel 最核心的功能,通过限制 QPS / 线程数,防止服务被压垮。

4.1.1 核心配置项说明
配置项 说明
资源名 唯一标识,默认请求路径
针对来源 限制调用方(默认 default,不区分来源)
阈值类型 QPS(每秒请求数)/ 线程数
流控模式 直接(限流当前接口)/ 关联(关联接口阈值触发限流)/ 链路(指定入口限流)
流控效果 快速失败 / Warm Up(预热)/ 排队等待
4.1.2 典型场景配置
(1)QPS 限流
  • 规则配置:资源名 /consumer/getUserById/{id},阈值类型 QPS,单机阈值 2;
  • 效果:接口 QPS 超过 2 时,直接触发限流。
(2)Warm Up(预热限流)
  • 适用场景:流量突增(如秒杀),避免瞬间打满服务;
  • 规则配置:阈值类型 QPS,单机阈值 6,预热时长 5 秒;
  • 效果:QPS 从 2(6/3)开始,5 秒后升至 6,平滑提升流量处理能力。
(3)排队等待
  • 适用场景:需要匀速处理请求(如削峰填谷);
  • 规则配置:阈值类型 QPS,单机阈值 1,排队超时时间 10ms;
  • 效果:请求匀速通过,超时未处理的请求直接丢弃。

4.2 热点参数限流

对接口参数做精细化限流,支持参数例外项(如特定 ID 放宽阈值)。

java 复制代码
@RequestMapping(value = "/getUserById/{id}")
@SentinelResource(value = "getUserById", blockHandler = "blockHandlerMethod")
public User getUserById(@PathVariable Integer id) {
    return userFeign.getUserById(id);
}

// 热点参数限流兜底方法
public User blockHandlerMethod(Integer id, BlockException e) {
    return new User(id, "热点参数限流触发", 0);
}
  • 规则配置:资源名 getUserById,参数索引 0(第一个参数),单机阈值 2;
  • 例外项配置:参数值 2,阈值 3(ID=2 时 QPS 阈值提升至 3)。

4.3 熔断降级规则

当接口响应慢 / 异常比例高时,暂时切断调用,避免级联故障。

4.3.1 三种熔断策略
策略 触发条件
慢调用比例 慢调用(RT 超过阈值)占比超过设定值,且请求数≥最小请求数
异常比例 异常请求占比超过设定值,且请求数≥最小请求数
异常数 异常请求数超过设定值,且请求数≥最小请求数
4.3.2 配置示例(慢调用比例)
  • 规则配置:资源名 /consumer/getUserById/{id},最大 RT 200ms,比例阈值 0.5,熔断时长 5s,最小请求数 5;
  • 效果:5 个请求中若 50% 以上 RT 超过 200ms,触发熔断,5 秒内拒绝所有请求。

4.4 授权规则

基于请求来源做黑白名单控制,适合接口访问权限管控。

4.4.1 实现来源解析
java 复制代码
@Component
public class RequestOriginParserDefinition implements RequestOriginParser {
    @Override
    public String parseOrigin(HttpServletRequest request) {
        // 从请求参数获取来源标识(可替换为请求头、Session等)
        return request.getParameter("origin");
    }
}
4.4.2 规则配置
  • 黑名单:资源名 /consumer/getUserById/{id},黑名单值 app1
  • 效果:来源为 app1 的请求直接被拒绝。

4.5 系统规则

针对整个应用的全局规则(粒度粗,慎用),支持:

  • LOAD(Linux 系统负载);
  • RT(所有请求平均响应时间);
  • 线程数(所有请求总线程数);
  • 入口 QPS(所有接口总 QPS);
  • CPU 使用率。

五、Sentinel 高级特性

5.1 自定义兜底逻辑(blockHandler)

5.1.1 同级别兜底(当前类)
java 复制代码
@SentinelResource(value = "getUserById", blockHandler = "blockHandlerMethod")
public User getUserById(@PathVariable Integer id) {
    return userFeign.getUserById(id);
}

// 兜底方法(参数与原方法一致,最后加BlockException)
public User blockHandlerMethod(Integer id, BlockException e) {
    return new User(0, "接口被流控/熔断:"+e, 0);
}
5.1.2 外置兜底类(解耦)
java 复制代码
// 外置兜底类(方法必须static)
public class BlockHandlerClass {
    public static User blockHandlerMethod(Integer id, BlockException e) {
        return new User(0, "外置兜底:"+e, 0);
    }
}

// 使用外置兜底类
@SentinelResource(value = "getUserById",
        blockHandler = "blockHandlerMethod",
        blockHandlerClass = BlockHandlerClass.class)
public User getUserById(@PathVariable Integer id) {
    return userFeign.getUserById(id);
}

5.2 全局异常处理

统一处理 Sentinel 各类异常,返回标准化响应。

java 复制代码
@Component
public class GlobalBlockExceptionHandler implements BlockExceptionHandler {
    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response, BlockException e) throws Exception {
        response.setContentType("application/json;charset=utf-8");
        Result data = null;
        if (e instanceof FlowException) {
            data = new Result(-1, "限流异常");
        } else if (e instanceof DegradeException) {
            data = new Result(-2, "降级异常");
        } else if (e instanceof ParamFlowException) {
            data = new Result(-3, "参数限流异常");
        } else if (e instanceof AuthorityException) {
            data = new Result(-4, "授权异常");
        } else if (e instanceof SystemBlockException) {
            data = new Result(-5, "系统负载异常");
        }
        response.getWriter().write(JSON.toJSONString(data));
    }
}

// 统一返回体
class Result {
    private int status;
    private String msg;
    private Object data;
    // 省略getter/setter/构造器
}

5.3 Sentinel 整合 Feign

实现 Feign 远程调用的熔断降级,避免下游服务异常影响上游。

5.3.1 实现 FallbackFactory
java 复制代码
@Component
public class UserFeignFallback implements FallbackFactory<UserFeign> {
    @Override
    public UserFeign create(Throwable t) {
        return new UserFeign() {
            @Override
            public User getUserById(Integer id) {
                return new User(id, "Feign调用失败:"+t, 0);
            }
        };
    }
}
5.3.2 配置 Feign 接口
java 复制代码
@FeignClient(value = "sentinel-provider", fallbackFactory = UserFeignFallback.class)
public interface UserFeign {
    @RequestMapping(value = "/provider/getUserById/{id}")
    User getUserById(@PathVariable Integer id);
}

六、总结

Sentinel 凭借轻量、易用、灵活的特性,成为 SpringCloud 微服务架构中服务保护的首选方案。核心要点总结:

  1. 资源定义:通过硬编码 / 注解 / 自动适配(SpringMVC/Feign)定义受保护资源;
  2. 规则配置:控制台 / 代码配置流量控制、熔断降级等规则,按需选择粒度;
  3. 兜底逻辑:通过 blockHandler / 全局异常 / FallbackFactory 处理限流 / 熔断场景;
  4. 核心价值:从流量入口到服务调用全链路保护,防止雪崩效应,保障微服务高可用。

建议结合 JMeter 压测工具验证各类规则效果,加深对 Sentinel 流量控制、熔断降级的理解,根据业务场景灵活配置规则,平衡系统稳定性和可用性。

相关推荐
霸道流氓气质7 小时前
Spring @Scheduled 单线程陷阱:当设备重连阻塞了整个定时任务体系
java·spring boot·spring
Java知识技术分享7 小时前
策略模式的两种实现:抽象类和接口
java·spring·策略模式
heimeiyingwang7 小时前
【架构实战】服务熔断与限流Sentinel:高可用服务的守护神
架构·sentinel
欢璃8 小时前
表白墙案例
java·开发语言·jvm·spring boot·spring·maven·mybatis
livemetee8 小时前
Spring Cloud Stream与Flink集成实战
spring cloud·flink
xuhaoyu_cpp_java9 小时前
SpringMVC学习(三)
java·经验分享·笔记·学习·spring
小碗羊肉9 小时前
【JavaWeb | 第十篇】Spring中的事务控制
java·后端·spring
NagatoYukee11 小时前
Spring/SpringMVC/SprongBoot知识复习
java·数据库·spring
JAVA面经实录91720 小时前
Java初级最终完整版学习路线图
java·spring·eclipse·maven
释怀°Believe21 小时前
Spring解析
java·后端·spring