Skip to content

Sentinel服务熔断与限流

Sentinel 是阿里巴巴开源的面向分布式服务架构的轻量级流量控制组件,主要以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。Spring Cloud Alibaba Sentinel 提供了 Spring Cloud 标准的服务熔断与限流实现。

Sentinel 核心功能

Sentinel 具有以下核心功能:

  1. 流量控制:根据系统负载和调用方式控制流量
  2. 熔断降级:当调用链路中某个资源出现问题时,暂时切断对该资源的调用
  3. 系统负载保护:根据系统指标(如 CPU 使用率、系统负载)动态调整流量
  4. 实时监控:提供实时的监控和统计功能
  5. 规则持久化:支持规则的动态配置和持久化

安装与部署 Sentinel 控制台

Sentinel 控制台是流量控制、熔断降级规则统一配置和管理的界面,也可以查看监控和实时规则。

方式一:从 GitHub 下载 jar 包

  1. GitHub Releases 下载 jar 包
  2. 运行控制台:
    bash
    java -Dserver.port=8080 -jar sentinel-dashboard-1.8.5.jar

方式二:使用 Docker

bash
docker run --name sentinel -d -p 8858:8858 bladex/sentinel-dashboard:latest

启动后,可以通过浏览器访问控制台:

http://localhost:8858

默认用户名和密码都是 sentinel

整合 Spring Boot 应用

1. 添加依赖

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

2. 配置应用

application.propertiesapplication.yml 中添加配置:

yaml
spring:
  cloud:
    sentinel:
      transport:
        dashboard: localhost:8858  # Sentinel 控制台地址
        port: 8719  # 应用与 Sentinel 控制台通信端口,默认为 8719
      eager: true  # 取消懒加载,即服务启动时就初始化 Sentinel

3. 定义资源

Sentinel 中的资源是保护的对象,可以是任何代码块。最常见的资源是 Spring MVC 的接口方法和 OpenFeign 客户端方法。

方式一:使用 @SentinelResource 注解定义资源

java
@RestController
public class HelloController {
    
    @GetMapping("/hello")
    @SentinelResource(value = "hello", 
                      blockHandler = "helloBlockHandler",
                      fallback = "helloFallback")
    public String hello(String name) {
        if (StringUtils.isEmpty(name)) {
            throw new IllegalArgumentException("参数不能为空");
        }
        return "Hello, " + name;
    }
    
    // 处理限流或降级
    public String helloBlockHandler(String name, BlockException ex) {
        log.warn("限流,资源名:{}", ex.getRule().getResource(), ex);
        return "系统繁忙,请稍后再试";
    }
    
    // 处理业务异常
    public String helloFallback(String name, Throwable t) {
        log.error("接口调用异常", t);
        return "服务异常,请稍后再试";
    }
}

在上面的例子中:

  • value 指定资源名称
  • blockHandler 指定被限流/降级/系统保护时的处理函数
  • fallback 指定业务异常时的处理函数

方式二:Spring MVC 和 OpenFeign 的自动资源定义

对于 Spring MVC 控制器和 OpenFeign 客户端,Sentinel 会自动将它们定义为资源,无需额外配置。

Spring MVC 控制器资源名规则:{HTTP_METHOD}:{requestPattern},如 GET:/hello

OpenFeign 客户端资源名规则:{ServiceName}:{MethodSignature},如 user-service:getUserById(Long)

4. 配置流量控制规则

规则可以通过代码、控制台或配置文件进行配置。

方式一:通过代码配置

java
@PostConstruct
public void initFlowRules() {
    List<FlowRule> rules = new ArrayList<>();
    
    // 创建流控规则
    FlowRule rule = new FlowRule();
    rule.setResource("hello");  // 资源名
    rule.setGrade(RuleConstant.FLOW_GRADE_QPS);  // 限流阈值类型(QPS)
    rule.setCount(10);  // 每秒允许10个请求
    
    rules.add(rule);
    FlowRuleManager.loadRules(rules);
}

方式二:通过控制台配置

在 Sentinel 控制台的"流控规则"页面,点击"新增流控规则"按钮,填写相关信息后保存。

方式三:通过配置文件配置

yaml
spring:
  cloud:
    sentinel:
      datasource:
        ds1:
          file:
            file: classpath:sentinel/flow-rule.json
            data-type: json
            rule-type: flow

JSON 配置示例:

json
[
  {
    "resource": "hello",
    "limitApp": "default",
    "grade": 1,
    "count": 10,
    "strategy": 0,
    "controlBehavior": 0
  }
]

流量控制详解

流控模式

Sentinel 支持三种流控模式:

  1. 直接模式(默认):直接对资源限流
  2. 关联模式:当关联的资源达到阈值时,限流自己
  3. 链路模式:对从指定入口进来的流量限流

流控效果

Sentinel 支持三种流控效果:

  1. 快速失败(默认):直接拒绝请求
  2. Warm Up:预热/冷启动,逐渐增加流量
  3. 排队等待:请求匀速通过,多余的请求排队等待

流控规则属性

流控规则主要包含以下属性:

属性说明可选值
resource资源名-
count限流阈值-
grade限流阈值类型QPS(1)、并发线程数(0)
limitApp流控针对的调用来源default 表示不区分调用来源
strategy调用关系限流策略直接(0)、关联(1)、链路(2)
controlBehavior流控效果快速失败(0)、Warm Up(1)、排队等待(2)
clusterMode是否集群限流true/false

熔断降级详解

熔断策略

Sentinel 支持三种熔断策略:

  1. 慢调用比例:当调用时间超过阈值的请求比例达到设定值时触发熔断
  2. 异常比例:当资源的每秒异常总数占通过量的比例超过阈值时触发熔断
  3. 异常数:当资源近一分钟的异常数目超过阈值时触发熔断

熔断规则配置

java
@PostConstruct
public void initDegradeRules() {
    List<DegradeRule> rules = new ArrayList<>();
    
    // 创建熔断规则
    DegradeRule rule = new DegradeRule();
    rule.setResource("hello");  // 资源名
    rule.setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_RATIO);  // 熔断策略(异常比例)
    rule.setCount(0.5);  // 异常比例阈值,范围是 [0.0, 1.0]
    rule.setTimeWindow(10);  // 熔断时长,单位为秒
    rule.setMinRequestAmount(5);  // 熔断触发的最小请求数
    rule.setStatIntervalMs(1000);  // 统计时长,单位为毫秒
    
    rules.add(rule);
    DegradeRuleManager.loadRules(rules);
}

系统自适应保护

Sentinel 支持系统自适应保护,根据系统的负载情况自动调整流量。

java
@PostConstruct
public void initSystemRules() {
    List<SystemRule> rules = new ArrayList<>();
    
    // 设置系统保护规则
    SystemRule rule = new SystemRule();
    rule.setHighestSystemLoad(10);  // 最大系统负载
    rule.setAvgRt(5000);  // 所有入口流量的平均响应时间
    rule.setMaxThread(200);  // 入口流量的最大并发数
    rule.setQps(2000);  // 所有入口资源的 QPS
    rule.setCpuUsageRatio(0.8);  // CPU 使用率
    
    rules.add(rule);
    SystemRuleManager.loadRules(rules);
}

整合 OpenFeign

当使用 Sentinel 整合 OpenFeign 时,需要在配置中开启 Sentinel 支持:

yaml
feign:
  sentinel:
    enabled: true

然后为 Feign 客户端定义回退类:

java
@FeignClient(name = "user-service", fallback = UserServiceFallback.class)
public interface UserService {
    @GetMapping("/users/{id}")
    User getUserById(@PathVariable("id") Long id);
}

@Component
public class UserServiceFallback implements UserService {
    @Override
    public User getUserById(Long id) {
        return new User(id, "默认用户", 0);
    }
}

规则持久化

为了防止规则在应用重启后丢失,Sentinel 支持将规则持久化到外部数据源。

整合 Nacos 实现规则持久化

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

配置 Nacos 数据源:

yaml
spring:
  cloud:
    sentinel:
      datasource:
        ds1:
          nacos:
            server-addr: localhost:8848
            dataId: ${spring.application.name}-flow-rules
            groupId: SENTINEL_GROUP
            data-type: json
            rule-type: flow

常见问题及解决方案

控制台无法显示应用实例

  • 检查应用与控制台的网络连通性
  • 确认 spring.cloud.sentinel.transport.dashboard 配置正确
  • 确认端口未被防火墙阻止

流控规则不生效

  • 检查资源名称是否与规则中定义的一致
  • 查看应用日志,确认规则是否正确加载
  • 尝试通过代码方式设置规则,验证功能是否正常

预热模式下流量不符合预期

预热模式(Warm Up)下,冷启动期间允许通过的 QPS 是设置的阈值的 1/3,然后逐渐增加到设定的阈值。确认 warmUpPeriodSec 参数设置合理。

Fallback 和 BlockHandler 的区别

  • fallback:处理业务异常,如超时、网络异常等
  • blockHandler:处理 Sentinel 控制台配置的规则触发的限流、熔断等

正确区分这两种情况,可以更精细地处理不同类型的异常。

最佳实践

  1. 明确资源定义边界:资源定义要明确,粒度要合适,过大或过小都不利于流控和熔断
  2. 灵活使用不同的流控模式:根据业务场景选择合适的流控模式
  3. 合理设置熔断条件:熔断条件既不能过于宽松(减弱保护能力),也不能过于严格(影响正常业务)
  4. 实现细粒度的 fallback:为不同的异常场景实现不同的 fallback 逻辑
  5. 持久化规则配置:使用 Nacos 等保存规则配置,避免规则丢失
  6. 结合监控系统:与 Prometheus、Grafana 等监控系统结合,实时监控系统状态
  7. 分布式限流:对于分布式环境,考虑使用集群限流功能

总结

Sentinel 作为 Spring Cloud Alibaba 的重要组件,提供了全面的流量控制、熔断降级和系统保护功能,有效保障了微服务的稳定性和可靠性。相比于 Hystrix,Sentinel 提供了更多的流控模式和效果,以及更直观的监控和配置界面,成为微服务保护的强大工具。