SpringCloudAlibaba–Sentinel
Sentinel被称为分布式系统的流量防卫兵,是阿里开源流量框架,从服务限流、降级、熔断等
多个纬度保护服务。Sentinel同时提供了简洁易用的控制台,可以看到接入应用的秒级数据,并可以在控制台设置一些规则保护应用。它比Hystrix支持的范围广泛,如Spring Cloud、Dubbo、gRPC都可以整合。集成简单,只需少量的配置和代码就可以完成,容易完成自己定制化的逻辑。
-
资源
是Sentinel最关键的概念,遵循Sentinel API的开发规范定义资源,就能将应用保护起来。 -
而
规则
可以通过控制面板配置,也可以和资源联合起来,规则可以在控制台修改并且即时生效。
名词解释
- 限流:对某个资源的访问数量做限制,不让流量一窝蜂地挤进资源访问
- 降级:即使系统出现问题情况下,也要尽可能提供服务,在可用和完全不可用之间找一个平衡点,如返回友好提示。
- 熔断:是一种资源访问的状态,熔断状态时,直接拒绝所有的访问,返回友好提示
同类产品对比
基础特性 | Sentinel | Hystrix | Resilience4j |
---|---|---|---|
限流 | QPS、线程数、调用关系 | 有限的支持 | Rate Limiter |
注解支持 | 支持 | 支持 | 支持 |
动态规则配置 | 支持多种数据源 | 支持多种数据源 | 有限支持数据源 |
熔断降级策略 | 平均响应时间、异常比例、异常数 | 异常比例 | 平均响应时间、异常比例 |
控制台 | 配置各种规则 | 简单监控 | 无控制台 |
常用适配框架 | Servlet、SpringCloud、Dubbo、gRPC | Servlet、Spring CloudNetflix | SpringBoot、Cloud |
Resilience4j在国外使用较多,而Hystrix框架已经停止更新进入维护了。
下载和运行
按照笔者之前的笔记,SpringCloudAlibaba是选择的2021.0.4.0
版本的,那么可以看下它们之间的版本对应关系
https://github.com/alibaba/spring-cloud-alibaba/wiki/%E7%89%88%E6%9C%AC%E8%AF%B4%E6%98%8E
选择这个1.8.5
版本即可,到sentinel的下载页面选择即可https://github.com/alibaba/Sentinel/releases
下载完毕后的jar包启动即可
java -jar sentinel-dashboard-1.8.5.jar
默认的端口是8080
,如需更改命令行添加即可
java -jar -Dserver.port=9090 sentinel-dashboard-1.8.5.jar
启动后,打开http://localhost:8080/,账号和密码都是sentinel
进入后发现没有任何的资源可以进行规则控制。sentinel是采用的懒加载的方式,当使用时才会进行加载。
集成Sentinel
生产者
项目中引入依赖
<dependencies>
<!-- 服务注册 服务发现需要引入的 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!--健康监控-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!--SpringBoot web-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--sentinel依赖-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
</dependencies>
bootstrap.yml
中做配置
server:
port: 8002
spring:
application:
name: provider # 应用名
cloud:
nacos:
discovery:
server-addr: localhost:8848 # nacos服务地址
sentinel:
transport:
port: 8719 # 启动http server,并且该服务与Sentinel仪表板进行交互,使sentinel可以控制应用,若端口占用则8719+1依次扫描
dashboard: 127.0.0.1:8080 # 仪表版访问地址
java controller做个资源
@RestController // @RestController注解是@Controller+@ResponseBody
public class TestController {
@RequestMapping("/test")
public String test() {
return "sentinel-provider8002 test()" + RandomUtils.nextInt(0, 1000);
}
}
消费者
同生产者引入依赖,做好配置,再到controller做个资源
使用RestTemplate+Ribbon做远程调用,添加依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
javaConfig配置
@Configuration
public class GenericConfiguration { // 常规配置类
@LoadBalanced // 标注此注解后,RestTemplate就具有了客户端负载均衡能力
@Bean
public RestTemplate restTemplate(){ // 创建RestTemplate,并交个Spring容器管理
return new RestTemplate();
}
}
@RestController // @RestController注解是@Controller+@ResponseBody
public class TestController {
private final String SERVER_URL = "http://provider";
@Autowired
private RestTemplate restTemplate;
@RequestMapping("/test")
public String test() {
return restTemplate.getForObject(SERVER_URL + "/test", String.class);
}
@RequestMapping("/sentinelTest")
public String sentinelTest() {
return "sentinel-consumer9001 sentinelTest" + RandomUtils.nextInt(0, 1000);
}
}
完成后,启动项目调用生产者的test
接口,然后到sentinel控制台。
curl localhost:9001/test
==> sentinel-provider8002 test()599
两个服务都出现在了控制台上。
Sentinel常用控制规则
我们需要对接口进行压测,所以使用jmeter吧,到jmter官方下载即可。
流控规则
流控主要是设置QPS或线程数等参数保护应用,针对某个资源的设置,下面操作sentinel控制台设置一些规则。
注意:要先调用接口后,才能添加规则(s加载)
QPS–直接–快速失败
QPS:(Query Per Second)指每秒可处理的请求数
在簇点链路–>列表视图–>到/sentinelTest
资源点击流控
,阈值选择QPS
,单机阈值1
,新增。
打开jmeter压测:
查看执行结果
10个请求也就两个成功了,其他都被限流了,直接blocked
QPS–直接–WarmUp
数据预热,即初始请求QPS等于阈值/codeFactor,codeFactor默认值3,经过预热时长1s后单机阈值变为100
压测数量100
看结果
前期接口正常返回,当访问量越来越多时,请求QPS=codeFactor(3)时,其他访问直接回绝,经过1s的预热,QPS变成了100后,后面的的所有请求全部正常访问。
QPS–直接–排队等待
让请求全部均匀访问通过,如果请求量超过阈值就等待,若等待超时就返回失败。
虽然QPS单机阈值是1,但是我们的超时时间为15s
,所以等得起访问全部成功。
QPS–关联–快速失败
如果访问B接口到达了阈值,那么就让A接口返回失败。适用于资源之间有资源竞争或依赖关系。
再写一个接口sentinelTestB
@RequestMapping("/sentinelTestB")
public String sentinelTestB() {
return "sentinel-consumer9001 sentinelTestB" + RandomUtils.nextInt(0, 1000);
}
设置规则,要注意当我们重启项目后,这些接口需要重新访问一遍才会出现在sentinel的簇点链路中
jmter不停访问/sentinelTestB
,让B接口超过达阈值,然后在去调用/sentinelTest
时直接回绝访问
因为sentinelTestB是没有做流控的,所以请求都是成功的,但是因为访问B接口的请求数是超过QPS阈值的,那么A接口则直接失败。
curl localhost:9001/sentinelTest
Blocked by Sentinel (flow limiting)
线程数–直接
限制处理请求的业务线程数,达到阈值就限流
可以看到很多请求都被限流了,这个跟服务器的配置有关,当服务器的配置较好时,可以适当将阈值设置的高一些,保证资源的访问情况。
控制台几个关键词
- 资源名:就是接口的资源,名称唯一即可
- 针对来源:此资源对调用者进行限流,默认defatult,对所有客户端限流;可填写调用者的
spring.application.name
指定对某个客户端进行限流。 - 阈值类型:QPS:每秒能接受的请求数量,线程数:能够使用的业务线程数(服务器内部的线程数)
- 流控模式:
- 直接:达到条件,直接执行某个流控效果
- 关联:如果关联资源达到条件,直接限流自身
- 链路:记录从入口资源的流量,达到条件也只限流入口资源
- 流控效果:
- 快速失败:达到条件,直接返回失败
- WarmUp:预热,给一个缓冲时间,缓慢增加阈值
- 排队等待:让系统匀速处理请求,其他请求进入等待,超时后未被处理的请求直接返回失败