Sentinel学习二

简介: 如果我们不对Sentinel的异常提示做自定义,那么此时的提示是非常不详细的。如果做了自定义,就可以看到下面自定义的提示。sentinel提供了@SentinelResource注解帮助我们来实现自定义的熔断限流后的自定义方法处理,可以根据sentinel的aop可以看到处理的example,从而更为清晰的认识sentinel强大的功能。

一、自定义限流效果

如果我们不对Sentinel的异常提示做自定义,那么此时的提示是非常不详细的。

正常情况下的:

image-20230202211907265.png

如果做了自定义,就可以看到下面自定义的异常提示:

image-20230202211733631.png

相关指标数据信息:

image-20230215182210057.png

二、限流aop增强实现方式

因此我们可以看到Sentinel里面是有对Sentinel的增强的。Sentinel基于aop的增强:

image-20230215154423552.png

看到下面的代码中,带有@SentinelResource这个注解。

1.带SentinelResource注解,写好对应的fallback方法进行自定义处理

    @Override

   @SentinelResource(value="hello", fallback="helloFallback")

   publicStringhello(longs) {

       if (s<0) {

           thrownewIllegalArgumentException("invalid arg");

       }

       returnString.format("Hello at %d", s);

   }

   //自定义处理的方法

   publicStringhelloFallback(longs, Throwableex) {

       ex.printStackTrace();

       return"Oops, error occurred at "+s;

   }

可以看到自定义的处理方法helloFallback。

2.采用blockHandler为异常的处理方法,blockHandlerClass为异常处理的类

   @Override

   @SentinelResource(value="test", blockHandler="handleException", blockHandlerClass= {ExceptionUtil.class})

   publicvoidtest() {

       System.out.println("Test");

   }

3.采用自定义的处理方法,同时忽略异常的类

   @Override

   @SentinelResource(value="helloAnother", defaultFallback="defaultFallback",

       exceptionsToIgnore= {IllegalStateException.class})

   publicStringhelloAnother(Stringname) {

       if (name==null||"bad".equals(name)) {

           thrownewIllegalArgumentException("oops");

       }

       if ("foo".equals(name)) {

           thrownewIllegalStateException("oops");

       }

       return"Hello, "+name;

   }

三、执行aop增强的实现

此时我们停下来想一想,如果想要实现对对应的方法进行增强,需要做哪些操作?

  • 1.首先基于注解做切面
  • 2.在切点中拿到originMethod.getAnnotation(SentinelResource.class)拿到带SentinelResource注解的class的请求
  • 3.根据拿到的注解信息去拿当前请求的资源名称和entry类型
  • 4.执行entry请求 entry = SphU.entry(resourceName, resourceType, entryType, pjp.getArgs());处理完成
  • 5.如果当前的处理出现了异常,会根据对应的注解的方法执行处理,匹配异常,如果是block异常,处理异常handleBlockException;如果是Throwable异常,忽略对应的异常,然后执行handleFallback
  • 6.完成处理之后,执行exit操作 entry.exit(1, pjp.getArgs());    

image-20230215160120869.png

可以看到其是基于切面实现的

   @Around("sentinelResourceAnnotationPointcut()")

   publicObjectinvokeResourceWithSentinel(ProceedingJoinPointpjp) throwsThrowable {

       MethodoriginMethod=resolveMethod(pjp);

       SentinelResourceannotation=originMethod.getAnnotation(SentinelResource.class);

       // 获取资源信息

       StringresourceName=getResourceName(annotation.value(), originMethod);

       EntryTypeentryType=annotation.entryType();

       intresourceType=annotation.resourceType();

       Entryentry=null;

       try {

           // 执行entry

           entry=SphU.entry(resourceName, resourceType, entryType, pjp.getArgs());

           returnpjp.proceed();

       } catch (BlockExceptionex) {

           returnhandleBlockException(pjp, annotation, ex);

       } catch (Throwableex) {

           Class<?extendsThrowable>[] exceptionsToIgnore=annotation.exceptionsToIgnore();

           // The ignore list will be checked first.

           if (exceptionsToIgnore.length>0&&exceptionBelongsTo(ex, exceptionsToIgnore)) {

               throwex;

           }

           if (exceptionBelongsTo(ex, annotation.exceptionsToTrace())) {

               traceException(ex);

               returnhandleFallback(pjp, annotation, ex);

           }

           // No fallback function can handle the exception, so throw it out.

           throwex;

       } finally {

           if (entry!=null) {

               entry.exit(1, pjp.getArgs());

           }

       }

   }

debug进去,可以看到切面中相关注解信息annotation:

@com.alibaba.csp.sentinel.annotation.SentinelResource(blockHandler=handleException, entryType=OUT, fallbackClass=[], exceptionsToIgnore=[], exceptionsToTrace=[classjava.lang.Throwable], defaultFallback=, value=test, fallback=, blockHandlerClass=[classcom.alibaba.csp.sentinel.demo.annotation.aop.service.ExceptionUtil], resourceType=0)

我们可以看到里面有我们熟悉的两个重要方法:

SphU.entry

entry.exit

entry=SphU.entry(resourceName, resourceType, entryType, pjp.getArgs());

entry.exit(1, pjp.getArgs())

可以看到entry操作首先是拿上下文的信息,执行处理链操作,这个过程中会涉及到spi的加载,加载对应的Slot,形成sentinel的责任链骨架。有了这个骨架就可执行对应的责任链的操作了,也即执行entry操作。

Contextcontext=ContextUtil.getContext();

ProcessorSlot<Object>chain=lookProcessChain(resourceWrapper);

Entrye=newCtEntry(resourceWrapper, chain, context);

chain.entry(context, resourceWrapper, null, count, prioritized, args);

可以看到对应的责任链操作:

spi形成对应的Slot之后,放入到map中,执行entry操作,形成责任链模式。这个流程的操作是按照下面这个顺序执行的:

984e9344fc97b66d32c7e94f8186626.png

我们之所以能够看到界面上的数据,那么需要统计之后,才会在界面上显示,因此StatisticSlot的子类DefaultNode里面进行了统计数据操作。

com.alibaba.csp.sentinel.slots.statistic.StatisticSlot#entry

统计的数据信息在这里可以看到会添加到node中,最终node的数据会设置到上下文context中。

四、相关校验规则check

1.白名单认证check

com.alibaba.csp.sentinel.slots.block.authority.AuthoritySlot#entry

checkBlackWhiteAuthority(resourceWrapper, context);

2.系统自适应check

com.alibaba.csp.sentinel.slots.system.SystemSlot#entry

SystemRuleManager.checkSystem(resourceWrapper, count);

3.限流check

com.alibaba.csp.sentinel.slots.block.flow.FlowSlot#entry

checkFlow(resourceWrapper, context, node, count, prioritized);

4.降级隔离check

com.alibaba.csp.sentinel.slots.block.degrade.DegradeSlot#entry

performChecking(context, resourceWrapper);

在限流中,check的过程中,会首先会根据对应的规则和策略拿到rule=>Node selectedNode = selectNodeByRequesterAndStrategy(rule, context, node);,通过ruleManager拿到。拿到之后,和通过当前拿到的数据信息和内存中的数据对比,从而判断是是否pass。

限流的接口:

com.alibaba.csp.sentinel.slots.block.flow.TrafficShapingController#canPass(com.alibaba.csp.sentinel.node.Node, int, boolean)

可以看到限流的方式有四种:

Default 默认限流方式,快速失败限流

RateLimiter 匀速限流

WarmUp 冷启动限流

WarmUpRateLimiter 冷启动匀速限流

限流涉及到滑动窗口的知识和相关限流的算法。

执行完成之后,就可执行exit操作了。


目录
相关文章
|
1月前
|
算法 Java API
Sentinel学习圣经:从入门到精通 Sentinel,最全详解 (40+图文全面总结)
尼恩给大家做一下系统化、体系化的梳理,联合社群小伙伴,来一个Sentinel学习圣经:从入门到精通Sentinel。
|
7月前
|
Java 数据安全/隐私保护 Sentinel
微服务学习 | Spring Cloud 中使用 Sentinel 实现服务限流
微服务学习 | Spring Cloud 中使用 Sentinel 实现服务限流
|
SpringCloudAlibaba 监控 Java
SpringCloud Alibaba学习(五):Sentinel的介绍与搭建
SpringCloud Alibaba学习(五):Sentinel的介绍与搭建
392 1
SpringCloud Alibaba学习(五):Sentinel的介绍与搭建
|
SpringCloudAlibaba Java UED
SpringCloud Alibaba学习(八):Sentinel的热点规则
热点即经常访问的数据,很多时候我们希望统计或者限制某个热点数据中访问频次最高的TopN数据,并对其访问进行限流或者其它操作 。
272 0
SpringCloud Alibaba学习(八):Sentinel的热点规则
|
SpringCloudAlibaba Nacos 数据库
SpringCloud Alibaba学习(十一):Sentinel的规则持久化
在前面学习Sentinel时我们发现:一旦重启应用,sentinel规则将消失,生产环境需要将配置规则进行持久化 ,非常不方便。这就需要本文介绍的sentinel的规则持久化。
226 0
SpringCloud Alibaba学习(十一):Sentinel的规则持久化
|
SpringCloudAlibaba 负载均衡 Java
SpringCloud Alibaba学习(十):Sentinel的服务熔断功能(Sentinel整合Ribbon+OpenFeign+fallback)
SpringCloud Alibaba学习(十):Sentinel的服务熔断功能(Sentinel整合Ribbon+OpenFeign+fallback)
332 0
SpringCloud Alibaba学习(十):Sentinel的服务熔断功能(Sentinel整合Ribbon+OpenFeign+fallback)
|
SpringCloudAlibaba API Sentinel
SpringCloud Alibaba学习(九):Sentinel的@SentinelResource注解详解
SpringCloud Alibaba学习(九):Sentinel的@SentinelResource注解详解
172 0
SpringCloud Alibaba学习(九):Sentinel的@SentinelResource注解详解
|
SpringCloudAlibaba Sentinel 微服务
SpringCloud Alibaba学习(七):Sentinel的降级规则
Sentinel 熔断降级会在调用链路中某个资源出现不稳定状态时(例如调用超时或异常比例升高),对这个资源的调用进行限制,让请求快速失败,避免影响到其它的资源而导致级联错误。
231 0
SpringCloud Alibaba学习(七):Sentinel的降级规则
|
SpringCloudAlibaba Sentinel 微服务
SpringCloud Alibaba学习(六):Sentinel的流控规则
SpringCloud Alibaba学习(六):Sentinel的流控规则
189 0
SpringCloud Alibaba学习(六):Sentinel的流控规则
|
Java BI Sentinel
Sentinel的SPI和责任链模式学习
通常spi可以配合责任链模式、策略模式使用。此时spi,类似于一个上下文的过程,拿到所有的实现class。 与之类似的还有:SpringUtil.getBeans或者ApplicationContext.getBeansOfType。在一些固定的场景下,处理业务的流程过程通常比较明确,第一步做什么,第二步做什么,第三步做什么的时候,这个时候就可以使用责任链模式在处理。也即存在固定的模式的时候,就可以使用。同时在Netty、Sentinel中有重要使用场景,其过程是一个pipeline流水线的过程。
484 0
 Sentinel的SPI和责任链模式学习