基于本文回答

播面 播面

文图音视,全方位拆解八股文
0
评论

Sentinel 的 @SentinelResource 注解中,blockHandler 和 fallback 有什么区别?

知识点图片

在 Sentinel 的 @SentinelResource 注解中,blockHandlerfallback 都用于处理方法执行失败时的“兜底”逻辑,但它们的触发条件处理范围设计初衷有非常明确的区别。

简单来说:blockHandler 管的是“被 Sentinel 限制了怎么办”,fallback 管的是“代码报错了怎么办”。

以下是详细的区别和对比:

1. blockHandler(限流/熔断兜底)

  • 触发条件:只有当触发了 Sentinel 的规则(如限流、熔断降级、系统保护、热点参数等),抛出 BlockException 异常时,才会进入 blockHandler 指定的方法。
  • 处理范围仅处理 Sentinel 内部的控制异常BlockException 及其子类,如 FlowException, DegradeException 等)。如果你的业务代码里抛出了 NullPointerException 或数据库异常,blockHandler 不会生效。
  • 方法签名要求
    • 返回值类型必须与原方法一致。
    • 参数列表必须与原方法一致,并且在最后追加一个 BlockException 类型的参数
    • (可选)如果是将其定义在其他类中,必须是 static 方法,并通过 blockHandlerClass 属性指定。

2. fallback(业务异常兜底)

  • 触发条件:当原方法抛出任何异常(默认情况下包含所有的 Throwable)时,都会进入 fallback 指定的方法。它类似于 try-catch 里的 catch 块。
  • 处理范围处理业务代码运行过程中的异常(如 RuntimeException, TimeoutException 等)。可以通过 exceptionsToIgnore 属性排除掉某些不需要兜底的异常。
  • 方法签名要求
    • 返回值类型必须与原方法一致。
    • 参数列表必须与原方法一致,可以额外在最后追加一个 Throwable 类型的参数(用于接收异常,非必须)。
    • (可选)如果是将其定义在其他类中,必须是 static 方法,并通过 fallbackClass 属性指定。

3. 核心区别对比表

特性 blockHandler (限流处理) fallback (降级/异常处理)
设计目的 处理 Sentinel 规则触发后的逻辑(如被限流提示“系统繁忙”) 处理业务代码抛出异常后的逻辑(如查询数据库失败则查询缓存)
触发异常 仅限 BlockException 所有异常 (Throwable),包含业务报错
附加参数要求 必须在参数最后加上 BlockException e 可在最后加上 Throwable e(可选)
异常排除 不支持排除异常 支持通过 exceptionsToIgnore 排除特定异常

4. 关键问题:如果两者同时配置了怎么办?

如果一个方法同时配置了 blockHandlerfallback

  1. 当业务代码抛出普通异常时(如空指针):只会触发 fallback
  2. 当触发 Sentinel 限流/熔断规则抛出 BlockExceptionblockHandler 的优先级更高,会进入 blockHandler 处理,而不会进入 fallback
  3. 特殊情况:如果只配置了 fallback 没有配置 blockHandler,那么触发限流抛出的 BlockException 也会被 fallback 捕获并处理(因为 BlockException 也是 Throwable 的子类)。但强烈建议将两者分开处理,因为限流(流量太大)和业务异常(代码出错)在业务上的应对策略通常是完全不同的。

5. 代码示例说明

java
@Service
public class OrderService {

    @SentinelResource(
        value = "createOrder",
        blockHandler = "handleLimit",  // 指定限流处理方法
        fallback = "handleError"       // 指定异常处理方法
    )
    public String createOrder(String userId, String productId) {
        if ("error".equals(userId)) {
            throw new RuntimeException("数据库异常"); // 触发 fallback
        }
        return "订单创建成功"; // 正常返回,如果请求太快触发限流,则触发 blockHandler
    }

    // --- blockHandler 处理方法 ---
    // 注意:参数必须与原方法完全一致,最后加一个 BlockException
    public String handleLimit(String userId, String productId, BlockException ex) {
        return "系统当前访问人数过多,请稍后再试!(限流了)";
    }

    // --- fallback 处理方法 ---
    // 注意:参数必须与原方法完全一致,最后加一个 Throwable (可选)
    public String handleError(String userId, String productId, Throwable ex) {
        return "创建订单失败,系统发生未知错误!(业务报错了)";
    }
}

总结最佳实践
在实际开发中,通常用 blockHandler 返回类似“服务器繁忙请稍后重试”的提示;用 fallback 返回默认数据、查询备用数据库或返回业务处理失败的错误码。两者各司其职。

00:00
00:00