官网
https://sentinelguard.io/zh-cn/index.html
简介
Sentinel 是阿里巴巴开源的一款面向分布式系统的 流量治理组件,专注于流量控制、熔断降级、系统负载保护等核心功能,旨在保障微服务架构的高可用性。
功能
- 流量控制:基于 QPS(每秒请求数)、线程数、系统负载等指标,限制资源访问速率,防止系统过载
- 熔断降级:当某个资源的异常比例或响应时间超过阈值时,触发熔断,短时间内不再访问该资源。支持失败率、慢调用比例等指标触发熔断,并提供自动恢复机制。
- 系统负载保护:自适应保护根据 CPU 使用率、平均 RT(响应时间)等系统指标动态调整流量,避免整体过载 。热点参数限流针对高频访问的参数单独限流,避免局部热点引发系统崩溃 。
- 实时监控与动态规则:Dashboard 控制台提供实时监控、规则配置、集群流量管理等功能,支持动态调整限流参数。
入门使用
1.引入依赖
java
<!-- https://mvnrepository.com/artifact/com.alibaba.cloud/spring-cloud-starter-alibaba-sentinel -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
<version>2021.0.5.0</version>
</dependency>
⚠️版本号要根据官方文档来选择。
下载并启动 Sentinel 控制台
使用命令启动(要求java版本>=1.8)
java
java -Dserver.port=8131 -jar sentinel-dashboard-1.8.6.jar
Dserver.port随便只要不重复
程序启动时需要加入 JVM 参数 -Dcsp.sentinel.dashboard.server=consoleIp:port 指定控制台地址和端口,与上述端口一致。
补充
Sentinel 的开发主要包括定义资源和定义规则
资源
任何需保护的代码单元,如接口、方法或服务,通过注解 @SentinelResource 或 API 定义
java
// value 默认为方法名 blockHandler控制限流 fallback降级处理
@SentinelResource(value = "listQuestionBankVOByPage", blockHandler = "handleBlockException", fallback = "handleFallback")
public BaseResponse<Page<QuestionBankVO>> listQuestionBankVOByPage(@RequestBody QuestionBankQueryRequest questionBankQueryRequest,
HttpServletRequest request) {
long current = questionBankQueryRequest.getCurrent();
long size = questionBankQueryRequest.getPageSize();
// 限制爬虫
ThrowUtils.throwIf(size > 20, ErrorCode.PARAMS_ERROR);
// 查询数据库
Page<QuestionBank> questionBankPage = questionBankService.page(new Page<>(current, size),
questionBankService.getQueryWrapper(questionBankQueryRequest));
// 获取封装类
return ResultUtils.success(questionBankService.getQuestionBankVOPage(questionBankPage, request));
}
/**
* 限流操作 要求方法名跟@SentinelResource中的blockHandler一样,并且返回值也得一样,参数在原有基础之上添加BlockException
*
* @param questionBankQueryRequest
* @param request
* @return
*/
public BaseResponse<Page<QuestionBankVO>> handleBlockException(@RequestBody QuestionBankQueryRequest questionBankQueryRequest,
HttpServletRequest request, BlockException ex) {
//降级操作 熔断后的异常只会在BlockException生效
if (ex instanceof DegradeException) {
return handleFallback(questionBankQueryRequest, request, ex);
}
// 限流操作
return ResultUtils.error(ErrorCode.SYSTEM_ERROR, "系统压力过大,请耐心等待");
}
`
/**
* 降级操作 要求方法名跟@SentinelResource中的fallback一样,并且返回值也得一样,参数在原有基础之上添加Throwable
*
* @param questionBankQueryRequest
* @param request
* @param ex
* @return
*/
public BaseResponse<Page<QuestionBankVO>> handleFallback(@RequestBody QuestionBankQueryRequest questionBankQueryRequest,
HttpServletRequest request, Throwable ex) {
return ResultUtils.success(null);
}
规则
流控规则、熔断规则等,可通过代码或控制台动态配置
热点参数限流
Sentinel 会针对高频访问的参数(如 IP)单独统计流量,避免局部流量过载导致系统崩溃。
java
// 基于 IP 限流
String remoteAddr = request.getRemoteAddr();
Entry entry = null;
try {
entry = SphU.entry("listQuestionVOByPage", EntryType.IN, 1, remoteAddr);
// 被保护的业务逻辑
// 查询数据库
Page<Question> questionPage = questionService.listQuestionByPage(questionQueryRequest);
// 获取封装类
return ResultUtils.success(questionService.getQuestionVOPage(questionPage, request));
} catch (Throwable ex) {
// 业务异常
if (!BlockException.isBlockException(ex)) {
Tracer.trace(ex);
return ResultUtils.error(ErrorCode.SYSTEM_ERROR, "系统错误");
}
// 降级操作
if (ex instanceof DegradeException) {
return handleFallback(questionQueryRequest, request, ex);
}
// 限流操作
return ResultUtils.error(ErrorCode.SYSTEM_ERROR, "访问过于频繁,请稍后再试");
} finally {
if (entry != null) {
entry.exit(1, remoteAddr);
}
}
/**
* listQuestionVOByPage 降级操作:直接返回本地数据
*/
public BaseResponse<Page<QuestionVO>> handleFallback(QuestionQueryRequest questionQueryRequest,
HttpServletRequest request, Throwable ex) {
// 可以返回本地数据或空数据
return ResultUtils.success(null);
}
通过编码方式定义规则。定义一个单独的 Manager 作为 Bean,利用 @PostConstruct 注解,在 Bean 加载后创建规则。
java
@Component
public class SentinelRulesManager {
@PostConstruct
public void initRules() {
initFlowRules();
initDegradeRules();
}
// 限流规则
public void initFlowRules() {
// 单 IP 查看题目列表限流规则
ParamFlowRule rule = new ParamFlowRule("listQuestionVOByPage")
//注意这里要和SphU.entry的参数对应
.setParamIdx(0) // 对第 0 个参数限流,即 IP 地址
.setCount(60) // 每分钟最多 60 次
.setDurationInSec(60); // 规则的统计周期为 60 秒
ParamFlowRuleManager.loadRules(Collections.singletonList(rule));
}
// 降级规则
public void initDegradeRules() {
// 单 IP 查看题目列表熔断规则
DegradeRule slowCallRule = new DegradeRule("listQuestionVOByPage")
.setGrade(CircuitBreakerStrategy.SLOW_REQUEST_RATIO.getType())
.setCount(0.2) // 慢调用比例大于 20%
.setTimeWindow(60) // 熔断持续时间 60 秒
.setStatIntervalMs(30 * 1000) // 统计时长 30 秒
.setMinRequestAmount(10) // 最小请求数
.setSlowRatioThreshold(3); // 响应时间超过 3 秒
DegradeRule errorRateRule = new DegradeRule("listQuestionVOByPage")
.setGrade(CircuitBreakerStrategy.ERROR_RATIO.getType())
.setCount(0.1) // 异常率大于 10%
.setTimeWindow(60) // 熔断持续时间 60 秒
.setStatIntervalMs(30 * 1000) // 统计时长 30 秒
.setMinRequestAmount(10); // 最小请求数
// 加载规则
DegradeRuleManager.loadRules(Arrays.asList(slowCallRule, errorRateRule));
}
}