美文网首页服务监控和治理
Sentinel之注解@SentinelResource

Sentinel之注解@SentinelResource

作者: 九点半的马拉 | 来源:发表于2020-04-25 21:38 被阅读0次

Sentinel提供了@SentinelResource注解用于定义注解,并提供了AspectJ的扩展用于自定义资源、处理BlockException等。

注解解释:

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface SentinelResource {
    // 定义的资源名
    String value() default "";
    // entry类型, 默认是 EntryType.OUT
    EntryType entryType() default EntryType.OUT;
    // 资源类型
    int resourceType() default 0;
    // 对应处理blockException的函数名称
    String blockHandler() default "";
    // 当希望使用其他类的函数时,可以通过这个来指定对应类的Class对象,注意对应的函数必须为static函数
    Class<?>[] blockHandlerClass() default {};
    // fallback函数名称,用于在抛出异常时提供fallback处理逻辑,可以处理所有类型的异常
    String fallback() default "";
    // 默认的fallback函数名称
    String defaultFallback() default "";
    // 当使用其他类的函数时
    Class<?>[] fallbackClass() default {};
    // 要跟踪的异常类列表
    Class<? extends Throwable>[] exceptionsToTrace() default {Throwable.class};
    // 忽略这些异常
    Class<? extends Throwable>[] exceptionsToIgnore() default {};
}

当出现异常执行上述注解中的指定的处理函数时,这时我们就要利用Spring的AOP特性。

先定义个切入点:

@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 = SphU.entry(resourceName, resourceType, entryType, pjp.getArgs());
            Object result = pjp.proceed();
            return result;
        } catch (BlockException ex) {
            return handleBlockException(pjp, annotation, ex);
        } 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;
            }
            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;
        } finally {
            if (entry != null) {
                entry.exit(1, pjp.getArgs());
            }
        }
    }

简单的说,就是先获取加了该注解的方法,然后解析获取注解里面的参数名等信息,然后根据获取的信息执行一个Sphu.entry()方法包装资源,判断是否需要限流等操作,可以通过的话,再利用反射执行业务逻辑代码;如果没有通过限流等操作,就会抛出BlockException的子类异常,然后获取在注解中定义的函数方法名,利用反射机制再进行执行。

protected Object handleBlockException(ProceedingJoinPoint pjp, SentinelResource annotation, BlockException ex)
        throws Throwable {

        // Execute block handler if configured.
        Method blockHandlerMethod = extractBlockHandlerMethod(pjp, annotation.blockHandler(),
            annotation.blockHandlerClass());
        if (blockHandlerMethod != null) {
            Object[] originArgs = pjp.getArgs();
            // Construct args.
            Object[] args = Arrays.copyOf(originArgs, originArgs.length + 1);
            args[args.length - 1] = ex;
            try {
                if (isStatic(blockHandlerMethod)) {
                    return blockHandlerMethod.invoke(null, args);
                }
                return blockHandlerMethod.invoke(pjp.getTarget(), args);
            } catch (InvocationTargetException e) {
                // throw the actual exception
                throw e.getTargetException();
            }
        }

        // If no block handler is present, then go to fallback.
        return handleFallback(pjp, annotation, ex);
    }

参考文章:
注解支持

相关文章

网友评论

    本文标题:Sentinel之注解@SentinelResource

    本文链接:https://www.haomeiwen.com/subject/vielwhtx.html