SpringCloud Alibaba使用 - sentinel
SpringCloud Alibaba使用(一) - Nacos服务注册、配置中心、集群和持久化
SpringCloud Alibaba使用(二) - sentinel 流控规则、降级规则、热点key限流、系统规则、@SentinelResource
SpringCloud Alibaba使用(三) - sentinel fallback整合ribbon+openFeign 服务熔断功能 规则持久化
SpringCloud Alibaba使用(四) - seata分布式事务
一.介绍 SpringCloud Alibaba sentinel
1.Sentinel: 分布式系统的流量防卫兵
2.Sentinel 的主要特性
3. 安装Sentinel控制台
启动 cmd
java -jar sentinel-dashboard-1.7.2.jar
登录
http://localhost:8080
账号密码 sintinel
4. 新建测试项目
alibaba-sentinel-service8401
4.1.pom
<dependencies>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>4.6.3</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
4.2.yml
server:
port: 8401
spring:
application:
name: cloudalibaba-sentinel-service
cloud:
nacos:
discovery:
server-addr: localhost:8848
ip: localhost
sentinel:
transport:
dashboard: localhost:8080
port: 8719 #默认8719,假如被占用了会自动从8719开始依次+1扫描。直至找到未被占用的端口
management:
endpoints:
web:
exposure:
include: '*'
4.3.启动类
@SpringBootApplication
@EnableDiscoveryClient
public class SentinelMain8401 {
public static void main(String[] args) {
SpringApplication.run(SentinelMain8401.class,args);
}
}
4.4.业务类
@RestController
public class SentinelController {
@GetMapping("/testA")
public String testA() {
return "testA";
}
@GetMapping("/testB")
public String testB() {
return "testB";
}
}
5.启动
5.1.启动 nacos
SpringCloud Alibaba使用 - Nacos服务注册、配置中心、集群和持久化
http://localhost:8848/nacos/#/login
账号密码 nacos
5.2启动 sentinel
http://localhost:8080
账号密码 sintinel
5.3.启动项目 alibaba-sentinel-service8401
6.测试
进入sentinel控制台
空的(Sentinel采用的懒加载说明)需要执行
执行
http://localhost:8401/testA
http://localhost:8401/testB
sentinel8080正在监控微服务8401
二.流控规则详解
1.流控模式
1.1.直接
接口达到限流条件时,直接限流
快速点击访问http://localhost:8401/testA
结果:Blocked by Sentinel (flow limiting)
1.2.关联
当关联的资源达到阈值时,就限流自己
postman模拟并发密集访问testB
执行psotman后,快速点击访问http://localhost:8401/testA,发现 Blocked by Sentinel (flow limiting)
1.3.链路
链路流控模式指的是,当从某个接口过来的资源达到限流条件时,开启限流;它的功能有点类似于针对 来源配置项,区别在于:针对来源是针对上级微服务,而链路流控是针对上级接口,也就是说它的粒度 更细;
只记录指定链路上的流量(指定资源从入口资源进来的流量,如果达到阈值,就可以限流)[api级别的针对来源]
2.流控效果
2.1.直接->快速失败(默认的流控处理)
直接拒绝(RuleConstant.CONTROL_BEHAVIOR_DEFAULT)方式是默认的流量控制方式,当QPS超过任意规则的阈值后,新的请求就会被立即拒绝,拒绝方式为抛出FlowException。这种方式适用于对系统处理能力确切已知的情况下,比如通过压测确定了系统的准确水位时。具体的例子参见 FlowQpsDemo。
[https://github.com/alibaba/Sentinel/wiki/%E6%B5%81%E9%87%8F%E6%8E%A7%E5%88%B6#%E7%9B%B4%E6%8E%A5%E6%8B%92%E7%BB%9D]
直接失败,抛出异常
2.2.预热
Warm Up(RuleConstant.CONTROL_BEHAVIOR_WARM_UP)方式,即预热/冷启动方式。当系统长期处于低水位的情况下,当流量突然增加时,直接把系统拉升到高水位可能瞬间把系统压垮。通过"冷启动",让通过的流量缓慢增加,在一定时间内逐渐增加到阈值上限,给冷系统一个预热的时间,避免冷系统被压垮。详细文档可以参考 流量控制 - Warm Up 文档,具体的例子可以参见 WarmUpFlowDemo。
[https://github.com/alibaba/Sentinel/wiki/%E6%B5%81%E9%87%8F%E6%8E%A7%E5%88%B6#warm-up]
根据codeFactor(冷加载因子,默认为3)的值,即请求 QPS 从 threshold / 3 开始,经预热时长逐渐升至设定的 QPS 阈值 ;
刚开始不行,后续慢慢OK
2.3.排队等待
匀速排队,让请求以均匀的速度通过,阈值类型必须设置成QPS,否则无效;
匀速排队,阈值必须设置为QPS
测试
3.降级规则
3.1.RT(平均响应时间)
平均响应时间 (DEGRADE_GRADE_RT):当 1s 内持续进入 N 个请求,对应时刻的平均响应时间(秒级)均超过阈值(count,以 ms 为单位),那么在接下的时间窗口(DegradeRule 中的 timeWindow,以 s 为单位)之内,对这个方法的调用都会自动地熔断(抛出 DegradeException)。注意 Sentinel 默认统计的 RT 上限是 4900 ms,超出此阈值的都会算作 4900 ms,若需要变更此上限可以通过启动配置项 -Dcsp.sentinel.statistic.max.rt=xxx 来配置。
3.2.异常比例
异常比例 (DEGRADE_GRADE_EXCEPTION_RATIO):当资源的每秒请求量 >= N(可配置),并且每秒异常总数占通过量的比值超过阈值(DegradeRule 中的 count)之后,资源进入降级状态,即在接下的时间窗口(DegradeRule 中的 timeWindow,以 s 为单位)之内,对这个方法的调用都会自动地返回。异常比率的阈值范围是 [0.0, 1.0],代表 0% - 100%。
3.3.异常数
异常数 (DEGRADE_GRADE_EXCEPTION_COUNT):当资源近 1 分钟的异常数目超过阈值之后会进行熔断。注意由于统计时间窗口是分钟级别的,若 timeWindow 小于 60s,则结束熔断状态后仍可能再进入熔断状态。
异常数是按照分钟统计的
注意:异常降级仅针对业务异常,对 Sentinel 限流降级本身的异常(BlockException)不生效。为了统计异常比例或异常数,需要通过 Tracer.trace(ex) 记录业务异常。
4.热点参数规则
4.1.热点key限流配置
@SentinelResource
@GetMapping("/testC")
@SentinelResource(value = "testC",blockHandler = "err")
//@RequestParam(value = "a1",required = false) false指非必要的参数
public String testC(@RequestParam(value = "a1",required = false) String a1,
@RequestParam(value = "a2",required = false)String a2) {
return "OK";
}
public String err(String a1, String a2, BlockException exception) {
return "exception";
}
运行成功
a1=1是第一个参数,带a1=1参数,快速刷新,QPS超过1秒1次点击后马上被限流
4.2.参数例外项
传入参数为1,没有任何问题
传入参数为1,快速点击,限流
4.3其他
5.系统自适应限流
Sentinel 系统自适应限流从整体维度对应用入口流量进行控制,结合应用的 Load、CPU 使用率、总体平均 RT、入口 QPS 和并发线程数等几个维度的监控指标,通过自适应的流控策略,让系统的入口流量和系统的负载达到一个平衡,让系统尽可能跑在最大吞吐量的同时保证系统整体的稳定性。
快速刷新 http://localhost:8401/testA,限流
结论:就是配置全局QPS
6.@SentinelResource注解使用
6.1 资源名称限流
@GetMapping("/rateLimit/byResource")
@SentinelResource(value = "byResource",blockHandler = "handleException")
public CommonResult byResource()
{
return new CommonResult(200,"按资源名称限流测试OK",new User(2,"dama"));
}
public CommonResult handleException(BlockException exception)
{
return new CommonResult(444,exception.getClass().getCanonicalName()+"\t 服务不可用");
}
表示1秒钟内查询次数大于1,就跑到我们自定义的处流,限流
正常情况:
限流情况:显示的自定义的输入
6.2按照Url地址限流
只需修改Sentinel控制台配置
限流情况:显示的默认
6.3自定义限流处理逻辑
//配置限流类
@GetMapping("/rateLimit/getUser")
@SentinelResource(value = "getUser",blockHandlerClass = CustomerBlockHandler.class,blockHandler = "BlockHandler1")
public CommonResult getUser(){
return new CommonResult (200,"成功!",new User(2,"dama"));
}
package com.psf.springcloud.Alibaba.handler;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.psf.springcloud.Alibaba.entity.CommonResult;
import com.psf.springcloud.Alibaba.entity.User;
public class CustomerBlockHandler {
public static CommonResult BlockHandler1(BlockException exception){
return new CommonResult(444,"自定义限流1",null);
}
public static CommonResult BlockHandler2(BlockException exception){
return new CommonResult(444,"自定义限流2",null);
}
}
package com.psf.springcloud.Alibaba.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@AllArgsConstructor
@Data
@NoArgsConstructor
public class CommonResult<T> {
private Integer code;
private String message;
private T data;
public CommonResult(Integer code, String message) {
this(code,message,null);
}
}
正常
限流
注意