2 服务熔断和限流 Sentinel
Sentinel特性
Sentinel分两个部分
- 核心库(Java客户端)不依赖任何框架/库,能够运行于所有Java运行时环境,同时对Dubbo/SpringCloud等框架也有较好的支持
- 控制台(Dashboard)基于SpringBoot开发,打包后可以直接运行,不需要额外的Tomcat等应用容器
Sentinel控制台安装步骤
下载地址
运行命令(前提Java8环境;8080端口)
1
java -jar sentinel-dashboard-1.8.6.jar
访问sentinel管理界面(账号密码均为sentinel)
初始化监控
启动Nacos http://localhost:8848/nacos
1.新建cloudalibaba-sentinel-service-8401
2.引入pom
3.配置yml
4.添加主启动
5.处理业务类
6.测试
启动8401,由于Sentinel采用懒加载
执行一次访问http://localhost:8401/testA和http://localhost:8401/testB
流控规则
- 资源名:唯一名称,默认请求路径
- 针对来源:Sentinel可以针对调用者进行限流,填写微服务名,默认default(不区分来源)
- 阈值类型/单机阈值:
- QPS(每秒钟的请求数量):当调用该api的QPS达到阈值时,进行限流
- 线程数:当调用该api的线程数达到阈值时,进行限流
- 是否集群,不需要集群
- 流控模式:
- 直接:api到达限流条件时,直接限流
- 关联:当关联的资源达到阈值时,就限流自己
- 链路:只记录指定链路上的流量(指定资源从入口资源进来时的流量,如果达到阈值,就进行限流)【api级别的针对来源】
- 流控效果:
- 快速失败::直接失败,抛异常
- Warm Up:根据coldFactor(冷加载因子,默认3)的值,从阈值/coldFactor,经过预热时长,才达到设置的QPS阈值
- 排队等待:匀速排队,让请求以匀速的速度通过,阈值类型必须设置为QPS,否则无效
降级规则
基本介绍
RT(平均响应时间,秒级)
平均响应时间 超出阈值且在时间窗内通过的请求>=5,两个条件同时满足后触发降级,窗口期过后关闭断路器,RT最大4900(更大的需要通过-Dcsp.sentinel.statistic.max.rt=XXXX才能生效)
异常比例(秒级)
QPS>=5且异常比例(秒级统计)超过阈值时,触发降级;时间窗口结束后,关闭降级
Sentinel熔断器降级会在调用链路中某个资源出现不稳定状态时(例如调用超时或异常比例升高),对这个资源的调用进行限制,让请求快速失败,避免影响到其他的资源而导致级联错误
当资源被降级后,在接下来的降级时间窗口之内,对该资源的调用都自动熔断(默认行为是抛出DegradeException)
Sentinel断路器是没有半开状态的
半开的状态系统自动检测是否有请求异常,没有异常就去关闭断路器恢复使用,有异常则继续打开断路器不可用
RT
异常比例 (ERROR_RATIO
)
当单位统计时长(statIntervalMs
)内请求数目大于设置的最小请求数目,并且异常的比例大于阈值,则接下来的熔断时长内请求会自动被熔断。经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN 状态),若接下来的一个请求成功完成(没有错误)则结束熔断,否则会再次被熔断。异常比率的阈值范围是 [0.0, 1.0]
,代表 0% - 100%。
异常数 (ERROR_COUNT
)
当单位统计时长内的异常数目超过阈值之后会自动进行熔断。经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN 状态),若接下来的一个请求成功完成(没有错误)则结束熔断,否则会再次被熔断。
热点规则
何为热点?热点即经常访问的数据。很多时候我们希望统计某个热点数据中访问频次最高的 Top K 数据,并对其访问进行限制。比如:
- 商品 ID 为参数,统计一段时间内最常购买的商品 ID 并进行限制
- 用户 ID 为参数,针对一段时间内频繁访问的用户 ID 进行限制
热点参数限流会统计传入参数中的热点参数,并根据配置的限流阈值与模式,对包含热点参数的资源调用进行限流。热点参数限流可以看做是一种特殊的流量控制,仅对包含热点参数的资源调用生效。
代码
1 |
|
配置
@SentinelResource(value = "testHotKey", blockHandler = "deal_testHotKey")
方法testHotKey里面的第一个参数只要QPS超过每秒一次,马上降级处理
参数例外项
特例情况
- 普通: 超过1s后阈值马上被限流
- 特殊:期望p1参数为某特殊值时,它的限流值和平时不一样
配置
@SentinelResource处理的是Sentinel控制台配置的违规情况,有blockHandler方法配置的兜底处理,主管配置出错,运行时异常不管的
系统规则
Sentinel 系统自适应过载保护从整体维度对应用入口流量进行控制,结合应用的 Load、CPU 使用率、总体平均 RT、入口 QPS 和并发线程数等几个维度的监控指标,通过自适应的流控策略,让系统的入口流量和系统的负载达到一个平衡,让系统尽可能跑在最大吞吐量的同时保证系统整体的稳定性。
系统规则
系统保护规则是从应用级别的入口流量进行控制,从单台机器的 load、CPU 使用率、平均 RT、入口 QPS 和并发线程数等几个维度监控应用指标,让系统尽可能跑在最大吞吐量的同时保证系统整体的稳定性。
系统保护规则是应用整体维度的,而不是资源维度的,并且仅对入口流量生效。入口流量指的是进入应用的流量(EntryType.IN
),比如 Web 服务或 Dubbo 服务端接收的请求,都属于入口流量。
系统规则支持以下的模式:
- 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配置
按资源名称限流+后续处理
1.启动Nacos
2.启动Sentinel
3.修改cloudalibaba-sentinel-service-8401
1 |
|
4.配置流控规则
测试流控后,将8401关闭,发现流控规则消失,无法持久化
按URL地址限流+后续处理
1 |
|
上述两种兜底方案存在问题
- 系统默认的,没有体现自己的业务要求
- 依照现有条件,自定义的处理方法和业务代码耦合在一起,不直观
- 每个业务方法都添加一个兜底的,造成代码膨胀
- 全局统一的异常处理方法没有体现
客户自定义限流处理逻辑
1.创建CustomerBlockHandler类用于自定义限流处理逻辑
1 | public class CustomerBlockHandler { |
2.controller
1 |
|
@SentinelResource 注解
注意:注解方式埋点不支持 private 方法。
@SentinelResource
用于定义资源,并提供可选的异常处理和 fallback 配置项。 @SentinelResource
注解包含以下属性:
value
:资源名称,必需项(不能为空)entryType
:entry 类型,可选项(默认为EntryType.OUT
)blockHandler
/blockHandlerClass
:blockHandler
对应处理BlockException
的函数名称,可选项。blockHandler 函数访问范围需要是public
,返回类型需要与原方法相匹配,参数类型需要和原方法相匹配并且最后加一个额外的参数,类型为BlockException
。blockHandler 函数默认需要和原方法在同一个类中。若希望使用其他类的函数,则可以指定blockHandlerClass
为对应的类的Class
对象,注意对应的函数必需为 static 函数,否则无法解析。fallback
/fallbackClass
:blockHandler
对应处理BlockException
的函数名称,可选项。blockHandler 函数访问范围需要是public
,返回类型需要与原方法相匹配,参数类型需要和原方法相匹配并且最后加一个额外的参数,类型为BlockException
。blockHandler 函数默认需要和原方法在同一个类中。若希望使用其他类的函数,则可以指定blockHandlerClass
为对应的类的Class
对象,注意对应的函数必需为 static 函数,否则无法解析。defaultFallback
(since 1.6.0):默认的 fallback 函数名称,可选项,通常用于通用的 fallback 逻辑(即可以用于很多服务或方法)。默认 fallback 函数可以针对所有类型的异常(除了exceptionsToIgnore
里面排除掉的异常类型)进行处理。若同时配置了 fallback 和 defaultFallback,则只有 fallback 会生效。defaultFallback 函数签名要求:- 返回值类型必须与原函数返回值类型一致;
- 方法参数列表需要为空,或者可以额外多一个
Throwable
类型的参数用于接收对应的异常。 - defaultFallback 函数默认需要和原方法在同一个类中。若希望使用其他类的函数,则可以指定
fallbackClass
为对应的类的Class
对象,注意对应的函数必需为 static 函数,否则无法解析。
exceptionsToIgnore
(since 1.6.0):用于指定哪些异常被排除掉,不会计入异常统计中,也不会进入 fallback 逻辑中,而是会原样抛出。
1.8.0 版本开始,defaultFallback
支持在类级别进行配置。
注:1.6.0 之前的版本 fallback 函数只针对降级异常(
DegradeException
)进行处理,不能针对业务异常进行处理。
特别地,若 blockHandler 和 fallback 都进行了配置,则被限流降级而抛出 BlockException
时只会进入 blockHandler
处理逻辑。若未配置 blockHandler
、fallback
和 defaultFallback
,则被限流降级时会将 BlockException
直接抛出(若方法本身未定义 throws BlockException 则会被 JVM 包装一层 UndeclaredThrowableException
)。
sentinel主要有三个核心API
- SphU定义资源
- Tracer定义统计
- ContextUtil定义上下文
服务熔断
Sentinel整合Ribbon+OpenFeign+fallback
Ribbon系列
提供者9003/9004
1.新建cloudalibaba-provider-payment-9003/9004
2.引入pom
3.配置yml
4.添加主启动
5.处理业务
消费者84
1.新建cloudalibaba-consumer-nacos-order-84
2.引入pom
3.配置yml
4.添加主启动
5.处理业务
目的
fallback负责运行时异常
blockHandler负责配置违规
若blockHandler和fallback都进配置,则被限流降级而抛出BlockException时只会进入blockHandler处理逻辑
1 | public class CircleBreakerController { |
Feign系列
**Feign组件一般是消费侧**1 |
|
1 |
|
测试84调用9003,此时9003微服务宕机,消费者84会被降级
熔断框架比较
Sentinel | Hystrix | resilience4j | |
---|---|---|---|
隔离策略 | 信号量隔离(并发线程数限流) | 线程池隔离/信号量隔离 | 信号量隔离 |
熔断降级策略 | 基于响应时间、异常比率、异常数 | 基于异常比率 | 基于异常比率、响应时间 |
实时统计实现 | 滑动窗口(LeapArray) | 滑动窗口(基于RxJava) | Ring Bit Buffer |
动态规则配置 | 支持多种数据源 | 支持多种数据源 | 有限支持 |
扩展性 | 多个扩展点 | 插件形式 | 接口形式 |
基于注解的支持 | 支持 | 支持 | 支持 |
限流 | 基于QPS、支持基于调用关系的限流 | 有限的支持 | Rate Limiter |
规则持久化
一旦重启应用,Sentinel规则将消失,生产环境需要将配置进行持久化
将限流规则持久化进Nacos进行保存,只要刷新8401某个rest地址,Sentinel控制台的流控规则就能看到,只要Nacos里面的配置不删除,针对8401上的Sentinel上的流控规则持续有效
步骤
修改cloudalibaba-sentinel-service-8401
pom
1 | <dependency> |
yml(添加Nacos数据源配置)
1 | spring: |
添加Nacos业务规则配置
1 | { |
属性 | 说明 |
---|---|
resource | 资源名称 |
limitApp | 来源应用 |
grade | 阈值类型,0表示线程数,1表示QPS |
count | 单机阈值 |
strategy | 流控模式,0表示直接,1表示关联,2表示链路 |
controllerBehavior | 流控效果,0表示快速失败,1表示Warm Up,2表示排队等待 |
clusterMode | 是否集群 |
启动8401,刷新Sentinel