序
本文主要研究一下sentinel的SentinelResourceAspect
SentinelResourceAspect
com/alibaba/csp/sentinel/annotation/aspectj/SentinelResourceAspect.java
@Aspectpublic class SentinelResourceAspect { private final Logger logger = LoggerFactory.getLogger(SentinelResourceAspect.class); @Pointcut("@annotation(com.alibaba.csp.sentinel.annotation.SentinelResource)") public void sentinelResourceAnnotationPointcut() { } @Around("sentinelResourceAnnotationPointcut()") public Object invokeResourceWithSentinel(ProceedingJoinPoint pjp) throws Throwable { Method originMethod = getMethod(pjp); SentinelResource annotation = originMethod.getAnnotation(SentinelResource.class); if (annotation == null) { // Should not go through here. throw new IllegalStateException("Wrong state for SentinelResource annotation"); } String resourceName = annotation.value(); EntryType entryType = annotation.entryType(); Entry entry = null; try { ContextUtil.enter(resourceName); entry = SphU.entry(resourceName, entryType); Object result = pjp.proceed(); return result; } catch (BlockException ex) { return handleBlockException(pjp, annotation, ex); } finally { if (entry != null) { entry.exit(); } ContextUtil.exit(); } } //......}
- 使用aspect的around拦截,拦截标注有SentinelResource的注解
- 进入方法之前调用SphU.entry(resourceName, entryType),结束之后调用entry.exit();
- 异常的时候调用handleBlockException方法
handleBlockException
private Object handleBlockException(ProceedingJoinPoint pjp, SentinelResource annotation, BlockException ex) throws Exception { // Execute fallback for degrading if configured. Object[] originArgs = pjp.getArgs(); if (isDegradeFailure(ex)) { Method method = extractFallbackMethod(pjp, annotation.fallback()); if (method != null) { return method.invoke(pjp.getTarget(), originArgs); } } // Execute block handler if configured. Method blockHandler = extractBlockHandlerMethod(pjp, annotation.blockHandler(), annotation.blockHandlerClass()); if (blockHandler != null) { // Construct args. Object[] args = Arrays.copyOf(originArgs, originArgs.length + 1); args[args.length - 1] = ex; if (isStatic(blockHandler)) { return blockHandler.invoke(null, args); } return blockHandler.invoke(pjp.getTarget(), args); } // If no block handler is present, then directly throw the exception. throw ex; }
- 这里会先判断是否是降级需要处理的异常,是的话,则调用fallback方法,否则调用block handler方法
SentinelResource
com/alibaba/csp/sentinel/annotation/SentinelResource.java
@Target(ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)@Inheritedpublic @interface SentinelResource { /** * @return name of the Sentinel resource */ String value(); /** * @return the entry type (inbound or outbound), outbound by default */ EntryType entryType() default EntryType.OUT; /** * @return name of the block exception function, empty by default */ String blockHandler() default ""; /** * The {@code blockHandler} is located in the same class with the original method by default. * However, if some methods share the same signature and intend to set the same block handler, * then users can set the class where the block handler exists. Note that the block handler method * must be static. * * @return the class where the block handler exists, should not provide more than one classes */ Class [] blockHandlerClass() default {}; /** * @return name of the fallback function, empty by default */ String fallback() default "";}
- 这里可以定义fallback方法,以及blockHandler
小结
sentinel的SentinelResourceAspect采用aspect的around拦截SentinelResource,在执行之前进行限流判断,在捕获异常的时候,会根据异常类型判断是调用fallback方法还是调用block handler方法。