Skip to content
清晨的一缕阳光
返回

Sentinel 基础

Sentinel 基础

Sentinel 简介

Sentinel 是面向分布式服务架构的流量控制组件,主要以流量为切入点,从流量路由、流量控制、熔断降级、系统负载保护等维度来维护系统的稳定性。

核心特性

与 Hystrix 对比

特性SentinelHystrix
隔离策略信号量隔离线程池/信号量隔离
熔断策略基于比例/慢调用基于异常比例
实时监控实时监控和控制台需要额外配置
规则配置支持多种数据源支持程序化配置
限流算法滑动窗口 + 令牌桶滑动窗口

核心概念

1. 资源(Resource)

Sentinel 中的资源可以是:

// 方式 1:注解方式
@SentinelResource(value = "getUser", blockHandler = "handleBlock")
public User getUser(Long id) {
    return userService.findById(id);
}

// 方式 2:API 方式
Entry entry = null;
try {
    entry = SphU.entry("getUser");
    // 被保护的代码
    return userService.findById(id);
} catch (BlockException e) {
    // 异常处理
    throw e;
} finally {
    if (entry != null) {
        entry.exit();
    }
}

2. 规则(Rule)

Sentinel 的规则定义了流量控制的策略:

3. 上下文(Context)

Sentinel 通过上下文追踪调用链路:

// 定义调用入口
ContextUtil.enter("enterContext");

// 调用资源
Entry entry = SphU.entry("resourceA");

// 退出资源
entry.exit();

// 退出上下文
ContextUtil.exit();

快速开始

1. 添加依赖

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

2. 基础配置

spring:
  cloud:
    sentinel:
      enabled: true
      transport:
        dashboard: localhost:8080  # Sentinel 控制台地址
        port: 8719  # 客户端端口
      datasource:
        ds1:
          nacos:
            server-addr: localhost:8848
            dataId: ${spring.application.name}-sentinel.json
            groupId: DEFAULT_GROUP
            rule-type: flow

3. 启用 Sentinel

@SpringBootApplication
public class UserServiceApplication {
    public static void main(String[] args) {
        SpringApplication.run(UserServiceApplication.class, args);
    }
}

4. 定义受保护的资源

@RestController
@RequestMapping("/users")
public class UserController {
    
    @Autowired
    private UserService userService;
    
    @GetMapping("/{id}")
    @SentinelResource(
        value = "getUserById",
        blockHandler = "handleBlock",
        fallback = "handleFallback"
    )
    public Result<User> getUser(@PathVariable Long id) {
        return Result.success(userService.findById(id));
    }
    
    // 流控处理
    public Result<User> handleBlock(Long id, BlockException ex) {
        return Result.fail("访问过于频繁,请稍后再试");
    }
    
    // 降级处理(业务异常)
    public Result<User> handleFallback(Long id, Throwable ex) {
        return Result.fail("服务暂时不可用");
    }
}

流量控制

1. QPS 限流

@Configuration
public class FlowRuleConfig {
    
    @PostConstruct
    public void initRules() {
        List<FlowRule> rules = new ArrayList<>();
        
        FlowRule rule = new FlowRule();
        rule.setResource("getUserById");
        rule.setGrade(RuleConstant.FLOW_GRADE_QPS);  // QPS 模式
        rule.setCount(100);  // 每秒最多 100 次请求
        rule.setLimitApp("default");  // 针对所有调用来源
        
        rules.add(rule);
        FlowRuleManager.loadRules(rules);
    }
}

2. 线程数限流

FlowRule rule = new FlowRule();
rule.setResource("getUserById");
rule.setGrade(RuleConstant.FLOW_GRADE_THREAD);  // 线程数模式
rule.setCount(50);  // 最多 50 个并发线程
rules.add(rule);

3. 限流模式

// 直接拒绝
rule.setLimitApp("default");

// 关联限流(关联接口限流)
rule.setLimitApp("orderService");
rule.setRelResource("createOrder");

// 链路限流(只统计指定链路的流量)
rule.setLimitApp("default");
rule.setResourceMode(RuleConstant.RESOURCE_MODE_ENTRY);

4. 限流效果

// 快速失败(默认)
rule.setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_DEFAULT);

// 预热(冷启动)
rule.setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_WARM_UP);
rule.setWarmUpPeriodSec(10);  // 预热时间 10 秒

// 排队等待(匀速排队)
rule.setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_RATE_LIMITER);
rule.setMaxQueueingTimeMs(500);  // 最大排队时间 500ms

// 预热 + 匀速排队
rule.setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_WARM_UP_RATE_LIMITER);

熔断降级

1. 异常比例熔断

@Configuration
public class DegradeRuleConfig {
    
    @PostConstruct
    public void initRules() {
        List<DegradeRule> rules = new ArrayList<>();
        
        DegradeRule rule = new DegradeRule();
        rule.setResource("getUserById");
        rule.setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_RATIO);  // 异常比例
        rule.setCount(0.5);  // 异常比例超过 50%
        rule.setTimeWindow(10);  // 熔断时长 10 秒
        rule.setMinRequestAmount(10);  // 最小请求数
        
        rules.add(rule);
        DegradeRuleManager.loadRules(rules);
    }
}

2. 异常数熔断

DegradeRule rule = new DegradeRule();
rule.setResource("getUserById");
rule.setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_COUNT);  // 异常数
rule.setCount(10);  // 异常数超过 10 个
rule.setTimeWindow(10);  // 熔断时长 10 秒

3. 慢调用比例熔断

DegradeRule rule = new DegradeRule();
rule.setResource("getUserById");
rule.setGrade(RuleConstant.DEGRADE_GRADE_SLOW_REQUEST_RATIO);  // 慢调用比例
rule.setCount(0.3);  // 慢调用比例超过 30%
rule.setSlowRatioThreshold(3);  // 响应时间超过 3 秒算慢调用
rule.setTimeWindow(10);  // 熔断时长 10 秒

热点参数限流

配置热点参数规则

@Configuration
public class ParamFlowRuleConfig {
    
    @PostConstruct
    public void initRules() {
        List<ParamFlowRule> rules = new ArrayList<>();
        
        ParamFlowRule rule = new ParamFlowRule();
        rule.setResource("getUserById");
        rule.setParamIdx(0);  // 对第一个参数限流
        rule.setCount(10);  // 每个参数值每秒最多 10 次
        rule.setDurationInSec(1);  // 统计时长 1 秒
        
        // 针对特定参数值设置限流
        List<ParamFlowItem> items = new ArrayList<>();
        ParamFlowItem item = new ParamFlowItem();
        item.setObject(String.valueOf(1));  // 参数值
        item.setCount(100);  // 该参数值每秒最多 100 次
        items.add(item);
        rule.setParamFlowItemList(items);
        
        rules.add(rule);
        ParamFlowRuleManager.loadRules(rules);
    }
}

使用

@GetMapping("/{id}")
@SentinelResource(
    value = "getUserById",
    blockHandler = "handleParamBlock"
)
public Result<User> getUser(@PathVariable Long id) {
    return Result.success(userService.findById(id));
}

public Result<User> handleParamBlock(Long id, ParamFlowException ex) {
    return Result.fail("热点参数限流");
}

系统保护

配置系统规则

@Configuration
public class SystemRuleConfig {
    
    @PostConstruct
    public void initRules() {
        List<SystemRule> rules = new ArrayList<>();
        
        // 基于系统负载保护
        SystemRule loadRule = new SystemRule();
        loadRule.setHighestSystemLoad(2.5);  // 系统 load 超过 2.5 触发保护
        
        // 基于 CPU 使用率保护
        SystemRule cpuRule = new SystemRule();
        cpuRule.setHighestCpuUsage(0.8);  // CPU 使用率超过 80% 触发保护
        
        // 基于平均响应时间保护
        SystemRule rtRule = new SystemRule();
        rtRule.setAvgRt(100);  // 平均响应时间超过 100ms 触发保护
        
        // 基于 QPS 保护
        SystemRule qpsRule = new SystemRule();
        qpsRule.setQps(1000);  // 总 QPS 超过 1000 触发保护
        
        rules.add(loadRule);
        rules.add(cpuRule);
        rules.add(rtRule);
        rules.add(qpsRule);
        
        SystemRuleManager.loadRules(rules);
    }
}

规则持久化

Nacos 数据源

spring:
  cloud:
    sentinel:
      datasource:
        # 流控规则
        flow:
          nacos:
            server-addr: localhost:8848
            dataId: ${spring.application.name}-sentinel-flow.json
            groupId: DEFAULT_GROUP
            rule-type: flow
        # 熔断规则
        degrade:
          nacos:
            server-addr: localhost:8848
            dataId: ${spring.application.name}-sentinel-degrade.json
            groupId: DEFAULT_GROUP
            rule-type: degrade
        # 系统规则
        system:
          nacos:
            server-addr: localhost:8848
            dataId: ${spring.application.name}-sentinel-system.json
            groupId: DEFAULT_GROUP
            rule-type: system

规则格式

[
  {
    "resource": "getUserById",
    "limitApp": "default",
    "grade": 1,
    "count": 100,
    "strategy": 0,
    "refResource": null,
    "controlBehavior": 0,
    "warmUpPeriodSec": 10,
    "maxQueueingTimeMs": 500
  }
]

监控与告警

集成 Actuator

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
management:
  endpoints:
    web:
      exposure:
        include: sentinel
  endpoint:
    sentinel:
      enabled: true

自定义告警

@Component
public class SentinelAlertHandler {
    
    @Autowired
    private AlertService alertService;
    
    @PostConstruct
    public void init() {
        // 注册回调
        FlowRuleManager.register2Property(new PropertyListener<FlowRule>() {
            @Override
            public void configUpdate(List<FlowRule> rules) {
                alertService.sendAlert("流控规则已更新");
            }
        });
    }
}

最佳实践

1. 资源定义

2. 规则配置

3. 异常处理

4. 规则管理

总结

Sentinel 提供了丰富的流量控制功能,包括 QPS 限流、线程数限流、熔断降级、热点参数限流等。

通过合理配置规则,可以有效保护系统免受突发流量影响,提高系统的稳定性和可用性。

在生产环境中,建议将规则持久化到配置中心,并建立完善的监控告警机制。


分享这篇文章到:

上一篇文章
Spring Boot SkyWalking 链路追踪
下一篇文章
MySQL 主从复制模式