DegradeSlot是 Sentinel (阿里巴巴开源的流量治理组件)中的 熔断降级插槽 的实现。它属于 Sentinel 责任链(Slot Chain)中的一环,专门用于实现 熔断(Circuit Breaking) 功能。
下面我将逐层解释它的作用、结构和关键逻辑,帮助你深入理解。
🔍 1. 背景知识:Sentinel 的 Slot 机制
Sentinel 使用 责任链模式 来处理每一次资源访问(比如一个 API 接口)。每个功能(限流、熔断、系统保护等)由一个 ProcessorSlot 实现,并按顺序组成一条链。
entry():请求进入时调用(前置处理)exit():请求结束时调用(后置处理)
DegradeSlot 是其中负责 熔断降级 的插槽。
🧱 2. 类定义与注解
java
@Spi(order = Constants.ORDER_DEGRADE_SLOT)
public class DegradeSlot extends AbstractLinkedProcessorSlot<DefaultNode>
@Spi:Sentinel 的 SPI 扩展机制,表示这是一个可插拔的组件。order = Constants.ORDER_DEGRADE_SLOT:指定在责任链中的执行顺序(通常在限流之后、系统规则之前)。- 继承
AbstractLinkedProcessorSlot<DefaultNode>:说明它处理的是DefaultNode类型的统计节点(用于记录 QPS、响应时间等指标)。
⚙️ 3. 核心方法解析
✅ entry() ------ 请求进入时检查熔断状态
java
@Override
public void entry(Context context, ResourceWrapper resourceWrapper, DefaultNode node, int count,
boolean prioritized, Object... args) throws Throwable {
performChecking(context, resourceWrapper); // ← 关键:熔断检查
fireEntry(...); // 继续责任链
}
performChecking() 做了什么?
java
void performChecking(Context context, ResourceWrapper r) throws BlockException {
List<CircuitBreaker> circuitBreakers = DegradeRuleManager.getCircuitBreakers(r.getName());
if (circuitBreakers == null || circuitBreakers.isEmpty()) {
return; // 没有熔断规则,直接放过
}
for (CircuitBreaker cb : circuitBreakers) {
if (!cb.tryPass(context)) { // ← 尝试通过熔断器
throw new DegradeException(cb.getRule().getLimitApp(), cb.getRule());
}
}
}
- 获取该资源(resource)关联的所有熔断器(CircuitBreaker)
- 对每个熔断器调用
tryPass():- 如果熔断器处于 OPEN(打开) 状态 → 返回
false - 则抛出
DegradeException,请求被 熔断拒绝
- 如果熔断器处于 OPEN(打开) 状态 → 返回
- 否则继续执行后续 Slot(如业务逻辑)
💡
tryPass()内部会根据熔断策略(慢调用比例、异常比例、异常数等)判断是否放行。
✅ exit() ------ 请求结束后上报结果,更新熔断状态
java
@Override
public void exit(Context context, ResourceWrapper r, int count, Object... args) {
Entry curEntry = context.getCurEntry();
// 如果请求已经被 block(比如被限流),就不需要更新熔断统计
if (curEntry.getBlockError() != null) {
fireExit(...);
return;
}
List<CircuitBreaker> circuitBreakers = DegradeRuleManager.getCircuitBreakers(r.getName());
if (circuitBreakers == null || circuitBreakers.isEmpty()) {
fireExit(...);
return;
}
// 只有正常完成的请求才会上报给熔断器
if (curEntry.getBlockError() == null) {
for (CircuitBreaker circuitBreaker : circuitBreakers) {
circuitBreaker.onRequestComplete(context); // ← 关键:上报本次请求结果
}
}
fireExit(...);
}
为什么只在 blockError == null 时上报?
- 熔断器关注的是 真实业务请求的成功/失败/耗时
- 如果请求被限流(BlockException)、参数非法等 非业务异常,不应计入熔断统计
- 所以只有 真正执行了业务逻辑 的请求,才会调用
onRequestComplete()
onRequestComplete()会:
- 记录本次请求耗时
- 判断是否异常(通过
Tracer.trace(ex)标记)- 更新滑动窗口统计数据
- 触发熔断状态转换(CLOSE → OPEN / OPEN → HALF_OPEN → CLOSE)
🔄 4. 熔断器工作流程简图
[请求进入]
↓
DegradeSlot.entry()
↓
performChecking() → 检查熔断器状态
├─ 若 OPEN → 抛 DegradeException(快速失败)
└─ 若 CLOSED/HALF_OPEN → 放行
↓
业务逻辑执行
↓
DegradeSlot.exit()
↓
onRequestComplete() → 上报耗时/异常 → 更新熔断状态
📌 5. 关键设计思想
| 特性 | 说明 |
|---|---|
| 非侵入式 | 业务代码无需关心熔断,Sentinel 自动拦截 |
| 多策略支持 | 异常比例、慢调用比例、异常数等(由 CircuitBreaker 实现类决定) |
| 实时反馈 | 每次请求完成后立即更新熔断状态 |
| 隔离性 | 每个资源(resource name)独立管理熔断器 |
✅ 举个例子
假设你配置了一条熔断规则:
资源:
/api/order策略:慢调用比例 > 50%(RT > 500ms),熔断时长 10s
那么:
- 当
/api/order的请求中有超过一半响应时间 > 500ms CircuitBreaker会自动切换到 OPEN 状态- 后续 10 秒内所有请求在
performChecking()阶段直接抛DegradeException - 10 秒后进入 HALF_OPEN ,放行一个请求试探
- 成功 → 恢复(CLOSE)
- 失败 → 再次熔断(OPEN)
❓常见问题
Q:为什么熔断检查在 entry,而统计在 exit?
A:这是责任链的标准做法------前置检查 + 后置清理/统计。
Q:DegradeException 是什么?
A:Sentinel 自定义的 BlockException 子类,表示因熔断被拒绝。
Q:如何自定义熔断逻辑?
A:可以通过 SPI 替换 CircuitBreaker 实现,或使用 DegradeRuleManager.loadRules() 动态加载规则。
✅ 总结
DegradeSlot 是 Sentinel 实现 熔断降级 的核心组件:
- 入口检查:是否被熔断?是 → 快速失败
- 出口上报:记录真实请求结果,驱动熔断状态机
- 与规则解耦 :通过
DegradeRuleManager和CircuitBreaker接口支持多种策略
它体现了 "故障快速失败 + 自动恢复" 的容错设计理念,是微服务稳定性的重要保障。
如果你正在使用 Sentinel,理解 DegradeSlot 有助于你更好地配置和排查熔断问题。