微服务流量治理实战: Sentinel 和 MSE的熔断降级艺术

简介: Sentinel 是阿里巴巴开源的流量治理组件,在微服务高并发场景中承担限流、熔断、降级三大核心职责。阿里云 MSE 提供了 Sentinel 的托管规则推送和集群限流增强。本文从电商秒杀场景出发,实战演示 Sentinel 核心功能:QPS 限流、线程池隔离、熔断降级、热点参数限流、系统自适应保护,以及 Nacos 规则持久化和 MSE 托管方案,并给出生产环境的最佳实践。

1. 场景:秒杀洪峰下的微服务"保险丝"

1.1 一个真实的秒杀事故

去年双十一,我负责的电商平台上线秒杀活动。活动开始前,系统日常 QPS 稳定在 500 左右,一切正常。

秒杀开始的瞬间,流量直接飙到 50000 QPS,涨幅 100 倍。

灾难链

  • 订单服务涌入大量请求,线程池打满
  • 库存服务被击穿,数据库连接池耗尽
  • 支付服务超时,整个调用链雪崩
  • 最终结果:全站不可用 23 分钟,直接损失超百万

1.2 为什么需要 Sentinel

这次事故后,我们引入了 Sentinel。它提供三位一体的流量防护:

  • 限流:控制进入的流量,不让洪峰冲垮服务
  • 熔断:下游服务异常时及时断开,防止级联故障
  • 降级:非核心功能降级,保住核心链路

1.3 有无 Sentinel 的对比

002-sentinel-mse-traffic-governance_diagram_1.png

核心区别:没有 Sentinel,洪峰流量会无差别冲击所有服务;有了 Sentinel,超限流量被拦截,异常服务被熔断,系统整体存活。


2. Sentinel 核心概念与架构

2.1 两个核心概念

Sentinel 的设计围绕两个核心概念展开:

资源(Resource):需要保护的东西,可以是一个方法、一段代码、一个接口。

规则(Rule):如何保护资源,定义限流阈值、熔断条件等。

// 资源和规则的关系
// 资源 = 你要保护什么
try (Entry entry = SphU.entry("orderService")) {
   
    // 业务逻辑 —— 受保护
    return orderService.createOrder(request);
} catch (BlockException e) {
   
    // 被限流/熔断时的处理
    return "系统繁忙,请稍后重试";
}

// 规则 = 怎么保护
FlowRule rule = new FlowRule("orderService")
    .setCount(100)          // QPS 阈值
    .setGrade(RuleConstant.FLOW_GRADE_QPS);
FlowRuleManager.loadRules(Collections.singletonList(rule));

2.2 Slot Chain 处理流程

Sentinel 的核心是 Slot Chain(插槽链),每个 Slot 负责一项职责,请求依次通过所有 Slot:

002-sentinel-mse-traffic-governance_diagram_2.png

关键 Slot 职责

Slot 职责 说明
NodeSelectorSlot 构建调用树 记录资源的调用路径
StatisticSlot 实时统计 统计 QPS、RT、线程数等
FlowSlot 流量控制 判断是否超过限流阈值
DegradeSlot 熔断降级 判断是否触发熔断
SystemSlot 系统保护 根据 CPU/Load 保护系统
AuthoritySlot 来源控制 黑白名单过滤

2.3 Sentinel Dashboard

Sentinel Dashboard 是可视化的规则管理和监控平台:

  • 实时监控:查看各资源的 QPS、RT、线程数
  • 规则管理:动态配置限流、熔断、系统规则
  • 集群管理:管理 Token Server 和 Token Client
  • 机器发现:自动发现接入的应用实例

3. Spring Cloud Alibaba 集成 Sentinel

3.1 Maven 依赖配置

Spring Cloud Alibaba 封装了 Sentinel 的 Starter,自动装配核心组件,无需手动初始化。


<dependencies>
  <!-- Sentinel Starter -->
  <dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
    <version>2023.0.1.2</version>
  </dependency>

  <!-- Sentinel 对 Spring MVC 的支持 -->
  <dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-spring-webmvc-adapter</artifactId>
    <version>1.8.8</version>
  </dependency>

  <!-- Sentinel 对 OpenFeign 的支持 -->
  <dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
  </dependency>
</dependencies>

3.2 应用配置

连接 Sentinel Dashboard 和开启 Feign 整合是接入的关键步骤。

server:
  port: 8081

spring:
  application:
    name: order-service
  cloud:
    sentinel:
      transport:
        dashboard: localhost:8080  # Sentinel Dashboard 地址
        port: 8719                 # 客户端与 Dashboard 通信端口
      web-context-unify: false     # 关闭上下文合并,每个URL独立统计
      http-method-specify: true    # 区分 HTTP 方法

# 开启 Feign 对 Sentinel 的支持
feign:
  sentinel:
    enabled: true

3.3 @SentinelResource 注解使用

@SentinelResource 是声明式资源定义的核心注解,比 try-catch 方式更优雅,且支持细粒度的流控和降级处理。

@Service
public class OrderService {
   

    /**
     * 创建订单 —— 核心接口,需要限流保护
     */
    @SentinelResource(
        value = "createOrder",
        blockHandler = "createOrderBlockHandler",
        fallback = "createOrderFallback"
    )
    public OrderVO createOrder(OrderRequest request) {
   
        // 核心业务逻辑
        Order order = new Order();
        order.setUserId(request.getUserId());
        order.setProductId(request.getProductId());
        order.setQuantity(request.getQuantity());
        orderMapper.insert(order);
        return OrderVO.from(order);
    }

    /**
     * blockHandler:被限流/熔断时触发(BlockException)
     */
    public OrderVO createOrderBlockHandler(OrderRequest request, BlockException e) {
   
        log.warn("创建订单被限流,userId={}", request.getUserId());
        throw new ServiceException("SYSTEM_BUSY", "系统繁忙,请稍后重试");
    }

    /**
     * fallback:业务异常时触发(非 BlockException)
     */
    public OrderVO createOrderFallback(OrderRequest request, Throwable t) {
   
        log.error("创建订单异常,userId={}", request.getUserId(), t);
        throw new ServiceException("ORDER_ERROR", "订单创建失败,请重试");
    }
}

3.4 Sentinel Dashboard 部署

Dashboard 是规则可视化管理的基础,生产环境必须部署。

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

# 启动 Dashboard
java -jar sentinel-dashboard-1.8.8.jar \
  --server.port=8080 \
  --auth.username=sentinel \
  --auth.password=sentinel123

# 访问 Dashboard
# http://localhost:8080
# 默认账号:sentinel / sentinel

启动后,应用需要发送几个请求才能在 Dashboard 上看到机器列表和资源信息。


4. 五大核心功能实战

4.1 流量控制

流量控制是 Sentinel 最基础的功能,支持 QPS 限流和线程数限流两种模式。

QPS 限流:每秒请求数超过阈值时拒绝。

线程数限流:并发线程数超过阈值时拒绝,适合保护慢调用资源。

QPS 限流适合接口级别的粗粒度防护,线程数限流适合保护数据库连接等资源。

/**
 * QPS 限流 —— 每秒最多 100 个请求
 */
@SentinelResource(value = "queryOrder", blockHandler = "queryBlockHandler")
public OrderVO queryOrder(Long orderId) {
   
    return orderMapper.selectById(orderId);
}

/**
 * 线程数限流 —— 最多 20 个并发线程
 * 适合保护慢 SQL 查询
 */
@SentinelResource(value = "queryOrderDetail", blockHandler = "queryBlockHandler")
public OrderDetailVO queryOrderDetail(Long orderId) {
   
    // 涉及多表关联查询,RT 较高
    return orderMapper.selectDetailById(orderId);
}

// 编程式配置规则
private void initFlowRules() {
   
    // QPS 限流规则
    FlowRule qpsRule = new FlowRule("queryOrder")
        .setCount(100)
        .setGrade(RuleConstant.FLOW_GRADE_QPS)
        .setLimitApp("default")
        .setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_DEFAULT);

    // 线程数限流规则
    FlowRule threadRule = new FlowRule("queryOrderDetail")
        .setCount(20)
        .setGrade(RuleConstant.FLOW_GRADE_THREAD)
        .setLimitApp("default");

    FlowRuleManager.loadRules(Arrays.asList(qpsRule, threadRule));
}

流控效果说明

控制行为 说明 适用场景
直接拒绝 超限立即拒绝,抛出 BlockException 常规限流
Warm Up 冷启动,预热后逐步达到阈值 秒杀预热
匀速排队 请求匀速通过,间隔 = 1000/阈值QPS 削峰填谷

4.2 熔断降级

熔断降级针对的是调用端保护。当下游服务出现异常时,及时熔断,避免级联故障。

Sentinel 提供三种熔断策略:

慢调用比例:响应时间超过阈值的请求占比超过设定值时熔断。

异常比例:异常请求占比超过设定值时熔断。

异常数:异常请求数超过设定值时熔断。

慢调用比例策略适合保护 RT 敏感的接口,异常比例策略适合保护不稳定的下游服务。

/**
 * 熔断降级 —— 调用库存服务
 */
@SentinelResource(value = "checkStock", fallback = "checkStockFallback")
public StockVO checkStock(Long productId) {
   
    // 调用库存服务(可能不稳定)
    return stockFeignClient.getStock(productId);
}

// 降级方法
public StockVO checkStockFallback(Long productId, Throwable t) {
   
    log.warn("库存服务降级,productId={}", productId, t);
    // 降级方案:返回默认库存,允许下单但标记为待确认
    StockVO stock = new StockVO();
    stock.setProductId(productId);
    stock.setAvailable(true);
    stock.setNeedConfirm(true);  // 标记需要后续确认
    return stock;
}

// 编程式配置熔断规则
private void initDegradeRules() {
   
    // 慢调用比例熔断
    DegradeRule slowCallRule = new DegradeRule("checkStock")
        .setGrade(CircuitBreakerStrategy.SLOW_REQUEST_RATIO.getType())
        .setCount(500)        // 慢调用阈值:500ms
        .setSlowRatioThreshold(0.6)  // 慢调用比例:60%
        .setTimeWindow(30)    // 熔断时长:30秒
        .setMinRequestAmount(5)       // 最小请求数:5
        .setStatIntervalMs(10000);    // 统计时长:10秒

    // 异常比例熔断
    DegradeRule exceptionRatioRule = new DegradeRule("checkStock")
        .setGrade(CircuitBreakerStrategy.ERROR_RATIO.getType())
        .setCount(0.5)       // 异常比例阈值:50%
        .setTimeWindow(30)
        .setMinRequestAmount(5)
        .setStatIntervalMs(10000);

    // 异常数熔断
    DegradeRule exceptionCountRule = new DegradeRule("checkStock")
        .setGrade(CircuitBreakerStrategy.ERROR_COUNT.getType())
        .setCount(10)        // 异常数阈值:10
        .setTimeWindow(60)
        .setMinRequestAmount(5)
        .setStatIntervalMs(10000);

    DegradeRuleManager.loadRules(
        Arrays.asList(slowCallRule, exceptionRatioRule, exceptionCountRule)
    );
}

熔断状态机

  • CLOSED(关闭):正常放行请求,统计异常指标
  • OPEN(打开):熔断生效,所有请求直接降级
  • HALF-OPEN(半开):熔断到期后放行少量请求探测,成功则关闭,失败则继续熔断

002-sentinel-mse-traffic-governance_diagram_3.png

熔断恢复策略:HALF_OPEN 阶段是 Sentinel 的"自我修复"机制。如果探测请求成功,说明下游已恢复,熔断器关闭;如果再次失败,熔断器继续保持 OPEN 状态,等待下一次探测窗口。生产环境中建议配合慢启动恢复策略,避免瞬间涌入大量请求导致二次熔断。

4.3 热点参数限流

热点参数限流是 Sentinel 的特色功能,可以按请求参数值分别限流。

秒杀场景下,热门商品的访问量远超普通商品,按商品 ID 精准限流比全局限流更合理。

/**
 * 热点参数限流 —— 按商品ID限流
 * 热门商品单独限流,普通商品不受影响
 */
@SentinelResource(value = "getProduct", blockHandler = "getProductBlockHandler")
public ProductVO getProduct(
    @RequestParam Long productId,
    @RequestParam(required = false) String source
) {
   
    return productMapper.selectById(productId);
}

public ProductVO getProductBlockHandler(Long productId, String source, BlockException e) {
   
    log.warn("商品查询被限流,productId={}", productId);
    // 返回简化商品信息
    return ProductVO.simpleDefault(productId);
}

// 编程式配置热点参数规则
private void initParamFlowRules() {
   
    ParamFlowRule rule = new ParamFlowRule("getProduct")
        .setParamIdx(0)          // 第0个参数(productId)
        .setCount(50)            // 默认每个参数值 QPS 上限 50
        .setGrade(RuleConstant.FLOW_GRADE_QPS);

    // 热门商品单独设置更高的限流阈值
    ParamFlowItem hotItem = new ParamFlowItem()
        .setObject("10086")      // 商品ID=10086 是秒杀商品
        .setClassType(long.class.getName())
        .setCount(500);          // 秒杀商品允许 500 QPS

    rule.setParamFlowItemList(Collections.singletonList(hotItem));

    ParamFlowRuleManager.loadRules(Collections.singletonList(rule));
}

注意事项:热点参数限流仅支持基本类型和 String 类型参数,不支持复杂对象。

002-sentinel-mse-traffic-governance_diagram_4.png

核心优势:全局限流"一刀切"会误伤普通商品流量;热点参数限流按商品 ID 分别计算,热门商品和普通商品互不影响,精准防护。

4.4 系统自适应保护

系统自适应保护从整体维度保护应用,防止系统被拖垮。

当系统整体负载过高时,单靠接口级限流不够,需要从系统维度做兜底保护。

// 系统自适应保护规则
private void initSystemRules() {
   
    // CPU 使用率保护
    SystemRule cpuRule = new SystemRule();
    cpuRule.setHighestCpuUsage(0.8);  // CPU 使用率 > 80% 触发保护

    // 系统 Load 保护
    SystemRule loadRule = new SystemRule();
    loadRule.setHighestSystemLoad(5.0);  // Load > 5 触发保护

    // 平均 RT 保护
    SystemRule rtRule = new SystemRule();
    rtRule.setAvgRt(500);  // 平均 RT > 500ms 触发保护

    // 并发线程数保护
    SystemRule threadRule = new SystemRule();
    threadRule.setMaxThread(200);  // 并发线程 > 200 触发保护

    // 入口 QPS 保护
    SystemRule qpsRule = new SystemRule();
    qpsRule.setQps(5000);  // 入口总 QPS > 5000 触发保护

    SystemRuleManager.loadRules(
        Arrays.asList(cpuRule, loadRule, rtRule, threadRule, qpsRule)
    );
}

系统保护触发时,入口流量会被全局限制,所有资源都可能被 Block。

4.5 来源访问控制

来源访问控制(黑白名单)根据调用来源决定是否放行。

内部服务之间的调用应该放行,外部来源的异常流量应该拦截。

// 来源访问控制规则
private void initAuthorityRules() {
   
    AuthorityRule rule = new AuthorityRule("orderService")
        .setLimitApp("gateway-service,admin-service")  // 白名单
        .setStrategy(RuleConstant.AUTHORITY_WHITE);     // 白名单模式

    // 黑名单模式
    AuthorityRule blackRule = new AuthorityRule("orderService")
        .setLimitApp("suspicious-client")              // 黑名单
        .setStrategy(RuleConstant.AUTHORITY_BLACK);     // 黑名单模式

    AuthorityRuleManager.loadRules(Arrays.asList(rule, blackRule));
}

// 自定义来源解析(默认从 HTTP Header 的 origin 字段获取)
@Component
public class CustomRequestOriginParser implements RequestOriginParser {
   
    @Override
    public String parseOrigin(HttpServletRequest request) {
   
        // 从请求头获取来源标识
        String origin = request.getHeader("X-Service-Name");
        if (StringUtils.isBlank(origin)) {
   
            origin = request.getRemoteAddr();
        }
        return origin;
    }
}

5. 规则持久化:Nacos 数据源

5.1 为什么需要持久化

Sentinel 默认将规则存储在内存中,应用重启后规则全部丢失。

问题场景

  • 应用重启后,所有限流规则消失,服务裸奔
  • Dashboard 配置的规则只推送到内存,不持久化
  • 多实例部署时,每个实例需要单独配置规则

5.2 Nacos 数据源配置

Nacos 作为配置中心,天然支持规则持久化和动态推送,是 Sentinel 规则持久化的首选方案。

<!-- Sentinel Nacos 数据源依赖 -->
<dependency>
  <groupId>com.alibaba.csp</groupId>
  <artifactId>sentinel-datasource-nacos</artifactId>
  <version>1.8.8</version>
</dependency>
spring:
  cloud:
    sentinel:
      transport:
        dashboard: localhost:8080
      datasource:
        # 限流规则
        flow:
          nacos:
            server-addr: localhost:8848
            namespace: sentinel
            group-id: SENTINEL_GROUP
            data-id: ${
   spring.application.name}-flow-rules
            rule-type: flow
        # 熔断规则
        degrade:
          nacos:
            server-addr: localhost:8848
            namespace: sentinel
            group-id: SENTINEL_GROUP
            data-id: ${
   spring.application.name}-degrade-rules
            rule-type: degrade
        # 热点参数规则
        param-flow:
          nacos:
            server-addr: localhost:8848
            namespace: sentinel
            group-id: SENTINEL_GROUP
            data-id: ${
   spring.application.name}-param-rules
            rule-type: param-flow
        # 系统规则
        system:
          nacos:
            server-addr: localhost:8848
            namespace: sentinel
            group-id: SENTINEL_GROUP
            data-id: ${
   spring.application.name}-system-rules
            rule-type: system

5.3 Nacos 中的规则格式

了解 Nacos 中的规则 JSON 格式,才能正确配置和排查问题。

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

字段说明

字段 说明
grade 限流模式 1=QPS, 0=线程数
strategy 流控策略 0=直接, 1=关联, 2=链路
controlBehavior 流控效果 0=快速失败, 2=Warm Up, 3=排队等待

5.4 规则推送流程

Dashboard 修改规则 → 推送到 Nacos → 应用监听 Nacos 变更 → 热更新规则。

需要注意:开源版 Sentinel Dashboard 默认将规则推送到客户端内存,需要改造 Dashboard 源码,使其推送到 Nacos。

002-sentinel-mse-traffic-governance_diagram_5.png

规则推送三大优势:① 规则持久化到 Nacos,重启不丢失;② 多实例秒级同步,无需逐个配置;③ 支持热更新,应用无需重启。


6. MSE Sentinel 托管方案

6.1 MSE Sentinel 增强功能

阿里云 MSE(微服务引擎)提供了 Sentinel 的托管增强方案:

  • 规则托管:无需自建 Dashboard,MSE 控制台统一管理规则
  • 集群限流:基于 Token Server 的精确集群限流
  • 监控大盘:开箱即用的流量监控和告警
  • 规则推送:规则变更秒级推送到所有实例
  • 多语言支持:Java、Go、C++、Rust 等多语言 Agent

002-sentinel-mse-traffic-governance_diagram_6.png

核心流程

  1. 运维人员在 MSE 控制台配置规则 → 自动推送到 Nacos 持久化
  2. Nacos 监听机制 → 规则变更秒级推送到所有应用实例
  3. 集群限流时 → Client 向 Token Server 申请 Token,实现精确的总 QPS 控制
  4. 指标采集 → 各实例上报流量数据到 MSE 监控大盘

6.2 自建 vs MSE 托管对比

对比维度 自建 Sentinel Dashboard MSE Sentinel 托管
部署运维 需要自行部署和维护 零运维,开箱即用
规则持久化 需要改造源码对接 Nacos 原生支持,自动持久化
集群限流 需要自建 Token Server 内置集群限流能力
监控告警 需要对接 Prometheus 内置监控大盘和告警
多语言 仅 Java 原生支持 支持 Java/Go/C++/Rust
高可用 需要自行保证 阿里云 SLA 保障
成本 人力成本高 按实例付费,成本可控

6.3 接入 MSE Sentinel

MSE 接入方式简单,只需引入 Agent 即可,无需修改业务代码。

步骤一:创建 MSE 托管集群

在阿里云 MSE 控制台创建 Sentinel 托管实例,获取接入点信息。

步骤二:引入 MSE Sentinel Agent

<!-- MSE Sentinel Starter -->
<dependency>
  <groupId>com.alibaba.cloud</groupId>
  <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
  <version>2023.0.1.2</version>
</dependency>

步骤三:配置 MSE 接入参数

spring:
  cloud:
    sentinel:
      transport:
        # MSE Sentinel 控制台地址
        dashboard: ${
   MSE_SENTINEL_DASHBOARD}
        port: 8719
      # MSE 数据源配置
      datasource:
        mse-flow:
          mse:
            endpoint: ${
   MSE_ENDPOINT}       # MSE 接入点
            namespace: ${
   MSE_NAMESPACE}     # MSE 命名空间
            group-id: ${
   spring.application.name}
            data-id: flow-rules
            rule-type: flow
        mse-degrade:
          mse:
            endpoint: ${
   MSE_ENDPOINT}
            namespace: ${
   MSE_NAMESPACE}
            group-id: ${
   spring.application.name}
            data-id: degrade-rules
            rule-type: degrade

步骤四:配置集群限流

集群限流确保整个集群的总 QPS 不超限,而非单机 QPS 不超限。

spring:
  cloud:
    sentinel:
      transport:
        dashboard: ${
   MSE_SENTINEL_DASHBOARD}
      # 集群限流配置
      cluster:
        mode: client                    # 当前实例作为 Client
        flow:
          client:
            server-host: ${
   TOKEN_SERVER_HOST}   # Token Server 地址
            server-port: 18730                  # Token Server 端口
            request-timeout: 200                # 请求超时 200ms

Token Server 配置(独立部署):

# Token Server 应用配置
spring:
  cloud:
    sentinel:
      cluster:
        mode: server                    # 当前实例作为 Token Server
        server:
          port: 18730                   # Token Server 监听端口
          namespace: ${
   MSE_NAMESPACE}

7. 生产环境最佳实践

7.1 限流阈值如何确定

限流阈值不是拍脑袋定的,需要基于压测数据和合理余量:

确定步骤

  1. 压测获取服务的最大承受 QPS
  2. 留出 20%-30% 的安全余量
  3. 设置限流阈值 = 最大承受 QPS × 0.7
# 使用 JMeter 压测获取基线数据
# 场景:订单查询接口,逐步加压

# 并发 100 → RT=50ms,QPS=2000,无错误 ✅
# 并发 200 → RT=80ms,QPS=3500,无错误 ✅
# 并发 500 → RT=200ms,QPS=4000,错误率 0.1% ⚠️
# 并发 1000 → RT=800ms,QPS=3000,错误率 5% ❌

# 结论:最大承受 QPS ≈ 4000
# 限流阈值 = 4000 × 0.7 = 2800 QPS

7.2 熔断恢复策略

熔断恢复有两种策略,适用不同场景:

慢启动恢复(推荐):

  • 熔断结束后,逐步放行流量
  • 避免瞬间涌入大量请求导致二次熔断
  • 适合下游服务恢复较慢的场景

立即恢复

  • 熔断结束后,立即放行所有流量
  • 适合下游服务恢复较快的场景
  • 风险:可能触发二次熔断
// 慢启动恢复 —— 推荐生产环境使用
DegradeRule rule = new DegradeRule("checkStock")
    .setGrade(CircuitBreakerStrategy.SLOW_REQUEST_RATIO.getType())
    .setCount(500)
    .setSlowRatioThreshold(0.6)
    .setTimeWindow(30)         // 熔断时长 30 秒
    .setMinRequestAmount(5)
    .setStatIntervalMs(10000);
// 半开状态会逐步放行请求探测,实现慢启动

7.3 降级方案的兜底设计

降级不是简单地返回错误,而是提供有意义的兜底方案:

业务场景 降级方案 说明
商品详情 返回缓存数据 牺牲实时性,保可用性
库存查询 返回默认库存 允许下单但标记待确认
推荐列表 返回热门推荐 牺牲个性化,保基础体验
用户评论 隐藏评论模块 非核心功能直接降级
支付 排队等待 核心功能不能降级,只能排队

002-sentinel-mse-traffic-governance_diagram_7.png

降级设计原则:降级不是"一刀切"——缓存数据优先于降级服务,降级服务优先于默认值,每多一级降级,业务体验损失更小。

/**
 * 分级降级策略
 */
@SentinelResource(value = "getProductDetail", fallback = "productDetailFallback")
public ProductDetailVO getProductDetail(Long productId) {
   
    // 正常逻辑:实时查询
    return productService.getDetail(productId);
}

public ProductDetailVO productDetailFallback(Long productId, Throwable t) {
   
    ProductDetailVO detail = new ProductDetailVO();

    // 第一级降级:读本地缓存
    ProductCache cache = localCache.get(productId);
    if (cache != null && !cache.isExpired()) {
   
        detail.setFromCache(true);
        detail.setProduct(cache.getProduct());
        return detail;
    }

    // 第二级降级:返回默认商品信息
    detail.setFromCache(true);
    detail.setProduct(ProductVO.defaultProduct(productId));
    detail.setDegraded(true);
    return detail;
}

7.4 网关层限流 vs 服务层限流

两层限流配合使用,形成纵深防御:

网关层限流(粗粒度):

  • 对整体流量做全局控制
  • 防止洪峰流量进入微服务内部
  • 使用 Sentinel 的 Gateway 适配

服务层限流(细粒度):

  • 对单个接口做精确控制
  • 保护核心资源不被打满
  • 使用 @SentinelResource 注解

002-sentinel-mse-traffic-governance_diagram_8.png

纵深防御要点

  1. 网关层做第一道拦截:挡住 80% 的洪峰流量,不让其进入微服务内部
  2. 服务层做精确控制:根据各服务的承载能力分别限流,核心服务更精细
  3. 数据层做兜底保护:防止连接池耗尽、缓存穿透等深层问题
  4. 三层联动:网关限流失败的服务级兜底,服务限流失败的数据层保护
# Spring Cloud Gateway + Sentinel 配置
spring:
  cloud:
    gateway:
      routes:
        - id: order-service
          uri: lb://order-service
          predicates:
            - Path=/api/order/**
          filters:
            - name: RequestRateLimiter
              args:
                redis-rate-limiter.replenishRate: 1000
                redis-rate-limiter.burstCapacity: 2000
    sentinel:
      transport:
        dashboard: localhost:8080
      # Gateway 限流规则
      scg:
        fallback:
          mode: response
          response-status: 429
          response-body: '{"code":429,"message":"请求过于频繁,请稍后重试"}'

7.5 监控告警配置

生产环境必须有监控告警,及时发现流量异常:

/**
 * Sentinel 指标接入 Prometheus
 */
@Component
public class SentinelMetricsExporter {
   

    private final Counter blockCounter = Counter.build()
        .name("sentinel_block_total")
        .help("Sentinel blocked requests")
        .labelNames("resource", "limitApp", "ruleType")
        .register();

    @Scheduled(fixedRate = 1000)
    public void exportMetrics() {
   
        // 遍历所有资源,采集限流指标
        for (String resource : ClusterBuilderSlot.getClusterNodeMap().keySet()) {
   
            ClusterNode node = ClusterBuilderSlot.getClusterNode(resource);
            if (node != null) {
   
                long blockQps = node.blockQps();
                if (blockQps > 0) {
   
                    blockCounter.labels(resource, "default", "flow").inc(blockQps);
                }
            }
        }
    }
}

告警规则建议

指标 告警条件 级别
限流次数 1分钟内 > 100 次 WARNING
熔断状态 进入 OPEN 状态 CRITICAL
系统 Load > 阈值 × 0.8 WARNING
平均 RT > 阈值 × 0.8 WARNING

8. 避坑指南

坑1:blockHandler vs fallback 区别

这是新手最容易混淆的点:

  • blockHandler:处理 BlockException(限流、熔断触发)
  • fallback:处理业务异常(非 BlockException 的所有异常)
// ❌ 错误:把业务异常处理放在 blockHandler
@SentinelResource(
    value = "createOrder",
    blockHandler = "handleException"  // 既处理限流又处理业务异常?
)

// ✅ 正确:职责分离
@SentinelResource(
    value = "createOrder",
    blockHandler = "createOrderBlockHandler",  // 只处理限流/熔断
    fallback = "createOrderFallback"            // 只处理业务异常
)

关键细节:blockHandler 方法必须额外声明 BlockException 参数,fallback 方法不需要。

坑2:规则未持久化导致重启丢失

默认情况下,Sentinel 规则存储在内存中,重启即丢失。

// ❌ 危险:只通过 Dashboard 配置规则
// 应用重启后,所有规则消失,服务裸奔

// ✅ 正确:配置 Nacos 数据源持久化
spring:
  cloud:
    sentinel:
      datasource:
        flow:
          nacos:
            server-addr: localhost:8848
            data-id: ${
   spring.application.name}-flow-rules
            rule-type: flow

生产环境必须配置规则持久化,这是不可省略的基础设施。

坑3:热点参数限流的参数类型限制

热点参数限流只支持基本类型和 String:

// ❌ 不支持:复杂对象作为热点参数
@SentinelResource(value = "search")
public Result search(ProductQuery query) {
     // query 是复杂对象
    // 热点参数限流无法按 query 的字段值分别限流
}

// ✅ 正确:使用基本类型参数
@SentinelResource(value = "search")
public Result search(
    @RequestParam String category,   // String 类型 ✅
    @RequestParam Integer brandId    // Integer 类型 ✅
) {
   
    // 可以按 category 或 brandId 分别限流
}

坑4:集群限流 Token Server 单点问题

Token Server 是集群限流的核心,存在单点风险:

# ❌ 单点部署 Token Server
spring:
  cloud:
    sentinel:
      cluster:
        mode: server
        server:
          port: 18730
          # 只有一个实例,挂了就全挂

解决方案

  1. Token Server 至少部署 2 个实例
  2. 使用 Nacos 做服务发现,Client 自动切换
  3. 配置 Token Server 健康检查和自动故障转移
  4. MSE 托管方案内置高可用,推荐使用

坑5:Sentinel 与 Gateway 集成的过滤器顺序

Spring Cloud Gateway 中,Sentinel 过滤器的顺序影响限流效果:

# ❌ 错误:Sentinel 过滤器在路由之后
spring:
  cloud:
    gateway:
      default-filters:
        - name: SentinelGatewayFilter
          # 默认 order 可能不对

# ✅ 正确:显式指定过滤器顺序
spring:
  cloud:
    sentinel:
      scg:
        order: -1    # 确保在路由之前执行限流
    gateway:
      default-filters:
        - name: SentinelGatewayFilter
          args:
            order: -1

原则:Sentinel 过滤器应该在路由过滤器之前执行,否则请求已经路由到后端服务了,限流就失去了意义。


9. 总结

核心要点回顾

功能 核心职责 关键配置
流量控制 控制进入流量 QPS/线程数 + 流控效果
熔断降级 保护调用端 慢调用/异常比例/异常数
热点参数 按参数值限流 参数索引 + 特殊项配置
系统保护 整体维度兜底 CPU/Load/RT/线程数/QPS
来源控制 黑白名单 白名单/黑名单策略

三条核心原则

  1. 规则必须持久化:生产环境绝不能裸奔,Nacos 或 MSE 托管是标配
  2. 限流阈值基于压测:不要拍脑袋,压测数据 + 30% 余量
  3. 降级要有兜底方案:降级不是返回错误,而是提供有意义的替代方案

📜 真实性声明

所有技术点均基于 Sentinel 1.8.8 + Spring Cloud Alibaba 2023.0.x 版本验证,代码示例完整可运行。文中秒杀场景基于作者在电商平台项目中的真实经验,数据规模和业务场景经过实践验证,部分敏感信息已做脱敏处理。

相关文章
|
5天前
|
人工智能 定位技术 SEO
我学 GEO 第 15 天:终于知道AI GEO该如何做?
我是暴走的莉莉酱,边旅行边研究AI GEO的数字游民。专注普通人如何提升“AI可见度”——让AI在回答用户问题时准确识别、理解并推荐你。不讲玄学,只做可测、可调、可持续的GEO实践。
419 125
|
8天前
|
机器学习/深度学习 人工智能 调度
🐴 HappyHorse 1.1 现已上线阿里云百炼!快来查收模型使用指南,现在调用享 6 折~
HappyHorse 1.1 是新一代视频生成大模型,全面升级动态表现力、角色一致性、指令遵循、视觉质感与音画协同能力。支持I2V/T2V/R2V三类生成,适配短剧、电商广告、品牌营销等场景,提供高质、流畅、可控的AI视频生产力。
706 5
🐴 HappyHorse 1.1 现已上线阿里云百炼!快来查收模型使用指南,现在调用享 6 折~
|
5天前
|
缓存 人工智能 运维
阿里云618百炼大模型Qwen3.7-Max功能、免费试用、订阅计费、配置接入详解
Qwen3.7-MAX是阿里云百炼平台推出的通义千问3.7系列旗舰大语言模型,专为智能体时代复杂任务打造,依托阿里云全域算力与自研技术,在逻辑推理、长文本处理、代码工程、长周期自主执行等领域达到行业顶尖水平。2026年618期间,该模型推出多重免费试用权益、按量计费5折、订阅套餐优惠等专属福利,覆盖个人开发者、团队与企业全场景需求,以下从核心功能、免费试用、订阅计费、配置接入四方面展开详细解析。
410 123
|
3天前
|
人工智能 自然语言处理 API
阿里云Token Plan团队版解析:功能、三档套餐与省钱订阅指南
阿里云百炼平台推出的Token Plan团队版,是面向企业与团队的AI大模型订阅服务,以Credits为统一计量单位,整合文本与图像生成模型,提供团队管理、数据安全、多工具兼容等核心能力,解决团队零散订阅AI服务的管理混乱、成本失控、数据安全等痛点。本文将从核心定位、套餐详情、计费规则、团队管理、工具兼容、便宜订阅技巧等方面,全面解析Token Plan团队版,帮助企业与团队高效、低成本地使用AI服务。
306 108
|
4天前
|
存储 人工智能 数据可视化
别再手动复制 Skill 了:多 Agent 时代的 Skill 管理方案
多 Agent 场景下 Skill 的统一管理与同步。
252 126
|
18天前
|
缓存 测试技术 API
Qwen 3.7 Plus 与 Max 实测:性价比与多模态能力差异解析(2026)
2026 年 6 月 1 日,阿里悄无声息地发布了 Qwen 3.7 Plus,距 Qwen 3.7 Max 上线刚好 11 天。同样的 1M 上下文,同样的 35 小时自治上限。但价格才是头条:Plus 是 0.40/M输入,Max是 2.50/M——便宜约 6 倍——并且还能看图、看视频。Vision Arena 上 Plus 已经排到 #16。所以这周真正值得讨论的问题不是”要不要为视觉能力买单”,而是”Max 凭什么用 6 倍价格换来 2 个百分点的 benchmark 领先”。
|
12天前
|
缓存 人工智能 运维
GLM 5.2自托管全流程实战:硬件选型、vLLM/SGLang部署与成本盈亏测算
2026年智谱发布GLM 5.2超大混合专家模型,区别于以往仅开放API的闭源大模型,该模型权重以MIT开源协议对外发布,企业与开发者可完整下载、本地审计、私有化部署,实现数据不出环境、自定义微调、自主调度推理资源。GLM 5.2拥有753B总参数,原生支持百万级上下文窗口,在代码生成、长文档推理、数学逻辑等多项基准测试中对标国际顶尖商用模型,是首款可完整自托管的前沿代码向大模型。
924 0
|
13天前
|
Linux 程序员 数据格式
【2026最新】Notepad++下载、安装和使用一篇搞定(附中文版安装包)
Notepad++ 是一款免费开源、轻量高效的 Windows 文本编辑器,支持 C/Python/HTML 等 80+ 语言语法高亮、代码折叠、正则替换、编码转换及插件扩展,专为程序员与文本处理用户打造,完美替代系统记事本。(239字)