文章目录
- Sentinel简介
- 核心代码
-
- 依赖
- 核心配置
- 流控规则解析
- 熔断降级
-
- 慢调用比例RT (SLOW_REQUEST_RATIO)
- 异常比例 (ERROR_RATIO)
- 异常数 (ERROR_COUNT)
- 热点key的流控
-
- 测试代码
- 配置热点参数的阈值
- 参数例外项
- 系统保护规则(整体维度)
- @SentinelResource使用
-
- value属性
- BlockHandler属性
- blockHandlerClass属性
- exceptionsToIgnore属性
- fallback属性
- 自定义降级处理类(可以代码解耦)
- 整合OpenFeign
- 规则的持久化配置
- 熔断降级框架对比
- 参考
Spring Cloud 系列笔记
Sentinel简介
-
是一个轻量级的流量控制、熔断降级 Java 库
-
主要特性如下:
-
Sentinel 组件由 2 部分组成
- 核心库(Java客户端):不依赖任何框架/库,能够运行于所有Java运行时环境,同时对 Dubbo /Spring Cloud等框架也有较好的支持。
- 控制台(Dashboard):基于Spring Boot 开发,打包后可以直接运行,不需要额外的Tomcat等应用容器。
-
下载后执行
java -jar sentinel-dashboard-x.x.x.jar
,然后访问本地8080端口即可,默认账号密码是sentinel
核心代码
依赖
<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
核心配置
spring:application:name: cloudalibaba-sentinel-servicecloud:nacos:discovery:server-addr: localhost:8848sentinel:transport:dashboard: localhost:8080port: 8719 #默认8719,假如被占用了会自动从8719开始依次+1扫描。直至找到未被占用的端口
- 启动项目后需要访问某个接口(懒加载)才能在sentinel界面看到监控数据
流控规则解析
- 资源名:唯一,默认请求路径(如:http://localhost:port/testA)
- 针对来源:Sentinel可以针对调用者进行限流,填写微服务名,指定对哪个微服务进行限流 ,默认default(不区分来源,全部限制)
- 阈值类型/单机阈值:
- 1、QPS(每秒钟的请求数量):当调用该接口的QPS达到了阈值的时候,进行限流;
- 2、线程数:当调用该接口的线程数达到阈值时,进行限流
- 线程数代表的是每秒内访问api接口的线程数,如果该接口的操作比较长,当排队的线程数到达阈值的时候,进行限流操作,相反的如果接口的操作很快,即是没秒内的操作很快,同样不会进行限流操作。QPS可以简单的理解为访问次数,但是线程数是和
接口处理的快慢
有关的。
- 是否集群:不需要集群
- 流控模式:
- 1、直接:接口达到限流条件时,直接限流
- 2、关联:当关联的资源达到阈值时,就限流自己(应用场景:
支付接口达到阈值,就限流下订单的接口
) - 3、链路:只记录指定链路上的流量(指定资源从入口资源进来的流量,如果达到阈值,就可以限流)[api级别的针对来源]
- 流控效果
- 1、快速失败:直接失败
- 2、Warm Up:即请求 QPS 从
最大阈值 / 3
(codeFactor,冷加载因子,默认为3)开始,经预热时长逐渐升至设定的阈值(应用场景:秒杀的瞬间,可能把系统打死,采用预热可以慢慢放流量进来,阈值不是一开始就最大
) - 3、排队等待(类似于漏桶算法)(应用场景:处理间隔性突发流量,例如消息队列)
熔断降级
- 注意熔断和流控的区别,熔断是接口直接不可用了
慢调用比例RT (SLOW_REQUEST_RATIO)
- 设置允许的 慢调用 RT(即
最大的响应时间
),请求的响应时间大于该值则统计为慢调用。 - 当
统计时长
内请求数目大于设置的最小请求数目,并且慢调用的比例大于阈值,则接下来的熔断时长内请求会自动被熔断。 - 经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN 状态),若接下来的一个请求响应时间小于设置的慢调用 RT 则结束熔断,若大于则会再次被熔断。
异常比例 (ERROR_RATIO)
- 这里的异常是指接口业务代码抛的异常
- 当统计时长内请求数目大于设置的最小请求数目,并且异常的比例大于阈值,则接下来的熔断时长内请求会自动被熔断。
- 经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN 状态),若接下来的一个请求成功完成(没有错误)则结束熔断,否则会再次被熔断。异常比率的阈值范围是 [0.0, 1.0],代表 0% - 100%。
异常数 (ERROR_COUNT)
- 当单位统计时长内的异常数目超过阈值之后会自动进行熔断。经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN 状态),若接下来的一个请求成功完成(没有错误)则结束熔断,否则会再次被熔断。
热点key的流控
- 热点即经常访问的数据。很多时候我们希望统计某个热点数据中访问频次最高的 Top K 数据,并对其访问进行限制。比如:
- 商品 ID 为参数,统计一段时间内最常购买的商品 ID 并进行限制
- 用户 ID 为参数,针对一段时间内频繁访问的用户 ID 进行限制
测试代码
@GetMapping("/testHotKey")
@SentinelResource(value = "testHotKey", blockHandler = "deal_testHotKey")
public String hotKeyTest(@RequestParam(value = "p1", required = false)String p1,@RequestParam(value = "p2", required = false)String p2){
return "===== (*^_^*) 成功了 (*^_^*) =====";
}
public String deal_testHotKey(String p1, String p2, BlockException exception){
return "===== (ㄒoㄒ) 失败了 (ㄒoㄒ) =====";
}
配置热点参数的阈值
- 发出请求并带上 p1 参数,访问 :http://localhost:8401/testHotKey?p1=aaa
- 如果 1 秒点一下,可以正常访问,但是 1 秒内,连续请求,就会走备选方案
- 注意资源名也可以是url地址哦
参数例外项
- 上述情况,不论被监控的参数传入的是何值,都会进行判断,并限流
- 但是有些时候有些特殊值,希望它的阈值和其他不一样,就要使用该配置
- 比如说:p1 传入 aaa 时的阈值可以允许达到 100,但是其他值只能达到 10
系统保护规则(整体维度)
- 简单来说,就是从整体维度对入口进行流控
- 名词解释:
- Load 自适应(仅对 Linux/Unix-like 机器生效):系统的 load1 作为启发指标,进行自适应系统保护。当系统 load1 超过设定的启发值,且系统当前的并发线程数超过估算的系统容量时才会触发系统保护(BBR 阶段)。系统容量由系统的 maxQps * minRt 估算得出。设定参考值一般是 CPU cores * 2.5。
- CPU usage(1.5.0+ 版本):当系统 CPU 使用率超过阈值即触发系统保护(取值范围 0.0-1.0),比较灵敏。
- 平均 RT:当单台机器上所有入口流量的平均 RT 达到阈值即触发系统保护,单位是毫秒。
- 并发线程数:当单台机器上所有入口流量的并发线程数达到阈值即触发系统保护。
- 入口 QPS:当单台机器上所有入口流量的 QPS 达到阈值即触发系统保护。
@SentinelResource使用
- 该注解用于配合sentinel控制台进行流控、熔断降级等操作,通过它可以指定自定义的降级策略,而不是阿里的直接返回一个blockException
@RequestMapping("/consumer/fallback/{id}")
@SentinelResource(value = "fallback",fallback = "handlerFallback",blockHandler = "blockHandler",exceptionsToIgnore = {
IllegalArgumentException.class})
public CommonResult<Payment> fallback(@PathVariable Long id)
{
CommonResult<Payment> result = restTemplate.getForObject(SERVICE_URL + "/paymentSQL/"+id,CommonResult.class,id);if (id == 4) {
throw new IllegalArgumentException ("IllegalArgumentException,非法参数异常....");}else if (result.getData() == null) {
throw new NullPointerException ("NullPointerException,该ID没有对应记录,空指针异常");}return result;
}
//本例是fallback
public CommonResult handlerFallback(@PathVariable Long id,Throwable e) {
Payment payment = new Payment(id,"null");return new CommonResult<>(444,"兜底异常handlerFallback,exception内容 "+e.getMessage(),payment);
}
//本例是blockHandler
public CommonResult blockHandler(@PathVariable Long id,BlockException blockException) {
Payment payment = new Payment(id,"null");return new CommonResult<>(445,"blockHandler-sentinel限流,无此流水: blockException "+blockException.getMessage(),payment);
}
value属性
- 资源名称,必填
BlockHandler属性
- 处理BlockException的函数,该函数只负责sentinel控制台配置的违规
- 注意:
- 必须是 public
- 返回类型与原方法一致
- 参数类型需要和原方法相匹配,并在最后加 BlockException 类型的参数。
- 默认需和原方法在同一个类中。若希望使用其他类的函数,可配置 blockHandlerClass ,并指定blockHandlerClass里面的方法。
blockHandlerClass属性
- 存放blockHandler的类
exceptionsToIgnore属性
- 指定忽略的异常,即对该异常不做任何处理
fallback属性
- fallback 函数名称
- 可选项,用于在接口抛出异常的时候提供 fallback 处理逻辑。fallback 函数可以针对所有类型的异常(除了 exceptionsToIgnore 里面排除掉的异常类型)进行处理。
- fallback 函数签名和位置要求
- 返回值类型必须与原函数返回值类型一致
- 方法参数列表需要和原函数一致,或者可以额外多一个 Throwable 类型的参数用于接收对应的异常
- fallback 函数默认需要和原方法在同一个类中。若希望使用其他类的函数,则可以指定
fallbackClass
为对应的类的 Class 对象,注意对应的函数必需为 static 函数,否则无法解析
自定义降级处理类(可以代码解耦)
public class CustomerBlockHandler
{
public static CommonResult handlerException(BlockException exception){
return new CommonResult(4444,"按客戶自定义,global handlerException----1");}public static CommonResult handlerException2(BlockException exception){
return new CommonResult(4444,"按客戶自定义,global handlerException----2");}
}
Controller配置
@GetMapping("/rateLimit/customerBlockHandler")
@SentinelResource(value = "customerBlockHandler",blockHandlerClass = CustomerBlockHandler.class,blockHandler = "handlerException2")
public CommonResult customerBlockHandler()
{
return new CommonResult(200,"按客戶自定义",new Payment(2020L,"serial003"));
}
整合OpenFeign
- 这里采用的是一个消费者,两个服务提供者,消费者服务需要引入Feign的依赖
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
- yaml要加一个配置:
feign:sentinel:enabled: true
- 其他的关于feign的配置之前的文章有提到,这里就不说了
规则的持久化配置
- 一旦我们重启应用,Sentinel规则将消失
- 生产环境需要将配置规则进行持久化
- 将限流配置规则持久化进 Nacos 保存
依赖
<dependency><groupId>com.alibaba.csp</groupId><artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
yaml
- 配置持久化文件在nacos中的唯一标志等
datasource:ds1:nacos:server-addr: localhost:8848dataId: cloudalibaba-sentinel-servicegroupId: DEFAULT_GROUPdata-type: jsonrule-type: flow
在nacos配置列表中添加对应的配置文件
熔断降级框架对比
- 可以看到Hystrix只支持降级保护,不支持限流
参考
SpringCloud-2.0-周阳(22. 流量监控 - Sentinel)学习笔记
SpringCloud-2.0-周阳(23. 熔断降级 - Sentinel)学习笔记