本文主要研究一下sentinel的SentinelResourceAspectjava
com/alibaba/csp/sentinel/annotation/aspectj/SentinelResourceAspect.javagit
@Aspect public 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(); } } //...... }
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; }
com/alibaba/csp/sentinel/annotation/SentinelResource.javagithub
@Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @Inherited public @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 ""; }
sentinel的SentinelResourceAspect採用aspect的around攔截SentinelResource,在執行以前進行限流判斷,在捕獲異常的時候,會根據異常類型判斷是調用fallback方法仍是調用block handler方法。ide