Spring Cloud在使用Sentinel进行服务降级和熔断时,如果同时配置了
fallback
和blockHandler
,则在服务熔断后,抛出的BlockException
不会再fallback
逻辑中执行,而是在blockHandler
逻辑中执行。
首先来看只配置了fallback的情况,接口代码如下
// 批量读取@GetMapping("/getBatch")@SentinelResource(value = "getTemplateInBatch", fallback = "getTemplateInBatch_fallback")public Map<Long, CouponTemplateInfo> getTemplateInBatch(@RequestParam("ids") Collection<Long> ids){// 如果服务熔断,则不会打印以下日志,直接进入服务降级getTemplateInBatch_fallback方法中log.info("getTemplateInBatch: {}", JSON.toJSONString(ids));// 添加条件,如果满足则手动抛出一个运行时异常if(ids.contains(Long.valueOf(2))) { throw new RuntimeException("测试sentinel熔断");}return this.couponTemplateService.getTemplateInfoMap(ids);}// getTemplateInBatch服务降级方法public Map<Long, CouponTemplateInfo> getTemplateInBatch_fallback(Collection<Long> ids){log.info("接口被降级了");return Maps.newHashMap();}// getTempalteInBatch限流后方法public Map<Long, CouponTemplateInfo> getTemplateInBatch_block(Collection<Long> ids,BlockException exception){log.info("接口被限流");return null;}
配置一个Sentinel熔断规则,即在10秒内5次及以上请求getTemplateInBatch
资源,如果异常次数比率达到了60%,则服务熔断10秒
我们通过postman或者编写测试脚本对/getBatch
接口进行测试,控制台打印日志如下
通过上面的日志可以看到,在前5次请求中打印了getTemplateInBatch: [2]
日志,说明执行了原方法,在第6次时因为满足了熔断条件,因此没有执行原方法,而是直接执行服务降级方法。这说明只配置fallback
时,服务熔断后会进入fallback
逻辑中进行处理。
接下来,在@SentinelResource注解中添加blockHandler属性
@GetMapping("/getBatch")@SentinelResource(value = "getTemplateInBatch", fallback = "getTemplateInBatch_fallback", blockHandler = "getTemplateInBatch_block")public Map<Long, CouponTemplateInfo> getTemplateInBatch(@RequestParam("ids") Collection<Long> ids){// 如果服务熔断,则不会打印以下日志,直接进入服务降级getTemplateInBatch_fallback方法中log.info("getTemplateInBatch: {}", JSON.toJSONString(ids));// 添加条件,如果满足则手动抛出一个运行时异常if(ids.contains(Long.valueOf(2))) { throw new RuntimeException("测试sentinel熔断");}return this.couponTemplateService.getTemplateInfoMap(ids);}
并在Sentinel控制台中增加一条流量规则
重启应用后再次进行测试
可以看到,在同时配置了fallback
和blockHandler
的情况下,当服务熔断后,直接进入了blockHandler
逻辑中处理,而没有进入fallback
,因此如果同时配置了blockHandler
和fallback
,则BlockException只会进到blockHandler
处理逻辑中(熔断后不会再进入原方法中,不会执行throw new RuntimeException,而是抛出BlockException)。