武宁网站ui专业设计,对话弹窗在网站上浮动,网站开发技巧,网站开发语言统计本文介绍Sentinel的blockHandler与fallback的区别#xff0c;背景是#xff1a;发生限流时#xff0c;配置的sentinel的blockhandler没有生效而fallback生效了#xff1b;排查原因#xff0c;从而给出Sentinel配置异常降级和限流降级的代码写法#xff1b;
在查看源码前…本文介绍Sentinel的blockHandler与fallback的区别背景是发生限流时配置的sentinel的blockhandler没有生效而fallback生效了排查原因从而给出Sentinel配置异常降级和限流降级的代码写法
在查看源码前查阅了相关的技术帖子1. Sentinel的blockHandler与fallback的区别 2.Sentinel服务熔断[fallBack/blockHandler]针对同时配置fallback和blockHandler的场景其中的结论存在不一致所以决定自己亲手实践下
1. 未配置fallback和blockHandler
代码如下仅配置SentinelResource的value并去sentinel控制台配置单机限流为1
限流方法 /*** 测试sentinel的降级方法*/SentinelResource(value testSentinelFallback)public String testSentinelFallback() {return 返回成功ok;}
测试代码 Overridepublic String mock() {// 异步调用 模拟并发情况for (int i 0; i 5; i) {CompletableFuture.runAsync(() - {try {final String result testSentinelService.testSentinelFallback();log.info(调用返回结果 [result{}], result);} catch (Throwable e) {log.warn(调用抛出异常, e);}});}return null;}
sentinel后台配置 执行结果
调用返回结果 [result返回成功ok]调用抛出异常
java.lang.reflect.UndeclaredThrowableException: null
Caused by: com.alibaba.csp.sentinel.slots.block.flow.FlowException: null调用抛出异常
java.lang.reflect.UndeclaredThrowableException: null
Caused by: com.alibaba.csp.sentinel.slots.block.flow.FlowException: null
...
2. 仅配置blockHandler
2.1 配置blockHandler时未带上额外参数BlockException SentinelResource(value testSentinelFallback, blockHandler myBlockHandler)public String testSentinelFallback() {return 返回成功ok;}public String myBlockHandler() {return 进入myBlockHandler逻辑;}
执行结果未进入限流降级方法
调用返回结果 [result返回成功ok]调用抛出异常
java.lang.reflect.UndeclaredThrowableException: null
Caused by: com.alibaba.csp.sentinel.slots.block.flow.FlowException: null调用抛出异常
java.lang.reflect.UndeclaredThrowableException: null
Caused by: com.alibaba.csp.sentinel.slots.block.flow.FlowException: null
...
2.2 正确的配置blockHandler SentinelResource(value testSentinelFallback, blockHandler myBlockHandler)public String testSentinelFallback() {return 返回成功ok;}public String myBlockHandler(BlockException blockException) {return 进入myBlockHandler逻辑;}
执行结果成功进入限流降级方法
调用返回结果 [result返回成功ok]调用返回结果 [result进入myBlockHandler逻辑]调用返回结果 [result进入myBlockHandler逻辑]
...
2.3 blockHandler能捕获业务异常 SentinelResource(value testSentinelFallback, blockHandler myBlockHandler)public String testSentinelFallback() {if (Boolean.TRUE) {throw new BusinessException(FacadeResultCodeEnum.BAD_PARAMS);}return 返回成功ok;}public String myBlockHandler(BlockException blockException) {return 进入myBlockHandler逻辑;}
执行结果接口被限流时成功进入限流降级方法接口出现业务异常时会抛到外层 调用抛出异常
BusinessException调用返回结果 [result进入myBlockHandler逻辑]调用返回结果 [result进入myBlockHandler逻辑]
...
3. 仅配置fallback
3.1 配置fallback时未带上额外参数Throwable SentinelResource(value testSentinelFallback, fallback myFallback)public String testSentinelFallback() {if (Boolean.TRUE) {throw new BusinessException(FacadeResultCodeEnum.BAD_PARAMS);}return 返回成功ok;}public String myFallback() {return 进入myFallback逻辑;}
执行结果接口被限流时或者接口出现业务异常时都会进入fallback降级方法
调用返回结果 [result进入myFallback逻辑]调用返回结果 [result进入myFallback逻辑]调用返回结果 [result进入myFallback逻辑]
...
3.2 配置fallback时带上额外参数Throwable SentinelResource(value testSentinelFallback, fallback myFallback)public String testSentinelFallback() {if (Boolean.TRUE) {throw new BusinessException(FacadeResultCodeEnum.BAD_PARAMS);}return 返回成功ok;}public String myFallback(Throwable throwable) {if (throwable instanceof BlockException) {return 进入myFallback逻辑 限流异常;}return 进入myFallback逻辑 业务异常;}
执行结果接口被限流时或者接口出现业务异常时都会进入fallback降级方法且可以通过异常类型区分出限流异常和业务异常
调用返回结果 [result进入myFallback逻辑 业务异常]调用返回结果 [result进入myFallback逻辑 限流异常]
调用返回结果 [result进入myFallback逻辑 限流异常]
...
4. 同时配置fallback和blockHandler SentinelResource(value testSentinelFallback, fallback myFallback, blockHandler myBlockHandler)public String testSentinelFallback() {if (Boolean.TRUE) {throw new BusinessException(FacadeResultCodeEnum.BAD_PARAMS);}return 返回成功ok;}public String myFallback(Throwable throwable) {if (throwable instanceof BlockException) {return 进入myFallback逻辑 限流异常;}return 进入myFallback逻辑 业务异常;}public String myBlockHandler(BlockException blockException) {return 进入myBlockHandler逻辑;}
执行结果若blockHandler和fallback都进行了配置在未触发限流进入到方法逻辑抛出业务异常时会进入fallback方法在触发限流时进入不到方法逻辑直接抛出BlockException进入blockHandler方法 5. 结论
5.1 异常捕获逻辑
1. blockHandler
blockHandler仅处理限流异常使用blockHandler时方法签名参数与原方法一致且必须要在参数的最后位置补充BlockException参数若未补充BlockException参数则不生效
2. fallback
fallback可以处理所有类型异常包括限流异常和业务异常使用fallback时方法签名参数可以与原方法完全一致或者也接受在参数的最后位置补充Throwable参数通过对Throwable参数的类型区分是限流异常还是其他异常当同时生效blockHandler和fallback时限流异常会优先被blockHandler处理而不再进入fallback逻辑
5.2 合理的代码写法
1同时配置生效blockHandler和fallback分别处理限流异常和业务异常 SentinelResource(value testSentinelFallback, fallback myFallback, blockHandler myBlockHandler)public String testSentinelFallback() {// ...return 返回成功ok;}public String myFallback(Throwable throwable) {return 进入myFallback逻辑 业务异常;}public String myBlockHandler(BlockException blockException) {return 进入myBlockHandler逻辑;}
2仅配置fallback并通过Throwable类型区分限流异常和业务异常 SentinelResource(value testSentinelFallback, fallback myFallback)public String testSentinelFallback() {// ...return 返回成功ok;}public String myFallback(Throwable throwable) {if (throwable instanceof com.alibaba.csp.sentinel.slots.block.flow.FlowException) {final FlowRule rule ((FlowException) throwable).getRule();final double count rule.getCount();final String resource rule.getResource();// 打印限流规则信息log.warn(testSentinelFallback触发限流降级 [sentinelResource{} QpsLimit{}]], resource, count);return null;} else {log.warn(testSentinelFallback触发异常降级 抛出异常, throwable);throw new RuntimeException(testSentinelFallback业务异常);}}
5.3 注解参数释义及注意事项
1. SentinelResource注解参数说明
属性默认值说明blockHandler 用于在抛出限流/熔断/系统保护等异常的降级处理逻辑blockHandler 针对BlockException类型的异常优先级比fallback高 blockHandler 函数访问范围需要是 public返回类型需要与原方法相匹配参数类型需要和原方法相匹配并且最后加一个额外的参数类型为 BlockException blockHandler 函数默认需要和原方法在同一个类中 blockHandlerClass若希望使用其他类的函数则可以指定 blockHandlerClass 为对应的类的 Class 对象注意对应的函数必需为 static 函数否则无法解析defaultFallback默认的 fallback 函数名称可选项通常用于通用的 fallback 逻辑即可以用于很多服务或方法 默认 fallback 函数可以针对所有类型的异常除了 exceptionsToIgnore 里面排除掉的异常类型进行处理 若同时配置了 fallback 和 defaultFallback则只有 fallback 会生效 entryTypeEntryType.OUT资源调用的流量类型是入口流量EntryType.IN还是出口流量EntryType.OUT注意系统保护规则只对 IN 生效exceptionsToIgnore用于指定哪些异常被排除掉不会计入异常统计中也不会进入 fallback 逻辑中而是会原样抛出 优先级高于exceptionsToTraceexceptionsToTraceThrowable.class用于指定哪些异常不被排除掉如果属于该类型则会计入异常统计中也会进入 fallback 逻辑中不会原样抛出不建议修改默认值fallback 用于在抛出异常的时候提供 fallback 处理逻辑fallback 针对所有类型的异常除了 exceptionsToIgnore 里面排除掉的异常类型 方法参数列表需要和原函数一致或者可以额外多一个 Throwable 类型的参数用于接收对应的异常注意和blockHandler添加的BlockException不一样 fallbackClass类似blockHandlerClass参数resourceType资源类型默认0value资源名称必需项
2. 区分限流异常和熔断异常
限流状态会抛异常FlowException继承BlockException
Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is com.alibaba.csp.sentinel.slots.block.flow.FlowException] with root causecom.alibaba.csp.sentinel.slots.block.flow.FlowException: null
熔断状态会抛异常DegradeException继承BlockException
Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is com.alibaba.csp.sentinel.slots.block.degrade.DegradeException] with root causecom.alibaba.csp.sentinel.slots.block.degrade.DegradeException: null 参考annotation-support | Sentinel