在微服务架构中,服务间的依赖关系错综复杂,一个服务的故障可能引发 “雪崩效应”,导致整个系统瘫痪。而 Sentinel 作为阿里巴巴开源的分布式系统流量防卫兵,以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度保障服务稳定性。本文将基于 SpringCloud Alibaba 技术栈,全面梳理 Sentinel 的核心技术要点与实战应用。

一、Sentinel 核心定位与核心特征

1.1 核心定位

Sentinel(分布式系统的流量防卫兵)是阿里开源的一套用于服务容错的综合性解决方案,它以流量为核心,解决微服务高并发场景下的服务雪崩、流量峰值冲击等问题,确保系统在复杂环境下的稳定运行。

1.2 核心特征

  • 丰富的应用场景:Sentinel 承接了阿里巴巴近 10 年的双十一大促流量核心场景,可应对秒杀(突发流量控制在系统容量范围内)、消息削峰填谷、集群流量控制、实时熔断下游不可用应用等场景。
  • 完备的实时监控:Sentinel 提供实时监控功能,通过控制台可查看接入应用的单台机器秒级数据,甚至 500 台以下规模集群的汇总运行情况。
  • 广泛的开源生态:Sentinel 提供开箱即用的与其他开源框架 / 库的整合模块,如与 Spring Cloud、Dubbo、gRPC 的整合,只需引入相应依赖并简单配置,即可快速接入。

1.3 组成部分

Sentinel 分为核心库(Java 客户端)和控制台(Dashboard)两部分:

  • 核心库(Java 客户端):不依赖任何框架 / 库,可运行于所有 Java 运行时环境,同时对 Dubbo、Spring Cloud 等框架有较好支持。
  • 控制台(Dashboard):基于 Spring Boot 开发,打包后可直接运行,无需额外的 Tomcat 等应用容器。

二、Sentinel 核心功能与规则配置

Sentinel 通过多样化的规则,实现对服务的全方位保护,核心包含五大规则,各规则的作用、配置要点如下:

2.1 流控规则:防止流量峰值冲垮系统

流控规则的核心是监控应用流量的 QPS(每秒查询率)或并发线程数等指标,当达到指定阈值时对流量进行控制,避免被瞬时流量高峰冲垮,保障应用高可用性。

关键配置项
  • 资源名:唯一名称,默认是请求路径,可自定义。
  • 针对来源:指定对哪个微服务进行限流,默认是default,表示不区分来源,全部限制。
  • 阈值类型 / 单机阈值
    • QPS(每秒请求数量):当调用该接口的 QPS 达到阈值时,进行限流。
    • 线程数:当调用该接口的线程数达到阈值时,进行限流。
  • 流控模式
    • 直接(默认):接口达到限流条件时,开启限流。
    • 关联:当关联的资源达到限流条件时,开启对当前接口的限流,适合应用让步场景(如读操作与写操作争抢资源时,写操作高频则限制读操作)。
    • 链路:当从某个接口过来的资源达到限流条件时,开启限流(如仅限制 “查询订单” 链路中对 “查询商品” 的请求)。
  • 流控效果
    • 快速失败(默认):直接失败,抛出异常,不做额外处理。
    • Warm Up:从开始阈值到最大 QPS 阈值有缓冲阶段,初始阈值为最大 QPS 阈值的 1/3,逐步增长至最大阈值,适用于突发流量转换为缓步增长的场景。
    • 排队等待:让请求以均匀速度通过,单机阈值为每秒通过数量,超超时时间未处理的请求会被丢弃。

2.2 降级规则:避免服务级联故障

降级规则用于设置服务降级的触发条件,当服务出现不稳定表现(如慢调用、异常比例升高)时,快速失败,避免影响其他资源导致级联故障。Sentinel 提供三种熔断策略:

三种熔断策略
  • 慢调用比例:需设置允许的慢调用 RT(最大响应时间),请求响应时间大于该值则统计为慢调用。当单位统计时长内请求数大于最小请求数,且慢调用比例大于阈值时,触发熔断,熔断时长内请求自动被熔断;熔断时长后进入半开状态,若后续一个请求响应时间小于慢调用 RT 则结束熔断,否则再次熔断。
  • 异常比例:单位统计时长内请求数大于最小请求数,且异常比例大于阈值(范围 0.0-1.0,代表 0%-100%)时,触发熔断;熔断时长后进入半开状态,后续一个请求成功则结束熔断,否则再次熔断。
  • 异常数:单位统计时长内异常数目超过阈值后自动熔断;熔断时长后进入半开状态,后续一个请求成功则结束熔断,否则再次熔断。

2.3 热点规则:针对性限制高频访问数据

热点规则用于对高频访问的热点数据(如商品 ID、用户 ID)进行限流,仅对包含热点参数的资源调用生效。配置时需注意:

  1. 需在请求方法上添加@SentinelResource注解,否则热点规则无效。
  2. 可设置参数例外项,对特定参数值单独设置限流阈值(如商品 ID 为 1 时阈值设为 3,其他商品 ID 阈值设为 10)。

2.4 授权规则:基于来源的访问控制

授权规则即黑白名单控制,根据请求来源(origin)限制资源是否通过:

  • 白名单:仅请求来源在白名单内时可通过。
  • 黑名单:请求来源在黑名单内时不通过,其余请求通过。配置时需先定义请求来源的获取方式(如从请求参数serviceName中获取),再针对资源设置授权类型与流控应用。

2.5 系统规则:保障应用整体稳定性

系统规则从应用级别入口流量进行控制,监控单台机器的 Load、CPU 使用率、平均 RT、入口 QPS 和并发线程数等指标,让系统在最大吞吐量下保持稳定,且仅对入口流量(如 Web 服务、Dubbo 服务端接收的请求)生效。支持的模式包括:

  • Load 自适应(仅 Linux/Unix-like 机器生效):以系统 Load1 为启发指标,Load1 超设定值且并发线程数超系统容量时触发保护。
  • CPU 使用率:CPU 使用率超阈值(0.0-1.0)时触发保护。
  • 平均 RT:所有入口流量的平均 RT 达到阈值时触发保护。
  • 并发线程数:所有入口流量的并发线程数达到阈值时触发保护。
  • 入口 QPS:所有入口流量的 QPS 达到阈值时触发保护。

三、Sentinel 实战集成

3.1 微服务集成 Sentinel

以订单微服务(shop-order-server)为例,集成步骤如下:

  1. 添加依赖:在 pom.xml 中引入 Sentinel 组件依赖。

xml

<!--sentinel组件-->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
  1. 安装并启动 Sentinel 控制台

    bash

    java -Dserver.port=8080 -Dcsp.sentinel.dashboard.server=localhost:8080 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard-1.8.5.jar
    
  2. 配置控制台地址:在微服务的 application.yml 中新增 Sentinel 配置,指定与控制台通信的端口和控制台地址。

yaml

spring:
  cloud:
    sentinel: 
      transport: 
        port: 9999 # 与控制台交流的端口,随意指定未使用的端口
        dashboard: localhost:8080 # 控制台服务地址
  1. 验证集成:启动微服务后,多次访问接口,刷新 Sentinel 控制台即可看到微服务的监控数据(默认不显示,需触发接口调用后刷新)。

3.2 Feign 整合 Sentinel

在微服务调用中,Feign 常用于远程调用,整合 Sentinel 可实现服务调用的降级兜底,步骤如下:

  1. 开启 Feign 对 Sentinel 的支持:在配置文件中添加配置。

yaml

feign:
  sentinel:
    enabled: true
  1. 创建容错类:实现 Feign 接口,定义服务降级时的兜底逻辑(如返回默认兜底数据)。

java

@Component
public class ProductFeignFallBack implements ProductFeignApi {
    @Override
    public Product findByPid(Long pid) {
        Product product = new Product();
        product.setPid(-1L);
        product.setPname("兜底数据");
        product.setPprice(0.0);
        return product;
    }
}
  1. 绑定容错类:在 Feign 接口的@FeignClient注解中通过fallback属性指定容错类。

java

@FeignClient(name = "product-service",path = "/product",fallback = ProductFeignFallBack.class)
public interface ProductFeignApi {
    @RequestMapping("/get")
    Product findByPid(@RequestParam("pid") Long pid);
}
  1. 验证效果:停止所有商品服务,重启订单服务并访问接口,可看到返回兜底数据。

3.3 Sentinel 规则持久化(基于 Nacos)

Sentinel 控制台配置的规则默认在服务重启后消失,通过 Nacos 可实现规则持久化,步骤如下:

  1. 添加依赖:在 pom.xml 中引入 Sentinel-Nacos 数据源依赖。

xml

<!-- sentinel持久化访问Nacos的数据源依赖 -->
<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
  1. 配置数据源:在 bootstrap.yml 中增加 Sentinel 数据源配置,指定 Nacos 地址、DataID、分组、数据类型和规则类型(如 flow 流控规则)。

yaml

spring:
  cloud:
    sentinel:
      datasource: # sentinel数据源
        ds1: # 自定义连接名
          nacos:
            server-addr: localhost:8848 # nacos服务地址
            dataId: sentinel-consumer-ds1 # nacos的dataId
            groupId: DEFAULT_GROUP # 默认分组
            data-type: json # 数据类型 json类型
            rule-type: flow # flow表示流控规则
  1. 在 Nacos 中配置规则:新建对应 DataID 的配置,以 JSON 格式编写规则内容(如流控规则)。

json

[
  {
    "resource":"/sentinel2",
    "limitApp":"default",
    "grade": 1,
    "count": 2,
    "strategy": 0,
    "controlBehavior": 0,
    "clusterMode": false
  }
]
  1. 验证:启动微服务并访问对应接口,在 Sentinel 控制台可看到持久化的规则。

3.4 自定义异常返回

当 Sentinel 触发规则限制时,默认返回 “Blocked by Sentinel (flow limiting)”,可通过实现BlockExceptionHandler接口自定义异常返回格式,支持区分限流、降级、授权等不同异常类型。

java

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

    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    class ResultData {
        private int code;
        private String message;
    }
}

3.5 @SentinelResource 注解的使用

@SentinelResource用于定义资源,并指定异常处理和降级逻辑,核心属性如下表所示:

属性 作用
value 资源名称,必需项(不能为空)
entryType 定义入口类型,可选EntryType.IN(方法执行前统计)和EntryType.OUT(方法执行后统计),默认EntryType.OUT
blockHandler / blockHandlerClass blockHandler指定处理BlockException的方法名,方法需为 public、与原方法返回值和参数匹配且额外加BlockException参数;blockHandlerClass指定方法所在类(需为 static 方法)
fallback / fallbackClass fallback指定处理业务异常的方法名,方法返回值需与原方法一致,参数可与原方法一致或额外加Throwable参数;fallbackClass指定方法所在类(需为 static 方法)
defaultFallback 默认降级方法名,用于通用降级逻辑,方法返回值需与原方法一致,参数可为空或额外加Throwable参数
exceptionsToIgnore 指定排除的异常类型,该类异常不计入异常统计,也不进入 fallback 逻辑

示例代码:

java

@RestController
@Slf4j
public class AnnoController {
    @RequestMapping("/anno1")
    @SentinelResource(
        value = "anno1",
        blockHandler = "anno1BlockHandler",
        fallback = "anno1Fallback"
    )
    public String anno1(String name) {
        if ("wolfcode".equals(name)) {
            throw new RuntimeException();
        }
        return "anno1";
    }

    // 处理BlockException(限流、降级等)
    public String anno1BlockHandler(String name, BlockException ex) {
        log.error("{}", ex);
        return "接口被限流或者降级了";
    }

    // 处理业务异常
    public String anno1Fallback(String name, Throwable throwable) {
        log.error("{}", throwable);
        return "接口发生异常了";
    }
}

四、Sentinel 在网关中的应用(Gateway 集成)

网关作为微服务的统一入口,可通过 Sentinel 实现网关层限流,Sentinel 支持对 Spring Cloud Gateway 的两种资源维度限流:

  • route 维度:以 Spring 配置文件中配置的路由条目(routeId)为资源。
  • 自定义 API 维度:用户通过 Sentinel API 自定义 API 分组,按分组限流。

4.1 网关集成 Sentinel 步骤

  1. 添加依赖:在网关模块(api-gateway)的 pom.xml 中引入 Sentinel 相关依赖。

xml

<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-spring-cloud-gateway-adapter</artifactId>
</dependency>
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>
</dependency>
  1. 配置控制台地址:在网关的 application.yml 中添加 Sentinel 配置。

yaml

spring:
  cloud:
    sentinel:
      transport:
        port: 9999
        dashboard: localhost:8080
  1. 验证:重启网关服务,频繁访问接口,可看到限流效果(默认返回 “Blocked by Sentinel: ParamFlowException”)。

4.2 自定义 API 分组限流

Sentinel 支持按 API 分组限流,提供三种匹配模式:

  • 精准匹配:精确匹配请求 URL(如/product-service/v1/test1),仅匹配指定 URL。
  • 前缀匹配:按 URL 前缀匹配(如/product-service/v1/),匹配该前缀下的所有 URL。
  • 正则匹配:按正则表达式匹配(如/product-service/v1/.*),匹配符合正则的所有 URL。

配置时需先在 Sentinel 控制台新建 API 分组并选择匹配模式,再在流控规则中选择 “API 分组” 类型,指定对应的 API 名称即可实现分组限流。

4.3 网关限流默认返回格式修改

网关限流默认返回格式可通过配置BlockRequestHandler自定义,示例如下:

java

@Configuration
public class GatewayConfiguration {
    @PostConstruct
    public void initBlockHandlers() {
        BlockRequestHandler blockRequestHandler = new BlockRequestHandler() {
            @Override
            public Mono<ServerResponse> handleRequest(ServerWebExchange serverWebExchange, Throwable throwable) {
                Map<String, Object> map = new HashMap<>();
                map.put("code", 0);
                map.put("message", "接口被限流了");
                return ServerResponse.status(HttpStatus.OK)
                        .contentType(MediaType.APPLICATION_JSON)
                        .body(BodyInserters.fromValue(map));
            }
        };
        GatewayCallbackManager.setBlockHandler(blockRequestHandler);
    }
}

配置后,限流时将返回自定义 JSON 格式(如{"code":0,"message":"接口被限流了"})。

五、总结

Sentinel 作为微服务架构下的流量防卫兵,通过流量控制、熔断降级、系统保护等核心能力,有效解决了服务雪崩、流量峰值冲击等问题。在 SpringCloud Alibaba 技术栈中,Sentinel 可无缝整合 Feign、Gateway 等组件,并通过 Nacos 实现规则持久化,为微服务系统的稳定性提供全方位保障。掌握 Sentinel 的核心规则与实战集成,是构建高可用微服务系统的关键一步。

Logo

码道开发者社区,聚焦华为云码道 CodeArts 代码智能体,沉淀 Agent、Skill、鸿蒙开发实战内容,供开发者查阅资料、交流技术、分享工程实践

更多推荐