Sentinel流量控制与熔断降级
Sentinel流量控制与熔断降级
流量控制(Flow Control)
流量控制是Sentinel的核心功能之一,它以流量为切入点,通过监控应用流量的QPS(每秒查询率)或并发线程数等指标,保证系统在高水位流量时仍可以保持稳定。
流量控制的基本概念
在Sentinel中,流量控制主要有以下几个核心概念:
资源:可以是Java应用程序中的任何内容,例如,由应用程序提供的服务,或由应用程序调用的其它应用提供的服务,甚至可以是一段代码。
规则:围绕资源的实时状态设定的规则,可以包括流量控制规则、熔断降级规则以及系统保护规则。
控制行为:当达到阈值时,需要执行的操作,例如直接拒绝、排队等待、预热等。
流量控制规则
流量控制规则(FlowRule)包含以下属性:
属性 | 说明 | 默认值 |
---|---|---|
resource | 资源名,资源名是限流规则的作用对象 | |
count | 限流阈值 | |
grade | 限流阈值类型,QPS模式(1)或线程数模式(0) | QPS模式 |
limitApp | 流控针对的调用来源 | default |
strategy | 调用关系限流策略:直接(0)、链路(1)、关联(2) | 直接 |
controlBehavior | 流控效果:直接拒绝(0)、Warm Up(1)、匀速排队(2) | 直接拒绝 |
clusterMode | 是否集群限流 | false |
流量控制模式
1. QPS流量控制
QPS(Queries Per Second)即每秒查询率,是一台服务器每秒能够响应的查询次数。当QPS超过设定的阈值时,新的请求会被拒绝。
QPS(Queries Per Second)即每秒查询率,是一台服务器每秒能够响应的查询次数。当QPS超过设定的阈值时,新的请求会被拒绝。可以通过rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
和rule.setCount(20);
来设置QPS限流。
2. 线程数流量控制
线程数限流用于保护业务线程数不被耗尽。当同时调用该资源的线程数超过阈值时,新的请求会被拒绝。可以通过rule.setGrade(RuleConstant.FLOW_GRADE_THREAD);
和rule.setCount(10);
来设置线程数限流。
流量控制策略
1. 直接拒绝(默认)
当QPS超过阈值时,新的请求会被立即拒绝,抛出FlowException
异常。这种方式适用于大部分场景,通过rule.setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_DEFAULT);
设置。
2. Warm Up(预热)
预热模式(Warm Up)也叫冷启动,适用于系统长期处于低水位的情况,当流量突然增加时,直接把系统拉升到高水位可能瞬间把系统压垮。通过"冷启动",让通过的流量缓慢增加,在一定时间内逐渐增加到阈值上限,给冷系统一个预热的时间,避免冷系统被压垮。通过rule.setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_WARM_UP);
和rule.setWarmUpPeriodSec(10);
设置。
3. 匀速排队
匀速排队(Rate Limiter)模式会严格控制请求通过的间隔时间,也即是让请求以均匀的速度通过,对应的是漏桶算法。这种方式主要用于处理间隔性突发的流量,例如消息队列。通过rule.setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_RATE_LIMITER);
和rule.setMaxQueueingTimeMs(500);
设置。
调用关系流量控制
调用关系包括调用方、被调用方;一个方法又可能会调用其它方法,形成一个调用链路。Sentinel支持以下几种调用关系的流量控制:
1. 根据调用方限流
limitApp
属性用于根据调用方进行流量控制。若限流规则未配置调用方(default
),则该限流规则对接口的所有调用方生效。若限制了调用方,则限流规则仅对指定调用方生效。
// 限制调用方为appA的请求
rule.setLimitApp("appA");
2. 根据调用链路入口限流
strategy
属性为RuleConstant.STRATEGY_CHAIN
时,表示该规则对从指定入口进入的请求生效。
// 设置链路限流策略
rule.setStrategy(RuleConstant.STRATEGY_CHAIN);
// 设置入口资源
rule.setRefResource("entryResource");
3. 关联流量限流
关联流量限流指的是,当关联的资源达到阈值时,就限流自己。
// 设置关联流量限流策略
rule.setStrategy(RuleConstant.STRATEGY_RELATE);
// 设置关联资源
rule.setRefResource("relatedResource");
实战:配置流量控制规则
下面我们通过一个实际的例子来演示如何配置流量控制规则。
1. 创建一个简单的Controller
FlowController完整代码
通过FlowController
,我们可以创建两个接口:/flow/qps/{count}
用于演示QPS限流,/flow/thread/{count}
用于演示线程数限流。这两个接口都使用了@SentinelResource
注解,并指定了blockHandler
方法来处理限流异常。
#### 2. 通过代码配置流量控制规则
::: details FlowRuleConfig完整代码
通过`FlowRuleConfig`,我们可以通过代码配置QPS和线程数模式的流控规则。例如,为`flowQps`资源设置每秒5个请求的QPS限流,为`flowThread`资源设置最多3个线程同时执行的线程数限流。
:::
3. 通过Sentinel控制台配置流量控制规则
除了通过代码配置,我们还可以通过Sentinel控制台来配置流量控制规则:
- 启动应用程序
- 访问
http://localhost:8080/flow/qps/1
和http://localhost:8080/flow/thread/1
产生流量 - 登录Sentinel控制台,在左侧菜单选择"流控规则"
- 点击"新增流控规则"按钮
- 填写规则信息,如资源名称、阈值类型、阈值等
- 点击"新增"按钮保存规则
流量控制最佳实践
根据业务场景选择合适的流控模式:QPS模式适用于大部分场景,而线程数模式适用于调用外部依赖比较慢的场景。
合理设置阈值:阈值设置过低会导致正常流量被拒绝,阈值设置过高则起不到保护作用。可以通过压测确定系统的承载能力,然后设置合适的阈值。
使用Warm Up预热模式:对于长期处于低水位的系统,当流量突然增加时,使用预热模式可以避免系统被瞬间压垮。
使用匀速排队模式处理突发流量:对于间隔性突发的流量,使用匀速排队模式可以让请求以均匀的速度通过,避免系统负载过高。
根据调用关系进行精细化流控:通过设置调用方、入口资源或关联资源,可以实现更精细化的流量控制。
熔断降级(Circuit Breaking)
熔断降级是Sentinel的另一个核心功能,它通过监控应用中的异常情况,当达到指定的阈值时,对服务进行熔断,防止应用被瞬时的高并发流量或不稳定的后端服务拖垮。
熔断降级的基本概念
熔断降级主要有以下几个核心概念:
熔断:当检测到调用链路中某个资源出现不稳定的表现,例如请求响应时间长或异常比例高时,暂时切断对该资源的调用。
降级:当系统负载较高时,暂时将一些非核心服务降级,以保证核心服务的正常运行。
恢复:当资源恢复正常后,熔断器会自动恢复,恢复对该资源的调用。
熔断降级规则
熔断降级规则(DegradeRule)包含以下属性:
属性 | 说明 | 默认值 |
---|---|---|
resource | 资源名,资源名是熔断规则的作用对象 | |
grade | 熔断策略,支持慢调用比例/异常比例/异常数策略 | 慢调用比例 |
count | 慢调用比例模式下为慢调用临界RT(超出该值计为慢调用);异常比例/异常数模式下为对应的阈值 | |
timeWindow | 熔断时长,单位为秒 | |
minRequestAmount | 熔断触发的最小请求数,请求数小于该值时即使异常比率超出阈值也不会熔断 | 5 |
statIntervalMs | 统计时长(单位为ms),如60*1000代表分钟级 | 1000 ms |
slowRatioThreshold | 慢调用比例阈值,仅慢调用比例模式有效 |
熔断策略
1. 慢调用比例 (SLOW_REQUEST_RATIO)
慢调用比例策略用于检测慢调用比例。当资源的响应时间超过设定的阈值(count)之后,资源进入准降级状态。如果接下来1秒内进入资源的请求数大于等于设置的最小请求数(minRequestAmount),并且慢调用的比例大于阈值,则接下来的熔断时长(timeWindow)内,对这个资源的调用都会自动熔断。可以通过设置rule.setGrade(RuleConstant.DEGRADE_GRADE_RT);
、rule.setCount(200);
、rule.setSlowRatioThreshold(0.5);
、rule.setTimeWindow(10);
、rule.setMinRequestAmount(5);
和rule.setStatIntervalMs(1000);
来配置。
2. 异常比例 (ERROR_RATIO)
异常比例策略用于检测异常比例。当资源的异常比例超过阈值后,资源进入降级状态。可以通过设置rule.setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_RATIO);
、rule.setCount(0.5);
、rule.setTimeWindow(10);
、rule.setMinRequestAmount(5);
和rule.setStatIntervalMs(1000);
来配置。
3. 异常数 (ERROR_COUNT)
异常数策略用于检测异常数。当资源近1分钟的异常数目超过阈值之后,资源进入降级状态。可以通过设置rule.setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_COUNT);
、rule.setCount(5);
、rule.setTimeWindow(10);
、rule.setMinRequestAmount(5);
和rule.setStatIntervalMs(60 * 1000);
来配置。
实战:配置熔断降级规则
下面我们通过一个实际的例子来演示如何配置熔断降级规则。
1. 创建一个简单的Controller
DegradeController完整代码
通过DegradeController
,我们可以创建两个接口:/degrade/slow/{timeout}
用于演示慢调用比例熔断,/degrade/error/{flag}
用于演示异常比例熔断。这两个接口都使用了@SentinelResource
注解,并指定了blockHandler
方法来处理熔断异常。
#### 2. 通过代码配置熔断降级规则
::: details DegradeRuleConfig完整代码
通过`DegradeRuleConfig`,我们可以通过代码配置慢调用比例和异常比例的熔断规则。例如,为`degradeSlow`资源设置慢调用临界值100ms和50%的慢调用比例阈值,为`degradeError`资源设置50%的异常比例阈值。
:::
3. 通过Sentinel控制台配置熔断降级规则
除了通过代码配置,我们还可以通过Sentinel控制台来配置熔断降级规则:
- 启动应用程序
- 访问
http://localhost:8080/degrade/slow/200
和http://localhost:8080/degrade/error/true
产生流量 - 登录Sentinel控制台,在左侧菜单选择"熔断规则"
- 点击"新增熔断规则"按钮
- 填写规则信息,如资源名称、熔断策略、阈值等
- 点击"新增"按钮保存规则
熔断降级最佳实践
根据业务场景选择合适的熔断策略:慢调用比例适用于调用时间敏感的场景,异常比例/异常数适用于调用稳定性要求高的场景。
合理设置阈值和熔断时长:阈值设置过低会导致正常流量被熔断,阈值设置过高则起不到保护作用。熔断时长设置过短可能导致系统还未恢复就重新接收请求,熔断时长设置过长则会影响用户体验。
设置合适的最小请求数:最小请求数设置过低可能导致少量异常就触发熔断,最小请求数设置过高则可能导致熔断不及时。
提供降级后的备选方案:当服务被熔断后,应该提供一个备选方案,例如返回缓存数据、默认值或友好的错误提示。
监控熔断情况:通过Sentinel控制台或监控系统监控熔断情况,及时发现并解决问题。
系统自适应保护
系统自适应保护从整体维度对应用入口流量进行控制,结合应用的Load、总体平均RT、入口QPS和线程数等几个维度的监控指标,让系统的入口流量和系统的负载达到一个平衡,让系统尽可能跑在最大吞吐量的同时保证系统整体的稳定性。
系统规则
系统规则(SystemRule)包含以下属性:
属性 | 说明 | 默认值 |
---|---|---|
highestSystemLoad | Load阈值,仅对Linux/Unix-like机器生效 | -1 (不生效) |
avgRt | 所有入口流量的平均响应时间 | -1 (不生效) |
maxThread | 入口流量的最大并发数 | -1 (不生效) |
qps | 所有入口资源的QPS | -1 (不生效) |
highestCpuUsage | CPU使用率阈值,取值范围[0.0, 1.0] | -1 (不生效) |
配置系统规则
可以通过设置rule.setQps(500);
、rule.setMaxThread(100);
、rule.setAvgRt(100);
、rule.setHighestSystemLoad(3.0);
和rule.setHighestCpuUsage(0.8);
来配置系统规则。
热点参数限流
热点参数限流是一种更细粒度的流量控制,它允许我们针对某个热点参数进行限流,例如针对某个用户ID、商品ID等进行限流。
热点参数规则
热点参数规则(ParamFlowRule)包含以下属性:
属性 | 说明 | 默认值 |
---|---|---|
resource | 资源名,资源名是热点参数规则的作用对象 | |
count | 限流阈值 | |
grade | 限流阈值类型,QPS模式(1)或线程数模式(0) | QPS模式 |
durationInSec | 统计窗口时间长度(单位为秒) | 1s |
controlBehavior | 流控效果(支持快速失败和匀速排队模式) | 快速失败 |
maxQueueingTimeMs | 最大排队等待时间(仅在匀速排队模式生效) | 0ms |
paramIdx | 热点参数的索引,从0开始 | |
paramFlowItemList | 参数例外项,可以针对指定的参数值单独设置限流阈值 | null |
clusterMode | 是否集群限流 | false |
配置热点参数规则
可以通过设置rule.setParamIdx(0);
、rule.setCount(5);
以及ParamFlowItem
来设置参数例外项,例如针对参数值为100的请求,设置限流阈值为10。
实战:配置热点参数规则
下面我们通过一个实际的例子来演示如何配置热点参数规则。
1. 创建一个简单的Controller
ParamFlowController完整代码
通过ParamFlowController
,我们可以创建一个接口/param/{id}
用于演示热点参数限流。该接口使用了@SentinelResource
注解,并指定了blockHandler
方法来处理限流异常。
#### 2. 通过代码配置热点参数规则
::: details ParamFlowRuleConfig完整代码
通过`ParamFlowRuleConfig`,我们可以通过代码配置热点参数限流规则。例如,为`paramFlow`资源设置热点参数索引为0,限流阈值为5,并针对参数值为100的请求设置例外项,限流阈值为10。
:::
@SentinelResource注解详解
@SentinelResource
注解是Sentinel提供的最重要的注解之一,它用于定义资源,并提供了丰富的配置项来处理各种异常情况。
@SentinelResource注解的属性
属性 | 说明 | 默认值 |
---|---|---|
value | 资源名称 | 必填项 |
entryType | entry类型,标记流量的方向 | EntryType.OUT |
blockHandler | 处理BlockException的函数名称 | 空 |
blockHandlerClass | blockHandler函数所在的类 | 空 |
fallback | 处理所有异常的函数名称 | 空 |
fallbackClass | fallback函数所在的类 | 空 |
defaultFallback | 默认的fallback函数名称 | 空 |
exceptionsToTrace | 需要trace的异常类型 | Throwable.class |
exceptionsToIgnore | 需要忽略的异常类型 | 空 |
blockHandler与fallback的区别
- blockHandler:只处理BlockException异常,也就是由Sentinel的流控、熔断、系统保护等规则触发的异常。
- fallback:处理所有类型的异常,包括业务异常和BlockException。
使用示例
@SentinelResource使用示例
@SentinelResource
注解可以配置value
(资源名称)、blockHandler
(处理BlockException
的方法)、fallback
(处理所有异常的方法)等属性。例如,可以定义一个资源resourceName
,并为其指定blockHandlerMethod
和fallbackMethod
来处理不同类型的异常。
### 注意事项
1. **blockHandler和fallback方法的参数和返回值**:必须与原方法一致,最后加一个BlockException或Throwable参数。
2. **blockHandlerClass和fallbackClass**:当blockHandler或fallback方法不在同一个类中时,需要指定这两个属性,并且对应的方法必须是static的。
3. **exceptionsToIgnore**:指定哪些异常类型不触发fallback。
4. **defaultFallback**:默认的fallback方法,当未指定fallback时使用。该方法不需要参数,只需要一个Throwable参数即可。
## 实战案例:电商商品服务
下面我们通过一个电商商品服务的例子来综合演示Sentinel的流量控制、熔断降级和热点参数限流功能。
### 项目结构
src/main/java/com/example/sentinel/
├── SentinelDemoApplication.java
├── config/
│ ├── SentinelConfig.java
│ ├── FlowRuleConfig.java
│ ├── DegradeRuleConfig.java
│ └── ParamFlowRuleConfig.java
├── controller/
│ └── ProductController.java
├── service/
│ ├── ProductService.java
│ └── InventoryService.java
└── model/
└── Product.java
### 模型类
`Product`模型类包含`id`、`name`、`price`和`stock`等字段,用于表示产品信息。
### 服务类
::: details ProductService完整代码
ProductService
提供了getProducts
、getProductById
和decreaseStock
等核心业务方法,并使用@SentinelResource
注解为这些方法配置了流量控制和熔断降级规则,包括blockHandler
和fallback
方法来处理限流和异常情况。
:::
InventoryService
提供了getInventory
方法用于查询产品库存,同样使用了@SentinelResource
注解进行保护,并定义了blockHandler
和fallback
方法。
### 控制器
::: details ProductController完整代码
`ProductController`作为RESTful接口层,提供了`getProduct`、`deductStock`、`listProducts`和`getInventory`等接口,分别调用`ProductService`和`InventoryService`中的方法来处理业务逻辑。这些接口是Sentinel流量控制和熔断降级规则的入口。
:::
配置类
SentinelConfig完整代码
SentinelConfig
类通过@Bean
注解注册SentinelResourceAspect
,以启用@SentinelResource
注解的AOP功能,从而实现对被注解方法的流量控制和熔断降级。
::: details 流量控制规则配置
FlowRuleConfig
类通过@PostConstruct
方法初始化并加载流量控制规则。例如,为getProduct
资源设置QPS阈值为10,为deductStock
资源设置QPS阈值为5,为listProducts
资源设置QPS阈值为20,为getInventory
资源设置QPS阈值为15。
:::
::: details 熔断降级规则配置
`DegradeRuleConfig`类通过`@PostConstruct`方法初始化并加载熔断降级规则。例如,为`getProduct`资源设置响应时间(RT)阈值,为`deductStock`资源设置异常比例阈值,为`getInventory`资源设置异常数阈值,并都配置了熔断时长和最小请求数.
:::
::: details 热点参数规则配置
`ParamFlowRuleConfig`类通过`@PostConstruct`方法初始化并加载热点参数限流规则。例如,为`getProductById`资源设置参数索引为0,默认QPS阈值为10,并为参数值`"100"`设置例外,QPS阈值为1。同时,为`decreaseStock`资源设置参数索引为0,默认QPS阈值为5。
:::
### 应用配置
::: details application.yml完整配置
```yaml
server:
port: 8081
spring:
application:
name: sentinel-product-service
cloud:
sentinel:
transport:
dashboard: localhost:8080
eager: true
management:
endpoints:
web:
exposure:
include: '*'
:::
### 测试应用
1. 启动Sentinel控制台
2. 启动应用程序
3. 使用以下命令测试API:
```bash
# 获取所有商品
curl "http://localhost:8081/products"
# 获取指定商品
curl "http://localhost:8081/products/1"
# 获取VIP商品(热点参数限流)
curl "http://localhost:8081/products/100"
# 减少库存
curl -X POST "http://localhost:8081/products/1/stock/decrease?count=1"
- 登录Sentinel控制台,查看流控规则、熔断规则和热点参数规则的效果
常见问题
注意事项
- 规则持久化:默认情况下,规则存储在内存中,应用重启后会丢失,建议配置规则持久化
- @SentinelResource注解不生效:确保已经配置了
SentinelResourceAspect
的Bean - 热点参数限流不生效:确保引入了
sentinel-parameter-flow-control
依赖
1. 如何解决流控规则不生效的问题?
可能的原因和解决方案:
- 检查资源名称是否正确
- 确保应用有足够的流量触发Sentinel的初始化
- 检查规则是否正确配置
- 检查应用日志中是否有Sentinel相关的错误信息
2. 如何解决热点参数限流不生效的问题?
可能的原因和解决方案:
- 确保引入了
sentinel-parameter-flow-control
依赖 - 检查热点参数的索引是否正确
- 确保使用了
@SentinelResource
注解 - 检查应用日志中是否有Sentinel相关的错误信息
总结
本文深入讲解了Sentinel的流量控制和熔断降级功能,包括各种策略和实战案例。通过Sentinel,我们可以实现精细化的流量控制、熔断降级和热点参数限流,保障微服务的稳定性。
在下一篇文章中,我们将探讨Sentinel的高级特性和最佳实践,包括规则持久化、集群流量控制、网关限流等内容,敬请期待!
下一步学习
- 学习Sentinel的规则持久化
- 了解Sentinel的集群流量控制
- 探索Sentinel的网关限流
- 掌握Sentinel的最佳实践