赞
踩
在前面学习 Spring Cloud Gateway
的时候,我们已经使用过了 Sentinel
来进行限流,但是并没有对 Sentinel
进行详细的学习,那今天就要补上这块知识了。
话不多说,开始今天的学习。
Sentinel 是阿里中间件团队开源的,面向分布式服务架构的轻量级高可用流量控制组件,主要以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度来帮助用户保护服务的稳定性。
资源是 Sentinel 的关键概念。它可以是 Java 应用程序中的任何内容,例如,由应用程序提供的服务,或由应用程序调用的其它应用提供的服务,甚至可以是一段代码。
只要通过 Sentinel API 定义的代码,就是资源,能够被 Sentinel 保护起来。大部分情况下,可以使用方法签名,URL,甚至服务名称作为资源名来标示资源。
围绕资源的实时状态设定的规则,可以包括流量控制规则、熔断降级规则以及系统保护规则。所有规则可以动态实时调整。
Sentinel
具有以下特征:
丰富的应用场景: Sentinel 承接了阿里巴巴近十年的双十一大促流量的核心场景,例如秒杀(即突发流量控制在系统容量可以承受的范围),消息削峰填谷,集群流量控制,实时熔断下游不可用应用等
完美的实时监控: Sentinel 同事提供实时的监控功能,您可以在控制台看到接入应用的单台机器秒级数据,甚至500台一下规模的集群的汇总运行情况
广泛的开源生态: Sentinel 提供开箱即用的与其他框架/库的整合模块,例如与SpringCloud,Dubbo,gRPC的整合,您只需要引入响应的依赖并进行简单的配置即可快速接入Sentinel
完美的SPI扩展点: Sentinel 提供简单易用的,完美的SPI扩展接口,可以通过实现扩展接口来快速定制逻辑,例如定制规则管理,适配动态数据源等
Sentinel
和之前常用的熔断降级库 Hystrix 有什么不同呐?
Hystrix
的不足之处:
Hystrix 的关注点在于以 隔离 和 熔断 为主的容错机制,超时或被熔断的调用将会快速失败,并可以提供 fallback 机制。
而 Sentinel 的侧重点在于:
Sentinel
可以简单的分为 Sentinel
核心库和 Dashboard控制台
。核心库不依赖 Dashboard
,但是结合 Dashboard
可以取得最好的效果。
上面有说 资源是 Sentinel 的关键概念
使用 Sentinel 来进行资源保护,主要分为这几个步骤:
看了上面这么多概念,感觉头都要秃了,我们还是来实战试试吧。
我们可以从https://github.com/alibaba/Sentinel/releases
下载sentinel-dashboard-$version.jar
包。
我们可以用以下命令来启动下载的 jar 包:
java -Dserver.port=8718 -jar sentinel-dashboard-1.8.3.jar
其中 -Dserver.port=8718
指定控制台端口
启动成功浏览器访问地址 http://localhost:8718 ,默认用户名密码:sentinel/sentinel
登录进去之后是这样的,空空如也,接下来我们就要看看到底如何使用了。
1、添加依赖
<!-- springcloud alibaba sentinel -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<!-- SpringBoot Web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
2、添加 Sentinel
配置
server:
port: 9201
spring:
application:
# 应用名称
name: cloud-sentinel
cloud:
sentinel:
transport:
# 控制台地址
dashboard: 127.0.0.1:8718
3、测试接口
@RestController
public class TestController {
@GetMapping("/testA")
public Object testA(){
return "testA......";
}
@GetMapping("/testB")
public Object testB(){
return "testB......";
}
}
4、启动项目,访问控制台
访问 Sentinel
控制台发现还是空空如也,这是怎么回事呐?
原来Sentinel
控制台有懒加载机制,我们需要访问一次我们服务的接口,控制台才会出现相关信息
我们来访问一下接口 localhost:9201/testA
再次刷新 Sentinel
控制台,发现出现了很多请求相关信息
我们也可以在配置文件中配置 spring.cloud.sentinel.eager: true 属性来取消控制台懒加载
这一步,到这里项目只是成功集成了 Sentinel
并打开了控制台,关于控制台上的相关操作,此文暂不讨论,下篇文章开始学习。
上面有说过,使用 Sentinel 来进行资源保护,主要分为这几个步骤:
Sentinel
定义资源的方式有好几种,有抛出异常的方式、返回布尔值的方式、注解的方式等,我们不再逐个讲解,详情可以查看官方文档 basic-api-resource-rule (sentinelguard.io)
这里我们使用注解的方式来定义资源,Sentinel
提供了@SentinelResource
注解用于定义资源,并提供了AspectJ
的扩展用于自动定义资源、处理BlockException
等。
因为我们是通过 Spring Cloud Alibaba 接入的 Sentinel,则无需额外进行配置即可使用 @SentinelResource
注解,否则的话需要引入如下依赖:
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-annotation-aspectj</artifactId>
<version>x.y.z</version>
</dependency>
我们来看一下注解的使用案例
@Service public class IUserServiceImpl implements IUserService { public static final String RESOURCE_NAME = "selectUserByName"; @Override @SentinelResource(value = RESOURCE_NAME, blockHandler = "selectUserByNameBlockHandler", fallback = "selectUserByNameFallback") public String selectUserByName(String username) { return "{"userName": " + username + ", "age": 25}"; } // 服务流量控制处理,注意细节,一定要跟原函数的返回值和形参一致,并且形参最后要加个BlockException参数,否则会报错,FlowException: null public String selectUserByNameBlockHandler(String username, BlockException ex) { System.out.println("selectUserByNameBlockHandler异常信息:" + ex.getMessage()); return "{"code":"500","msg": "" + username + "服务流量控制处理"}"; } // 服务熔断降级处理,函数签名与原函数一致或加一个 Throwable 类型的参数 public String selectUserByNameFallback(String username, Throwable throwable) { System.out.println("selectUserByNameFallback异常信息:" + throwable.getMessage()); return "{"code":"500","msg": "" + username + "服务熔断降级处理"}"; } }
@SentinelResource
注解包含以下属性:
参数 | 描述 |
---|---|
value | 资源名称,必需项(不能为空) |
entryType | 资源调用方向,可选项(默认为EntryType.OUT ) |
resourceType | 资源的分类 |
blockHandler | 对应处理BlockException 的函数名称 |
blockHandlerClass | 处理类的Class 对象,函数必需为static 函数 |
fallback | 用于在抛出异常的时候提供fallback 处理逻辑 |
defaultFallback | 用作默认的回退的方法 |
fallbackClass | 异常类的Class 对象,函数必需为static 函数 |
exceptionsToTrace | 异常类跟踪列表(默认为Throwable.class) |
exceptionsToIgnore | 排除掉的异常类型 |
注意:注解方式埋点不支持 private 方法。
注意:
blockHandler
/ blockHandlerClass
: blockHandler
对应处理 BlockException
的函数名称,可选项。blockHandler 函数访问范围需要是 public
,返回类型需要与原方法相匹配,参数类型需要和原方法相匹配并且最后加一个额外的参数,类型为 BlockException
。blockHandler 函数默认需要和原方法在同一个类中。若希望使用其他类的函数,则可以指定 blockHandlerClass
为对应的类的 Class
对象,注意对应的函数必需为 static 函数,否则无法解析。官方注解支持文档:注解支持 · alibaba/Sentinel Wiki · GitHub
@SpringBootApplication public class SentinelApplication { public static void main(String[] args) { SpringApplication.run(SentinelApplication.class, args); initFlowQpsRule(); } //定义了每秒最多接收2个请求 private static void initFlowQpsRule() { List<FlowRule> rules = new ArrayList<>(); FlowRule rule = new FlowRule(IUserServiceImpl.RESOURCE_NAME); // set limit qps to 2 rule.setCount(2); rule.setGrade(RuleConstant.FLOW_GRADE_QPS); rule.setLimitApp("default"); rules.add(rule); FlowRuleManager.loadRules(rules); } }
注意 FlowRule rule = new FlowRule(IUserServiceImpl.RESOURCE_NAME) 资源名称
流量控制规则(FlowRule
)重要属性
参数 | 描述 | 描述 |
---|---|---|
resource | 资源名,资源名是限流规则的作用对象 | |
limitApp | 流控针对的调用来源,若为 default 则不区分调用来源 | default,代表不区分调用来源 |
grade | 限流阈值类型,QPS 模式(1)或并发线程数模式(0) | QPS 模式 |
count | 限流阈值 | |
strategy | 调用关系限流策略:直接、链路、关联 | 根据资源本身(直接) |
controlBehavior | 流量控制效果(直接拒绝、Warm Up、匀速排队) | 直接拒绝 |
clusterMode | 是否集群限流 | 否 |
@RestController
public class UserController {
@Autowired
private IUserService userService;
@GetMapping("/user/getUserByName")
public String getUserByName(String userName){
return userService.selectUserByName(userName);
}
}
浏览器访问地址 localhost:9201/user/getUserByName?userName=小黑
快速刷新几次接口之后触发限流
同时观察控制台簇点链路
Sentinel
的功能强大,肯定不是我们一篇文章能容纳的,此文只是提供了一个入门案例,后面会继续学习 Sentinel
的其他知识。
PS: 都看到这里了,点个赞吧,彦祖!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。