springCloud-Alibaba--Sentinel
gitHub: https://github.com/alibaba/Sentinel
Sentinel 是什么?
随着微服务的流行,服务和服务之间的稳定性变得越来越重要。Sentinel 以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。相当于SpringCloud 的 Hystrix
Sentinel 具有以下特征:
- 丰富的应用场景:Sentinel 承接了阿里巴巴近 10 年的双十一大促流量的核心场景,例如秒杀(即突发流量控制在系统容量可以承受的范围)、消息削峰填谷、集群流量控制、实时熔断下游不可用应用等。
- 完备的实时监控:Sentinel 同时提供实时的监控功能。您可以在控制台中看到接入应用的单台机器秒级数据,甚至 500 台以下规模的集群的汇总运行情况。
- 广泛的开源生态:Sentinel 提供开箱即用的与其它开源框架/库的整合模块,例如与 Spring Cloud、Dubbo、gRPC 的整合。您只需要引入相应的依赖并进行简单的配置即可快速地接入 Sentinel。
- 完善的 SPI 扩展点:Sentinel 提供简单易用、完善的 SPI 扩展接口。您可以通过实现扩展接口来快速地定制逻辑。例如定制规则管理、适配动态数据源等。
官网下载Sentinel: https://github.com/alibaba/Sentinel/releases/tag/1.7.2
启动jar
访问: IP + 8080
账户: sentinel 密码: sentinel
maven依赖:
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<!-- sentinel-datasource-nacos 后续做持久化用到-->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
修改yml:
server:
port: 8401
spring:
application:
name: cloud-alibaba-sentinel-service
cloud:
nacos:
discovery:
# Nacos 服务注册中心
server-addr: localhost:8848
sentinel:
transport:
# 配置sentinel dashboard 地址
dashboard: localhost:8080
# 默认8719端口,假如被占用会自动从8719开始依次+1扫描,直至找到未被占用的端口
port: 8791
management:
endpoints:
web:
exposure:
include: '*'
新建controller
浏览器访问:
查看Sentinel Dashboard:
Sentinel 流控规则:
流量控制(flow control),其原理是监控应用流量的 QPS 或并发线程数等指标,当达到指定的阈值时对流量进行控制,以避免被瞬时的流量高峰冲垮,从而保障应用的高可用性。
字段解释:
资源名: 唯一名称,默认的请求路径。
针对来源: Sentinel 可以针对调用者进行限流,填写微服务名,默认default(不区分来源)
阀值类型/单机阀值:
QPS(每秒钟的请求数量): 当调用API的QPS达到阀值的时候,进行限流。
线程数: 当调用该API的线程数达到阀值的时候进行限流
是否集群: 不需要集群
流控模式:
直接: API达到限流时,直接限流
关联: 当关联的资源达到阀值时,就限流自己
链路: 只记录指定链路上的流量(指定资源从入口进来的流量,如果达到阀值,就进行限流)【Api级别的针对来源】
流控效果:
快速失败: 直接失败,抛异常。
Warm Up: 根据codeFactor(冷加载因子,默认3)的值,从 单机阀值 / codeFactor 经过预热时长,才达到设置的QPS阀值。
排队等待: 匀速排队,让请求以匀速的速度通过,阀值类型必须设置为QPS才有效。
流控配置并测试:
1:QPS限流:
1秒内 访问/testA没有问题
但是1秒内多次访问:
Sentinel 降级规则:
除了流量控制以外,对调用链路中不稳定的资源进行熔断降级也是保障高可用的重要措施之一。由于调用关系的复杂性,如果调用链路中的某个资源不稳定,最终会导致请求发生堆积。Sentinel 熔断降级会在调用链路中某个资源出现不稳定状态时(例如调用超时或异常比例升高),对这个资源的调用进行限制,让请求快速失败,避免影响到其它的资源而导致级联错误。当资源被降级后,在接下来的降级时间窗口之内,对该资源的调用都自动熔断(默认行为是抛出 DegradeException
)。
降级策略:
- (RT)平均响应时间 (
DEGRADE_GRADE_RT
): 当 1s 内持续进入 N 个请求,对应时刻的平均响应时间(秒级)均超过阈值(count
,以 ms 为单位),那么在接下的时间窗口(DegradeRule
中的timeWindow
,以 s 为单位)之内,对这个方法的调用都会自动地熔断(抛出DegradeException
)。注意 Sentinel 默认统计的 RT 上限是 4900 ms,超出此阈值的都会算作 4900 ms,若需要变更此上限可以通过启动配置项-Dcsp.sentinel.statistic.max.rt=xxx
来配置。 - 异常比例 (
DEGRADE_GRADE_EXCEPTION_RATIO
): 当资源的每秒请求量 >= N(可配置),并且每秒异常总数占通过量的比值超过阈值(DegradeRule
中的count
)之后,资源进入降级状态,即在接下的时间窗口(DegradeRule
中的timeWindow
,以 s 为单位)之内,对这个方法的调用都会自动地返回。异常比率的阈值范围是[0.0, 1.0]
,代表 0% - 100%。 - 异常数 (
DEGRADE_GRADE_EXCEPTION_COUNT
): 当资源近 1 分钟的异常数目超过阈值之后会进行熔断。注意由于统计时间窗口是分钟级别的,若timeWindow
小于 60s,则结束熔断状态后仍可能再进入熔断状态。
eg:
当 1s 内持续进入 N 个请求 , 所有访问 /testA 的线程必须200毫秒内处理完成,否则在时间窗口期10秒内都将不能访问
Sentinel 热点参数限流:
何为热点?热点即经常访问的数据。很多时候我们希望统计某个热点数据中访问频次最高的 Top K 数据,并对其访问进行限制。比如:
- 商品 ID 为参数,统计一段时间内最常购买的商品 ID 并进行限制
- 用户 ID 为参数,针对一段时间内频繁访问的用户 ID 进行限制
热点参数限流会统计传入参数中的热点参数,并根据配置的限流阈值与模式,对包含热点参数的资源调用进行限流。热点参数限流可以看做是一种特殊的流量控制,仅对包含热点参数的资源调用生效。
参数索引: 0: 表示 /testC方法的第一个参数QPS超过每秒1次,则进行限流
兜底方法:
当达到我们配置的限流条件后,系统都是默认提示: Blocked by Sentinel (flow limiting)
当然我们也可以使用自定义的降级方法: @SentinelResource 注解的方式。
但是这样代码就会冗余到业务代码中,可以提取公共的全局异常处理(这里的异常是指超过了我们配置限流规则的异常):
自定义全局的异常处理类(必须是静态的方法):
public class CustomerBlockHandler {
public static CommonResult handlerException(BlockException blockException){
return new CommonResult(444, "按照客户自定义,global handlerException----1");
}
public static CommonResult handlerException2(BlockException blockException) {
return new CommonResult(444, "按照客户自定义,global handlerException----12");
}
}
controller使用:
@GetMapping("/customerBlockHandler")
@SentinelResource(value = "customerBlockHandler", blockHandlerClass = CustomerBlockHandler.class,blockHandler = "handlerException")
public CommonResult customerBlockHandler(){
return new CommonResult(200, "客户自定义异常", new Payment(2020, "00001"));
}
blockHandlerClass : 指定处理异常的类。
blockHandler :指定具体的处理方法。
注意: @SentinelResource 处理的是控制台配置的流控规则超出预期的错误,由BlockHandler方法配置的兜底方法处理,java运行时的其他错误是不会处理的。
可以通过配置fallback来处理java运行时的业务异常处理:
@GetMapping("/customerBlockHandler")
@SentinelResource(value = "customerBlockHandler",
blockHandlerClass = CustomerBlockHandler.class,
blockHandler = "handlerException",
fallback = "fallbackJavaExceptionHandler")
public CommonResult customerBlockHandler(){
return new CommonResult(200, "客户自定义异常", new Payment(2020, "00001"));
}
若fallback和blockhandler都进行了配置,则被限流降级抛出blockException时只会进入blockhandler处理。
@SentinelResource 参数之: exceptionsToIgnore
热点规则之参数例外项说明:
参数例外项: 当第0个参数的值等于my-test的时候,重置限流阀值
Sentinel 系统规则:
Sentinel 系统自适应限流从整体维度对应用入口流量进行控制,结合应用的 Load、CPU 使用率、总体平均 RT、入口 QPS 和并发线程数等几个维度的监控指标,通过自适应的流控策略,让系统的入口流量和系统的负载达到一个平衡,让系统尽可能跑在最大吞吐量的同时保证系统整体的稳定性。
- 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 达到阈值即触发系统保护。
Sentinel 对OpenFeign的支持
maven依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
yml 添加:
feign:
sentinel:
enabled: true
启动类添加@EnableFeignClients
添加调用接口:
Sentinel 配置的持久化
maven依赖:
<!-- sentinel-datasource-nacos sentinel做持久化用到-->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
Nacos平台中创建我们的流控规则
[{
"resource": "/ getOrderSentinel",
"limitApp": "default",
"grade": 1,
"count": 5,
"strategy": 0,
"controlBehavior": 0,
"clusterMode": false
}]
resource:资源名,即限流规则的作用对象
limitApp:流控针对的调用来源,若为 default 则不区分调用来源
grade:限流阈值类型(QPS 或并发线程数);0代表根据并发数量来限流,1代表根据QPS来进行流量控制
count:限流阈值
strategy:调用关系限流策略
controlBehavior:流量控制效果(直接拒绝、Warm Up、匀速排队)
clusterMode:是否为集群模式
yml配置文件:
spring:
application:
name: cloud-alibaba-sentinel-service
cloud:
nacos:
discovery:
# Nacos 服务注册中心
server-addr: localhost:8848
sentinel:
transport:
# 配置sentinel dashboard 地址
dashboard: localhost:8080
#开启Http Server 与dashboard交互 默认8719端口,假如被占用会自动从8719开始依次+1扫描,直至找到未被占用的端口
port: 8791
datasource:
ds1:
nacos:
# nacos连接地址
server-addr: localhost:8848
# 读取配置文件的 data-id
dataId: cloud-alibaba-sentinel-service
# nacos连接的分组
groupId: DEFAULT_GROUP
# 读取配置文件类型为json
data-type: json
#路由存储规则
rule-type: flow