一、fallback 与 blockHandler 的执行逻辑
当 @SentinelResource(
ini
// 处理业务异常
fallback = "fallbackHandler",
// 处理熔断/限流
blockHandler = "blockHandler",
)
两者都配置时,Sentinel 会根据不同的触发条件选择不同的执行路径:
执行逻辑流程图
text
请求进入
│
├─ 是否被熔断/限流? → Yes → 执行 blockHandler
│ No
│
├─ 执行业务逻辑
│ │
│ ├─ 是否抛出异常? → Yes → 执行 fallback
│ No
│
└─ 返回正常结果
具体执行规则
-
blockHandler 优先:
- 当触发 Sentinel 的系统级保护规则(熔断、限流、系统负载保护等)时
- 直接执行
blockHandler
方法 - 完全跳过主逻辑和
fallback
-
fallback 次之:
- 当业务代码主动抛出异常时(非 BlockException)
- 执行
fallback
方法 - 仅在业务逻辑执行后触发
-
两者共存示例:
java
@SentinelResource(
value = "resourceName",
blockHandler = "handleBlock", // 处理系统级BlockException
fallback = "handleFallback" // 处理业务异常
)
public String someMethod(String param) {
if ("block".equals(param)) {
// 模拟系统过载(实际中由Sentinel自动触发)
throw new RuntimeException("Should be blocked by rule");
}
if ("error".equals(param)) {
// 业务异常
throw new RuntimeException("Business error");
}
return "Success";
}
二、fallback 与 blockHandler 的场景区别
特性 | fallback | blockHandler |
---|---|---|
触发条件 | 业务代码抛出异常 | Sentinel规则触发(熔断/限流等) |
异常类型 | 任何Throwable(除exceptionsToIgnore) | 仅BlockException及其子类 |
执行阶段 | 业务逻辑执行后 | 业务逻辑执行前 |
典型场景 | - 服务调用异常 - 数据库操作失败 | - 熔断状态 - QPS超过阈值 |
配置必要性 | 可选 | 可选(未配置则抛出BlockException) |
三、Sentinel 与 Hystrix 的设计差异
Hystrix 的简化设计
java
@HystrixCommand(fallbackMethod = "fallback")
public String doSomething() {
// 业务逻辑
}
// 统一降级方法
public String fallback() {
return "fallback";
}
特点:
- 熔断和业务异常共用同一个降级逻辑
- 无法区分是熔断触发还是业务异常触发
- 设计简单但不够灵活
Sentinel 的精细化设计
java
@SentinelResource(
value = "resource",
blockHandler = "blockHandle", // 专门处理系统级阻塞
fallback = "fallback" // 专门处理业务异常
)
public String doSomething() {
// 业务逻辑
}
优势:
-
关注点分离:系统级保护与业务异常处理解耦
-
更精细的控制:
- 可对熔断和限流做不同处理
- 能获取具体的BlockException类型
-
更合理的恢复机制:
- 熔断有半开状态
- 可针对不同异常配置不同降级策略
四、设计对比
Hystrix 的设计思路
- 熔断即降级:认为系统保护状态下的处理与业务异常处理本质相同
- 简单优先:减少配置项,降低使用复杂度
- 适用场景:适合快速实现基本熔断需求的传统应用
Sentinel 的设计思路
-
分层防护:
- 系统级防护(blockHandler)
- 业务级容错(fallback)
-
精细化控制:
- 可区分DegradeException/FlowException/ParamFlowException等
- 支持基于来源、调用关系的规则
-
适用场景:需要精细控制流量的复杂分布式系统
五、最佳实践建议
1. 常规使用方案
java
// 推荐配置方式:
@SentinelResource(
value = "orderServiceQuery",
blockHandler = "queryBlockHandler", // 处理系统保护状态
fallback = "queryFallback", // 处理业务异常
blockHandlerClass = OrderBlockHandlers.class, // 可提取到单独类
fallbackClass = OrderFallbacks.class
)
public Order queryOrder(Long orderId) {
// 业务逻辑
}
2. 异常处理策略
java
// 在专门的类中定义处理逻辑
public class OrderBlockHandlers {
// 处理系统级阻塞
public static Order queryBlockHandler(Long orderId, BlockException ex) {
// 记录不同类型的BlockException
if (ex instanceof DegradeException) {
logger.warn("订单查询触发熔断,orderId: {}", orderId);
} else if (ex instanceof FlowException) {
logger.warn("订单查询触发限流,orderId: {}", orderId);
}
return Order.EMPTY_ORDER;
}
}
public class OrderFallbacks {
// 处理业务异常
public static Order queryFallback(Long orderId, Throwable ex) {
logger.error("订单查询业务异常,orderId: {}", orderId, ex);
return Order.errorOrder(ex.getMessage());
}
}
3. 配置建议
-
核心服务:同时配置 blockHandler 和 fallback
-
非核心服务:可只配置 fallback
-
特殊场景:
- 对读操作:配置较宽松的熔断策略+详细的fallback
- 对写操作:配置严格的熔断策略+简单的blockHandler
六、迁移注意事项
从 Hystrix 迁移到 Sentinel 时需要特别注意:
-
概念映射:
- Hystrix 的 fallback 对应 Sentinel 的 blockHandler + fallback
-
行为差异:
- Sentinel 的熔断有半开状态,Hystrix 是固定时间窗口
-
监控变化:
- Sentinel 提供更丰富的埋点指标和实时监控
这种设计差异使 Sentinel 更适合云原生时代的精细化流量控制需求,而 Hystrix 的方案更适合快速实现基本容错。根据系统复杂度选择合适的方案是关键。