1. 场景:秒杀洪峰下的微服务"保险丝"
1.1 一个真实的秒杀事故
去年双十一,我负责的电商平台上线秒杀活动。活动开始前,系统日常 QPS 稳定在 500 左右,一切正常。
秒杀开始的瞬间,流量直接飙到 50000 QPS,涨幅 100 倍。
灾难链:
- 订单服务涌入大量请求,线程池打满
- 库存服务被击穿,数据库连接池耗尽
- 支付服务超时,整个调用链雪崩
- 最终结果:全站不可用 23 分钟,直接损失超百万
1.2 为什么需要 Sentinel
这次事故后,我们引入了 Sentinel。它提供三位一体的流量防护:
- 限流:控制进入的流量,不让洪峰冲垮服务
- 熔断:下游服务异常时及时断开,防止级联故障
- 降级:非核心功能降级,保住核心链路
1.3 有无 Sentinel 的对比

核心区别:没有 Sentinel,洪峰流量会无差别冲击所有服务;有了 Sentinel,超限流量被拦截,异常服务被熔断,系统整体存活。
2. Sentinel 核心概念与架构
2.1 两个核心概念
Sentinel 的设计围绕两个核心概念展开:
资源(Resource):需要保护的东西,可以是一个方法、一段代码、一个接口。
规则(Rule):如何保护资源,定义限流阈值、熔断条件等。
// 资源和规则的关系
// 资源 = 你要保护什么
try (Entry entry = SphU.entry("orderService")) {
// 业务逻辑 —— 受保护
return orderService.createOrder(request);
} catch (BlockException e) {
// 被限流/熔断时的处理
return "系统繁忙,请稍后重试";
}
// 规则 = 怎么保护
FlowRule rule = new FlowRule("orderService")
.setCount(100) // QPS 阈值
.setGrade(RuleConstant.FLOW_GRADE_QPS);
FlowRuleManager.loadRules(Collections.singletonList(rule));
2.2 Slot Chain 处理流程
Sentinel 的核心是 Slot Chain(插槽链),每个 Slot 负责一项职责,请求依次通过所有 Slot:

关键 Slot 职责:
| Slot | 职责 | 说明 |
|---|---|---|
| NodeSelectorSlot | 构建调用树 | 记录资源的调用路径 |
| StatisticSlot | 实时统计 | 统计 QPS、RT、线程数等 |
| FlowSlot | 流量控制 | 判断是否超过限流阈值 |
| DegradeSlot | 熔断降级 | 判断是否触发熔断 |
| SystemSlot | 系统保护 | 根据 CPU/Load 保护系统 |
| AuthoritySlot | 来源控制 | 黑白名单过滤 |
2.3 Sentinel Dashboard
Sentinel Dashboard 是可视化的规则管理和监控平台:
- 实时监控:查看各资源的 QPS、RT、线程数
- 规则管理:动态配置限流、熔断、系统规则
- 集群管理:管理 Token Server 和 Token Client
- 机器发现:自动发现接入的应用实例
3. Spring Cloud Alibaba 集成 Sentinel
3.1 Maven 依赖配置
Spring Cloud Alibaba 封装了 Sentinel 的 Starter,自动装配核心组件,无需手动初始化。
<dependencies>
<!-- Sentinel Starter -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
<version>2023.0.1.2</version>
</dependency>
<!-- Sentinel 对 Spring MVC 的支持 -->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-spring-webmvc-adapter</artifactId>
<version>1.8.8</version>
</dependency>
<!-- Sentinel 对 OpenFeign 的支持 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
</dependencies>
3.2 应用配置
连接 Sentinel Dashboard 和开启 Feign 整合是接入的关键步骤。
server:
port: 8081
spring:
application:
name: order-service
cloud:
sentinel:
transport:
dashboard: localhost:8080 # Sentinel Dashboard 地址
port: 8719 # 客户端与 Dashboard 通信端口
web-context-unify: false # 关闭上下文合并,每个URL独立统计
http-method-specify: true # 区分 HTTP 方法
# 开启 Feign 对 Sentinel 的支持
feign:
sentinel:
enabled: true
3.3 @SentinelResource 注解使用
@SentinelResource 是声明式资源定义的核心注解,比 try-catch 方式更优雅,且支持细粒度的流控和降级处理。
@Service
public class OrderService {
/**
* 创建订单 —— 核心接口,需要限流保护
*/
@SentinelResource(
value = "createOrder",
blockHandler = "createOrderBlockHandler",
fallback = "createOrderFallback"
)
public OrderVO createOrder(OrderRequest request) {
// 核心业务逻辑
Order order = new Order();
order.setUserId(request.getUserId());
order.setProductId(request.getProductId());
order.setQuantity(request.getQuantity());
orderMapper.insert(order);
return OrderVO.from(order);
}
/**
* blockHandler:被限流/熔断时触发(BlockException)
*/
public OrderVO createOrderBlockHandler(OrderRequest request, BlockException e) {
log.warn("创建订单被限流,userId={}", request.getUserId());
throw new ServiceException("SYSTEM_BUSY", "系统繁忙,请稍后重试");
}
/**
* fallback:业务异常时触发(非 BlockException)
*/
public OrderVO createOrderFallback(OrderRequest request, Throwable t) {
log.error("创建订单异常,userId={}", request.getUserId(), t);
throw new ServiceException("ORDER_ERROR", "订单创建失败,请重试");
}
}
3.4 Sentinel Dashboard 部署
Dashboard 是规则可视化管理的基础,生产环境必须部署。
# 下载 Sentinel Dashboard JAR
wget https://github.com/alibaba/Sentinel/releases/download/1.8.8/sentinel-dashboard-1.8.8.jar
# 启动 Dashboard
java -jar sentinel-dashboard-1.8.8.jar \
--server.port=8080 \
--auth.username=sentinel \
--auth.password=sentinel123
# 访问 Dashboard
# http://localhost:8080
# 默认账号:sentinel / sentinel
启动后,应用需要发送几个请求才能在 Dashboard 上看到机器列表和资源信息。
4. 五大核心功能实战
4.1 流量控制
流量控制是 Sentinel 最基础的功能,支持 QPS 限流和线程数限流两种模式。
QPS 限流:每秒请求数超过阈值时拒绝。
线程数限流:并发线程数超过阈值时拒绝,适合保护慢调用资源。
QPS 限流适合接口级别的粗粒度防护,线程数限流适合保护数据库连接等资源。
/**
* QPS 限流 —— 每秒最多 100 个请求
*/
@SentinelResource(value = "queryOrder", blockHandler = "queryBlockHandler")
public OrderVO queryOrder(Long orderId) {
return orderMapper.selectById(orderId);
}
/**
* 线程数限流 —— 最多 20 个并发线程
* 适合保护慢 SQL 查询
*/
@SentinelResource(value = "queryOrderDetail", blockHandler = "queryBlockHandler")
public OrderDetailVO queryOrderDetail(Long orderId) {
// 涉及多表关联查询,RT 较高
return orderMapper.selectDetailById(orderId);
}
// 编程式配置规则
private void initFlowRules() {
// QPS 限流规则
FlowRule qpsRule = new FlowRule("queryOrder")
.setCount(100)
.setGrade(RuleConstant.FLOW_GRADE_QPS)
.setLimitApp("default")
.setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_DEFAULT);
// 线程数限流规则
FlowRule threadRule = new FlowRule("queryOrderDetail")
.setCount(20)
.setGrade(RuleConstant.FLOW_GRADE_THREAD)
.setLimitApp("default");
FlowRuleManager.loadRules(Arrays.asList(qpsRule, threadRule));
}
流控效果说明:
| 控制行为 | 说明 | 适用场景 |
|---|---|---|
| 直接拒绝 | 超限立即拒绝,抛出 BlockException | 常规限流 |
| Warm Up | 冷启动,预热后逐步达到阈值 | 秒杀预热 |
| 匀速排队 | 请求匀速通过,间隔 = 1000/阈值QPS | 削峰填谷 |
4.2 熔断降级
熔断降级针对的是调用端保护。当下游服务出现异常时,及时熔断,避免级联故障。
Sentinel 提供三种熔断策略:
慢调用比例:响应时间超过阈值的请求占比超过设定值时熔断。
异常比例:异常请求占比超过设定值时熔断。
异常数:异常请求数超过设定值时熔断。
慢调用比例策略适合保护 RT 敏感的接口,异常比例策略适合保护不稳定的下游服务。
/**
* 熔断降级 —— 调用库存服务
*/
@SentinelResource(value = "checkStock", fallback = "checkStockFallback")
public StockVO checkStock(Long productId) {
// 调用库存服务(可能不稳定)
return stockFeignClient.getStock(productId);
}
// 降级方法
public StockVO checkStockFallback(Long productId, Throwable t) {
log.warn("库存服务降级,productId={}", productId, t);
// 降级方案:返回默认库存,允许下单但标记为待确认
StockVO stock = new StockVO();
stock.setProductId(productId);
stock.setAvailable(true);
stock.setNeedConfirm(true); // 标记需要后续确认
return stock;
}
// 编程式配置熔断规则
private void initDegradeRules() {
// 慢调用比例熔断
DegradeRule slowCallRule = new DegradeRule("checkStock")
.setGrade(CircuitBreakerStrategy.SLOW_REQUEST_RATIO.getType())
.setCount(500) // 慢调用阈值:500ms
.setSlowRatioThreshold(0.6) // 慢调用比例:60%
.setTimeWindow(30) // 熔断时长:30秒
.setMinRequestAmount(5) // 最小请求数:5
.setStatIntervalMs(10000); // 统计时长:10秒
// 异常比例熔断
DegradeRule exceptionRatioRule = new DegradeRule("checkStock")
.setGrade(CircuitBreakerStrategy.ERROR_RATIO.getType())
.setCount(0.5) // 异常比例阈值:50%
.setTimeWindow(30)
.setMinRequestAmount(5)
.setStatIntervalMs(10000);
// 异常数熔断
DegradeRule exceptionCountRule = new DegradeRule("checkStock")
.setGrade(CircuitBreakerStrategy.ERROR_COUNT.getType())
.setCount(10) // 异常数阈值:10
.setTimeWindow(60)
.setMinRequestAmount(5)
.setStatIntervalMs(10000);
DegradeRuleManager.loadRules(
Arrays.asList(slowCallRule, exceptionRatioRule, exceptionCountRule)
);
}
熔断状态机:
- CLOSED(关闭):正常放行请求,统计异常指标
- OPEN(打开):熔断生效,所有请求直接降级
- HALF-OPEN(半开):熔断到期后放行少量请求探测,成功则关闭,失败则继续熔断

熔断恢复策略:HALF_OPEN 阶段是 Sentinel 的"自我修复"机制。如果探测请求成功,说明下游已恢复,熔断器关闭;如果再次失败,熔断器继续保持 OPEN 状态,等待下一次探测窗口。生产环境中建议配合慢启动恢复策略,避免瞬间涌入大量请求导致二次熔断。
4.3 热点参数限流
热点参数限流是 Sentinel 的特色功能,可以按请求参数值分别限流。
秒杀场景下,热门商品的访问量远超普通商品,按商品 ID 精准限流比全局限流更合理。
/**
* 热点参数限流 —— 按商品ID限流
* 热门商品单独限流,普通商品不受影响
*/
@SentinelResource(value = "getProduct", blockHandler = "getProductBlockHandler")
public ProductVO getProduct(
@RequestParam Long productId,
@RequestParam(required = false) String source
) {
return productMapper.selectById(productId);
}
public ProductVO getProductBlockHandler(Long productId, String source, BlockException e) {
log.warn("商品查询被限流,productId={}", productId);
// 返回简化商品信息
return ProductVO.simpleDefault(productId);
}
// 编程式配置热点参数规则
private void initParamFlowRules() {
ParamFlowRule rule = new ParamFlowRule("getProduct")
.setParamIdx(0) // 第0个参数(productId)
.setCount(50) // 默认每个参数值 QPS 上限 50
.setGrade(RuleConstant.FLOW_GRADE_QPS);
// 热门商品单独设置更高的限流阈值
ParamFlowItem hotItem = new ParamFlowItem()
.setObject("10086") // 商品ID=10086 是秒杀商品
.setClassType(long.class.getName())
.setCount(500); // 秒杀商品允许 500 QPS
rule.setParamFlowItemList(Collections.singletonList(hotItem));
ParamFlowRuleManager.loadRules(Collections.singletonList(rule));
}
注意事项:热点参数限流仅支持基本类型和 String 类型参数,不支持复杂对象。

核心优势:全局限流"一刀切"会误伤普通商品流量;热点参数限流按商品 ID 分别计算,热门商品和普通商品互不影响,精准防护。
4.4 系统自适应保护
系统自适应保护从整体维度保护应用,防止系统被拖垮。
当系统整体负载过高时,单靠接口级限流不够,需要从系统维度做兜底保护。
// 系统自适应保护规则
private void initSystemRules() {
// CPU 使用率保护
SystemRule cpuRule = new SystemRule();
cpuRule.setHighestCpuUsage(0.8); // CPU 使用率 > 80% 触发保护
// 系统 Load 保护
SystemRule loadRule = new SystemRule();
loadRule.setHighestSystemLoad(5.0); // Load > 5 触发保护
// 平均 RT 保护
SystemRule rtRule = new SystemRule();
rtRule.setAvgRt(500); // 平均 RT > 500ms 触发保护
// 并发线程数保护
SystemRule threadRule = new SystemRule();
threadRule.setMaxThread(200); // 并发线程 > 200 触发保护
// 入口 QPS 保护
SystemRule qpsRule = new SystemRule();
qpsRule.setQps(5000); // 入口总 QPS > 5000 触发保护
SystemRuleManager.loadRules(
Arrays.asList(cpuRule, loadRule, rtRule, threadRule, qpsRule)
);
}
系统保护触发时,入口流量会被全局限制,所有资源都可能被 Block。
4.5 来源访问控制
来源访问控制(黑白名单)根据调用来源决定是否放行。
内部服务之间的调用应该放行,外部来源的异常流量应该拦截。
// 来源访问控制规则
private void initAuthorityRules() {
AuthorityRule rule = new AuthorityRule("orderService")
.setLimitApp("gateway-service,admin-service") // 白名单
.setStrategy(RuleConstant.AUTHORITY_WHITE); // 白名单模式
// 黑名单模式
AuthorityRule blackRule = new AuthorityRule("orderService")
.setLimitApp("suspicious-client") // 黑名单
.setStrategy(RuleConstant.AUTHORITY_BLACK); // 黑名单模式
AuthorityRuleManager.loadRules(Arrays.asList(rule, blackRule));
}
// 自定义来源解析(默认从 HTTP Header 的 origin 字段获取)
@Component
public class CustomRequestOriginParser implements RequestOriginParser {
@Override
public String parseOrigin(HttpServletRequest request) {
// 从请求头获取来源标识
String origin = request.getHeader("X-Service-Name");
if (StringUtils.isBlank(origin)) {
origin = request.getRemoteAddr();
}
return origin;
}
}
5. 规则持久化:Nacos 数据源
5.1 为什么需要持久化
Sentinel 默认将规则存储在内存中,应用重启后规则全部丢失。
问题场景:
- 应用重启后,所有限流规则消失,服务裸奔
- Dashboard 配置的规则只推送到内存,不持久化
- 多实例部署时,每个实例需要单独配置规则
5.2 Nacos 数据源配置
Nacos 作为配置中心,天然支持规则持久化和动态推送,是 Sentinel 规则持久化的首选方案。
<!-- Sentinel Nacos 数据源依赖 -->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
<version>1.8.8</version>
</dependency>
spring:
cloud:
sentinel:
transport:
dashboard: localhost:8080
datasource:
# 限流规则
flow:
nacos:
server-addr: localhost:8848
namespace: sentinel
group-id: SENTINEL_GROUP
data-id: ${
spring.application.name}-flow-rules
rule-type: flow
# 熔断规则
degrade:
nacos:
server-addr: localhost:8848
namespace: sentinel
group-id: SENTINEL_GROUP
data-id: ${
spring.application.name}-degrade-rules
rule-type: degrade
# 热点参数规则
param-flow:
nacos:
server-addr: localhost:8848
namespace: sentinel
group-id: SENTINEL_GROUP
data-id: ${
spring.application.name}-param-rules
rule-type: param-flow
# 系统规则
system:
nacos:
server-addr: localhost:8848
namespace: sentinel
group-id: SENTINEL_GROUP
data-id: ${
spring.application.name}-system-rules
rule-type: system
5.3 Nacos 中的规则格式
了解 Nacos 中的规则 JSON 格式,才能正确配置和排查问题。
[
{
"resource": "createOrder",
"limitApp": "default",
"grade": 1,
"count": 100,
"strategy": 0,
"controlBehavior": 0,
"clusterMode": false
}
]
字段说明:
| 字段 | 说明 | 值 |
|---|---|---|
| grade | 限流模式 | 1=QPS, 0=线程数 |
| strategy | 流控策略 | 0=直接, 1=关联, 2=链路 |
| controlBehavior | 流控效果 | 0=快速失败, 2=Warm Up, 3=排队等待 |
5.4 规则推送流程
Dashboard 修改规则 → 推送到 Nacos → 应用监听 Nacos 变更 → 热更新规则。
需要注意:开源版 Sentinel Dashboard 默认将规则推送到客户端内存,需要改造 Dashboard 源码,使其推送到 Nacos。

规则推送三大优势:① 规则持久化到 Nacos,重启不丢失;② 多实例秒级同步,无需逐个配置;③ 支持热更新,应用无需重启。
6. MSE Sentinel 托管方案
6.1 MSE Sentinel 增强功能
阿里云 MSE(微服务引擎)提供了 Sentinel 的托管增强方案:
- 规则托管:无需自建 Dashboard,MSE 控制台统一管理规则
- 集群限流:基于 Token Server 的精确集群限流
- 监控大盘:开箱即用的流量监控和告警
- 规则推送:规则变更秒级推送到所有实例
- 多语言支持:Java、Go、C++、Rust 等多语言 Agent

核心流程:
- 运维人员在 MSE 控制台配置规则 → 自动推送到 Nacos 持久化
- Nacos 监听机制 → 规则变更秒级推送到所有应用实例
- 集群限流时 → Client 向 Token Server 申请 Token,实现精确的总 QPS 控制
- 指标采集 → 各实例上报流量数据到 MSE 监控大盘
6.2 自建 vs MSE 托管对比
| 对比维度 | 自建 Sentinel Dashboard | MSE Sentinel 托管 |
|---|---|---|
| 部署运维 | 需要自行部署和维护 | 零运维,开箱即用 |
| 规则持久化 | 需要改造源码对接 Nacos | 原生支持,自动持久化 |
| 集群限流 | 需要自建 Token Server | 内置集群限流能力 |
| 监控告警 | 需要对接 Prometheus | 内置监控大盘和告警 |
| 多语言 | 仅 Java 原生支持 | 支持 Java/Go/C++/Rust |
| 高可用 | 需要自行保证 | 阿里云 SLA 保障 |
| 成本 | 人力成本高 | 按实例付费,成本可控 |
6.3 接入 MSE Sentinel
MSE 接入方式简单,只需引入 Agent 即可,无需修改业务代码。
步骤一:创建 MSE 托管集群
在阿里云 MSE 控制台创建 Sentinel 托管实例,获取接入点信息。
步骤二:引入 MSE Sentinel Agent
<!-- MSE Sentinel Starter -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
<version>2023.0.1.2</version>
</dependency>
步骤三:配置 MSE 接入参数
spring:
cloud:
sentinel:
transport:
# MSE Sentinel 控制台地址
dashboard: ${
MSE_SENTINEL_DASHBOARD}
port: 8719
# MSE 数据源配置
datasource:
mse-flow:
mse:
endpoint: ${
MSE_ENDPOINT} # MSE 接入点
namespace: ${
MSE_NAMESPACE} # MSE 命名空间
group-id: ${
spring.application.name}
data-id: flow-rules
rule-type: flow
mse-degrade:
mse:
endpoint: ${
MSE_ENDPOINT}
namespace: ${
MSE_NAMESPACE}
group-id: ${
spring.application.name}
data-id: degrade-rules
rule-type: degrade
步骤四:配置集群限流
集群限流确保整个集群的总 QPS 不超限,而非单机 QPS 不超限。
spring:
cloud:
sentinel:
transport:
dashboard: ${
MSE_SENTINEL_DASHBOARD}
# 集群限流配置
cluster:
mode: client # 当前实例作为 Client
flow:
client:
server-host: ${
TOKEN_SERVER_HOST} # Token Server 地址
server-port: 18730 # Token Server 端口
request-timeout: 200 # 请求超时 200ms
Token Server 配置(独立部署):
# Token Server 应用配置
spring:
cloud:
sentinel:
cluster:
mode: server # 当前实例作为 Token Server
server:
port: 18730 # Token Server 监听端口
namespace: ${
MSE_NAMESPACE}
7. 生产环境最佳实践
7.1 限流阈值如何确定
限流阈值不是拍脑袋定的,需要基于压测数据和合理余量:
确定步骤:
- 压测获取服务的最大承受 QPS
- 留出 20%-30% 的安全余量
- 设置限流阈值 = 最大承受 QPS × 0.7
# 使用 JMeter 压测获取基线数据
# 场景:订单查询接口,逐步加压
# 并发 100 → RT=50ms,QPS=2000,无错误 ✅
# 并发 200 → RT=80ms,QPS=3500,无错误 ✅
# 并发 500 → RT=200ms,QPS=4000,错误率 0.1% ⚠️
# 并发 1000 → RT=800ms,QPS=3000,错误率 5% ❌
# 结论:最大承受 QPS ≈ 4000
# 限流阈值 = 4000 × 0.7 = 2800 QPS
7.2 熔断恢复策略
熔断恢复有两种策略,适用不同场景:
慢启动恢复(推荐):
- 熔断结束后,逐步放行流量
- 避免瞬间涌入大量请求导致二次熔断
- 适合下游服务恢复较慢的场景
立即恢复:
- 熔断结束后,立即放行所有流量
- 适合下游服务恢复较快的场景
- 风险:可能触发二次熔断
// 慢启动恢复 —— 推荐生产环境使用
DegradeRule rule = new DegradeRule("checkStock")
.setGrade(CircuitBreakerStrategy.SLOW_REQUEST_RATIO.getType())
.setCount(500)
.setSlowRatioThreshold(0.6)
.setTimeWindow(30) // 熔断时长 30 秒
.setMinRequestAmount(5)
.setStatIntervalMs(10000);
// 半开状态会逐步放行请求探测,实现慢启动
7.3 降级方案的兜底设计
降级不是简单地返回错误,而是提供有意义的兜底方案:
| 业务场景 | 降级方案 | 说明 |
|---|---|---|
| 商品详情 | 返回缓存数据 | 牺牲实时性,保可用性 |
| 库存查询 | 返回默认库存 | 允许下单但标记待确认 |
| 推荐列表 | 返回热门推荐 | 牺牲个性化,保基础体验 |
| 用户评论 | 隐藏评论模块 | 非核心功能直接降级 |
| 支付 | 排队等待 | 核心功能不能降级,只能排队 |

降级设计原则:降级不是"一刀切"——缓存数据优先于降级服务,降级服务优先于默认值,每多一级降级,业务体验损失更小。
/**
* 分级降级策略
*/
@SentinelResource(value = "getProductDetail", fallback = "productDetailFallback")
public ProductDetailVO getProductDetail(Long productId) {
// 正常逻辑:实时查询
return productService.getDetail(productId);
}
public ProductDetailVO productDetailFallback(Long productId, Throwable t) {
ProductDetailVO detail = new ProductDetailVO();
// 第一级降级:读本地缓存
ProductCache cache = localCache.get(productId);
if (cache != null && !cache.isExpired()) {
detail.setFromCache(true);
detail.setProduct(cache.getProduct());
return detail;
}
// 第二级降级:返回默认商品信息
detail.setFromCache(true);
detail.setProduct(ProductVO.defaultProduct(productId));
detail.setDegraded(true);
return detail;
}
7.4 网关层限流 vs 服务层限流
两层限流配合使用,形成纵深防御:
网关层限流(粗粒度):
- 对整体流量做全局控制
- 防止洪峰流量进入微服务内部
- 使用 Sentinel 的 Gateway 适配
服务层限流(细粒度):
- 对单个接口做精确控制
- 保护核心资源不被打满
- 使用 @SentinelResource 注解

纵深防御要点:
- 网关层做第一道拦截:挡住 80% 的洪峰流量,不让其进入微服务内部
- 服务层做精确控制:根据各服务的承载能力分别限流,核心服务更精细
- 数据层做兜底保护:防止连接池耗尽、缓存穿透等深层问题
- 三层联动:网关限流失败的服务级兜底,服务限流失败的数据层保护
# Spring Cloud Gateway + Sentinel 配置
spring:
cloud:
gateway:
routes:
- id: order-service
uri: lb://order-service
predicates:
- Path=/api/order/**
filters:
- name: RequestRateLimiter
args:
redis-rate-limiter.replenishRate: 1000
redis-rate-limiter.burstCapacity: 2000
sentinel:
transport:
dashboard: localhost:8080
# Gateway 限流规则
scg:
fallback:
mode: response
response-status: 429
response-body: '{"code":429,"message":"请求过于频繁,请稍后重试"}'
7.5 监控告警配置
生产环境必须有监控告警,及时发现流量异常:
/**
* Sentinel 指标接入 Prometheus
*/
@Component
public class SentinelMetricsExporter {
private final Counter blockCounter = Counter.build()
.name("sentinel_block_total")
.help("Sentinel blocked requests")
.labelNames("resource", "limitApp", "ruleType")
.register();
@Scheduled(fixedRate = 1000)
public void exportMetrics() {
// 遍历所有资源,采集限流指标
for (String resource : ClusterBuilderSlot.getClusterNodeMap().keySet()) {
ClusterNode node = ClusterBuilderSlot.getClusterNode(resource);
if (node != null) {
long blockQps = node.blockQps();
if (blockQps > 0) {
blockCounter.labels(resource, "default", "flow").inc(blockQps);
}
}
}
}
}
告警规则建议:
| 指标 | 告警条件 | 级别 |
|---|---|---|
| 限流次数 | 1分钟内 > 100 次 | WARNING |
| 熔断状态 | 进入 OPEN 状态 | CRITICAL |
| 系统 Load | > 阈值 × 0.8 | WARNING |
| 平均 RT | > 阈值 × 0.8 | WARNING |
8. 避坑指南
坑1:blockHandler vs fallback 区别
这是新手最容易混淆的点:
- blockHandler:处理
BlockException(限流、熔断触发) - fallback:处理业务异常(非 BlockException 的所有异常)
// ❌ 错误:把业务异常处理放在 blockHandler
@SentinelResource(
value = "createOrder",
blockHandler = "handleException" // 既处理限流又处理业务异常?
)
// ✅ 正确:职责分离
@SentinelResource(
value = "createOrder",
blockHandler = "createOrderBlockHandler", // 只处理限流/熔断
fallback = "createOrderFallback" // 只处理业务异常
)
关键细节:blockHandler 方法必须额外声明 BlockException 参数,fallback 方法不需要。
坑2:规则未持久化导致重启丢失
默认情况下,Sentinel 规则存储在内存中,重启即丢失。
// ❌ 危险:只通过 Dashboard 配置规则
// 应用重启后,所有规则消失,服务裸奔
// ✅ 正确:配置 Nacos 数据源持久化
spring:
cloud:
sentinel:
datasource:
flow:
nacos:
server-addr: localhost:8848
data-id: ${
spring.application.name}-flow-rules
rule-type: flow
生产环境必须配置规则持久化,这是不可省略的基础设施。
坑3:热点参数限流的参数类型限制
热点参数限流只支持基本类型和 String:
// ❌ 不支持:复杂对象作为热点参数
@SentinelResource(value = "search")
public Result search(ProductQuery query) {
// query 是复杂对象
// 热点参数限流无法按 query 的字段值分别限流
}
// ✅ 正确:使用基本类型参数
@SentinelResource(value = "search")
public Result search(
@RequestParam String category, // String 类型 ✅
@RequestParam Integer brandId // Integer 类型 ✅
) {
// 可以按 category 或 brandId 分别限流
}
坑4:集群限流 Token Server 单点问题
Token Server 是集群限流的核心,存在单点风险:
# ❌ 单点部署 Token Server
spring:
cloud:
sentinel:
cluster:
mode: server
server:
port: 18730
# 只有一个实例,挂了就全挂
解决方案:
- Token Server 至少部署 2 个实例
- 使用 Nacos 做服务发现,Client 自动切换
- 配置 Token Server 健康检查和自动故障转移
- MSE 托管方案内置高可用,推荐使用
坑5:Sentinel 与 Gateway 集成的过滤器顺序
Spring Cloud Gateway 中,Sentinel 过滤器的顺序影响限流效果:
# ❌ 错误:Sentinel 过滤器在路由之后
spring:
cloud:
gateway:
default-filters:
- name: SentinelGatewayFilter
# 默认 order 可能不对
# ✅ 正确:显式指定过滤器顺序
spring:
cloud:
sentinel:
scg:
order: -1 # 确保在路由之前执行限流
gateway:
default-filters:
- name: SentinelGatewayFilter
args:
order: -1
原则:Sentinel 过滤器应该在路由过滤器之前执行,否则请求已经路由到后端服务了,限流就失去了意义。
9. 总结
核心要点回顾
| 功能 | 核心职责 | 关键配置 |
|---|---|---|
| 流量控制 | 控制进入流量 | QPS/线程数 + 流控效果 |
| 熔断降级 | 保护调用端 | 慢调用/异常比例/异常数 |
| 热点参数 | 按参数值限流 | 参数索引 + 特殊项配置 |
| 系统保护 | 整体维度兜底 | CPU/Load/RT/线程数/QPS |
| 来源控制 | 黑白名单 | 白名单/黑名单策略 |
三条核心原则:
- 规则必须持久化:生产环境绝不能裸奔,Nacos 或 MSE 托管是标配
- 限流阈值基于压测:不要拍脑袋,压测数据 + 30% 余量
- 降级要有兜底方案:降级不是返回错误,而是提供有意义的替代方案
📜 真实性声明
所有技术点均基于 Sentinel 1.8.8 + Spring Cloud Alibaba 2023.0.x 版本验证,代码示例完整可运行。文中秒杀场景基于作者在电商平台项目中的真实经验,数据规模和业务场景经过实践验证,部分敏感信息已做脱敏处理。