点赞再看,养成习惯,微信搜索「小大白日志」关注这个搬砖人。
文章不定期同步公众号,还有各种一线大厂面试原题、我的学习系列笔记。
什么是sentinel
- sentinel是Spring Cloud Alibaba的一个重要组件,类似于spring clound的hystrix,与hystrix-dashboard控制台一样,sentinel-dashboard控制台可以提供对流量的实时监控、在线维护流量规则、熔断规则,前提是微服务整合了sentinel
- 对比hystrix
Sentinel | Hystrix | |
隔离策略 | 信号量隔离 | 线程池隔离/信号量隔离 |
熔断降级策略 | 基于响应时间或失败比率 | 线程池隔离/ 基于响应时间或失败比率 |
实时指标实现 | 滑动窗口 | 滑动窗口(基于 RxJava) |
规则配置 | 支持多种数据源 | 支持多种数据源 |
扩展性 | 多个扩展点 | 插件的形式 |
基于注解的支持 | 支持 | 支持 |
限流 | 基于 QPS,支持基于调用关系的限流 | 有限的支持 |
流量整形 | 支持慢启动、匀速器模式 | 不支持 |
系统负载保护 | 支持 | 不支持 |
控制台 | 开箱即用,可配置规则、查看秒级监控、机器发现等 | 不完善 |
常见框架的适配 | Servlet、Spring Cloud、Dubbo、gRPC 等 | Servlet、Spring Cloud Netflix |
hystrix官方已停止更新,而sentinel则保持着开源
基础概念
- Resource:资源resource可以是代码块、方法(普通方法、接口)等,把它们定义为资源后,再定义限流规则,就可以结合sentinel使用了
- Slot插槽:sentinel中定义了7种slot插槽,sentinel正是通过各个插槽间的固定调用顺序来实现限流的,因为后面的插槽可能依赖于前面插槽的计算结果
- Entry:是否通过限流的凭证,sentinel有三种形式来定义资源
- 调用SphU.entry("资源")来定义资源:定义成功则返回一个Entry对象,否则抛出异常以拒绝往下执行限流代码,代表此资源已被定义,需要执行其他处理代码,不管是否成功定义资源最后都要执行entry.exit()退出资源
- 调用SphO.entry("资源")来定义资源:返回true表示定义成功,若定义资源失败则返回false以拒绝往下执行限流代码,需要执行其他处理代码,不管是否成功定义资源最后都要执行SphO.exit()退出资源调用
- 注解的方式定义资源:上面两种方式对代码侵入性很高,可用@SentinelResource注解的方式作用于方法上,并配置blockHandler指定限流处理方式
- Node节点:DefaultNode=链路节点,可统计调用链路上某个资源的数据;ClusterNode=簇节点,可统计某个资源的全局数据;StatisticNode=基础节点,其数据结构有秒级/分钟级别的滑动窗口结构;EntranceNode=入口节点,包含一些入口数据
- Context:上下文,ThreadLocal传递,包含一次链路调用的所有信息,如链路节点DefaultNode,入口节点EntranceNode
使用sentinel:定义限流规则及定义资源
- 引入依赖
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-core</artifactId>
<version>1.7.1</version>
</dependency>
- 定义规则及定义资源
规则是要作用于资源上的,下面先定义规则,再用【SphU.entry()】或【SphO.entry()】或注解的形式定义资源:
public class demo {
public static void main(String[] args) {
// 定义规则
initFlowRules();
//用SphU.entry()的形式定义资源
while (true) {
try (Entry entry = SphU.entry("myResource")) {//与规则定义中的rule.setResource("myResource")一致
// 被保护的业务逻辑...
System.out.println("业务资源访问成功!");
} catch (BlockException ex) {
// 处理被流控的逻辑:限流或降级...
System.out.println("资源访问失败!!!");
} finally {
if (entry != null) {
entry.exit();//必须退出资源调用
}
}
}
//用SphO.entry()的形式定义资源
while (true) {
if(SphO.entry("myResource")){//与规则定义中的rule.setResource("myResource")一致
try{
// 被保护的业务逻辑...
System.out.println("业务资源访问成功!");
} catch (BlockException ex) {
// 处理被流控的逻辑:限流或降级...
System.out.println("资源访问失败!!!");
}finally{
SphO.exit();//必须退出资源调用
}
}
}
//上面两种方式对代码侵入性很高,可用注解的方式定义资源
while(true){
getUserById("111");
}
}
//定义规则
private static void initFlowRules(){
List<FlowRule> rules = new ArrayList<>();// 存储规则 FlowRule
FlowRule rule = new FlowRule();
rule.setResource("myResource"); // 指定限流规则作用于哪个资源上,资源名为字符串,可为任意有标识意义的方法名/接口名/其他字符串,此处资源名为"myResource"
rule.setGrade(RuleConstant.FLOW_GRADE_QPS); // 限流类型为QPS模式:限制QPS
rule.setCount(10); // QPS不得超出10
rule.setLimitApp("default"); // 针对的调用来源,default代表不区分来源
rules.add(rule);
FlowRuleManager.loadRules(rules);// 加载规则
}
//定义"myResource"资源,并设置违背sentinel流控规则时的处理方法handlerException()
@SentinelResource(value="myResource",blockHandler="handlerException")
public User getUserById(String id){
return new User("数据库用户");
}
//注意:此处理方法的参数必须和定义资源的方法getUserById参数一致()同时加上【BlockException exception】参数
public User handlerException(String id,BlockException exception){
return new User("流控用户");
}
}
Entry entry = null;
try {
entry = SphU.entry("myResource"); //此处说明资源
// 被保护的业务逻辑
...
} catch (BlockException e1) {
// 资源访问阻止,被限流或被降级,进行相应的处理操作
...
} finally {
if (entry != null) {
entry.exit();
}
}
单独启动sentinel
- 下载sentinel-dashboard-1.6.0.jar包(++链接++),启动:java -jar
-Dserver.port=8888 sentinel-dashboard-1.6.0.jar
- 访问localhost:8888登录sentinel-dashboard控制台,默认用户名/密码是sentinel/sentinel
可以看到控制台没有对任何的微服务进行流量监控 - 项目整合sentinel
- pom.xml引入依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
- 在项目的properties文件中加入:
spring.clound.sentinel.transport.dashboard=localhost:8888 #设置sentinel控制台的地址
spring.application.name=myapp #项目名
- 浏览器访问该项目后,再次回到sentinel控制台,可以看到myapp项目中所有对controller接口的监控,可以在左侧“簇点链路”新增流控规则,设置每个接口的QPS(每秒允许访问多少次)
OK,如果文章哪里有错误或不足,欢迎各位留言。