• 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 成对使用,记录最终请求的响应时间
                }
            }
        }
    }
    

    从切面中可以看到 Sentinel 的使用大致分 3 步:

    1. SphU.entry(...)
      请求进来前先调用 entry(...)方法,它有一个 String resourceName 参数用来表示要访问的资源。内部先创建一个全新的 Entry 对象,然后进行链式的规则校验:授权、流控、降级、系统保护、黑名单等。
      若通过了规则校验,则放行本次请求并记录统计信息;否则抛出 BlockException 的子类对象,对应规则链上第一个未通过的规则,开发者通过 catch 这个异常并判断其类别来处理请求被拒绝的业务逻辑。

    2. 访问资源
      通过规则校验的请求则可以访问资源,资源先简单粗暴的理解成将要调用的方法。
      若在访问资源的过程中出现了错误,开发者可以 catch Throwable 并用 Tracer.trace(ex) 将异常放入对应的 Entry 对象。

    3. entry.exit(...)
      entry(...)方法和 entry.exit(...)必须成对使用,通常 entry.exit(...) 放在 finally 中,确保它最后会被执行。
      该方法对本次请求进行统计收尾工作,比如:计算本次请求的响应时长,处理第 2 步中可能存在的异常等。

    Sentinel 主工作流程:

    1. 工作原理

    2. 流程图:来源 https://blog.csdn.net/prestigeding/article/details/103842382

    3. slot chain 架构图:

  • 相关阅读:
    创建型设计模式-原型模式(单例) MemberwiseClone()
    Oracle 查看没有释放的链接 和删除,相关sql
    win10 安装 SQL Developer 工具
    修改nuget包默认存放路径 win10
    使用端口查询
    未能加载文件或程序集“Newtonsoft.Json, Version=12.0.0.0,
    微信错误码
    sqlserver 时间转换记录
    Homebrew 使用指南
    在Mac检查安装的.net core 版本
  • 原文地址:https://www.cnblogs.com/magexi/p/13124441.html
Copyright © 2020-2023  润新知