Spring Cloud Alibaba学习 3- Sentinel入门使用
中文文档参考:Sentinel中文文档
一. SpringCloud整合Sentinel
1.1 下载Sentinel-Dashboard
Sentinel下载地址:Sentinel-Dashboard
到下载目录,cmd输入
java -jar sentinel-dashboard-1.8.8.jar
如果8080端口被占用,可以指定其他端口
java -jar sentinel-dashboard-1.8.6.jar --server.port=8082
如果不指定账号和密码,则都是sentinel
初次访问的时候发现什么都没有,只有在首次在程序中调用Sentinel资源时,F5刷新后才会有东西
1.2 引入Sentinel相关依赖
在公共模块中引入Sentinel相关依赖
<!-- Sentinel -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
1.3 配置Sentinel客户端
spring:
cloud:
# sentinel
sentinel:
transport:
dashboard: localhost:8080 # dashboard地址
port: 8080 # Sentinel地址
# nacos
nacos:
server-addr: 127.0.0.1:8848 # Nacos客户端
discovery:
cluster-name: order #集群名
namespace: public #命名空间
service: order #服务名
metadata: #服务元数据,会给每个实例都配置对应的元数据
name: orderService
config:
server-addr: 127.0.0.1:8848 # Nacos作为配置中心地址
namespace: dev
group: orderservice
file-extension: yml # 指定 yml 格式的配置
import-check:
enabled: false # 禁用导入检查
refresh-enabled: true
# 用 application.yml作为Nacos配置中心的配置文件需要配置如下
config:
import:
- optional:nacos:${spring.application.name}.${spring.cloud.nacos.config.file-extension}
server:
port: 8081
1.4 配置Sentinel资源
用@SentinelResource配置到Controller的接口方法上,不配置也可以,Sentinel会自动监听所有的Controller的接口方法
@RestController
@RequestMapping("/order")
public class OrderController {
@Autowired
public DiscoveryClient client;
@Autowired
private GoodClient goodClient;
@SentinelResource
@GetMapping("output")
public void output(ServletResponse response) {
HttpServletResponse res = (HttpServletResponse) response;
try {
res.getWriter().write("ABCDEFG");
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
请求
http://localhost:8081/order/output
查看Sentinel控制台,已经有了应用,整合成功
二. Sentinel使用配置
参考前辈最后一支迷迭香的文章SpringCloud Alibaba微服务-- Sentinel的使用(保姆级)-CSDN博客
1. 流控规则
1.1 参数介绍
- 资源名
接口访问的URL
- 针对来源
服务的调用者,默认为defalut所有来源
- 阈值类型
QPS
:接口每秒的访问量
并发线程数
:调用的线程数
- 单机阈值
阈值类型对应的值
- 流控模式
直接
:只要达到了流控标准,就会限流当前资源
关联
:当关联的资源达到了流控标准,就会限流当前资源
链路
:当从入口资源去调用某个@SentinelResource指定的资源达到了流控标准,就会限流当前入口资源对该资源的调用
- 流控效果
快速失败
:直接抛出错误
Warm Up
:根据预热因子和指定的预热时间,慢慢增加接收的流量直到达到阈值
排队等待
:匀速排队接收流量
1.2 流控规则演示
1.2.1 直接流控演示
正常访问接口http://localhost:8081/order/output
时,会在浏览器输出ABCDEFG
配置了下图规则
快速F5刷新页面,会触发流控
1.2.2 关联流控演示
在当前接口创建了测试关联流控的接口
@GetMapping("/testRelated")
public String testRelated() {
return "hello";
}
配置了下图规则
快速请求关联资源,当前接口被流控
1.2.3 链路流控演示
在配置文件中关闭sentinel对同一个Controller里所有方法的整合,这样不会把所有方法放在一个链路里(链路流控无效)
sentinel:
transport:
dashboard: localhost:8080 # dashboard地址
port: 8080 # Sentinel地址
# 关闭整合
web-context-unify: false
可以看到,现在每个方法都是一个链路
OrderController接口方法如下,重点记住要给被链路流控的资源加上@SentinelResource(“xxx”),这样该接口才会作为入口资源下的链路!!
@RestController
@RequestMapping("/order")
@Slf4j
@RefreshScope
public class OrderController {
@SentinelResource("resource")
@GetMapping("/testRelated")
public String testRelated() {
return "hello";
}
@GetMapping("/testFeign")
public void testFeign() {
testRelated();
}
}
可以看到,控制台已经将 resource
资源置于 /order/testFeign
链路下了
接着在Sentinel控制台配置了下图规则
直接访问localhost:8081/order/testRelated
,快速刷新,依然可以看到正常返回
访问localhost:8081/order/testFeign
,快速刷新,报错,这是由于从/order/testFeign链路下的resource被流控了抛出的错误
2. 熔断规则
2.1 参数介绍
- 熔断器状态
熔断器类似一个开关,有 全开
、半开
、关闭
三个状态
全开(OPEN):正常接收请求
半开(HALF_OPEN):熔断器在指定的熔断时长后,进入半开状态,此时会发送一个探测请求,如果此次请求成功,则进入关闭状态,否则退回全开状态,等待下一个熔断时长结束再进行探测。
关闭(CLOSED):当处于关闭状态时,请求均可以通过。
- 熔断策略
熔断器都是根据一段统计时间的请求的状况来进行状态切换的。
1. 慢调用比例
最大RT:RT 表示 Reponse time,即最大响应时间,当超过了设置的时间就会算作一个请求无效
比例阈值:当超过设定的比例阈值(百分之几)的请求都是慢调用的时候,就会触发熔断
2. 异常比例
比例阈值:当超过设定的比例阈值(百分之几)的请求都出现异常的时候,就会触发熔断
3. 异常数
异常数:当异常请求数超过了设定的异常数时,就会触发熔断
- 熔断时长
顾名思义,熔断器在触发熔断策略后,进入熔断状态(关闭状态)的时长
- 最小请求数
只有请求超过了最小请求数之后,才会开始进入统计时长
- 统计时长
熔断策略中的指标都是在指定的一段统计时长进行统计
2.2 熔断演示
这里只拿慢调用比例来演示,其他的也都差不多,要演示熔断,需要用到压测工具,apipost
、jmeter
都是好用的压测工具,这里就直接用 apipost
进行简单压测
配置了下图的熔断规则
让请求休眠一段时间,接口方法如下:
@RestController
@RequestMapping("/order")
public class OrderController {
@GetMapping("/testRelated")
public String testRelated() {
try {
TimeUnit.SECONDS.sleep(1);
}
catch (Exception e) {
}
return "hello";
}
}
对接口http://localhost:8081/order/testRelated
进行压测
浏览器访问时,已经熔断了
3. 热点规则
3.1 参数介绍
- 参数索引
对应的接口方法的传入的参数索引,Sentinel会对配置的相同参数的请求会进行流控
- 参数例外项
配置需要特殊管理的参数值
3.2 热点演示
通过热点规则,可以限制接口方法参数,实现一些热点数据的管理,比如秒杀活动时一个用户在30s内只能对该商品下一次单,但是VIP用户可以多次下单
接口 OrderController
@RestController
@RequestMapping("/order")
public class OrderController {
@SentinelResource("testHotPointInfo")
public String testHotPointInfo(int userID) {
return "下单成功";
}
}
userID为2的是VIP用户,无需流控,其他用户只能在30s内下一次单,如下图所配置
非VIP用户多次下单
VIP用户多次下单
4. @SentinelResource
通过@SentinelResource注解,可以帮助我们快速处理异常
4.1 常用参数说明
- **value:**定义资源名
- blockHandlerClass:指定资源如果被Sentinel限流了,抛出的自定义兜底方法所在的类
- blockHandler:指定资源如果被Sentinel限流了,抛出的自定义兜底方法(该自定义方法要求是静态的,该方法的返回参数与原方法的返回参数相同,方法参数需要有BlockException)
- fallbackClass:指定资源如果出现了错误,抛出的自定义兜底方法
- fallback:指定资源如果出现了错误了,抛出的自定义兜底方法(该自定义方法要求是静态的,该方法的返回参数与原方法的返回参数相同)
4.2 测试异常处理兜底返回
定义异常处理类 OrderBlockHandler,关键是方法要静态
public class OrderBlockHandler {
//限流兜底抛出
public static String blockFallback(BlockException ex) {
return "我被限流了,直接失败";
}
//异常兜底抛出
public static String ExceptionFallback() {
return "我出错了,直接失败"
}
}
定义接口类 OrderController
@RestController
@RequestMapping("/order")
public class OrderController {
@GetMapping("/testHotPointInfo")
@SentinelResource(value = "testHotPointInfo", blockHandlerClass = OrderBlockHandler.class, blockHandler = "blockFallback")
public String testHotPointInfo() {
return "123";
}
}
结合上面提到的流控(这里就不再记录配置了),访问http://localhost:8081/order/testHotPointInfo
在接口里加上
int i = 1 / 0;
访问报错
5. Sentinel异常处理机制
尚硅谷新版SpringCloud上有一张很好的图,有空再补充