Sentinel:SentinelResourceAspect

@SentinelResource 注解的使用方法

官网文档:Sentinel 注解支持

对应 Spring 中的切面:SentinelResourceAspect

/**
 * Aspect for methods with {@link SentinelResource} annotation.
 *
 * @author Eric Zhao
 */
@Aspect
public class SentinelResourceAspect extends AbstractSentinelAspectSupport {// 抽象的父类包含一些通用的方法

    @Pointcut("@annotation(com.alibaba.csp.sentinel.annotation.SentinelResource)")// 切点
    public void sentinelResourceAnnotationPointcut() {
    }

    @Around("sentinelResourceAnnotationPointcut()")
    public Object invokeResourceWithSentinel(ProceedingJoinPoint pjp) throws Throwable {
        Method originMethod = resolveMethod(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 = getResourceName(annotation.value(), originMethod);
        EntryType entryType = annotation.entryType();
        int resourceType = annotation.resourceType();
        Entry entry = null;
        try {// 每次请求都会创建新的 entry 对象,记录了请求开始的时间,然后会在 slot chain 上经过授权,流控,降级等一系列 check 之后,没通过 check 会抛出对应的异常
            entry = SphU.entry(resourceName, resourceType, entryType, pjp.getArgs());// 最后进入 statisticsSlot 记录各项统计数据
            Object result = pjp.proceed();// 如果请求被拒绝了会抛出 BlockException,直接进入 catch 分支了,也就不会访问资源了
            return result;
        } catch (BlockException ex) {// DegradeException、FlowException 等异常的父类
            return handleBlockException(pjp, annotation, ex);// 处理请求被拒绝的情况 blockHandler,如果没有 blockHandler 则会尝试调用 fallback 方法
        } catch (Throwable ex) {// 访问的资源内部抛出了异常,也就是业务异常
            Class<? extends Throwable>[] exceptionsToIgnore = annotation.exceptionsToIgnore();// 需要忽略的异常
            // The ignore list will be checked first.
            if (exceptionsToIgnore.length > 0 && exceptionBelongsTo(ex, exceptionsToIgnore)) {
                throw ex;// 该异常属于 ignore,那么直接上抛,不做处理
            }
            if (exceptionBelongsTo(ex, annotation.exceptionsToTrace())) {
                traceException(ex);// 属于需要 trace 的异常,将该异常放入 entry 中,exit 时去处理
                return handleFallback(pjp, annotation, ex);// 调用可能存在的 fallback 方法
            }

            // No fallback function can handle the exception, so throw it out.
            throw ex;
        } finally {
            if (entry != null) {
                entry.exit(1, pjp.getArgs());// entry 和 exit 成对使用,记录最终请求的响应时间
            }
        }
    }
}
上一篇:分布式锁Redis实现方式


下一篇:ProceedingJoinPoint获取实现类接口上的注解