@SentinelResource 限流不走 ExceptionHandler 自定义问题探究

在微服务开发中,流量控制是保障系统稳定性的重要手段,Sentinel 作为一款强大的流量控制框架被广泛使用。本文将探讨在使用 @SentinelResource 注解时,限流不走自定义 ExceptionHandler 的问题及解决方案。

一、问题背景

在我们的应用中,使用了 Sentinel 进行流量控制,并且定义了一个自定义的异常处理器 MyExceptionHandler 来处理 BlockException。然而,在实际测试中发现,当发生限流时,自定义的异常处理器并没有被触发。

二、相关代码及分析

(一)自定义异常处理器 MyExceptionHandler

java

@Component
public class MyExceptionHandler implements BlockExceptionHandler {
    @Override
    public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, BlockException e) throws Exception {
        String msg ="";
        if (e instanceof FlowException){
           msg = "手速太快了,慢点";
        }else if (e instanceof ParamFlowException){
            msg="数据太热";
        }else if (e instanceof DegradeException){
            msg = "走降级";
        } else if (e instanceof AuthorityException) {
            msg = "级别不够";
        }else {
            msg = "被系统制裁了";
        }
        httpServletResponse.setContentType("text/html;charset=utf-8");
        httpServletResponse.getWriter().println(msg);
    }
}

这个处理器实现了 BlockExceptionHandler 接口,理论上应该能处理各种 BlockException 相关的异常。

(二)Sentinel 资源注解及异常处理流程

  1. 资源定义

java

@SentinelResource(value = "register",blockHandler ="handleBlock")

在方法上添加了 @SentinelResource 注解,并指定了 blockHandler 方法。

  1. 全局异常处理器

java

@RestControllerAdvice
public class GlobalExceptionHandler {
    //    处理异常
    @ExceptionHandler(BlockException.class) //指定能够处理的异常类型
    public R ex(BlockException  e){
        e.printStackTrace();//打印堆栈中的异常信息
        //捕获到异常之后,响应一个标准的Result
        return R.error("对不起,操作失败,请联系管理员666");
    }
    @ExceptionHandler(Exception.class) //指定能够处理的异常类型
    public R ex(Exception e){
        e.printStackTrace();//打印堆栈中的异常信息
        //捕获到异常之后,响应一个标准的Result
        return R.error("对不起,操作失败,请联系管理员888");
    }
}

定义了全局异常处理器,用于处理 BlockException 和其他通用异常。

(三)异常处理流程分析

当在方法上添加 @SentinelResource 注解时,Sentinel 会通过 AOP 拦截方法调用,并在内部处理限流 / 降级逻辑。此时:

  1. 如果指定了 blockHandler,会优先调用该方法。
  2. 如果未指定 blockHandler,Sentinel 默认会将 BlockException 重新抛出,而不是交给 BlockExceptionHandler 处理。

这就是为什么自定义的全局 MyExceptionHandler 没有被触发的原因。

三、解决方案

如果想要自定义的异常处理器生效,可以考虑以下两种方式:

  1. 移除 blockHandler 指定:如果不需要特殊的 blockHandler 处理逻辑,可以移除 @SentinelResource 注解中的 blockHandler 属性,这样异常会按照正常的 BlockExceptionHandler 流程进行处理。
  2. 在 blockHandler 中手动调用自定义异常处理逻辑:在 blockHandler 方法中,手动调用自定义异常处理器的逻辑,以实现更灵活的异常处理。

四、总结

通过本文的分析,我们了解了 @SentinelResource 注解在异常处理方面的机制,以及为什么自定义的 ExceptionHandler 可能不会被触发。在实际开发中,我们需要根据具体的业务需求,合理配置和使用 Sentinel 的异常处理机制,以确保系统的稳定性和健壮性。

希望本文能对大家在使用 Sentinel 进行流量控制和异常处理时有所帮助。如果你有任何疑问或建议,欢迎在评论区留言交流。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值