23springcloudAlibaba Sentinel
官网参考地址:https://github.com/alibaba/Sentinel/wiki
是什么:
Spring Cloud Alibaba Sentinel 是面向于云原生微服务的高可用流控防护组件,
主要以流量为切入点,从流量控制、熔断降级、系统自适应保护等多个维度来帮助用户保障微服务的稳定性。
一句话解释,就是之前学习过的 Hystrix 升级版。
Hystrix VS Sentinel:
Hystrix
|
Sentinel
|
需要程序员手工搭建监控平台
|
单独一个组件、可以独立出来
|
没有一套Web界面可以给程序员进行更加细粒度化得配置,比如流控、速率控制、服务熔断、服务降级
|
直接界面化的细粒度统一配置
|
服务中遇到的各种问题:
1.服务雪崩
2.服务降级
3.服务熔断
4.服务限流
Sentinel分为两部分:
1.核心库(java客户端):不依赖任何框架/库,能够运行与所有的java运行时环境,同样对Dubbo/Spring Cloud框架也有较好的支持
2.控制台(Dashbord):基于springboot开发,打包后可以直接运行,不需要额外的tomcat等应用容器。
sentinel的dashbord安装(前台页面)
下载地址:https://github.com/alibaba/Sentinel/release
如下图所示:
下载的前台页面包是springboot写的jar包,所以启动方式是java -jar 的形式启动,需要注意的是,该端口为8080,所以要保障8080端口无人占用!!
启动成功后登陆:http://localhost:8080/
用户名/密码:sentinel/sentinel
2.编写java客户端代码:
1.pom文件中的写法:没有用到alibaba的服务配置中心nacos-config,所以未引入该包:spring-cloud-starter-alibaba-nacos-config
<dependencies>
重点1
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
重点2:
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
重点3:
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
...
</dependencies>
2.application.yml中的配置:
server:
port: 8401
spring:
application:
name: cloudalibaba-sentinel-service
cloud:
nacos:
discovery:
#Nacos服务注册中心地址
server-addr: 192.168.2.129:8848
sentinel:
transport:
#配置sentinel的dashbord地址
dashboard: localhost:8080
#默认是8719端口,假如被占用会自动从8719开始依次+1扫描,直至找到未被占用的端口
#固定写法
port: 8719
management:
endpoints:
web:
exposure:
include: '*'
3.启动类写法:
@SpringBootApplication
重点:@EnableDiscoveryClient标签,使注册中心可以扫描到
@EnableDiscoveryClient
public class ConfigClientApplication3377 {
public static void main(String[] args) {
SpringApplication.run(ConfigClientApplication3377.class, args);
}
}
4.控制层代码:简单的请求方法
@RestController
@Slf4j
public class SentinelController {
@GetMapping("/sentinel/id/{id}")
public int getIn(@PathVariable("id") int id){
log.info("调用获取id方法:"+id);
return id;
}
@GetMapping("/sentinel/date/{date}")
public String getDate(@PathVariable("date") String date){
log.info("调用日期请求方法!"+date);
return DateUtil.now();
}
}
1.sentinel页面:
2.Nacos页面(服务注册中心)
1.流控讲解:
1.资源名:唯一的名称,默认请求路径
2.针对来源:Sentinel可以针对调用者进行限流,填写微服务名称,默认是default(不区分来源)
3.阈值类型/单机阈值:
3.1 QPS(每秒钟的请求数量):当调用该api的QPS达到阈值的时候,进行限流
3.2 线程数:当调用该api的线程数达到阈值的时候,进行限流。
4.是否集群:不需要集群
5.流控模式:
5.1 直接:API达到限流条件时,直接限流
5.2 关联:当关联的资源达到阈值时,就限流自己
5.3 链路: 只记录指定链路上的流量(指定资源从入口资源进来的流量,如果达到阈值,就进行限流。)【api级别的针对来源】
6.流控效果:
1.快速失败:直接失败,抛异常
2.Warm Up:根据codeFactor(冷加载因子,默认是3)的值,从阈值/codeFactor,经过预热时长,才达到设置的QPS阈值
3.排队等待:匀速排队,让请求以均匀的速度通过,预支类型必须设置为qps,否则无效
1.流控规则
1.1 流控模式:直接
1.QPS:每秒钟的请求次数
2.并发线程数:内部设置同时的并发量
1.2 流控模式:关联
流控模式选择关联:如下
总结:
如果访问/sentinel/id/1时,发现其关联资源无法访问,会导致其/sentinel/id/1的访问失败,返回官方信息:Blocked by Sentinel (flow limiting)
1.3 流控模式:链路
2.流控效果:预热
QPS的单机阈值是10:即每秒最大支持10次的访问
当流控效果为:warm up(预热)
冷启动的默认coldFactor为3,即请求QPS从:单机阈值/冷启动因子(coldFactor默认是3),经过预热时长逐渐升值设定的QPS阈值
场景:平时的访问量很低,突然访问量剧增,容易把系统压垮,有了预热,使系统逐渐增加访问量,有个过程
常见用到秒杀系统里
2.流控效果:排队等待
这种方式主要用于处理间隔性突发的流量,假如消息队列。
场景:想象一下这样的场景,在某一秒有大量的请求到来,而接下来的几秒则处于空闲状态,我们希望能够接下来的空闲期间,逐渐请处理这些请求。
而不是在第一秒直接拒绝多余的请求。
降级规则
RT(平均响应时间,秒级)
平均响应时间,超出阈值 且 在时间窗口通过的请求>=5,两个条件同时满足后触发降级
窗口期过后关闭断路器。
RT最大4900(更大的要通过-Dcsp.sentnel.staticstic.max.rt=xxxx才能生效)
异常比例:
QPS >=5 且异常比例(秒级统计)超过阈值时,触发降级;时间窗口结束后,关闭降级
异常数:
异常数(分钟统计)超过阈值时,触发降级;时间窗口结束后,关闭降级。
Sentinel我们断降级会在调用链路中某个资源出现不稳定状态时(例如调用超时或异常比例升高),对这个资源的调用进行限制。
让请求快速失败,避免影响到其他的资源而导致级联错误
当资源被降级后,在接下来的降级时间窗口之内,对该资调用都自动熔断(默认是抛出DegrareException)
Sentinel的断路器没有半开状态(半开状态参考Hystrix)
热点key限流
何为热点?热点即经常访问的数据。很多时候我们希望统计某个热点数据中访问频次最高的 Top K 数据,并对其访问进行限制。比如:
商品 ID 为参数,统计一段时间内最常购买的商品 ID 并进行限制
用户 ID 为参数,针对一段时间内频繁访问的用户 ID 进行限制
热点参数限流会统计传入参数中的热点参数,并根据配置的限流阈值与模式,对包含热点参数的资源调用进行限流。热点参数限流可以看做是一种特殊的流量控制,仅对包含热点参数的资源调用生效。
具体的测试代码结构如下:重要的是@SentinelResource标签的使用:
控制层代码:
@GetMapping("/sentinel/testHotkey")
重点1:@SentinelResource标签的石永红,value值是在sentinel页面上配置的资源名称,blockHandler 定义的就是兜底的方法
@SentinelResource(value = "testHotkey",blockHandler = "deal_testHotkey")
public String testHotkey(
@RequestParam(value = "parm1",required = false) String parm1,
@RequestParam(value = "parm2",required = false) String parm2
){
log.info("测试热点限流:第一个参数->"+parm1+" 第二个参数:"+parm2);
return "测试热点限流:第一个参数->"+parm1+" 第二个参数:"+parm2;
}
public String deal_testHotkey(){
return "测试热点数据的兜底方法!";
}
系统规则
做整体的配置
@SentinelResource标签
1.场景一:如何设置共有的降级处理方法(即降级处理方法和原业务逻辑分开)
当访问 /testGlobl点击量超过1秒1次后,会调用到公共的降级方法进行服务降级!
@SentinelResource(value = "testGloble",
blockHandlerClass = MyHandler.class,
blockHandler = "hadleException1")
属性解析:
1.value :对应的资源名称,和sentinel上配置的一样
2.blockHandlerClass:公共的降级类
3.blockHandler :对应的降级方法
服务熔断
@SentinelResource(value = "testGloble",
blockHandlerClass = MyHandler.class,
blockHandler = "hadleException1")
上述的配置只能解决sentinel页面上配置的限流导致的降级服务降级问题,如果是程序运行时异常,应该如何进行服务熔断和降级呢
使用fallback指定运行时异常导致的服务熔断和降级方法
样例:
@GetMapping("/testGloble")
@SentinelResource(value = "testGloble",
blockHandlerClass = MyHandler.class,
blockHandler = "hadleException1",
重点:使用fallback指定程序运行时异常导致的服务熔断和降级方法!
fallback = "deal_fall")
public String testGloble(){
//重点2:这里会抛出java运行时异常,当访问时可以走到下面的运行时异常服务熔断降级方法
int a=10/0;
return DateUtil.now();
}
public String deal_fall(){
return "运行时异常导致的熔断降级!";
}
总结:
1.SentinelResource中的blockHandlerClass/blockHandler 只能处理sentinel页面上配置的限流等导致的服务熔断和限流(sentinel控制台的配置违规),
不处理java运行时异常导致的问题(页面会直接报错,但当又满足了sentinel控制台的控制违规,是会走其服务降级方法)
2.fallback:可以解决java运行时异常的服务熔断和降级
3.两者的配合使用:
3.1 当出现java运行时异常时,会走fallback的服务熔断降级方法
3.2 但当又有java运行时异常,又满足sentinel控制台配置的blockHandler配置,以sentinel即blockHandler的为主!走其服务熔断降级方法!