流量整形与熔断:Sentinel 流控实战
xml com.alibaba.cloud spring-cloud-starter-alibaba-sentinel 2021.0.5.0
### 3. 配置控制台
Sentinel 提供一个轻量级控制台用于规则管理和监控。下载 [sentinel-dashboard.jar](https://github.com/alibaba/Sentinel/releases) ,启动命令:
```bash
java -Dserver.port=8080 -Dcsp.sentinel.dashboard.server=localhost:8080 -jar sentinel-dashboard.jar
在 Spring Boot 的 application.yml 中配置控制台地址:
spring:
cloud:
sentinel:
transport:
dashboard: localhost:8080 # 控制台地址
port: 8719 # 本地通信端口,选一个未被占用的
启动你的应用并访问 http://localhost:8080 ,默认账号密码均为 sentinel,即可看到控制台。
流量控制:实现精准限流
流控规则概览
Sentinel 通过对资源的调用进行限制来保护服务。资源可以是 URL、方法等。流控规则主要包含以下属性:
- 资源名:唯一标识,如
/order/create。 - 限流阈值类型:QPS(每秒请求数)或并发线程数。
- 流控模式:直接、关联、链路。
- 流控效果:快速失败、Warm Up(预热)、匀速排队。
实战:基于 QPS 的直接限流
创建一个简单的 REST 接口:
@RestController
public class DemoController {
@GetMapping("/hello")
@SentinelResource(value = "hello", blockHandler = "helloBlockHandler")
public String hello() {
return "Hello Sentinel!";
}
// 限流后的降级处理逻辑
public String helloBlockHandler(BlockException ex) {
return "系统繁忙,请稍后再试";
}
}
访问一次 /hello 后,在控制台左侧出现名为 hello 的资源。点 “流控规则” → “新增流控规则”,设置:
- 阈值类型:QPS
- QPS 阈值:2
- 流控模式:直接
- 流控效果:快速失败
保存后,用工具(如 JMeter 或 curl)在 1 秒内连续请求 3 次,会看到第 3 次及后续请求返回 “系统繁忙,请稍后再试”。
流量整形效果详解
1. 快速失败(直接拒绝)
这是最直接的方式,当 QPS 超过阈值时,新请求立刻被拒绝,抛出 FlowException。适用于对突发流量零容忍的场景,如秒杀下单。
2. Warm Up(预热)
系统长期处于低水位时,突然涌入大量流量可能瞬间压垮系统(例如缓存未预热)。Warm Up 让通过的 QPS 缓慢增加,经过一段预热时间后才到达设定的阈值。
配置示例:
- 阈值:100
- 流控效果:Warm Up
- 预热时长:10 秒
效果:最初允许通过的 QPS 为 100/3 ≈ 33,然后在 10 秒内线性增长至 100。这为系统留出预热时间。
3. 匀速排队(排队等待)
请求以均匀的速度通过,多余请求排队等待,若等待超时则拒绝。它使流量曲线变得平滑,类似漏桶算法。
配置示例:
- 阈值:QPS 为 5
- 流控效果:匀速排队
- 超时时间:500 毫秒
效果:每秒严格通过 5 个请求,后续请求进入队列,如果等待超过 500ms 则拒绝。这种方式适合处理突发流量后需要“削峰填谷”的场景,如消息处理。
关联与链路流控模式
- 关联模式:当关联资源达到阈值时,限流当前资源。比如支付接口
/pay关联到下单接口/order,当/order的 QPS 过高时,限制/pay的访问,优先保证核心下单链路。 - 链路模式:针对一条调用链路上的入口限流。例如
getUserInfo方法被多个接口调用,只想限制来自/api/v1的调用,则可指定入口资源。
熔断降级:防止级联雪崩
当依赖的服务出现不稳定时,如果不加以隔离,调用方会因为等待超时或处理异常而堆积线程,最终耗尽资源导致自身不可用。Sentinel 的熔断降级策略有三种:
1. 慢调用比例 (SLOW_REQUEST_RATIO)
当资源的 慢调用比例 超过阈值,且统计时长内的请求数达到最小请求数,则触发熔断。
参数说明:
- 最大 RT:响应时间超过该值称为慢调用。
- 比例阈值:慢调用占所有调用的比例。
- 熔断时长:熔断持续的时间,之后尝试放行一个探测请求。
- 最小请求数:统计周期内至少需要的请求数。
示例:设置最大 RT=200ms,比例阈值=0.5,最小请求数=5,熔断时长=10 秒。若 1 秒内出现 5 个请求,其中 3 个 RT>200ms(比例=0.6),则触发熔断,之后 10 秒内所有请求直接失败。
2. 异常比例 (ERROR_RATIO)
当资源的 异常比例 超过阈值,且请求数≥最小请求数时触发熔断。适用于依赖服务频繁抛出异常的情况。
3. 异常数 (ERROR_COUNT)
当 1 分钟内异常数超过阈值直接熔断。注意统计时间窗口是分钟级别,相对较少使用。
编码实现熔断降级
以慢调用比例为例,定义一个模拟远程调用的接口:
@GetMapping("/remote")
@SentinelResource(value = "remoteService",
fallback = "remoteFallback")
public String callRemote() throws InterruptedException {
// 模拟随机延迟
long sleepTime = new Random().nextInt(500);
Thread.sleep(sleepTime);
return "remote response";
}
// fallback 处理异常或熔断
public String remoteFallback(Throwable t) {
return "服务降级,请稍后重试";
}
在 Sentinel 控制台为 remoteService 资源添加降级规则(熔断):
- 降级策略:慢调用比例
- 最大 RT:100ms
- 比例阈值:0.3
- 最小请求数:5
- 熔断时长:5 秒
使用压测工具发送多次请求,当慢调用比例满足条件时,控制台会显示资源处于熔断状态,请求直接进入 fallback 逻辑。
系统自适应保护
除了针对资源的规则,Sentinel 还提供系统层面的保护规则,从整体维度控制入口流量:
- Load:仅对 Linux/Unix 有效,当系统 load1 超过阈值时触发保护。
- CPU 使用率:系统 CPU 使用率超过阈值时保护。
- 平均 RT:所有入口流量的平均 RT 过高时保护。
- 并发线程数:所有入口并发线程数过高时保护。
- 入口 QPS:总入口 QPS 过高时保护。
这些规则不需要针对单一资源,是从集群大局出发的兜底策略。
规则持久化
默认情况下,Sentinel 规则存储在内存中,应用重启即丢失。生产环境推荐使用配置中心(如 Nacos)进行持久化。以 Nacos 为例:
添加依赖:
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
配置 application.yml:
spring:
cloud:
sentinel:
datasource:
ds1:
nacos:
server-addr: 127.0.0.1:8848
data-id: ${spring.application.name}-sentinel
group-id: DEFAULT_GROUP
data-type: json
rule-type: flow # 持久化流控规则