一、Sentinel 是什么
Sentinel 是阿里巴巴开源的流量防护组件,面向分布式服务架构的流量控制、熔断降级、系统保护。其核心理念是:把流量经过的每一个服务,都加上"哨兵"监控和保护,实现对微服务全链路的安全防护,避免因单一服务故障引发整个体系崩溃。
二、为什么需要 Sentinel
2.1 无Sentinel的微服务系统(雪崩灾难)
调用链路:用户 → 网关 → 用户服务 → 订单服务 → 商品服务 → 数据库
故障传导过程:
-
用户请求量达到10000 QPS,正常流向各个服务;
-
数据库出现慢查询,导致商品服务响应变慢;
-
订单服务调用商品服务时,线程被持续占用(等待超时),最终线程池被占满;
-
订单服务线程耗尽,对外不可用;
-
用户服务调用订单服务受阻,线程也被耗光;
-
整个微服务系统彻底崩溃,发生雪崩。
2.2 有Sentinel的微服务系统(雪崩防护)
调用链路:用户 → 网关 → 用户服务 → 订单服务 → 商品服务 → 数据库
防护过程:
-
用户请求量10000 QPS正常流入,数据库出现慢查询,商品服务响应变慢;
-
Sentinel实时监控到商品服务异常比例(或慢调用比例)升高;
-
Sentinel自动触发熔断,断开对商品服务的调用;
-
订单服务调用商品服务时,直接收到Sentinel的降级响应(秒级返回),线程不被占用;
-
订单服务、用户服务保持正常可用,整个系统得以保全。
三、Sentinel 核心概念
3.1 资源(Resource)
资源是Sentinel最基础的概念,一切可以被保护的对象都称为资源,是Sentinel防护的核心目标。
| 资源类型 | 示例 |
|---|---|
| HTTP 接口 | /order/select/{id} |
| Feign 远程调用 | GET http://zk-item-service/item/select/1 |
| 自定义方法 | 任何加了 @SentinelResource 注解的方法 |
| 数据库连接 | 需手动埋点进行保护 |
资源命名规则:通常使用接口路径作为资源名,直观易识别,便于后续规则配置和监控排查。
3.2 规则(Rule)
规则定义了"如何保护资源",Sentinel提供5种核心规则,覆盖流量控制、故障熔断、参数防护、系统保护、权限控制全场景:
-
流控规则(FlowRule):控制每秒请求通过的数量,防止流量过载;
-
熔断规则(DegradeRule):服务故障时自动断开调用,避免故障传导;
-
热点规则(ParamFlowRule):针对接口特定参数值限流,解决热点数据访问压力;
-
系统规则(SystemRule):从JVM全局维度保护应用,防止服务器宕机;
-
授权规则(AuthorityRule):通过黑白名单控制访问权限,限制非法调用。
3.3 槽链(Slot Chain)
Sentinel内部的核心工作机制,所有请求都会经过一条"槽链"(一系列处理节点),依次完成规则校验、流量统计、监控等操作:
请求进来 → 槽链校验(流量统计、规则匹配等) → 放行(执行业务逻辑)/ 拒绝(抛出BlockException)
无需手动操作槽链,Sentinel自动完成所有处理,了解槽链仅用于面试和深入理解其工作原理。
四、流量控制(Flow Control)详解
流量控制的核心是"限制请求的通过速率",避免服务因流量突增被打垮,支持3种模式和3种效果,可根据实际场景灵活选择。
4.1 流控的三种模式
(1)直接模式:对自身资源限流
调用链路:请求 → /order/select/{id} → Sentinel检查(当前QPS > 阈值?)→ 是则直接拒绝,返回"被限流"提示。
适用场景:直接保护单个接口,防止该接口被过量请求压垮。
(2)关联模式:保护关联资源
场景:订单创建接口(/order/create)依赖商品查询接口(/item/select/{id}),当订单创建请求量过大时,限流订单创建,保护商品查询接口不被拖垮。
配置示例:
-
资源名:/order/create(限流入口)
-
关联资源:/item/select/{id}(被保护资源)
-
阈值类型:QPS
-
流控阈值:50
效果:当/order/create的QPS超过50时,拒绝新的订单创建请求,确保商品查询接口能正常响应。
(3)链路模式:只限制特定调用链路
场景:同一个Service层方法(如queryItem())被多个Controller调用,仅需限制其中一个调用链路(如ControllerA → queryItem()),另一个链路(ControllerB → queryItem())不限流。
效果:仅统计从指定入口进来的调用流量,精准控制特定链路的请求速率。
4.2 流控的三种效果
(1)快速失败(默认)
逻辑:请求超过阈值 → 立刻拒绝 → 抛出FlowException。
示例:配置QPS阈值=100,第101个请求直接被拒绝,返回限流提示,适用于允许少量请求丢失的场景(如普通查询接口)。
(2)Warm Up(冷启动)
场景:系统刚启动时,JVM未预热、资源未初始化,处理能力较弱,若直接接收满负荷流量,会直接打崩服务。
冷启动过程:第1秒仅处理10个请求 → 第2秒处理25个请求 → ... → 预热完成后处理100个请求(阈值QPS=100)。
配置:阈值QPS=100,预热时长=10秒,效果:10秒内从100/3≈33 QPS逐步提升至100 QPS,给系统预热时间。
(3)匀速排队
场景:消息队列消费、订单异步处理等,请求不能被丢弃,需按顺序匀速处理。
配置:阈值QPS=10,效果:不管请求量多大,每100ms放行一个请求,多余请求在队列中等待,队列满后再拒绝。
五、熔断降级(Circuit Breaking)详解
熔断降级的核心是"当服务出现故障时,自动断开调用,避免故障传导",Sentinel支持3种熔断策略,通过状态机实现故障恢复。
5.1 三种熔断策略
(1)慢调用比例
定义:"慢调用"指响应时间超过设定的最大响应时间(最大RT)的请求,当慢调用比例达到阈值时触发熔断。
配置示例:
-
最大RT:500ms(超过500ms算慢调用)
-
比例阈值:60%(慢调用占比超过60%触发熔断)
-
熔断时长:10秒(熔断后等待10秒再尝试恢复)
-
最小请求数:10(至少接收10个请求才开始统计)
工作过程:时间窗口内收到100个请求 → 65个响应时间>500ms(慢调用比例65%>60%)→ 触发熔断 → 10秒内所有请求直接降级 → 10秒后进入半开状态,放1个请求试探 → 成功则关闭熔断,失败则继续熔断10秒。
(2)异常比例
配置示例:
-
比例阈值:50%(异常请求占比超过50%触发熔断)
-
熔断时长:10秒
-
最小请求数:10
工作过程:时间窗口内收到20个请求 → 12个抛出异常(异常比例60%>50%)→ 触发熔断,后续请求直接降级。
(3)异常数
配置示例:
-
异常数:5(1分钟内异常数超过5个触发熔断)
-
熔断时长:10秒
-
最小请求数:10
工作过程:1分钟内第6个异常出现 → 触发熔断,后续请求直接降级。
5.2 熔断状态机(核心)
Sentinel通过三种状态的切换,实现熔断与恢复的自动化管理:
-
闭合状态(CLOSED):正常状态,服务正常调用,Sentinel实时统计请求异常情况;
-
打开状态(OPEN):熔断状态,统计窗口内异常达到阈值,触发熔断,所有请求直接返回降级结果,不再调用目标服务;
-
半开状态(HALF-OPEN):探测状态,熔断时长结束后进入该状态,放行1个请求试探目标服务 → 成功则关闭熔断(回到闭合状态),失败则重新打开熔断(回到打开状态)。
六、热点规则(Param Flow Rule)
热点规则是"针对接口的特定参数值进行限流",解决"单个热点参数请求量暴增,拖垮整个接口"的问题。
场景:查询商品接口(/item/select/{id}),大部分商品查询正常,但热门商品(id=1)的查询量暴增,需单独限制该参数值的请求量。
配置对比:
-
普通流控:/item/select/{id} → QPS限制500(所有商品一起统计);
-
热点限流:/item/select/{id} → 普通商品QPS限制500,id=1的商品QPS限制50(单独控制)。
Dashboard配置:
-
资源名:/item/select/{id}
-
参数索引:0(第1个参数是id)
-
限流阈值:500
-
参数例外:参数类型=long,参数值=1,限流阈值=50。
代码示例:
@GetMapping("/item/select/{id}") @SentinelResource(value = "item.select", blockHandler = "selectBlock") public Result select(@PathVariable Long id) { return itemService.selectById(id); }
七、系统保护规则
系统规则不针对某个具体接口,而是从全局维度保护整个应用,防止服务器因资源耗尽而宕机,支持5种保护维度:
| 保护维度 | 含义 | 示例 |
|---|---|---|
| LOAD | 系统负载 | Linux load1 > 3 触发限流 |
| RT | 所有请求的平均响应时间 | 平均RT > 500ms 触发限流 |
| CPU | CPU使用率 | CPU > 80% 触发限流 |
| 并发线程数 | 所有请求占用的线程数 | 线程数 > 500 触发限流 |
| 入口QPS | 所有接口的总QPS | 总QPS > 1000 触发限流 |
配置示例:CPU使用率 > 80% → 全局限流,不管哪个接口,只要CPU超过阈值,服务就会拒绝新请求,保护服务器稳定。
八、@SentinelResource 注解详解
@SentinelResource是Sentinel的核心注解,用于标记需要被保护的资源,支持自定义限流/熔断降级逻辑,详细用法如下:
java
@GetMapping("/order/select/{id}")
@SentinelResource(
value = "order.select", // ① 资源名(必填),唯一标识该资源
blockHandler = "selectBlock", // ② 限流/熔断时调用的降级方法
blockHandlerClass = OrderBlock.class, // ③ blockHandler所在类(可选,需是静态方法)
fallback = "selectFallback", // ④ 业务异常时调用的降级方法
fallbackClass = OrderFallback.class, // ⑤ fallback所在类(可选,需是静态方法)
exceptionsToIgnore = {BizException.class} // ⑥ 忽略的异常(不触发fallback)
)
public Result select(@PathVariable Long id) {
return orderService.selectById(id);
}
// ② 限流/熔断触发(收到BlockException)
public Result selectBlock(Long id, BlockException e) {
// BlockException子类:FlowException(流控)、DegradeException(熔断)、SystemBlockException(系统保护)、AuthorityException(授权)
return Result.error("系统繁忙,请稍后再试");
}
// ④ 业务异常触发(收到Throwable,如NullPointerException、SQLException)
public Result selectFallback(Long id, Throwable t) {
return Result.error("服务异常:" + t.getMessage());
}
blockHandler vs fallback 的区别(面试高频)
| 对比维度 | blockHandler | fallback |
|---|---|---|
| 触发条件 | Sentinel 限流、熔断、系统保护、授权规则触发(抛出BlockException) | 业务代码抛出异常(抛出Throwable,如空指针、数据库异常) |
| 接收参数 | 最后一个参数必须是BlockException | 最后一个参数必须是Throwable |
| 典型场景 | QPS超了、服务熔断、CPU过载、非法IP访问 | 数据库连接失败、空指针异常、业务逻辑报错 |
九、Feign 整合 Sentinel(核心实战)
Feign是微服务中声明式远程调用组件,而Feign整合Sentinel是生产环境中最常用的方式,直接解决"远程调用超时、服务故障导致的级联失败"问题,提供两种降级方式。
9.1 方式一:Fallback 类(统一降级,无异常信息)
java
// Feign 接口(调用商品服务)
@FeignClient(name = "zk-item-service",
fallback = ItemFeignFallback.class) // 指定降级实现类
public interface ItemFeign {
@GetMapping("/item/select/{id}")
Result selectById(@PathVariable("id") Long id);
}
// 降级实现类(需交给Spring管理)
@Component
public class ItemFeignFallback implements ItemFeign {
@Override
public Result selectById(Long id) {
// 商品服务不可用时,返回降级提示
return Result.error("商品服务暂不可用,请稍后再试");
}
}
9.2 方式二:FallbackFactory(降级+异常日志,生产推荐)
java
// Feign 接口
@FeignClient(name = "zk-item-service",
fallbackFactory = ItemFeignFallbackFactory.class) // 指定降级工厂
public interface ItemFeign {
@GetMapping("/item/select/{id}")
Result selectById(@PathVariable("id") Long id);
}
// 降级工厂(能获取异常信息,便于排查问题)
@Component
public class ItemFeignFallbackFactory implements FallbackFactory<ItemFeign> {
private static final Logger log = LoggerFactory.getLogger(ItemFeignFallbackFactory.class);
@Override
public ItemFeign create(Throwable cause) {
return new ItemFeign() {
@Override
public Result selectById(Long id) {
// 记录异常日志,便于排查服务故障原因
log.error("调用商品服务失败: {}", cause.getMessage());
return Result.error("商品服务暂不可用: " + cause.getMessage());
}
};
}
}
Fallback vs FallbackFactory 对比
| 对比维度 | Fallback | FallbackFactory |
|---|---|---|
| 能拿到异常原因 | ❌ 不能 | ✅ 能 |
| 能记录异常日志 | ❌ 不能 | ✅ 能 |
| 复杂度 | 简单 | 稍复杂 |
| 推荐场景 | 简单测试、无需排查异常的场景 | 生产环境(需排查故障、记录日志) |
十、Sentinel Dashboard 详解(可视化管控)
Sentinel Dashboard是Sentinel的可视化控制台,用于配置规则、查看实时监控、管理接入的服务,是开发和运维的核心工具。
10.1 启动方式
java
java -jar sentinel-dashboard-1.8.6.jar
# 默认端口:8080
# 默认账号/密码:sentinel / sentinel
10.2 核心功能
-
实时监控:查看各服务、各资源的QPS、RT、通过数、拒绝数,实时掌握流量情况;
-
聚合监控:从集群维度查看所有服务的整体数据,便于全局管控;
-
规则管理:配置、修改、删除流控、熔断、热点、系统、授权规则,配置后立即生效,无需重启服务;
-
集群限流:多台机器共享限流配额,实现集群层面的流量控制;
-
机器列表:查看所有接入Sentinel的服务实例,了解服务运行状态。
10.3 核心规则配置(Dashboard操作)
(1)流控规则配置
操作路径:点击【流控规则】→【新增流控规则】
-
资源名:填写需要限流的资源(如/order/select/{id});
-
流控应用:集群限流时填写,单机限流无需填写;
-
阈值类型:选择QPS(每秒请求数)或线程数;
-
单机阈值:核心参数,填写允许通过的最大QPS或线程数;
-
流控模式:选择直接、关联或链路;
-
流控效果:选择快速失败、Warm Up或排队等待;
-
点击【新增】,规则立即生效。
(2)熔断规则配置
操作路径:点击【熔断规则】→【新增熔断规则】
-
资源名:填写需要熔断保护的资源(如/item/select/{id});
-
熔断策略:选择慢调用比例、异常比例或异常数;
-
核心参数:根据策略填写(如慢调用比例需填写最大RT、比例阈值,异常数需填写异常数阈值);
-
熔断时长:填写熔断后等待恢复的时间(单位:秒);
-
最小请求数:填写触发熔断的最小请求数量;
-
统计时长:填写请求统计的时间窗口(单位:毫秒);
-
点击【新增】,规则立即生效。
十一、Sentinel 与 zk_parent 项目完整集成步骤(落地实战)
以zk_order_service(订单服务)为例,完整集成Sentinel,实现对Feign远程调用的熔断降级保护。
第1步:添加依赖(zk_order_service 的 pom.xml)
java
<!-- Sentinel 核心依赖 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
第2步:配置application.yml
java
spring:
cloud:
sentinel:
transport:
dashboard: localhost:8080 # Sentinel Dashboard 地址
port: 8719 # 本地服务与Dashboard通信的端口(默认8719,冲突可修改)
eager: true # 启动时立即连接Dashboard,避免首次请求才注册
# 开启Feign整合Sentinel
feign:
sentinel:
enabled: true
第3步:编写FallbackFactory(生产推荐)
java
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import feign.hystrix.FallbackFactory;
@Component
public class ItemFeignFallbackFactory implements FallbackFactory<ItemFeign> {
private static final Logger log = LoggerFactory.getLogger(ItemFeignFallbackFactory.class);
@Override
public ItemFeign create(Throwable cause) {
return new ItemFeign() {
@Override
public Result selectById(Long id) {
// 记录异常日志,便于排查
log.error("调用商品服务selectById方法失败,异常原因:{}", cause.getMessage());
// 降级返回
return Result.error("商品服务暂不可用,请稍后再试");
}
};
}
}
第4步:测试验证
-
启动Sentinel Dashboard(java -jar sentinel-dashboard-1.8.6.jar);
-
启动Nacos、zk_item_service(商品服务)、zk_order_service(订单服务);
-
正常访问订单服务接口(如/order/select/1),能正常返回数据,Dashboard实时监控能看到通过数;
-
停掉zk_item_service(商品服务),再次访问订单服务接口,秒级返回降级提示;
-
查看Dashboard,能看到该资源的拒绝数增加,熔断状态正常。
十二、Spring Cloud Alibaba 全家桶串联(核心闭环)
Spring Cloud Alibaba 是微服务开发的一站式解决方案,整合了Nacos、Sentinel、Gateway、Seata等核心组件,各组件各司其职、协同工作,形成完整的微服务架构闭环。结合前文的Sentinel,我们将所有组件串联,明确各组件的角色和关联关系,让你彻底打通微服务全链路。
12.1 全家桶核心组件及角色
| 组件 | 核心角色 | 核心功能 | 与Sentinel的关联 |
|---|---|---|---|
| Nacos | 注册中心 + 配置中心 | 1. 服务注册发现:所有微服务(订单、商品、用户)注册到Nacos,实现服务间的动态发现;2. 配置中心:统一管理所有服务的配置(如Sentinel规则、数据库配置),支持动态刷新。 | 1. Sentinel规则持久化:将Sentinel的限流、熔断规则存储到Nacos,服务重启后自动拉取规则,避免规则丢失;2. 服务发现:Sentinel通过Nacos获取各服务实例信息,实现集群限流。 |
| Sentinel | 流量防护组件 | 流量控制、熔断降级、热点防护、系统保护、授权控制,防止服务雪崩,保护微服务链路安全。 | 1. 与Feign整合:保护远程调用,避免下游服务故障传导;2. 与Gateway整合:实现网关层全局限流,在入口拦截恶意流量;3. 与Nacos整合:实现规则持久化,支持集群管控。 |
| Gateway | API网关(统一入口) | 1. 统一入口:所有前端请求都经过Gateway,避免前端直接访问后端服务;2. 路由转发:根据请求路径将请求转发到对应的微服务;3. 统一过滤器:实现统一鉴权、日志、跨域处理;4. 网关限流:与Sentinel整合,实现全局限流。 | 1. 网关层限流:Sentinel在Gateway层面拦截请求,提前过滤过量流量,不进入后端服务集群,减轻后端压力;2. 链路关联:Gateway路由转发后,Sentinel可监控整个调用链路的流量情况。 |
| Feign | 声明式远程调用 | 简化微服务间的远程调用,无需手动编写HTTP请求,通过接口+注解即可实现调用。 | Feign与Sentinel强制整合,是微服务远程调用的"安全带",当下游服务故障时,Sentinel自动触发熔断降级,避免调用线程被耗尽,防止雪崩。 |
| Seata | 分布式事务组件 | 解决微服务间分布式事务问题,保证多服务操作的原子性(如订单创建+库存扣减+支付扣款,要么全部成功,要么全部回滚)。 | Sentinel保护Seata的事务协调接口,避免事务协调服务被流量压垮,确保分布式事务的正常执行;同时,Seata的事务回滚可作为Sentinel降级逻辑的补充,保证业务数据一致性。 |
12.2 微服务全链路完整调用流程(串联所有组件)
结合你的zk_parent项目,完整调用链路如下,清晰体现各组件的协同工作:
-
前端发起请求(如查询订单),请求首先进入Gateway(API网关);
-
Gateway做三件事:① 统一鉴权(检查Token);② 根据请求路径(如/order/**)路由到zk_order_service(订单服务);③ Gateway层Sentinel限流,拦截过量请求;
-
订单服务(zk_order_service)从Nacos获取商品服务(zk_item_service)的实例地址,通过Feign发起远程调用,查询商品信息;
-
Feign整合Sentinel,调用过程中被Sentinel拦截,实时监控调用状态:
-
若商品服务正常,Sentinel放行,调用正常返回,订单服务组装数据后返回给前端;
-
若商品服务响应慢、报错,Sentinel触发熔断,Feign执行FallbackFactory的降级逻辑,返回降级提示,订单服务线程不被占用,继续正常提供服务;
-
-
Sentinel的限流、熔断规则存储在Nacos,订单服务、商品服务重启后,自动从Nacos拉取规则,无需重新配置;
-
若涉及分布式事务(如订单创建+库存扣减),Seata负责协调订单服务、商品服务的事务,确保操作原子性;Sentinel保护Seata的协调接口,避免其被流量压垮;
-
所有服务的运行状态、流量数据,都可在Sentinel Dashboard、Nacos控制台查看,便于开发和运维监控。
12.3 核心总结(为什么必须整合全家桶)
单独使用某一个组件,无法实现稳定、可扩展的微服务架构,全家桶的整合核心是"各司其职、协同防护":
-
Nacos解决"服务怎么发现、配置怎么管理"的问题,是微服务的"基础底座";
-
Sentinel解决"流量怎么控制、故障怎么隔离"的问题,是微服务的"安全哨兵";
-
Gateway解决"请求怎么入口、怎么转发"的问题,是微服务的"统一大门";
-
Feign解决"服务怎么调用"的问题,是微服务的"通信桥梁";
-
Seata解决"事务怎么保证"的问题,是微服务的"数据保障"。
而Sentinel作为"安全核心",串联了Gateway、Feign、Nacos,实现了从入口限流、远程调用保护、规则持久化的全链路防护,是微服务能应对高并发、避免雪崩的关键组件。
十三、常见问题与解决方案(落地避坑)
-
问题1:Sentinel Dashboard看不到服务实例? 解决方案:① 检查服务配置中sentinel.dashboard地址是否正确;② 确认sentinel.eager=true(启动立即注册);③ 发起一次请求(Sentinel默认懒加载,首次请求才注册);④ 检查8719端口是否被占用,冲突可修改sentinel.transport.port。
-
问题2:Feign整合Sentinel后,降级不生效? 解决方案:① 确认feign.sentinel.enabled=true;② Fallback类/Factory需交给Spring管理(加@Component注解);③ Feign接口的@FeignClient注解需正确指定fallback或fallbackFactory;④ 检查降级方法的参数、返回值与Feign接口一致。
-
问题3:Sentinel规则重启后丢失? 解决方案:将规则持久化到Nacos,配置Sentinel规则持久化依赖,在Dashboard中配置规则时选择"推送到Nacos",服务重启后自动拉取。
-
问题4:热点规则配置后不生效? 解决方案:① 确认参数索引正确(如接口参数id是第1个参数,索引为0);② 资源名与@SentinelResource的value一致;③ 热点参数的类型与配置一致(如id是long类型,配置时选择long)。