Sentinel 流控的原理是什么,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。
我们提供的服务有:成都网站建设、成都做网站、微信公众号开发、网站优化、网站认证、天心ssl等。为上千多家企事业单位解决了网站和推广的问题。提供周到的售前咨询和贴心的售后服务,是有科学管理、有技术的天心网站制作公司
@ResoureSetinel 工作原理
配置流控规则我们最简单的方式就是通过 @ResoureSetinel 的方式来管理,该注解可以直接定义流控规则、降级规则。下面是一个简单的使用例子:
@SentinelResource(value = "ResOrderGet", fallback = "fallback", fallbackClass = SentinelResourceExceptionHandler.class, blockHandler = "blockHandler", blockHandlerClass = SentinelResourceExceptionHandler.class ) @GetMapping("/order/get/{id}") public CommonResult getStockDetails(@PathVariable Integer id) { StockModel stockModel = new StockModel(); stockModel.setCode("STOCK==>1000"); stockModel.setId(id); return CommonResult.success(stockModel); }
如果大家熟悉 Spring 相关的组件大家都可以想到,这里多半是通过Spring Aop. 的方式来拦截 getStockDetails 方法。我们先看看SentinelAutoConfiguration 配置文件,我们可以找到 SentinelResourceAspect Bean 的定义方法。
@Bean @ConditionalOnMissingBean public SentinelResourceAspect sentinelResourceAspect() { return new SentinelResourceAspect(); }
让后我们再来看看 SentinelResourceAspect 具体是怎么处理的,源码如下:
// 定义 Pointcut @Pointcut("@annotation(com.alibaba.csp.sentinel.annotation.SentinelResource)") public void sentinelResourceAnnotationPointcut() { } // Around 来对被标记 @SentinelResource 注解的方法进行处理 @Around("sentinelResourceAnnotationPointcut()") public Object invokeResourceWithSentinel(ProceedingJoinPoint pjp) throws Throwable { Method originMethod = resolveMethod(pjp); // 获取注解信息 SentinelResource annotation = originMethod.getAnnotation(SentinelResource.class); // 获取资源名称 String resourceName = getResourceName(annotation.value(), originMethod); EntryType entryType = annotation.entryType(); int resourceType = annotation.resourceType(); Entry entry = null; try { // 执行 entry entry = SphU.entry(resourceName, resourceType, entryType, pjp.getArgs()); // 执行业务方法 Object result = pjp.proceed(); // 返回 return result; } catch (BlockException ex) { // 处理 BlockException return handleBlockException(pjp, annotation, ex); } catch (Throwable ex) { Class[] exceptionsToIgnore = annotation.exceptionsToIgnore(); // The ignore list will be checked first. if (exceptionsToIgnore.length > 0 && exceptionBelongsTo(ex, exceptionsToIgnore)) { throw ex; } if (exceptionBelongsTo(ex, annotation.exceptionsToTrace())) { traceException(ex); // 处理降级 return handleFallback(pjp, annotation, ex); } // No fallback function can handle the exception, so throw it out. throw ex; } }
我们总结一下, @SentinelResource 的执行过程, 首先是通过 Aop 进行拦截,然后通过 SphU.entry 执行对应的流控规则,最后调用业务方法。如果触发流控规则首先处理流控异常 BlockException 然后在判断是否有服务降级的处理,如果有就调用 fallback 方法。通过 handleBlockException 、handleFallback 进行处理。
责任链模式处理流控
通过上面的梳理,我们知道对于流控的过程,核心处理方法就是 SphU.entry 。在这个方法中其实主要就是初始化流控 Solt 和执行 Solt. 在这个过程中会对:簇点定义、流量控制、熔断降级、系统白名单等页面功能进行处理。
1. 初始化责任链
下面是初始化 Solt 的核心代码在 SphU.entryWithPriority
// 删减部分代码 private Entry entryWithPriority(ResourceWrapper resourceWrapper, int count, boolean prioritized, Object... args) throws BlockException { // 初始化责任链 ProcessorSlot