Sentinel 基础
Sentinel 简介
Sentinel 是面向分布式服务架构的流量控制组件,主要以流量为切入点,从流量路由、流量控制、熔断降级、系统负载保护等维度来维护系统的稳定性。
核心特性
- 丰富的应用场景:支持秒杀、流量整形、熔断降级等场景
- 实时监控:提供实时的监控和规则管理界面
- 广泛的生态:与 Spring Cloud、Dubbo、gRPC 等框架无缝集成
- 灵活的规则配置:支持多种数据源动态推送规则
- 轻量级高性能:单机支持数百万 QPS 流量控制
与 Hystrix 对比
| 特性 | Sentinel | Hystrix |
|---|---|---|
| 隔离策略 | 信号量隔离 | 线程池/信号量隔离 |
| 熔断策略 | 基于比例/慢调用 | 基于异常比例 |
| 实时监控 | 实时监控和控制台 | 需要额外配置 |
| 规则配置 | 支持多种数据源 | 支持程序化配置 |
| 限流算法 | 滑动窗口 + 令牌桶 | 滑动窗口 |
核心概念
1. 资源(Resource)
Sentinel 中的资源可以是:
- 代码块(方法)
- API 接口
- 数据库调用
- 外部服务调用
// 方式 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 的规则定义了流量控制的策略:
- 流控规则:控制 QPS 或线程数
- 熔断规则:定义熔断条件
- 热点参数规则:针对热点参数限流
- 系统规则:基于系统负载保护
- 授权规则:黑白名单控制
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. 规则管理
- 使用配置中心持久化规则
- 建立规则变更审批流程
- 定期review规则有效性
总结
Sentinel 提供了丰富的流量控制功能,包括 QPS 限流、线程数限流、熔断降级、热点参数限流等。
通过合理配置规则,可以有效保护系统免受突发流量影响,提高系统的稳定性和可用性。
在生产环境中,建议将规则持久化到配置中心,并建立完善的监控告警机制。